diff --git a/src/denomination.ml b/src/denomination.ml index 28622e9c..ec5f7905 100644 --- a/src/denomination.ml +++ b/src/denomination.ml @@ -15,3 +15,76 @@ type t = { h_pub: denom_hash; master_sig: Signatures.DenominationKeyValidity.t; } + +let make_denom_group denominations = + let open Syntax in + let ht = Hashtbl.create 0xff in + List.iter + (fun coin -> + let open Config.Coin in + assert (coin.cipher = `RSA); + let k = + ( coin.value, + coin.fee_withdraw, + coin.fee_deposit, + coin.fee_refresh, + coin.fee_refund ) + in + let v = [] in + Hashtbl.replace ht k v) + Config.Coin.all_coins; + let+ () = + list_iter + (fun { + 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; + } -> + let k = (value, fee_withdraw, fee_deposit, fee_refresh, fee_refund) in + let v = + Api.RsaDenom. + { + rsa_pub= pub; + master_sig; + stamp_start; + stamp_expire_withdraw; + stamp_expire_deposit; + stamp_expire_legal; + lost= None; + } + in + let+ l = + match Hashtbl.find_opt ht k with + | None -> + Error "denomination does not match any coin in configuration" + | Some l -> Ok l + in + Hashtbl.replace ht k (v :: l)) + denominations + in + Hashtbl.to_seq ht + |> List.of_seq + |> List.map + (fun + ((value, fee_withdraw, fee_deposit, fee_refresh, fee_refund), denoms) + -> + Api.DenomGroup.Rsa + Api.RsaDenomGroup. + { + denoms; + value; + fee_withdraw; + fee_deposit; + fee_refresh; + fee_refund; + }) diff --git a/src/http_info.ml b/src/http_info.ml index f7043ff8..90e10dc2 100644 --- a/src/http_info.ml +++ b/src/http_info.ml @@ -20,44 +20,6 @@ let config req _server _env = let res = Api.encode Api.ExchangeVersionResponse.jsont config in Respond.result res req -(* TODO - for now we only have one item in each "denom group" - change this once we have denom/signkey rotation *) -let denomgroup_of_denomdata - Denomination. - { - 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; - } = - 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 (module Keys : Keys.S) ~last_issue_date = let version = Api.protocol_version in let base_url = Config.base_url in @@ -96,62 +58,64 @@ let mk_keys ~db_conn (module Keys : Keys.S) ~last_issue_date = let wallet_balance_limit_without_kyc = None in let hard_limits = [] in let zero_limits = [] in - let* dn_l = - let+ l = Keys.denominations () in + + let* denom_l = Keys.denominations () in + let denom_l = (* reverse chronological order *) List.sort (fun a b -> Stdlib.compare b.Denomination.stamp_start a.stamp_start) - l + denom_l in let list_issue_date = - match dn_l with + match denom_l with | [] -> Timestamp.never | dn :: _ -> dn.Denomination.stamp_start in - let denominations = + let denom_l = (* if `?last_issue_date` query param does not exactly match the `stamp_start` of one of the denomination keys, all keys are returned *) - let open Denomination in - let l = + let stamp_start_opt = match last_issue_date with - | None -> dn_l - | Some last_issue_date -> ( - match - List.find_opt - (fun v -> Timestamp.compare v.stamp_start last_issue_date = 0) - dn_l - with - | None -> dn_l - | Some _ -> - List.filter - (fun v -> - Time.Timestamp.compare v.stamp_start last_issue_date >= 0) - dn_l) + | None -> None + | Some timestamp -> + List.find_map + (fun v -> + if Timestamp.compare v.Denomination.stamp_start timestamp = 0 then + Some v.stamp_start + else None) + denom_l in - List.map denomgroup_of_denomdata l + match stamp_start_opt with + | None -> denom_l + | Some timestamp -> + List.filter + (fun v -> Timestamp.compare v.Denomination.stamp_start timestamp >= 0) + denom_l in + let* denominations = Denomination.make_denom_group denom_l in - let* signkeys = - let+ l = Keys.signkeys () in - l + let* signkeys = Keys.signkeys () in + let signkeys = + signkeys |> List.sort (fun a b -> let open Signkey in Stdlib.compare b.stamp_start a.stamp_start) |> List.map Api.SignKey.of_signkey in - let exchange_pub = - (* the eddsa pub key used to sign exchange_sig *) + (* the eddsa pub key used to sign exchange_sig *) + let* exchange_pub = match signkeys with - | [] -> Fmt.failwith "exchange has no active signkey" - | sk :: _ -> sk.SignKey.key + | [] -> Fmt.error "exchange has no active signkey" + | sk :: _ -> Ok sk.SignKey.key in + + (* TODO *) + (* Compact eddsa signature over the contatentation of all of the master_sigs + (in reverse chronological order by group) in the arrays under "denominations" *) 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 hc = - dn_l + denom_l |> List.map (fun dn -> dn.Denomination.master_sig) |> List.map Signatures.DenominationKeyValidity.to_octets |> String.concat "" @@ -222,9 +186,7 @@ let keys req server _env = | [] -> Ok None | s :: _ -> ( match Int64.of_string_opt s with - | None -> - Error - "invalid `?last_issue_date` query param, int_of_string failure" + | None -> Error "invalid `?last_issue_date` query param, not an int" | Some n -> Ok (Some (Timestamp.of_s n))) in let* v = mk_keys ~db_conn keys ~last_issue_date in