diff --git a/src/bin_sig.ml b/src/bin_sig.ml index 70d86584..6caece8b 100644 --- a/src/bin_sig.ml +++ b/src/bin_sig.ml @@ -92,6 +92,10 @@ end) : sig val jsont : t Jsont.t val caqti : t Caqti_type.t + + (* TODO rm *) + (* escape hatch, only needed for /keys `exchange_sig` (signature over contatentation of all of the master_sigs) *) + val to_octets : t -> string end = struct open Crypto @@ -102,6 +106,7 @@ end = struct let verify_f ~f t r = f t ~msg:(Bin.to_string R.bin r) let jsont = EddsaSignature.jsont let caqti : EddsaSignature.t Caqti_type.t = EddsaSignature.caqti + let to_octets t = EddsaSignature.to_octets t end module DenominationKeyAnnouncement = struct diff --git a/src/config.ml b/src/config.ml index 7c62ffb2..fd098af0 100644 --- a/src/config.ml +++ b/src/config.ml @@ -20,9 +20,13 @@ module Exchange = struct let port = get "port" |> int let bind_to = get "bind_to" let master_public_key = get "master_public_key" |> ed25519 + + (* TODO Defaults to 0.0 if not specified. *) let stefan_abs = get "stefan_abs" |> amount let stefan_log = get "stefan_log" |> amount - let stefan_lin = get_opt "stefan_lin" |> Option.map float + + let stefan_lin = + get_opt "stefan_lin" |> Option.map float |> Option.value ~default:0.0 let aggregator_idle_sleep_interval = get "aggregator_idle_sleep_interval" |> duration diff --git a/src/http_keys.ml b/src/http_keys.ml index 481c1f57..c19ac2b4 100644 --- a/src/http_keys.ml +++ b/src/http_keys.ml @@ -4,6 +4,43 @@ open Syntax open Api module String_map = Stdlib.Map.Make (Stdlib.String) +let denomgroup_of_denomdata + Denom_data. + { + pub; + value; + stamp_start; + stamp_expire_withdraw; + stamp_expire_deposit; + stamp_expire_legal; + fee_withdraw; + fee_deposit; + fee_refresh; + fee_refund; + age_mask; + h_pub; + master_sig; + revoked_sig; + } = + let master_sig = match master_sig with None -> assert false | Some v -> v in + let denoms = + [ + RsaDenom. + { + rsa_pub= pub; + master_sig; + stamp_start; + stamp_expire_withdraw; + stamp_expire_deposit; + stamp_expire_legal; + lost= None; + }; + ] + in + DenomGroup.Rsa + RsaDenomGroup. + { denoms; value; fee_withdraw; fee_deposit; fee_refresh; fee_refund } + let mk_keys ~db_conn ~sm ~last_issue_date = let version = "0" in let base_url = Config.base_url in @@ -51,12 +88,97 @@ let mk_keys ~db_conn ~sm ~last_issue_date = let kyc_enabled = false in let disable_direct_deposit = (* todo *) false in let master_public_key = Config.master_public_key in - let reserve_closing_delay = Config.Exchangedb.idle_reserve_expiration_time in + let reserve_closing_delay = + Some Config.Exchangedb.idle_reserve_expiration_time + in (* todo *) let wallet_balance_limit_without_kyc = None in let hard_limits = [] in let zero_limits = [] in - (* + let* denom_data_l = Pg.get_denominations db_conn |> unwrap_err_caqti in + (* TODO check order!! *) + let denom_data_l = + List.sort + (fun a b -> + let open Denom_data in + Stdlib.compare a.stamp_start b.stamp_start) + denom_data_l + in + let list_issue_date = + (* TODO is this the last [stamp_start] value? *) + (* date when the denomination keys were last updated *) + match denom_data_l with + | [] -> None + | v :: _ -> v.stamp_start + in + let denominations = + (* TODO really need to understand and correctly group denoms + 'exchange_sig' depends on correct denom group/order *) + List.map denomgroup_of_denomdata denom_data_l + in + + let* signkeys = + let+ signkey_data_l = Pg.get_active_signkeys db_conn |> unwrap_err_caqti in + let signkey_data_l = + List.sort + (fun a b -> + let open Signkey_data in + Stdlib.compare a.stamp_start b.stamp_start) + signkey_data_l + in + List.map + (fun Signkey_data. + { + pub; + stamp_start; + stamp_expire; + stamp_end; + master_sig; + revoked_sig= _; + } -> + let master_sig = + match master_sig with + | None -> Fmt.failwith "signkey_data without master_sig" + | Some v -> v + in + SignKey.{ key= pub; stamp_start; stamp_expire; stamp_end; master_sig }) + signkey_data_l + in + + let exchange_pub = + (* the eddsa pub key used to sign exchange_sig *) + match signkeys with + | [] -> Fmt.failwith "exchange has no active signkey" + | v :: _ -> v.SignKey.key + in + let exchange_sig = + (* Compact EdDSA signature (binary-only) over the + contatentation of all of the master_sigs (in reverse + chronological order by group) in the arrays under "denominations". *) + let l = + List.map + (fun v -> + match v.Denom_data.master_sig with + | None -> Fmt.failwith "denom_data without master_sig" + | Some v -> v) + denom_data_l + in + let l = List.map (fun v -> Bin_sig.DenominationKeyValidity.to_octets v) l in + let data = String.concat "" l in + let hc = Bin_type.Hash_64.hash data in + let open Bin_sig.ExchangeKeySet in + sign_f + ~f:(Secmod.sign_with_signkey sm ~pub:exchange_pub) + R.{ list_issue_date; hc } + in + + let recoup = [] in + let global_fees = (* TODO *) [] in + let auditors = (* TODO *) [] in + let extensions = None in + let extensions_sig = None in + Ok + ExchangeKeysResponse. { version; base_url; @@ -92,8 +214,6 @@ let mk_keys ~db_conn ~sm ~last_issue_date = extensions; extensions_sig; } - *) - assert false let jsont = ExchangeKeysResponse.jsont diff --git a/src/mte.ml b/src/mte.ml index c6c3424e..d2767816 100644 --- a/src/mte.ml +++ b/src/mte.ml @@ -26,7 +26,7 @@ let routes = let open Vif.Type in let get_ path = get (path /?? nil) in let post path jsont = post (json_encoding jsont) (path /?? nil) in - let static = + let tos = let v s = rel / s in [ get_ rel --> hello; @@ -34,6 +34,7 @@ let routes = get_ (v "privacy") --> Static.privacy; ] in + let status_info = [ get_ (rel / "keys") --> Http_keys.f ] in let management = let open Http_management in let v s = rel / "management" / s in @@ -56,7 +57,7 @@ let routes = post (v "partners") Partners.jsont --> Partners.f; ] in - static @ management + tos @ status_info @ management let () = Util.Log_reporter.setup (); diff --git a/src/pg.ml b/src/pg.ml index 1a2dce80..7ff7a010 100644 --- a/src/pg.ml +++ b/src/pg.ml @@ -61,7 +61,7 @@ let get_active_signkeys = esk_serial FROM signkey_revocations skr WHERE esk.esk_serial = \ skr.esk_serial)" in - fun (module Conn : CONN) () -> + fun (module Conn : CONN) -> let now = Ptime_clock.now () |> Option.some in Conn.collect_list get_active_signkeys now diff --git a/src/secmod.mli b/src/secmod.mli index 9dda7677..9262bf65 100644 --- a/src/secmod.mli +++ b/src/secmod.mli @@ -1,3 +1,4 @@ +(* TODO functorize *) open Crypto type t