open Crypto type t = { pub: rsa_pub; value: Amount.t; stamp_start: Timestamp.t; stamp_expire_withdraw: Timestamp.t; stamp_expire_deposit: Timestamp.t; stamp_expire_legal: Timestamp.t; fee_withdraw: Amount.t; fee_deposit: Amount.t; fee_refresh: Amount.t; fee_refund: Amount.t; age_mask: int; h_pub: denom_hash; master_sig: Signatures.DenominationKeyValidity.t; } let verify_denomination_key_validity ~key dn = let open Signatures.DenominationKeyValidity in verify key dn.master_sig { R.master= key; start= dn.stamp_start; expire_withdraw= dn.stamp_expire_withdraw; expire_spend= dn.stamp_expire_deposit; expire_legal= dn.stamp_expire_legal; value= dn.value; fee_withdraw= dn.fee_withdraw; fee_deposit= dn.fee_deposit; fee_refresh= dn.fee_refresh; fee_refund= dn.fee_refund; denom_hash= dn.h_pub; } let make_denom_group_sorted denominations = let open Syntax in (* use hashtbl to re-group denoms *) 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 match Hashtbl.find_opt ht k with | None -> Error "denomination does not match any coin in configuration" | Some l -> Hashtbl.replace ht k (v :: l); Ok ()) denominations in let l = Hashtbl.to_seq ht |> List.of_seq in (* ! important for /keys .exchange_sig each group must be ordered in _reverse_ chronological order order of groups to compute hash, must be the same as the order in /keys .denominations *) let open Api in let open DenomGroup in let open RsaDenomGroup in let open RsaDenom in let cmp_denom b a = Timestamp.compare a.stamp_start b.stamp_start in let cmp_group = fun (Rsa a) (Rsa b) -> Amount.compare a.value b.value in let l = l |> List.map (fun ((value, fee_withdraw, fee_deposit, fee_refresh, fee_refund), denoms) -> Rsa { denoms= List.sort cmp_denom denoms; value; fee_withdraw; fee_deposit; fee_refresh; fee_refund; }) |> List.sort cmp_group in l let denoms_of_denomgroups l = let open Api in l |> List.concat_map (fun (DenomGroup.Rsa RsaDenomGroup. { denoms; value; fee_withdraw; fee_deposit; fee_refresh; fee_refund; }) -> let open RsaDenom in denoms |> List.map (fun { rsa_pub; master_sig; stamp_start; stamp_expire_withdraw; stamp_expire_deposit; stamp_expire_legal; lost= _; } -> let h_pub = DenominationHash.hash_of_rsa rsa_pub in { pub= rsa_pub; value; stamp_start; stamp_expire_withdraw; stamp_expire_deposit; stamp_expire_legal; fee_withdraw; fee_deposit; fee_refresh; fee_refund; age_mask= 0; h_pub; master_sig; })) let hash_over_master_sigs denominations = denominations |> List.map (fun (Api.DenomGroup.Rsa g) -> g.Api.RsaDenomGroup.denoms) |> List.concat_map (List.map (fun dn -> dn.Api.RsaDenom.master_sig)) |> List.map Signatures.DenominationKeyValidity.to_octets |> String.concat "" |> Hash.H64.hash