(* https://docs.taler.net/core/api-common.html#binary-formats - numeric values are in network byte order (big endian) *) (* structs that are ‘packed’ and do not contain pointers and are thus suitable for hashing or similar operations are distinguished by adding a “P” at the end of the name. (NEW) Note that this convention does not hold for the GNUnet-structs (yet). structs that are used with a purpose for signatures, additionally get an “S” at the end of the name. (from https://docs.taler.net/taler-developer-manual.html) *) (* TODO - check that our struct are well packed - it looks like Bin only define packed structs - we don't need to worry about struct having "P" suffix remove them - test them - some purpose (`TALER_SIGNATURE_XXX`) are missing exchange and gana master branch are not in sync and we should use a specific git tag instead *) (* -- Crypto keys -- *) module RsaPublicKey = struct (* libgnuutil format: https://docs.gnunet.org/doxygen/d9/dbe/structGNUNET__CRYPTO__RsaPublicKeyHeaderP.html https://docs.gnunet.org/doxygen/d6/d70/group__libgnunetutil.html#ga9c99a81e8cd649c1c925d23211a0738f https://www.gnupg.org/documentation/manuals/gcrypt/MPI-formats.html format: - rsa header - modulus - public_exponent integer in big-endian format (MSB first). Leading zeroes are stripped unless they are required to keep a value positive. *) type header = { n_len: int; e_len: int; } type t = { header: header; n: Z.t; e: Z.t; } (* need to strip leading zeros or something? *) let z_to_bigendian_bits v = let s = Z.to_bits v in let len = String.length s in let s = String.init len (fun i -> s.[len - 1 - i]) in s let header_bin = let open Bin in record (fun n_len e_len -> { n_len; e_len }) |+ field beint16 (fun t -> t.n_len) |+ field beint16 (fun t -> t.e_len) |> sealr let bin = let open Bin in record (fun header n e -> let n = Z.of_bits n in let e = Z.of_bits e in { header; n; e }) |+ field header_bin (fun t -> t.header) (* TODO Z.to_bits is in little endian but we need it in big endian *) |+ field cstring (fun t -> z_to_bigendian_bits t.n) |+ field cstring (fun t -> z_to_bigendian_bits t.e) |> sealr end open Include let int32_size = 4 let int64_size = 8 (* -- Time -- *) module MK_TIME () = struct type t = { v: int64 } (* not BE (?) *) let bin = let open Bin in record (fun v -> { v }) |+ field neint64 (fun t -> t.v) |> sealr end module MK_TIME_NBO () = struct type t = { v: int64 } let bin = let open Bin in record (fun v -> { v }) |+ field beint64 (fun t -> t.v) |> sealr end module TimeAbsolute = MK_TIME () module TimeAbsoluteNBO = MK_TIME_NBO () module TimeRelative = MK_TIME () module TimeRelativeNBO = MK_TIME_NBO () module Timestamp = MK_TIME () module TimestampNBO = MK_TIME_NBO () (* -- Cryptographic primitives -- *) (* MK_BASIC_XX functor for structs like: struct Foo { uint8t bar[XX]; } *) module MKMK_BASIC (S : sig val v : int end) = struct type t = { v: string } let bin = let open Bin in record (fun v -> { v }) |+ field (bytes S.v) (fun t -> t.v) |> sealr end module SIZE_32 = struct let v = 32 end module SIZE_64 = struct let v = 64 end module MK_BASIC_32 () = MKMK_BASIC (SIZE_32) module MK_BASIC_64 () = MKMK_BASIC (SIZE_64) (* MK_XX functor for structs like: struct FooWrap { struct Foo { uint8t bar[XX]; } } *) module MKMK (S : sig val v : int end) = struct module H = MKMK_BASIC (S) type t = { v: H.t } let bin = let open Bin in record (fun v -> { v }) |+ field H.bin (fun t -> t.v) |> sealr end module MK_32 () = MKMK (SIZE_32) module MK_64 () = MKMK (SIZE_64) (* - *) module ShortHashCode = MK_BASIC_32 () module HashCode = MK_BASIC_64 () module DenominationHash = MK_64 () module PrivateContractHash = MK_64 () module ExtensionsPolicyHash = MK_64 () module MerchantWireHash = MK_64 () (* Hash over a full payto://-URI, including receiver-name (and possibly BIC and other optional fields). *) module FullPaytoHash = MK_32 () (* Hash over a normalized payto://-URI, including all optional fields and also with account-part canonicalized (so no BIC). *) module NormalizedPaytoHash = MK_32 () (* TODO Taler doc: missing *) module AgeCommitmentHash = MK_64 () (* TODO Taler doc: missing *) module PublicRefreshCoinNonceP = MK_64 () (* TODO Taler doc: missing *) module PursePublicKey = MK_32 () (* TODO Taler doc: missing *) module AuditorPublicKeyP = MK_32 () (* TODO // Secret for blinding/unblinding. // An RSA blinding secret, which is basically // a 256-bit nonce, converted to Crockford `Base32`. type DenominationBlindingKeyP = string; *) module DenominationBlindingKeyP = MK_64 () (* Hash over: a) the hash of the denomination's public key, b) an enum value identifying the cipher, and c) cipher-dependant blinded information. See implementation of `TALER_CoinEvHash` in libtalerexchange for details. *) module BlindedCoinHash = MK_64 () (* -- *) module CoinPubHash = MK_64 () module OutputCommitmentHash = MK_64 () module ReservePublicKeyP = MK_32 () module ReservePrivateKeyP = MK_32 () module ReserveSignatureP = MK_64 () module MerchantPublicKeyP = MK_32 () module MerchantPrivateKeyP = MK_32 () (*module MerchantSignatureP = MK_64 () *) module TransferPublicKeyP = MK_32 () module TransferPrivateKeyP = MK_32 () (* enum TALER_AmlDecisionState { NORMAL, PENDING, FROZEN }; *) module AmlOfficerPublicKeyP = MK_32 () module AmlOfficerPrivateKeyP = MK_32 () module ExchangePublicKeyP = MK_32 () module ExchangePrivateKeyP = MK_32 () module ExchangeSignatureP = MK_64 () module MasterPublicKeyP = MK_32 () module MasterPrivateKeyP = MK_32 () module MasterSignatureP = MK_64 () module WireTransferIdentifierRawP = MK_BASIC_32 () module UUID = struct (* uint32t value[4]; *) type t = { value: string } let size = 4 * int32_size let bin = let open Bin in record (fun value -> { value }) |+ field (bytes size) (fun t -> t.value) |> sealr end module WadId = struct (* uint32t value[6]; *) type t = { raw: string } let size = 6 * int32_size let bin = let open Bin in record (fun raw -> { raw }) |+ field (bytes size) (fun t -> t.raw) |> sealr end (* TODO not sure what to do of union, probably not needed *) (* union TALER_CoinSpendPublicKeyP { uint8t eddsaPub[32]; uint8t ecdhePub[32]; }; union TALER_CoinSpendPrivateKeyP { uint8t eddsaPriv[32]; uint8t ecdhePriv[32]; }; *) module CoinSpendPublicKeyP = MK_32 () module CoinSpendPrivateKeyP = MK_32 () module CoinSpendSignatureP = MK_64 () (* TODO padding: sizeof used here (assume no padding for now) *) (* struct TALER_TransferSecretP { uint8t key[sizeof (struct HashCode)]; }; uint8t key[sizeof (struct HashCode)]; }; struct TALER_EncryptedLinkSecretP { uint8t enc[sizeof (struct TALER_LinkSecretP)]; }; *) module TransferSecretP = MK_64 () module LinkSecretP = MK_64 () module EncryptedLinkSecretP = MK_64 () (* union TALER_TokenPublicKeyP { uint8t eddsaPub[32]; uint8t ecdhePub[32]; }; *) module TokenPublicKeyP = MK_32 () (* -- Signatures -- *) (* EccSignaturePurpose *) module Purpose = struct type t = { (* This field equals the number of bytes being signed, namely 'sizeof (struct Data)'. *) size: int32; (* This field is used to express the context in which the signature is made, ensuring that a signature cannot be lifted from one part of the protocol to another. *) purpose: int32; } let bin = let open Bin in record (fun size purpose -> { size; purpose }) |+ field beint32 (fun t -> t.size) |+ field beint32 (fun t -> t.purpose) |> sealr let make ~size purpose = { size= Int32.of_int size; purpose } let dummy = make ~size:0 0_l (* helper function to make ['signature Bin.t] *) let make_bin = let get_size f = let open Bin in match Size.of_value (Size.size_of (f dummy)) with | Dynamic _ | Unknown -> Fmt.failwith "size_of failure: size is not Static" | Static n -> n in fun code f -> make ~size:(get_size f) code |> f let field purpose = Bin.field bin (fun _t -> purpose) 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 HashPlanchetsP = MK_64 () module AgeMask = struct type t = { mask: int32 } let bin = let open Bin in record (fun mask -> { mask }) |+ field beint32 (fun t -> t.mask) |> sealr end (* TODO - why is the non-NBO version only used in TALER_WithdrawRequestPS? *) (* Number of characters (plus 1 for 0-termination) for currency names. typically an ISO 4217 currency code when an alphanumeric 3-digit code is used. For regional currencies, the first character should be a "*" followed by a region-specific name (i.e. "*BRETAGNEFR"). Currency string, left adjusted and padded with zeros. All zeros for "invalid" values. *) let currency_len = 12 (* TODO Taler doc: missing found in src/include/taler/taler_amount_lib.h *) module Amount = struct type t = { value: int64; fraction: int32; currency: string; } (* TODO BE here? *) let bin = let open Bin in record (fun value fraction currency -> { value; fraction; currency }) |+ field beint64 (fun t -> t.value) |+ field beint32 (fun t -> t.fraction) |+ field (bytes currency_len) (fun t -> t.currency) |> sealr end module AmountNBO = struct type t = { value: int64; fraction: int32; currency: string; } let bin = let open Bin in record (fun value fraction currency -> { value; fraction; currency }) |+ field beint64 (fun t -> t.value) |+ field beint32 (fun t -> t.fraction) |+ field (bytes currency_len) (fun t -> t.currency) |> sealr end module BlindingMasterSeed = MK_BASIC_32 () module WithdrawRequestPS = struct (* Purpose is #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW *) type t = { amount: Amount.t; fee: Amount.t; h_planchets: HashPlanchetsP.t; (* TODO TALER doc `TALER_BlindingMasterSecretP` in doc, but probably TALER_BlindingMasterSeed *) blinding_seed: BlindingMasterSeed.t; max_age_group: int32; mask: AgeMask.t; } let bin = let open Bin in Purpose.make_bin Taler_signatures.wallet_reserve_withdraw @@ fun purpose -> record (fun _purpose amount fee h_planchets blinding_seed max_age_group mask -> { amount; fee; h_planchets; blinding_seed; max_age_group; mask }) |+ Purpose.field purpose |+ field Amount.bin (fun t -> t.amount) |+ field Amount.bin (fun t -> t.fee) |+ field HashPlanchetsP.bin (fun t -> t.h_planchets) |+ field BlindingMasterSeed.bin (fun t -> t.blinding_seed) |+ field beint32 (fun t -> t.max_age_group) |+ field AgeMask.bin (fun t -> t.mask) |> sealr end module WithdrawConfirmationPS = struct (* Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW. Signed by a `struct TALER_ExchangePrivateKeyP` using EdDSA. *) type t = { (* TODO TALER doc missing TALER_HashBlindedPlanchetsP*) h_planchets: HashPlanchetsP.t; noreveal_index: int32; } let bin = let open Bin in Purpose.make_bin Taler_signatures.exchange_confirm_withdraw @@ fun purpose -> record (fun _purpose h_planchets noreveal_index -> { h_planchets; noreveal_index }) |+ Purpose.field purpose |+ field HashPlanchetsP.bin (fun t -> t.h_planchets) |+ field beint32 (fun t -> t.noreveal_index) |> sealr end module DenominationKeyAnnouncementPS = struct (* purpose.purpose = TALER_SIGNATURE_SM_DENOMINATION_KEY *) type t = { h_denom_pub: DenominationHash.t; h_section_name: HashCode.t; anchor_time: TimeAbsoluteNBO.t; duration_withdraw: TimeRelativeNBO.t; } (* TODO management *) (* let bin = ... *) let to_string _ = assert false end module SingleWithdrawRequestPS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW *) type t = { amount_with_fee: AmountNBO.t; h_denomination_pub: DenominationHash.t; h_coin_envelope: BlindedCoinHash.t; } end module DepositRequestPS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_COIN_DEPOSIT *) type t = { h_contract_terms: PrivateContractHash.t; h_age_commitment: AgeCommitmentHash.t; h_policy: ExtensionsPolicyHash.t; h_wire: MerchantWireHash.t; h_denom_pub: DenominationHash.t; timestamp: TimeAbsoluteNBO.t; refund_deadline: TimeAbsoluteNBO.t; amount_with_fee: AmountNBO.t; deposit_fee: AmountNBO.t; merchant: MerchantPublicKeyP.t; wallet_data_hash: HashCode.t; } end module DepositConfirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT *) type t = { h_contract_terms: PrivateContractHash.t; h_wire: MerchantWireHash.t; h_policy: ExtensionsPolicyHash.t; timestamp: TimeAbsoluteNBO.t; refund_deadline: TimeAbsoluteNBO.t; amount_without_fee: AmountNBO.t; coin_pub: CoinSpendPublicKeyP.t; merchant: MerchantPublicKeyP.t; } end module RefreshCommitmentP = MK_64 () module RefreshMeltCoinAffirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_COIN_MELT *) type t = { session_hash: RefreshCommitmentP.t; h_denom_pub: DenominationHash.t; h_age_commitment: AgeCommitmentHash.t; amount_with_fee: AmountNBO.t; melt_fee: AmountNBO.t; } end module RefreshMeltConfirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT *) type t = { session_hash: RefreshCommitmentP.t; noreveal_index: int; (* uint16_t mapped to OCaml int *) } end module ExchangeSigningKeyValidityPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY *) type t = { start: TimeAbsoluteNBO.t; expire: TimeAbsoluteNBO.t; end_: TimeAbsoluteNBO.t; (* "end" renamed to end_ *) signkey_pub: ExchangePublicKeyP.t; } end module ExchangeKeySetPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_KEY_SET *) type t = { list_issue_date: TimeAbsoluteNBO.t; hc: HashCode.t; } end module DenominationKeyValidityPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY *) type t = { master: MasterPublicKeyP.t; start: TimeAbsoluteNBO.t; expire_withdraw: TimeAbsoluteNBO.t; expire_spend: TimeAbsoluteNBO.t; expire_legal: TimeAbsoluteNBO.t; value: AmountNBO.t; fee_withdraw: AmountNBO.t; fee_deposit: AmountNBO.t; fee_refresh: AmountNBO.t; denom_hash: DenominationHash.t; } end module MasterWireDetailsPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_WIRE_DETAILS *) type t = { h_wire_details: FullPaytoHash.t; h_conversion_url: HashCode.t; h_credit_restrictions: HashCode.t; h_debit_restrictions: HashCode.t; } end module MasterWireFeePS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_WIRE_FEES *) type t = { h_wire_method: HashCode.t; start_date: TimeAbsoluteNBO.t; end_date: TimeAbsoluteNBO.t; wire_fee: AmountNBO.t; closing_fee: AmountNBO.t; } end module GlobalFeesPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_GLOBAL_FEES *) type t = { start_date: TimeAbsoluteNBO.t; end_date: TimeAbsoluteNBO.t; purse_timeout: TimeRelativeNBO.t; kyc_timeout: TimeRelativeNBO.t; history_expiration: TimeRelativeNBO.t; history_fee: AmountNBO.t; kyc_fee: AmountNBO.t; account_fee: AmountNBO.t; purse_fee: AmountNBO.t; purse_account_limit: int; (* uint32_t → int *) } end module MasterDrainProfitPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_DRAIN_PROFITS *) type t = { wtid: WireTransferIdentifierRawP.t; date: TimeAbsoluteNBO.t; amount: AmountNBO.t; h_section: HashCode.t; h_payto: FullPaytoHash.t; } end module DepositTrackPS = struct (* purpose.purpose = TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION *) type t = { h_contract_terms: PrivateContractHash.t; h_wire: MerchantWireHash.t; coin_pub: CoinSpendPublicKeyP.t; } end module WireDepositDetailP = struct type t = { h_contract_terms: PrivateContractHash.t; execution_time: TimeAbsoluteNBO.t; coin_pub: CoinSpendPublicKeyP.t; deposit_value: AmountNBO.t; deposit_fee: AmountNBO.t; } end module WireDepositDataPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT *) type t = { total: AmountNBO.t; wire_fee: AmountNBO.t; merchant_pub: MerchantPublicKeyP.t; h_wire: MerchantWireHash.t; h_details: HashCode.t; } end module ExchangeKeyValidityPS = struct (* purpose.purpose = TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS *) type t = { auditor_url_hash: HashCode.t; master: MasterPublicKeyP.t; start: TimeAbsoluteNBO.t; expire_withdraw: TimeAbsoluteNBO.t; expire_spend: TimeAbsoluteNBO.t; expire_legal: TimeAbsoluteNBO.t; value: AmountNBO.t; fee_withdraw: AmountNBO.t; fee_deposit: AmountNBO.t; fee_refresh: AmountNBO.t; denom_hash: DenominationHash.t; } end module PaymentResponsePS = struct (* purpose.purpose = TALER_SIGNATURE_MERCHANT_PAYMENT_OK *) type t = { h_contract_terms: PrivateContractHash.t } end module ContractPS = struct (* purpose.purpose = TALER_SIGNATURE_MERCHANT_CONTRACT *) type t = { h_contract_terms: PrivateContractHash.t } end module ConfirmWirePS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE *) type t = { h_wire: MerchantWireHash.t; h_contract_terms: PrivateContractHash.t; wtid: WireTransferIdentifierRawP.t; coin_pub: CoinSpendPublicKeyP.t; execution_time: TimeAbsoluteNBO.t; coin_contribution: AmountNBO.t; } end module RefundConfirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND *) type t = { h_contract_terms: PrivateContractHash.t; coin_pub: CoinSpendPublicKeyP.t; merchant: MerchantPublicKeyP.t; rtransaction_id: int64; refund_amount: AmountNBO.t; } end module DepositTrackPS2 = struct (* purpose.purpose = TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION *) type t = { h_contract_terms: PrivateContractHash.t; h_wire: MerchantWireHash.t; merchant: MerchantPublicKeyP.t; coin_pub: CoinSpendPublicKeyP.t; } end module RefundRequestPS = struct (* purpose.purpose = TALER_SIGNATURE_MERCHANT_REFUND *) type t = { h_contract_terms: PrivateContractHash.t; coin_pub: CoinSpendPublicKeyP.t; rtransaction_id: int64; refund_amount: AmountNBO.t; refund_fee: AmountNBO.t; } end module MerchantRefundConfirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_MERCHANT_REFUND_OK *) (* Hash of the order ID (a string), hashed without the 0-termination. *) type t = { h_order_id: HashCode.t } end module RecoupRequestPS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_COIN_RECOUP or TALER_SIGNATURE_WALLET_COIN_RECOUP_REFRESH *) type t = { h_denom_pub: DenominationHash.t; coin_blind: DenominationBlindingKeyP.t; } end module RecoupRefreshConfirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH *) type t = { timestamp: TimeAbsoluteNBO.t; recoup_amount: AmountNBO.t; coin_pub: CoinSpendPublicKeyP.t; old_coin_pub: CoinSpendPublicKeyP.t; } end module RecoupConfirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP *) type t = { timestamp: TimeAbsoluteNBO.t; recoup_amount: AmountNBO.t; coin_pub: CoinSpendPublicKeyP.t; reserve_pub: ReservePublicKeyP.t; } end module DenominationUnknownAffirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN *) type t = { timestamp: TimeAbsoluteNBO.t; h_denom_pub: DenominationHash.t; } end module DenominationExpiredAffirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_GENERIC_DENOMINATIN_EXPIRED *) type t = { timestamp: TimeAbsoluteNBO.t; operation: string; (* char[8] → string *) h_denom_pub: DenominationHash.t; } end module ReserveCloseConfirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED *) type t = { timestamp: TimeAbsoluteNBO.t; closing_amount: AmountNBO.t; reserve_pub: ReservePublicKeyP.t; h_wire: FullPaytoHash.t; } end module CoinLinkSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_COIN_LINK *) type t = { h_denom_pub: DenominationHash.t; old_coin_pub: CoinSpendPublicKeyP.t; transfer_pub: TransferPublicKeyP.t; coin_envelope_hash: BlindedCoinHash.t; } end module RefreshNonceSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_COIN_LINK *) type t = { nonce: PublicRefreshCoinNonceP.t } end module ReserveStatusRequestSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_RESERVE_STATUS_REQUEST *) type t = { request_timestamp: TimeAbsoluteNBO.t } end module ReserveHistoryRequestSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_RESERVE_HISTORY_REQUEST *) type t = { history_fee: AmountNBO.t; request_timestamp: TimeAbsoluteNBO.t; } end module PurseStatusRequestSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_PURSE_STATUS_REQUEST *) type t = unit end module PurseStatusResponseSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_PURSE_STATUS_RESPONSE *) type t = { total_purse_amount: AmountNBO.t; total_deposit_amount: AmountNBO.t; max_deposit_fees: AmountNBO.t; purse_expiration: TimeAbsoluteNBO.t; status_timestamp: TimeAbsoluteNBO.t; h_contract_terms: PrivateContractHash.t; } end module ReserveCloseRequestSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_CLOSE *) type t = unit end module PurseRequestSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_PURSE_CREATE *) type t = { purse_expiration: TimeAbsoluteNBO.t; merge_value_after_fees: AmountNBO.t; h_contract_terms: PrivateContractHash.t; min_age: int; } end module PurseDepositSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_PURSE_DEPOSIT *) type t = { coin_contribution: AmountNBO.t; h_denom_pub: DenominationHash.t; h_age_commitment: AgeCommitmentHash.t; purse_pub: PursePublicKey.t; h_exchange_base_url: HashCode.t; } end module PurseDepositSignaturePS2 = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT *) type t = { reserve_sig: ReserveSignatureP.t; coin_contribution: AmountNBO.t; } end module PurseDepositConfirmedSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_PURSE_DEPOSIT_CONFIRMED *) type t = { total_purse_amount: AmountNBO.t; total_deposit_fees: AmountNBO.t; purse_pub: PursePublicKey.t; purse_expiration: TimeAbsoluteNBO.t; h_contract_terms: PrivateContractHash.t; } end module PurseMergeSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_PURSE_MERGE *) type t = { merge_timestamp: TimeAbsoluteNBO.t; h_wire: NormalizedPaytoHash.t; } end module AccountMergeSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_ACCOUNT_MERGE *) type t = { reserve_pub: ReservePublicKeyP.t; purse_pub: PursePublicKey.t; merge_amount_after_fees: AmountNBO.t; merge_timestamp: TimeAbsoluteNBO.t; purse_expiration: TimeAbsoluteNBO.t; h_contract_terms: PrivateContractHash.t; min_age: int; } end module AccountSetupRequestSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_ACCOUNT_SETUP *) type t = { threshold: AmountNBO.t } end module PurseMergeSuccessSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_PURSE_MERGE_SUCCESS *) type t = { reserve_pub: ReservePublicKeyP.t; purse_pub: PursePublicKey.t; merge_amount_after_fees: AmountNBO.t; contract_time: TimeAbsoluteNBO.t; h_contract_terms: PrivateContractHash.t; h_wire: NormalizedPaytoHash.t; min_age: int; } end module WadDataSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_WAD_DATA *) type t = { wad_execution_time: TimeAbsoluteNBO.t; total_amount: AmountNBO.t; h_items: HashCode.t; wad_id: WadId.t; } end module WadPartnerSignaturePS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_PARTNER_DETAILS *) type t = { h_partner_base_url: HashCode.t; master_public_key: MasterPublicKeyP.t; start_date: TimeAbsoluteNBO.t; end_date: TimeAbsoluteNBO.t; wad_fee: AmountNBO.t; wad_frequency: TimeRelativeNBO.t; } end module P2PFeesPS = struct (* purpose.purpose = TALER_SIGNATURE_P2P_FEES *) type t = { start_date: TimeAbsoluteNBO.t; end_date: TimeAbsoluteNBO.t; kyc_fee: AmountNBO.t; purse_fee: AmountNBO.t; account_history_fee: AmountNBO.t; account_annual_fee: AmountNBO.t; account_kyc_timeout: TimeRelativeNBO.t; purse_timeout: TimeRelativeNBO.t; purse_account_limit: int; } end module CoinPurseRefundConfirmationPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND *) type t = { purse_pub: PursePublicKey.t; coin_pub: CoinSpendPublicKeyP.t; refunded_amount: AmountNBO.t; refund_fee: AmountNBO.t; } end module SigningKeyAnnouncementPS = struct (* purpose.purpose = TALER_SIGNATURE_SM_SIGNING_KEY *) type t = { exchange_pub: ExchangePublicKeyP.t; anchor_time: TimeAbsoluteNBO.t; duration: TimeRelativeNBO.t; } end module MasterDenominationKeyRevocationPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED *) type t = { h_denom_pub: DenominationHash.t } end module MasterSigningKeyRevocationPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_SIGNING_KEY_REVOKED *) type t = { exchange_pub: ExchangePublicKeyP.t } end module MasterAddAuditorPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_ADD_AUDITOR *) type t = { start_date: TimeAbsoluteNBO.t; auditor_pub: AuditorPublicKeyP.t; h_auditor_url: HashCode.t; } end module MasterDelAuditorPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_DEL_AUDITOR *) type t = { end_date: TimeAbsoluteNBO.t; auditor_pub: AuditorPublicKeyP.t; } end module MasterAddWirePS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_ADD_WIRE *) type t = { start_date: TimeAbsoluteNBO.t; h_wire: FullPaytoHash.t; h_conversion_url: HashCode.t; h_credit_restrictions: HashCode.t; h_debit_restrictions: HashCode.t; } end module MasterDelWirePS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_DEL_WIRE *) type t = { end_date: TimeAbsoluteNBO.t; h_wire: FullPaytoHash.t; } end module MasterAmlOfficerStatusPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_AML_KEY *) type t = { change_date: TimestampNBO.t; officer_pub: AmlOfficerPublicKeyP.t; h_officer_name: HashCode.t; is_active: int; } end module AmlDecisionPS = struct (* purpose.purpose = TALER_SIGNATURE_AML_DECISION *) type t = { h_justification: HashCode.t; decision_time: TimestampNBO.t; new_threshold: AmountNBO.t; h_payto: NormalizedPaytoHash.t; h_kyc_requirements: HashCode.t; new_state: int; } end module PartnerConfigurationPS = struct (* purpose.purpose = TALER_SIGNATURE_MASTER_PARNTER_DETAILS *) type t = { partner_pub: MasterPublicKeyP.t; start_date: TimestampNBO.t; end_date: TimestampNBO.t; wad_frequency: TimeRelativeNBO.t; wad_fee: AmountNBO.t; h_url: HashCode.t; } end module ReserveOpenPS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_OPEN *) type t = { reserve_payment: AmountNBO.t; request_timestamp: TimestampNBO.t; reserve_expiration: TimestampNBO.t; purse_limit: int; } end module ReserveClosePS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_RESERVE_CLOSE *) type t = { request_timestamp: TimestampNBO.t; target_account_h_payto: FullPaytoHash.t; } end module ReserveAttestRequestPS = struct (* purpose.purpose = TALER_SIGNATURE_WALLET_ATTEST_REQUEST *) type t = { request_timestamp: TimestampNBO.t; h_details: HashCode.t; } end module ExchangeAttestPS = struct (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS *) type t = { attest_timestamp: TimestampNBO.t; expiration_time: TimestampNBO.t; reserve_pub: ReservePublicKeyP.t; h_attributes: HashCode.t; } end