From 6ee1a994ad4f923c36c4d76cbf17ccb869fda0b5 Mon Sep 17 00:00:00 2001 From: swrup Date: Tue, 3 Feb 2026 17:24:19 +0100 Subject: [PATCH] offline tool: add enable/disable-auditor cmd . --- .gitignore | 5 - data/auditor_private_key | 1 + data/auditor_public_key | 1 + global_fees.json | 1 - src/amount.mli | 3 + src/crypto.ml | 5 +- src/http_keys.ml | 6 +- src/http_management.ml | 10 +- src/pg.ml | 38 ++---- src/secmod.mli | 4 +- tools/do_management.sh | 12 +- tools/offline.ml | 143 ++++++++++++++------- tools/offline_impl.ml | 75 ++++++++--- tools/offline_sig.ml | 268 +++++++++++++++++++-------------------- 14 files changed, 330 insertions(+), 242 deletions(-) create mode 100644 data/auditor_private_key create mode 100644 data/auditor_public_key delete mode 100644 global_fees.json diff --git a/.gitignore b/.gitignore index 672457c9..dbd4866f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,3 @@ _build data/secmod/* !data/secmod/.gitkeep - - -# default output files of offline-tool -response.json -request.json diff --git a/data/auditor_private_key b/data/auditor_private_key new file mode 100644 index 00000000..82aad694 --- /dev/null +++ b/data/auditor_private_key @@ -0,0 +1 @@ +Iî÷q¸àwÇ´Y—›gbÙ'R+5µ™â°ƒˆyë> \ No newline at end of file diff --git a/data/auditor_public_key b/data/auditor_public_key new file mode 100644 index 00000000..2824b9ce --- /dev/null +++ b/data/auditor_public_key @@ -0,0 +1 @@ +A17JXR3E6J4CXDPYT7S1H25PGJ3ABS26TQ38654QCX0TB59RPMF0==== diff --git a/global_fees.json b/global_fees.json deleted file mode 100644 index de002698..00000000 --- a/global_fees.json +++ /dev/null @@ -1 +0,0 @@ -{"start_date":{"t_s":0},"end_date":{"t_s":99999999.900000006},"history_fee":"EUR:0.00","account_fee":"EUR:0.00","purse_fee":"EUR:0.00","history_expiration":{"t_s":9999999000000},"purse_account_limit":1,"purse_timeout":{"t_s":9999999000000},"master_sig":"EHBTKAC30EYD2NGYB76B7JPG1VREYP4W3EQB6YQJJ41NHFWQSX9HQJXTZR9N65V6HAJB5KKHXAYTNBWBDJBE4YV38W6FGZYG6595E00="} \ No newline at end of file diff --git a/src/amount.mli b/src/amount.mli index ab6c7da7..920bed18 100644 --- a/src/amount.mli +++ b/src/amount.mli @@ -1,3 +1,6 @@ +(* TODO + ? have a currency agnostic amount_lib.ml and specialize amount.ml to Config.currency *) + type sign = | Sign_plus | Sign_minus diff --git a/src/crypto.ml b/src/crypto.ml index b61979e4..c304962b 100644 --- a/src/crypto.ml +++ b/src/crypto.ml @@ -28,9 +28,8 @@ module EddsaPublicKey = struct let* pub = of_octets octets in Ok pub - let jsont = - let to_b32 t = B32.encode (to_octets t) in - Jsont.of_of_string ~kind:"EddsaPublicKey" of_b32 ~enc:to_b32 + let to_b32 t = B32.encode (to_octets t) + let jsont = Jsont.of_of_string ~kind:"EddsaPublicKey" of_b32 ~enc:to_b32 let caqti = Caqti_type.custom diff --git a/src/http_keys.ml b/src/http_keys.ml index dd924c90..58e58594 100644 --- a/src/http_keys.ml +++ b/src/http_keys.ml @@ -194,7 +194,11 @@ let mk_keys ~db_conn (module Sm : Secmod.S) ~last_issue_date = let* global_fees = Pg.get_global_fees db_conn ~start_date:Timestamp.epoch |> unwrap_err_caqti in - let auditors = (* TODO *) [] in + let* auditors = + (* TODO /auditors/$AUDITOR_PUB/$H_DENOM_PUB *) + (* does not contains auditor_keys with empty denomination_keys *) + Pg.get_auditor_keys db_conn + in let extensions = None in let extensions_sig = None in Ok diff --git a/src/http_management.ml b/src/http_management.ml index 3e3f046e..31ada445 100644 --- a/src/http_management.ml +++ b/src/http_management.ml @@ -308,12 +308,16 @@ module Auditors = struct match last_date_opt with | None -> let+ () = Pg.insert_auditor db_conn v |> unwrap_err_caqti in + Logs.info (fun m -> m "enabled auditor"); () | Some last_date -> let cmp = Timestamp.compare last_date validity_start |> Option.get in - if cmp > 0 then Error "more recent management auditor already present" + if cmp > 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 + Logs.info (fun m -> m "updated auditor"); () let jsont = AuditorSetupMessage.jsont @@ -347,7 +351,9 @@ module Auditors_disable = struct | None -> Error "auditor not found" | Some last_date -> let cmp = Timestamp.compare last_date validity_end |> Option.get in - if cmp > 0 then Error "more recent management auditor already present" + if cmp > 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 diff --git a/src/pg.ml b/src/pg.ml index b759999c..0d877ba6 100644 --- a/src/pg.ml +++ b/src/pg.ml @@ -11,7 +11,9 @@ transaction - should check validity of signatures got from db, for /management at least *) + should check validity of signatures got from db, for /management at least + + clean up caqti error type *) (* TODO time fix comparison with timestamp footgun *) @@ -186,39 +188,21 @@ let insert_auditor_denom_sig = fun (module Conn : CONN) ~auditor_pub ~h_denom_pub ~auditor_sig -> Conn.exec insert_auditor_denom_sig (auditor_pub, h_denom_pub, auditor_sig) -let _get_auditors = - let get_auditors = - Caqti_type.(unit ->* t3 eddsa_pub string string) - "SELECT auditor_pub, auditor_url, auditor_name FROM auditors WHERE \ - is_active" - in - fun (module Conn : CONN) () -> Conn.collect_list get_auditors () - -let _get_auditor_denoms = - let get_auditor_denoms = - let auditor_sig = Bin_sig.ExchangeKeyValidity.caqti in - Caqti_type.(unit ->* t3 eddsa_pub denomination_hash auditor_sig) - "SELECT auditors.auditor_pub, denominations.denom_pub_hash, \ - auditor_denom_sigs.auditor_sig FROM auditor_denom_sigs JOIN auditors \ - USING (auditor_uuid) JOIN denominations USING (denominations_serial) \ - WHERE auditors.is_active" - in - fun (module Conn : CONN) () -> Conn.collect_list get_auditor_denoms () - -(* TODO +(* todo auditors maybe check that url and name are unique/same for each auditor_pub - do the ht logic out of pg.ml *) + and do the ht logic out of pg.ml? *) +(* this does not return auditors that are not auditing any denom *) let get_auditor_keys = let get_auditor_keys = let auditor_sig = Bin_sig.ExchangeKeyValidity.caqti in Caqti_type.( unit ->* t5 eddsa_pub string string denomination_hash auditor_sig) - "SELECT auditors.auditor_pub, auditors.url, auditors.name, \ - denominations.denom_pub_hash, auditor_denom_sigs.auditor_sig FROM \ - auditor_denom_sigs JOIN auditors USING (auditor_uuid) JOIN \ - denominations USING (denominations_serial) WHERE auditors.is_active" + "SELECT a.auditor_pub, a.auditor_url, a.auditor_name, dn.denom_pub_hash, \ + ads.auditor_sig FROM auditor_denom_sigs AS ads JOIN auditors AS a USING \ + (auditor_uuid) JOIN denominations AS dn USING (denominations_serial) \ + WHERE a.is_active" in - fun (module Conn : CONN) () -> + fun (module Conn : CONN) -> let open Syntax in let* l = Conn.collect_list get_auditor_keys () |> unwrap_err_caqti in let ht = Hashtbl.create 0xff in diff --git a/src/secmod.mli b/src/secmod.mli index 6faafd11..33b6aa21 100644 --- a/src/secmod.mli +++ b/src/secmod.mli @@ -19,8 +19,8 @@ module type S = sig (* - management operations - *) (* TODO - problem of keeping db and secmod state syncronized - do db interaction from secmod? *) + problem of keeping db and secmod state syncronized + do db interaction from secmod? *) val add_signkey_master_signatures : (eddsa_pub * Bin_sig.ExchangeSigningKeyValidity.t) list -> diff --git a/tools/do_management.sh b/tools/do_management.sh index ca1958a3..bb27251f 100755 --- a/tools/do_management.sh +++ b/tools/do_management.sh @@ -5,13 +5,21 @@ set -e file1="tmp_file1.json" file2="tmp_file2.json" file3="tmp_file3.json" +file4="tmp_file4.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 -- global-fees --output $file3 --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 $file3 --url "/management/global-fees" + +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 -- 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" rm $file1 rm $file2 rm $file3 +rm $file4 diff --git a/tools/offline.ml b/tools/offline.ml index 2f9137e9..2b6c2aa2 100644 --- a/tools/offline.ml +++ b/tools/offline.ml @@ -2,24 +2,54 @@ open Cmdliner open Cmdliner.Term.Syntax open Offline_impl +module Arg = struct + include Arg + + let timestamp = + Arg.Conv.make ~docv:"timestamp argument" ~parser:Timestamp.of_string + ~pp:Timestamp.pp () + + let relative_time = + Arg.Conv.make ~docv:"relative time argument" + ~parser:Timestamp.Span.of_string ~pp:Timestamp.Span.pp () + + let amount = + Arg.Conv.make ~docv:"amount argument" ~parser:Amount.of_string ~pp:Amount.pp + () + + let eddsa_pub = + let parser s = Crypto.EddsaPublicKey.of_b32 s in + let pp fmt key = + let s = Crypto.EddsaPublicKey.to_b32 key in + Fmt.pf fmt "%s" s + in + Arg.Conv.make ~docv:"eddsa public key argument" ~parser ~pp () +end + let default_master_offline_key_file = "data/master_offline_private_key" +(* let default_response_file = "response.json" let default_request_file = "request.json" +*) -(*let to_term_ret = function Error e -> `Error (false, e) | Ok () -> `Ok ()*) -let to_term_ret = Fun.id +let master_key = + let doc = "Master offline Eddsa private key file." in + Arg.( + value + & opt file default_master_offline_key_file + & info [ "master_key_file" ] ~doc) -let timestamp = - Arg.Conv.make ~docv:"timestamp argument" ~parser:Timestamp.of_string - ~pp:Timestamp.pp () +let input = + let doc = "input file" in + Arg.(required & opt (some file) None & info [ "i"; "input" ] ~doc) -let relative_time = - Arg.Conv.make ~docv:"relative time argument" ~parser:Timestamp.Span.of_string - ~pp:Timestamp.Span.pp () +let output = + let doc = "output file" in + Arg.(required & opt (some filepath) None & info [ "o"; "output" ] ~doc) -let amount = - Arg.Conv.make ~docv:"amount argument" ~parser:Amount.of_string ~pp:Amount.pp - () +let url = + let doc = "url" in + Arg.(required & opt (some string) None & info [ "url" ] ~doc) let setup_cmd = let doc = "Generate offline master keys" in @@ -33,56 +63,31 @@ let setup_cmd = Cmd.make (Cmd.info "setup" ~doc) @@ let+ output = output in - setup ~output |> to_term_ret + setup ~output let download_cmd = let doc = "GET /management/keys/" in let man = [ `S Manpage.s_description; `P "$(cmd) download /management/keys." ] in - let output = - let doc = "output file" in - Arg.( - value & opt filepath default_response_file & info [ "o"; "output" ] ~doc) - in Cmd.make (Cmd.info "download" ~doc ~man) @@ let+ output = output in - download ~output |> to_term_ret + download ~output let upload_cmd = let doc = "POST input.json data to url (default /management/keys)" in - let input = - let doc = "input file" in - Arg.(value & opt file default_request_file & info [ "i"; "input" ] ~doc) - in - let url = - let doc = "url" in - Arg.(value & opt string "/management/keys" & info [ "url" ] ~doc) - in Cmd.make (Cmd.info "upload" ~doc) @@ let+ input = input and+ url = url in - upload ~input ~url |> to_term_ret - -let master_key = - let doc = "Master offline Eddsa private key file." in - Arg.(value & opt file default_master_offline_key_file & info [ "key" ] ~doc) - -let input = - let doc = "input file" in - Arg.(value & opt file default_response_file & info [ "i"; "input" ] ~doc) - -let output = - let doc = "output file" in - Arg.(value & opt filepath default_request_file & info [ "o"; "output" ] ~doc) + upload ~input ~url let sign_cmd = let doc = "Sign FutureKeysResponse." in Cmd.make (Cmd.info "sign" ~doc) @@ let+ input = input and+ output = output and+ master_key = master_key in - sign ~input ~output ~master_key |> to_term_ret + sign ~input ~output ~master_key let revoke_denom_cmd = let doc = "Revoke denomination." in @@ -93,18 +98,59 @@ let revoke_denom_cmd = Cmd.make (Cmd.info "revoke-denom" ~doc) @@ let+ output = output and+ master_key = master_key and+ h_denom = h_denom in - revoke_denom ~output ~master_key ~h_denom |> to_term_ret + revoke_denom ~output ~master_key ~h_denom let revoke_signkey_cmd = let doc = "Revoke signkey." in let signkey = let doc = "public signing key" in - Arg.(required & pos 0 (some string) None & info [] ~doc) + Arg.(required & pos 0 (some eddsa_pub) None & info [] ~doc) in Cmd.make (Cmd.info "revoke-signkey" ~doc) @@ let+ output = output and+ master_key = master_key and+ signkey = signkey in - revoke_signkey ~output ~master_key ~signkey |> to_term_ret + revoke_signkey ~output ~master_key ~signkey + +let enable_auditor_cmd = + let doc = "Enable auditor." in + let auditor_url = + Arg.(required & opt (some string) None & info [ "auditor_url" ]) + in + let auditor_name = + Arg.(required & opt (some string) None & info [ "auditor_name" ]) + in + 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 + 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 let global_fees_cmd = let doc = "Provides global fee configuration." in @@ -148,7 +194,6 @@ let global_fees_cmd = global_fees ~output ~master_key ~start_date ~end_date ~history_fee ~account_fee ~purse_fee ~history_expiration ~purse_account_limit ~purse_timeout - |> to_term_ret let cli = let info = @@ -163,8 +208,18 @@ let cli = upload_cmd; revoke_denom_cmd; revoke_signkey_cmd; + enable_auditor_cmd; + disable_auditor_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 + /management/wire + /management/wire/disable + /management/drain + /management/aml-officers + /management/partners *) diff --git a/tools/offline_impl.ml b/tools/offline_impl.ml index 2ad704ba..5915cd5d 100644 --- a/tools/offline_impl.ml +++ b/tools/offline_impl.ml @@ -5,6 +5,10 @@ let read_file fname = Bos.OS.File.read (Fpath.v fname) |> unwrap_err_msg let write_file fname content = Bos.OS.File.write (Fpath.v fname) content |> unwrap_err_msg +let read_master_key_file filename = + let* master_key = read_file filename in + Crypto.EddsaPrivateKey.of_octets master_key + let base_url = Uri.of_string "http://localhost:3434/" let full_url path = Uri.with_path base_url path |> Uri.to_string @@ -40,39 +44,44 @@ let setup ~output = let sign ~master_key ~input ~output = let open Crypto in + let* master_key = read_master_key_file master_key in let* input = read_file input in - let* master_key = read_file master_key in - let* master_key = EddsaPrivateKey.of_octets master_key in let master_pub = EddsaPrivateKey.pub_of_priv master_key in let* future_keys_response = Api.decode Api.FutureKeysResponse.jsont input in let* () = Offline_sig.verify_future_keys_response master_pub future_keys_response in let master_signatures = - Offline_sig.make_master_signatures ~master_key future_keys_response + Offline_sig.mk_future_keys ~master_key future_keys_response in let* s = Api.encode Api.MasterSignatures.jsont master_signatures in let* () = write_file output s in Ok () let revoke_denom ~output ~master_key ~h_denom = - let open Crypto in - let* key = read_file master_key in - let* key = EddsaPrivateKey.of_octets key in - let* h_denom = B32.decode h_denom in - let h_denom = Bin_type.DenominationHash.of_octets h_denom in - let denom_revoke = Offline_sig.mk_denom_revoke ~key h_denom in + let* key = read_master_key_file master_key in + let* h_denom_pub = Bin_type.DenominationHash.of_b32 h_denom in + let denom_revoke = + let master_sig = + let open Bin_sig.MasterDenominationKeyRevocation in + sign_f ~f:(Crypto.EddsaSignature.sign ~key) { h_denom_pub } + in + Api.DenomRevocationSignature.{ master_sig } + in let* s = Api.encode Api.DenomRevocationSignature.jsont denom_revoke in let* () = write_file output s in Ok () let revoke_signkey ~output ~master_key ~signkey = - let open Crypto in - let* key = read_file master_key in - let* key = EddsaPrivateKey.of_octets key in - let* signkey = EddsaPublicKey.of_b32 signkey in - let v = Offline_sig.mk_signkey_revoke ~key signkey in - let* s = Api.encode Api.SignkeyRevocationSignature.jsont v in + let* key = read_master_key_file master_key in + let signkey_revoke = + let master_sig = + let open Bin_sig.MasterSigningKeyRevocation in + sign_f ~f:(Crypto.EddsaSignature.sign ~key) { exchange_pub= signkey } + in + Api.SignkeyRevocationSignature.{ master_sig } + in + let* s = Api.encode Api.SignkeyRevocationSignature.jsont signkey_revoke in let* () = write_file output s in Ok () @@ -80,8 +89,7 @@ let global_fees ~output ~master_key ~start_date ~end_date ~history_fee ~account_fee ~purse_fee ~history_expiration ~purse_account_limit ~purse_timeout = let open Crypto in - let* key = read_file master_key in - let* key = EddsaPrivateKey.of_octets key in + let* key = read_master_key_file master_key in let* purse_account_limit = match purse_account_limit >= 0 @@ -126,3 +134,36 @@ let global_fees ~output ~master_key ~start_date ~end_date ~history_fee let* s = Api.encode Api.GlobalFees.jsont global_fees in let* () = write_file output s in Ok () + +let enable_auditor ~output ~master_key ~auditor_url ~auditor_name ~auditor_pub + ~validity_start = + let open Crypto in + let* key = read_master_key_file master_key in + let master_sig = + let open Bin_sig.MasterAddAuditor in + sign_f ~f:(EddsaSignature.sign ~key) + { + start_date= validity_start; + auditor_pub; + h_auditor_url= Bin_type.Hash_64_cstr.hash auditor_url; + } + in + let v = + Api.AuditorSetupMessage. + { auditor_url; auditor_name; auditor_pub; master_sig; validity_start } + in + let* s = Api.encode Api.AuditorSetupMessage.jsont v in + let* () = write_file output s in + Ok () + +let disable_auditor ~output ~master_key ~auditor_pub ~validity_end = + let open Crypto in + let* key = read_master_key_file master_key in + let master_sig = + let open Bin_sig.MasterDelAuditor in + sign_f ~f:(EddsaSignature.sign ~key) { end_date= validity_end; auditor_pub } + in + let v = Api.AuditorTeardownMessage.{ master_sig; validity_end } in + let* s = Api.encode Api.AuditorTeardownMessage.jsont v in + let* () = write_file output s in + Ok () diff --git a/tools/offline_sig.ml b/tools/offline_sig.ml index eaeda431..0c07ce22 100644 --- a/tools/offline_sig.ml +++ b/tools/offline_sig.ml @@ -2,116 +2,49 @@ open Crypto open Bin_type open Api -let denom_signature ~master_key - FutureDenom. - { - section_name= _; - value; - stamp_start; - stamp_expire_withdraw; - stamp_expire_deposit; - stamp_expire_legal; - denom_pub; - fee_withdraw; - fee_deposit; - fee_refresh; - fee_refund= _; - denom_secmod_sig= _; - } = - let octets = DenominationKey.to_octets denom_pub in - let h_denom_pub = DenominationHash.hash octets in - let master_sig = - let open Bin_sig.DenominationKeyValidity in - let master = EddsaPrivateKey.(pub_of_priv master_key) in - sign_f - ~f:(EddsaSignature.sign ~key:master_key) - { - master; - start= stamp_start; - expire_withdraw= stamp_expire_withdraw; - expire_spend= stamp_expire_deposit; - expire_legal= stamp_expire_legal; - value; - fee_withdraw; - fee_deposit; - fee_refresh; - denom_hash= h_denom_pub; - } +let verify_future_keys_response = + let verify_future_denom ~sm_denom_pub + FutureDenom. + { + section_name; + value= _; + stamp_start; + stamp_expire_withdraw; + stamp_expire_deposit= _; + stamp_expire_legal= _; + denom_pub; + fee_withdraw= _; + fee_deposit= _; + fee_refresh= _; + fee_refund= _; + denom_secmod_sig; + } = + let h_denom_pub = + DenominationHash.hash (DenominationKey.to_octets denom_pub) + in + let h_section_name = Hash_64_cstr.hash section_name in + let anchor_time = stamp_start in + let duration_withdraw = Timestamp.diff stamp_start stamp_expire_withdraw in + let open Bin_sig.DenominationKeyAnnouncement in + verify_f + ~f:(EddsaSignature.verify ~key:sm_denom_pub) + denom_secmod_sig + { h_denom_pub; h_section_name; anchor_time; duration_withdraw } in - DenomSignature.{ h_denom_pub; master_sig } - -let signkey_signature ~master_key - FutureSignKey. - { key; stamp_start; stamp_expire; stamp_end; signkey_secmod_sig= _ } = - let master_sig = - let open Bin_sig.ExchangeSigningKeyValidity in - sign_f - ~f:(EddsaSignature.sign ~key:master_key) - { - start= stamp_start; - expire= stamp_expire; - end_= stamp_end; - signkey_pub= key; - } + let verify_future_signkey ~sm_signkey_pub + FutureSignKey. + { key; stamp_start; stamp_expire; stamp_end= _; signkey_secmod_sig } = + let exchange_pub = key in + let anchor_time = stamp_start in + let duration = Timestamp.diff stamp_start stamp_expire in + let open Bin_sig.SigningKeyAnnouncement in + verify_f + ~f:(EddsaSignature.verify ~key:sm_signkey_pub) + signkey_secmod_sig + { exchange_pub; anchor_time; duration } in - SignKeySignature.{ key; master_sig } -let make_master_signatures ~master_key - FutureKeysResponse. - { - future_denoms; - future_signkeys; - master_pub= _; - denom_secmod_public_key= _; - signkey_secmod_public_key= _; - } = - let denom_sigs = List.map (denom_signature ~master_key) future_denoms in - let signkey_sigs = List.map (signkey_signature ~master_key) future_signkeys in - MasterSignatures.{ denom_sigs; signkey_sigs } - -(* - ** - *) - -let verify_future_signkey ~sm_signkey_pub - FutureSignKey. - { key; stamp_start; stamp_expire; stamp_end= _; signkey_secmod_sig } = - let exchange_pub = key in - let anchor_time = stamp_start in - let duration = Timestamp.diff stamp_start stamp_expire in - let open Bin_sig.SigningKeyAnnouncement in - verify_f - ~f:(EddsaSignature.verify ~key:sm_signkey_pub) - signkey_secmod_sig - { exchange_pub; anchor_time; duration } - -let verify_future_denom ~sm_denom_pub - FutureDenom. - { - section_name; - value= _; - stamp_start; - stamp_expire_withdraw; - stamp_expire_deposit= _; - stamp_expire_legal= _; - denom_pub; - fee_withdraw= _; - fee_deposit= _; - fee_refresh= _; - fee_refund= _; - denom_secmod_sig; - } = - let h_denom_pub = - DenominationHash.hash (DenominationKey.to_octets denom_pub) - in - let h_section_name = Hash_64_cstr.hash section_name in - let anchor_time = stamp_start in - let duration_withdraw = Timestamp.diff stamp_start stamp_expire_withdraw in - let open Bin_sig.DenominationKeyAnnouncement in - verify_f - ~f:(EddsaSignature.verify ~key:sm_denom_pub) - denom_secmod_sig - { h_denom_pub; h_section_name; anchor_time; duration_withdraw } - -let verify_future_keys_response our_master_public_key + fun our_master_public_key FutureKeysResponse. { future_denoms; @@ -119,37 +52,96 @@ let verify_future_keys_response our_master_public_key master_pub; denom_secmod_public_key; signkey_secmod_public_key; - } = - let open Syntax in - let* () = - match master_pub = our_master_public_key with - | false -> - Fmt.error - "master public key of the future key response does not match ours" - | true -> Ok () - in - let* () = - list_iter - (verify_future_denom ~sm_denom_pub:denom_secmod_public_key) - future_denoms - in - let* () = - list_iter - (verify_future_signkey ~sm_signkey_pub:signkey_secmod_public_key) - future_signkeys - in - Ok () + } + -> + let open Syntax in + let* () = + match master_pub = our_master_public_key with + | false -> + Fmt.error + "master public key of the future key response does not match ours" + | true -> Ok () + in + let* () = + list_iter + (verify_future_denom ~sm_denom_pub:denom_secmod_public_key) + future_denoms + in + let* () = + list_iter + (verify_future_signkey ~sm_signkey_pub:signkey_secmod_public_key) + future_signkeys + in + Ok () -let mk_denom_revoke ~key h_denom_pub = - let master_sig = - let open Bin_sig.MasterDenominationKeyRevocation in - sign_f ~f:(EddsaSignature.sign ~key) { h_denom_pub } +let mk_future_keys = + let denom_signature ~master_key + FutureDenom. + { + section_name= _; + value; + stamp_start; + stamp_expire_withdraw; + stamp_expire_deposit; + stamp_expire_legal; + denom_pub; + fee_withdraw; + fee_deposit; + fee_refresh; + fee_refund= _; + denom_secmod_sig= _; + } = + let octets = DenominationKey.to_octets denom_pub in + let h_denom_pub = DenominationHash.hash octets in + let master_sig = + let open Bin_sig.DenominationKeyValidity in + let master = EddsaPrivateKey.(pub_of_priv master_key) in + sign_f + ~f:(EddsaSignature.sign ~key:master_key) + { + master; + start= stamp_start; + expire_withdraw= stamp_expire_withdraw; + expire_spend= stamp_expire_deposit; + expire_legal= stamp_expire_legal; + value; + fee_withdraw; + fee_deposit; + fee_refresh; + denom_hash= h_denom_pub; + } + in + DenomSignature.{ h_denom_pub; master_sig } + in + let signkey_signature ~master_key + FutureSignKey. + { key; stamp_start; stamp_expire; stamp_end; signkey_secmod_sig= _ } = + let master_sig = + let open Bin_sig.ExchangeSigningKeyValidity in + sign_f + ~f:(EddsaSignature.sign ~key:master_key) + { + start= stamp_start; + expire= stamp_expire; + end_= stamp_end; + signkey_pub= key; + } + in + SignKeySignature.{ key; master_sig } in - DenomRevocationSignature.{ master_sig } -let mk_signkey_revoke ~key exchange_pub = - let master_sig = - let open Bin_sig.MasterSigningKeyRevocation in - sign_f ~f:(EddsaSignature.sign ~key) { exchange_pub } - in - SignkeyRevocationSignature.{ master_sig } + fun ~master_key + FutureKeysResponse. + { + future_denoms; + future_signkeys; + master_pub= _; + denom_secmod_public_key= _; + signkey_secmod_public_key= _; + } + -> + let denom_sigs = List.map (denom_signature ~master_key) future_denoms in + let signkey_sigs = + List.map (signkey_signature ~master_key) future_signkeys + in + MasterSignatures.{ denom_sigs; signkey_sigs }