From 10be281cfa2e674990e1dde9805e67ffdb5fcfb8 Mon Sep 17 00:00:00 2001 From: swrup Date: Wed, 25 Feb 2026 20:12:13 +0100 Subject: [PATCH] + test disable auditor --- src/auditor.ml | 19 +++++++++++++ src/http_management.ml | 56 ++++++++++++++++++++++---------------- src/pg.ml | 40 +++++++-------------------- src/pg_type.ml | 11 ++++++++ test/offline_management.sh | 10 +++++-- tools/dune | 2 +- tools/offline.ml | 15 ++-------- tools/offline_impl.ml | 9 ++++-- 8 files changed, 89 insertions(+), 73 deletions(-) create mode 100644 src/auditor.ml diff --git a/src/auditor.ml b/src/auditor.ml new file mode 100644 index 00000000..7534ac4a --- /dev/null +++ b/src/auditor.ml @@ -0,0 +1,19 @@ +type t = { + auditor_pub: Crypto.EddsaPublicKey.t; + auditor_url: string; + auditor_name: string; + last_change: Timestamp.t; + is_active: bool; +} + +let of_setup_message + Api.AuditorSetupMessage. + { auditor_url; auditor_name; auditor_pub; master_sig= _; validity_start } + = + { + auditor_url; + auditor_name; + auditor_pub; + last_change= validity_start; + is_active= true; + } diff --git a/src/http_management.ml b/src/http_management.ml index a431f362..afacfe6e 100644 --- a/src/http_management.ml +++ b/src/http_management.ml @@ -153,24 +153,22 @@ module Auditors = struct h_auditor_url= Hash.Cstring.H64.hash auditor_url; } - (* TODO monotonic time *) let do_ ~db_conn v = let auditor_pub = v.AuditorSetupMessage.auditor_pub in let validity_start = v.AuditorSetupMessage.validity_start in - let* last_date_opt = - Pg.get_auditor_timestamp db_conn auditor_pub |> unwrap_err_caqti - in - match last_date_opt with + let* opt = Pg.find_auditor db_conn auditor_pub |> unwrap_err_caqti in + match opt with | None -> - let+ () = Pg.insert_auditor db_conn v |> unwrap_err_caqti in + let auditor = Auditor.of_setup_message v in + let+ () = Pg.update_auditor db_conn auditor |> unwrap_err_caqti in Logs.info (fun m -> m "enabled auditor"); () - | Some last_date -> - if Timestamp.compare last_date validity_start > 0 then + | Some auditor -> + if Timestamp.compare auditor.last_change validity_start > 0 then Error "database has more recent auditor data for this auditor public key" else - let+ () = Pg.update_auditor db_conn v |> unwrap_err_caqti in + let+ () = Pg.update_auditor db_conn auditor |> unwrap_err_caqti in Logs.info (fun m -> m "updated auditor"); () @@ -198,26 +196,36 @@ module Auditors_disable = struct let do_ ~db_conn auditor_pub AuditorTeardownMessage.{ master_sig= _; validity_end } = - let* last_date_opt = - Pg.get_auditor_timestamp db_conn auditor_pub |> unwrap_err_caqti - in - match last_date_opt with + let* opt = Pg.find_auditor db_conn auditor_pub |> unwrap_err_caqti in + match opt with | None -> Error "auditor not found" - | Some last_date -> - if Timestamp.compare last_date validity_end > 0 then - Error - "database has more recent auditor data for this auditor public key" - else - let+ () = - Pg.disable_auditor db_conn ~auditor_pub ~change_date:validity_end - |> unwrap_err_caqti - in - () + | Some auditor -> ( + match Timestamp.compare auditor.last_change validity_end > 0 with + | true -> + Error + "database has more recent auditor data for this auditor public \ + key" + | false -> ( + match auditor.is_active with + | false -> + Logs.info (fun m -> m "auditor was already revoked"); + Ok () + | true -> + let auditor = + { auditor with last_change= validity_end; is_active= false } + in + let+ () = + Pg.update_auditor db_conn auditor |> unwrap_err_caqti + in + Logs.info (fun m -> + m "revoked auditor `%s`" + (Crypto.EddsaPublicKey.to_b32 auditor_pub)); + ())) let jsont = AuditorTeardownMessage.jsont let f req auditor_pub server _env = - Logs.info (fun m -> m "POST /management/auditors/$AUDITOR_PUB/revoke/"); + Logs.info (fun m -> m "POST /management/auditors/$AUDITOR_PUB/disable/"); let keys = Vif.Server.device Devices.keys server in let db_conn = Vif.Server.device Devices.db_connection server in let res = diff --git a/src/pg.ml b/src/pg.ml index 28e3d5d5..1e36e1df 100644 --- a/src/pg.ml +++ b/src/pg.ml @@ -115,43 +115,23 @@ let insert_signkey_revocation = fun (module Conn : CONN) exchange_pub master_sig -> Conn.exec req (exchange_pub, master_sig) -let get_auditor_timestamp = +let find_auditor = let req = - Caqti_type.(eddsa_pub ->? time) - "SELECT last_change FROM auditors WHERE auditor_pub=$1" + Caqti_type.(eddsa_pub ->? auditor) + "SELECT auditor_pub, auditor_name, auditor_url, last_change, is_active \ + FROM auditors WHERE auditor_pub=$1" in fun (module Conn : CONN) auditor_pub -> Conn.find_opt req auditor_pub -let insert_auditor = - let req = - Caqti_type.(t4 eddsa_pub string string time ->. unit) - "INSERT INTO auditors (auditor_pub, auditor_name, auditor_url, \ - is_active, last_change) VALUES ($1, $2, $3, true, $4)" - in - fun (module Conn : CONN) - AuditorSetupMessage. - { auditor_url; auditor_name; auditor_pub; master_sig= _; validity_start } - -> Conn.exec req (auditor_pub, auditor_name, auditor_url, validity_start) - let update_auditor = let req = - Caqti_type.(t5 eddsa_pub string string bool time ->. unit) - "UPDATE auditors SET auditor_url=$2, auditor_name=$3, is_active=$4, \ - last_change=$5 WHERE auditor_pub=$1" + Caqti_type.(auditor ->. unit) + "INSERT INTO auditors (auditor_pub, auditor_name, auditor_url, \ + last_change, is_active) VALUES ($1, $2, $3, $4, $5) ON CONFLICT \ + (auditor_pub) DO UPDATE SET auditor_name=$2, auditor_url=$3, \ + last_change=$4, is_active=$5" in - fun (module Conn : CONN) - AuditorSetupMessage. - { auditor_url; auditor_name; auditor_pub; master_sig= _; validity_start } - -> Conn.exec req (auditor_pub, auditor_url, auditor_name, true, validity_start) - -let disable_auditor = - let req = - Caqti_type.(t5 eddsa_pub string string bool time ->. unit) - "UPDATE auditors SET auditor_url=$2, auditor_name=$3, is_active=$4, \ - last_change=$5 WHERE auditor_pub=$1" - in - fun (module Conn : CONN) ~auditor_pub ~change_date -> - Conn.exec req (auditor_pub, "", "", false, change_date) + fun (module Conn : CONN) auditor -> Conn.exec req auditor let insert_auditor_denom_sig = let req = diff --git a/src/pg_type.ml b/src/pg_type.ml index 546c0b4f..a78f274a 100644 --- a/src/pg_type.ml +++ b/src/pg_type.ml @@ -351,3 +351,14 @@ let exchange_partner_setup = wad_fee; }) Caqti_type.(t7 eddsa_pub time time time_span amount master_sig string) + +let auditor = + let open Auditor in + Caqti_type.custom + ~encode:(fun + { auditor_pub; auditor_url; auditor_name; last_change; is_active } -> + Ok (auditor_pub, auditor_url, auditor_name, last_change, is_active)) + ~decode:(fun + (auditor_pub, auditor_url, auditor_name, last_change, is_active) -> + Ok { auditor_pub; auditor_url; auditor_name; last_change; is_active }) + Caqti_type.(t5 eddsa_pub string string time bool) diff --git a/test/offline_management.sh b/test/offline_management.sh index 27e3815e..b80bbc73 100755 --- a/test/offline_management.sh +++ b/test/offline_management.sh @@ -46,12 +46,16 @@ offline_tool enable-auditor \ --output $b \ --auditor_url "auditor.example.com" \ --auditor_name "auditor example" \ ---auditor_pub $auditor_pub \ ---validity_start 0 +--auditor_pub $auditor_pub offline_tool upload --input $b --url $url"/management/auditors" echo "[OK] /management/auditors" -# todo test disable auditor +offline_tool disable-auditor \ +--master_key $master_key \ +--output $b \ +--auditor_pub $auditor_pub +offline_tool upload --input $b --url $url"/management/auditors/"$auditor_pub"/disable" +echo "[OK] /management/auditors/\$AUDITOR_PUB/disable" offline_tool wire-fee \ --master_key $master_key \ diff --git a/tools/dune b/tools/dune index 7b747b57..d761cb4e 100644 --- a/tools/dune +++ b/tools/dune @@ -2,7 +2,7 @@ (public_name offline) (name offline) (modules offline offline_impl) - (libraries cmdliner bos fmt mirage-crypto ptime mte vif)) + (libraries cmdliner bos fmt mirage-crypto mtime ptime mte vif)) (executable (public_name gen_registry_files) diff --git a/tools/offline.ml b/tools/offline.ml index 7c1059b7..86217734 100644 --- a/tools/offline.ml +++ b/tools/offline.ml @@ -199,35 +199,26 @@ let enable_auditor_cmd = let auditor_pub = Arg.(required & opt (some eddsa_pub) None & info [ "auditor_pub" ]) in - let validity_start = - Arg.(required & opt (some timestamp) None & info [ "validity_start" ]) - in Cmd.make (Cmd.info "enable-auditor" ~doc) @@ let+ output = output and+ master_key = master_key and+ auditor_url = auditor_url and+ auditor_name = auditor_name - and+ auditor_pub = auditor_pub - and+ validity_start = validity_start in + and+ auditor_pub = auditor_pub in enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub - ~validity_start let disable_auditor_cmd = let doc = "Disable auditor." in let auditor_pub = Arg.(required & opt (some eddsa_pub) None & info [ "auditor_pub" ]) in - let validity_end = - Arg.(required & opt (some timestamp) None & info [ "validity_end" ]) - in Cmd.make (Cmd.info "disable-auditor" ~doc) @@ let+ output = output and+ master_key = master_key - and+ auditor_pub = auditor_pub - and+ validity_end = validity_end in - disable_auditor ~output ~master_key ~auditor_pub ~validity_end + and+ auditor_pub = auditor_pub in + disable_auditor ~output ~master_key ~auditor_pub let wire_fee_cmd = let doc = "Provides wire fee configuration." in diff --git a/tools/offline_impl.ml b/tools/offline_impl.ml index f8c1c895..39ae19c2 100644 --- a/tools/offline_impl.ml +++ b/tools/offline_impl.ml @@ -275,9 +275,10 @@ let global_fees ~output ~master_key ~start_date ~end_date ~history_fee let* () = write_file output s in Ok () -let enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub - ~validity_start = +let enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub = let* key = read_master_key_file master_key in + let ns = Mtime_clock.now_ns () in + let validity_start = Timestamp.of_s @@ Int64.unsigned_div ns 1_000_000_000L in let master_sig = let open Signatures.MasterAddAuditor in signf (EddsaSignature.sign ~key) @@ -295,8 +296,10 @@ let enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub let* () = write_file output s in Ok () -let disable_auditor ~output ~master_key ~auditor_pub ~validity_end = +let disable_auditor ~output ~master_key ~auditor_pub = let* key = read_master_key_file master_key in + let ns = Mtime_clock.now_ns () in + let validity_end = Timestamp.of_s @@ Int64.unsigned_div ns 1_000_000_000L in let master_sig = let open Signatures.MasterDelAuditor in signf (EddsaSignature.sign ~key) { end_date= validity_end; auditor_pub }