From 17be86bfd4e6badec6f334dcddfe1f4dca49a940 Mon Sep 17 00:00:00 2001 From: swrup Date: Tue, 3 Feb 2026 22:03:25 +0100 Subject: [PATCH] offline tool: add wire-fee cmd --- src/api.ml | 3 --- src/http_management.ml | 13 ++++++++++- tools/do_management.sh | 49 +++++++++++++++++++++++++++++------------- tools/offline.ml | 37 +++++++++++++++++++++++++++++-- tools/offline_impl.ml | 30 ++++++++++++++++++++++++++ 5 files changed, 111 insertions(+), 21 deletions(-) diff --git a/src/api.ml b/src/api.ml index 4f294418..42c98345 100644 --- a/src/api.ml +++ b/src/api.ml @@ -525,9 +525,6 @@ end module WireFeeSetupMessage = struct type t = { wire_method: string; - (* TODO over which struct? - Signature using the exchange's offline key - with purpose TALER_SIGNATURE_MASTER_WIRE_FEES *) master_sig_wire: MasterWireFee.t; fee_start: Timestamp.t; fee_end: Timestamp.t; diff --git a/src/http_management.ml b/src/http_management.ml index 31ada445..dce80c96 100644 --- a/src/http_management.ml +++ b/src/http_management.ml @@ -407,8 +407,19 @@ module Wire_fee = struct match wire_fees with | [] -> let+ () = Pg.insert_wire_fee db_conn v |> unwrap_err_caqti in + Logs.info (fun m -> m "added wire fee"); () - | _l -> Error "wire-fee already setup" + | [ vv ] -> ( + match v.master_sig_wire = vv.sig_ with + | false -> + Error "a different wire-fee was already setup for this time frame" + | true -> + Logs.info (fun m -> m "an identical wire-fee was already setup"); + Ok ()) + | _ -> + Error + "invalid database state, multiple wire-fee found in database for \ + this time frame" let jsont = WireFeeSetupMessage.jsont diff --git a/tools/do_management.sh b/tools/do_management.sh index bb27251f..867a460b 100755 --- a/tools/do_management.sh +++ b/tools/do_management.sh @@ -2,24 +2,43 @@ set -e -file1="tmp_file1.json" -file2="tmp_file2.json" -file3="tmp_file3.json" -file4="tmp_file4.json" +a="tmp_a.json" +b="tmp_b.json" auditor_pub=$(<"./data/auditor_public_key") -dune exec offline -- download --output $file1 -dune exec offline -- sign --input $file1 --output $file2 -dune exec offline -- upload --input $file2 --url "/management/keys" +dune exec offline -- download --output $a +dune exec offline -- sign --input $a --output $b +dune exec offline -- upload --input $b --url "/management/keys" -dune exec offline -- enable-auditor --output $file3 --auditor_url "auditor.example.com" --auditor_name "auditor example" --auditor_pub $auditor_pub --validity_start "0.0" -dune exec offline -- upload --input $file3 --url "/management/auditors" +dune exec offline -- enable-auditor \ +--output $b \ +--auditor_url "auditor.example.com" \ +--auditor_name "auditor example" \ +--auditor_pub $auditor_pub \ +--validity_start "0.0" +dune exec offline -- upload --input $b --url "/management/auditors" -dune exec offline -- global-fees --output $file4 --start_date "0.0" --end_date "99999999.9" --history_fee "EUR:0.0" --account_fee "EUR:0.0" --purse_fee "EUR:0.0" --history_expiration "9999999.0" --purse_account_limit 1 --purse_timeout "9999999.0" -dune exec offline -- upload --input $file4 --url "/management/global-fees" +dune exec offline -- wire-fee \ +--output $b \ +--wire_method "magic" \ +--fee_start "0.0" \ +--fee_end "99999999.9" \ +--closing_fee "EUR:0.0" \ +--wire_fee "EUR:0.0" +dune exec offline -- upload --input $b --url "/management/wire-fee" -rm $file1 -rm $file2 -rm $file3 -rm $file4 +dune exec offline -- global-fees \ +--output $b \ +--start_date "0.0" \ +--end_date "99999999.9" \ +--history_fee "EUR:0.0" \ +--account_fee "EUR:0.0" \ +--purse_fee "EUR:0.0" \ +--history_expiration "9999999.0" \ +--purse_account_limit 1 \ +--purse_timeout "9999999.0" +dune exec offline -- upload --input $b --url "/management/global-fees" + +rm $a +rm $b diff --git a/tools/offline.ml b/tools/offline.ml index 2b6c2aa2..c9026624 100644 --- a/tools/offline.ml +++ b/tools/offline.ml @@ -152,6 +152,35 @@ let disable_auditor_cmd = and+ validity_end = validity_end in disable_auditor ~output ~master_key ~auditor_pub ~validity_end +let wire_fee_cmd = + let doc = "Provides wire fee configuration." in + let wire_method = + Arg.(required & opt (some string) None & info [ "wire_method" ]) + in + let fee_start = + Arg.(required & opt (some timestamp) None & info [ "fee_start" ]) + in + let fee_end = + Arg.(required & opt (some timestamp) None & info [ "fee_end" ]) + in + let closing_fee = + Arg.(required & opt (some amount) None & info [ "closing_fee" ]) + in + let wire_fee = + Arg.(required & opt (some amount) None & info [ "wire_fee" ]) + in + Cmd.make (Cmd.info "wire-fee" ~doc) + @@ + let+ output = output + and+ master_key = master_key + and+ wire_method = wire_method + and+ fee_start = fee_start + and+ fee_end = fee_end + and+ closing_fee = closing_fee + and+ wire_fee = wire_fee in + Offline_impl.wire_fee ~output ~master_key ~wire_method ~fee_start ~fee_end + ~closing_fee ~wire_fee + let global_fees_cmd = let doc = "Provides global fee configuration." in let start_date = @@ -210,16 +239,20 @@ let cli = revoke_signkey_cmd; enable_auditor_cmd; disable_auditor_cmd; + wire_fee_cmd; global_fees_cmd; ] let main () = Cmd.eval_result cli let () = if !Sys.interactive then () else exit (main ()) -(* TODO all management operations: - /management/wire-fee +(* TODO + all management operations: /management/wire /management/wire/disable + -> how to build WireSetupMessage? + we need additional data to craft master_sig + maybe supposed to be found in the full payto-uri? /management/drain /management/aml-officers /management/partners *) diff --git a/tools/offline_impl.ml b/tools/offline_impl.ml index 5915cd5d..63d5b120 100644 --- a/tools/offline_impl.ml +++ b/tools/offline_impl.ml @@ -167,3 +167,33 @@ let disable_auditor ~output ~master_key ~auditor_pub ~validity_end = let* s = Api.encode Api.AuditorTeardownMessage.jsont v in let* () = write_file output s in Ok () + +let wire_fee ~output ~master_key ~wire_method ~fee_start ~fee_end ~closing_fee + ~wire_fee = + let open Crypto in + let* key = read_master_key_file master_key in + let master_sig_wire = + let open Bin_sig.MasterWireFee in + sign_f ~f:(EddsaSignature.sign ~key) + { + h_wire_method= Bin_type.Hash_64_cstr.hash wire_method; + start_date= fee_start; + end_date= fee_end; + closing_fee; + wire_fee; + } + in + let v = + Api.WireFeeSetupMessage. + { + wire_method; + fee_start; + fee_end; + closing_fee; + wire_fee; + master_sig_wire; + } + in + let* s = Api.encode Api.WireFeeSetupMessage.jsont v in + let* () = write_file output s in + Ok ()