2025-12-15 16:43:49 +01:00
|
|
|
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;
|
2026-02-17 09:30:20 +01:00
|
|
|
h_pub: denom_hash;
|
|
|
|
|
master_sig: Signatures.DenominationKeyValidity.t;
|
2025-12-15 16:43:49 +01:00
|
|
|
}
|
2026-02-23 09:02:39 +01:00
|
|
|
|
|
|
|
|
let make_denom_group_sorted denominations =
|
|
|
|
|
let open Syntax in
|
2026-02-24 17:23:03 +01:00
|
|
|
(* use hashtbl to re-group denoms *)
|
2026-02-23 09:02:39 +01:00
|
|
|
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
|
2026-02-24 17:23:03 +01:00
|
|
|
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 ())
|
2026-02-23 09:02:39 +01:00
|
|
|
denominations
|
|
|
|
|
in
|
2026-02-24 17:23:03 +01:00
|
|
|
let l = Hashtbl.to_seq ht |> List.of_seq in
|
2026-02-23 09:02:39 +01:00
|
|
|
|
|
|
|
|
(* ! 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 =
|
|
|
|
|
let cmp_amount a b =
|
2026-02-24 17:23:03 +01:00
|
|
|
(* TODO amount *)
|
2026-02-23 09:02:39 +01:00
|
|
|
let open Amount in
|
|
|
|
|
match Int64.unsigned_compare a.value b.value with
|
|
|
|
|
| 0 -> Int32.unsigned_compare a.fraction b.fraction
|
|
|
|
|
| n -> n
|
|
|
|
|
in
|
|
|
|
|
fun (Rsa a) (Rsa b) -> cmp_amount a.value b.value
|
|
|
|
|
in
|
|
|
|
|
let l =
|
2026-02-24 17:23:03 +01:00
|
|
|
l
|
2026-02-23 09:02:39 +01:00
|
|
|
|> 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
|
2026-02-27 18:40:20 +01:00
|
|
|
|
2026-02-27 19:38:34 +01:00
|
|
|
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 (Crypto.RsaPublicKey.to_octets 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;
|
|
|
|
|
}))
|
|
|
|
|
|
2026-02-27 18:40:20 +01:00
|
|
|
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
|