From dfb47fdc81ffa965820e42fb1ec3d27199566576 Mon Sep 17 00:00:00 2001 From: swrup Date: Tue, 7 Oct 2025 11:10:40 +0200 Subject: [PATCH] --- src/binary_formats.ml | 120 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 114 insertions(+), 6 deletions(-) diff --git a/src/binary_formats.ml b/src/binary_formats.ml index 502d0c3f..9bb7f255 100644 --- a/src/binary_formats.ml +++ b/src/binary_formats.ml @@ -3,10 +3,11 @@ - numeric values are in network byte order (big endian) *) (* TODO - use Bin.seq instead of Bin.bytes? - less boilerplate (just make type t abstract)? + less boilerplate? + - type t abstract + - type t = { v = string } padding issues? - how to encode union? + how to encode union? not really needed? test *) (* -- Time -- *) @@ -16,10 +17,11 @@ module Time = struct type t = { timestamp_us: int64 } type t_nbo = { abs_value_us__: int64 } + (* not BE here? never used? *) let bin = let open Bin in record (fun timestamp_us -> { timestamp_us }) - |+ field neint64 (fun t -> t.timestamp_us) (* not BE here? *) + |+ field neint64 (fun t -> t.timestamp_us) |> sealr let nbo_bin = @@ -219,7 +221,7 @@ module Wad_id = struct |> sealr end -(* TODO not sure what to do of unions *) +(* TODO not sure what to do of union, probably not needed *) (* union TALER_CoinSpendPublicKeyP { uint8_t eddsa_pub[32]; @@ -230,7 +232,8 @@ union TALER_CoinSpendPrivateKeyP { uint8_t ecdhe_priv[32]; }; *) - +module Coin_spend_public_key_p = MAKE_EDDSA_PUB () +module Coin_spend_private_key_p = MAKE_EDDSA_PRIV () module Coin_spend_signature_p = MAKE_EDDSA_SIG () (* TODO padding: sizeof used here (assume no padding for now) *) @@ -254,6 +257,7 @@ union TALER_TokenPublicKeyP { uint8_t ecdhe_pub[32]; }; *) +module Token_public_key_p = MAKE_EDDSA_PUB () (* -- Signatures -- *) @@ -276,3 +280,107 @@ module Ecc_signature_purpose = struct |+ field beint32 (fun t -> t.purpose) |> sealr end + +(* This is the running SHA512-hash over all + `TALER_BlindedCoinHashP` values of an array of coins. + Note that each `TALER_BlindedCoinHashP` itself + captures the hash of the corresponding denomination's + public key. *) +module Hash_planchets_p = MAKE_H (Hash_code) + +(* Binary representation of the age groups. + The bits set in the mask mark the edges at the beginning of a next age + group. F.e. for the age groups + 0-7, 8-9, 10-11, 12-13, 14-15, 16-17, 18-20, 21-* + the following bits are set: + + 31 24 16 8 0 + | | | | | + oooooooo oo1oo1o1 o1o1o1o1 ooooooo1 + + A value of 0 means that the exchange does not support the extension for + age-restriction. *) +module Age_mask = struct + type t = { mask: int32 } + + let bin = + let open Bin in + record (fun mask -> { mask }) |+ field beint32 (fun t -> t.mask) |> sealr +end + +(* TODO not in doc + dummy impl + struct TALER_BlindingMasterSecretP blinding_seed; *) +module Blinding_master_secret_p = MAKE_H (Hash_code) + +(* TODO not in doc + struct TALER_Amount amount; *) +module Amount = MAKE_H (Hash_code) + +(* Format used for to generate the signature on a request to withdraw + coins from a reserve. *) +module Withdraw_request_ps = struct + type t = { + (* TODO set it in encode/decode *) + (* Purpose is #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW *) + purpose: Ecc_signature_purpose.t; + (* Amount to withdraw, excluding fees, i.e. + the total sum of the denominations of the coins. + Note that the reserve must have a value of at least amount+fee. *) + amount: Amount.t; + (* Total fee for the withdrawal. + Note that the reserve must have a value of at least amount+fee. *) + fee: Amount.t; + (* This is the running SHA512-hash over all + `TALER_BlindedCoinHashP` values of the coins. + Note that each `TALER_BlindedCoinHashP` itself + captures the hash of the corresponding denomination's + public key. + If max_age was set in the withdraw request, there will be + n*κ many such values. The iteration MUST be first over + all coins belonging to κ index=0, then all coins + to κ index=1 etc: + h[0][0]…h[0][n-1]h[1][0]…h[1][n-1] … h[κ-1][0]…h[κ-1][n-1] + + Note also that this value is required for /recoup and + -- in case of a withdraw request with required age proof -- + in the subsequent call to /reveal-withdraw *) + h_planchets: Hash_planchets_p.t; + (* The master seed that was used in the call to /blinding-prepare blinding, + or all zeros, if no denomination of cipher type Clause-Schnorr is used. *) + blinding_seed: Blinding_master_secret_p.t; + (* If age restriction proof is required, the maximum age _group_ + to commit to, 0 otherwise. Note that in this case, all + denominations for all coins MUST support age restriction. + Also note that this is not an age (in years), but the age group + (an index) according to list of age groups in the configuration + of the exchange. See TALER_get_max_group() how to calculate + the age group to a given age (in years). *) + max_age_group: int32; + (* The age groups as configured for the exchange, represented as a mask. + If max_age_group is > 0, the mask MUST be non-zero, too. *) + mask: Age_mask.t; + } + + let bin = + let open Bin in + record + (fun purpose amount fee h_planchets blinding_seed max_age_group mask -> + { + purpose; + amount; + fee; + h_planchets; + blinding_seed; + max_age_group; + mask; + }) + |+ field Ecc_signature_purpose.bin (fun t -> t.purpose) + |+ field Amount.bin (fun t -> t.amount) + |+ field Amount.bin (fun t -> t.fee) + |+ field Hash_planchets_p.bin (fun t -> t.h_planchets) + |+ field Blinding_master_secret_p.bin (fun t -> t.blinding_seed) + |+ field beint32 (fun t -> t.max_age_group) + |+ field Age_mask.bin (fun t -> t.mask) + |> sealr +end