diff --git a/src/api.ml b/src/api.ml index 0f245fff..77a38f33 100644 --- a/src/api.ml +++ b/src/api.ml @@ -1,5 +1,23 @@ (* TODO + ppx? + + normalized JSON-object + for signature of ExchangeKeysResponse.exetensions field + why is this one not defined by a struct? + + how to handle protocol versions: + - "@deprecated" fields + - "@since protocol xx" + + better jsont cases handling: + - factorize common fields (DenomCommon/DenomGroupCommon) + - "+age_restricted"/CS variants + - raise error not implemented if not RSA + + monotonic time + payto_uri + uri option: correct use opt_mem or Jsont.option number - number is "float", but we probably want int everywhere instead @@ -42,9 +60,10 @@ module Account_operation = struct |> Jsont.enum ~kind:"account operation type" end -module ErrorDetail = struct - (* TODO GANA error codes +(* TODO error response + - use GANA error codes https://git.gnunet.org/gana.git/tree/gnu-taler-error-codes/registry.rec *) +module ErrorDetail = struct type t = { code: int; hint: string option; @@ -477,7 +496,7 @@ module AuditorSetupMessage = struct auditor_name: string; auditor_pub: EddsaPublicKey.t; master_sig: MasterAddAuditorPS.t; - (* TODO time + (* TODO monotonic time something about using monotonic system time here! *) validity_start: Timestamp.t; } @@ -504,8 +523,7 @@ end module AuditorTeardownMessage = struct type t = { master_sig: MasterDelAuditorPS.t; - (* TODO time - something about using monotonic system time here! *) + (* TODO monotonic time *) validity_end: Timestamp.t; } @@ -526,7 +544,7 @@ module WireFeeSetupMessage = struct (* TODO over which struct? Signature using the exchange's offline key with purpose TALER_SIGNATURE_MASTER_WIRE_FEES *) - master_sig_wire: EddsaSignature.t; + master_sig_wire: MasterWireFeePS.t; fee_start: Amount.t; fee_end: Amount.t; closing_fee: Amount.t; @@ -554,7 +572,7 @@ module WireFeeSetupMessage = struct let open Jsont.Object in map ~kind:"WireFeeSetupMessage" make |> mem "wire_method" Jsont.string ~enc:wire_method - |> mem "master_sig_wire" EddsaSignature.jsont ~enc:master_sig_wire + |> mem "master_sig_wire" MasterWireFeePS.jsont ~enc:master_sig_wire |> mem "fee_start" Amount.jsont ~enc:fee_start |> mem "fee_end" Amount.jsont ~enc:fee_end |> mem "closing_fee" Amount.jsont ~enc:closing_fee @@ -619,7 +637,7 @@ module WireSetupMessage = struct payto_uri: string; master_sig_wire: MasterWireDetailsPS.t; master_sig_add: MasterAddWirePS.t; - (* TODO time monotonic *) + (* TODO monotonic time *) validity_start: Timestamp.t; bank_label: string option; priority: int option; @@ -658,7 +676,7 @@ module WireTeardownMessage = struct type t = { payto_uri: string; master_sig_del: MasterDelWirePS.t; - (* TODO time monotonic *) + (* TODO monotonic time *) validity_end: Timestamp.t; } @@ -1030,11 +1048,6 @@ module RsaDenomGroup = struct |> finish end -(* TODO cases - better jsont cases handling - factorize common fields (DenomCommon/DenomGroupCommon) - "+age_restricted"/CS variants - raise error not implemented if not RSA *) module DenomGroup = struct type t = Rsa of RsaDenomGroup.t @@ -1178,3 +1191,197 @@ module ExchangeWireAccount = struct |> opt_mem "priority" Jsont.int ~enc:priority |> finish end + +module ExtensionManifest = struct + type t = { + critical: bool; + version: string; + config: Jsont.json option; + } + + let jsont = + let make critical version config = { critical; version; config } in + let critical v = v.critical in + let version v = v.version in + let config v = v.config in + let open Jsont.Object in + map ~kind:"ExtensionManifest" make + |> mem "critical" Jsont.bool ~enc:critical + |> mem "version" Jsont.string ~enc:version + |> opt_mem "config" (Jsont.any ()) ~enc:config + |> finish +end + +module ExchangeKeysResponse = struct + module String_map = Map.Make (String) + + type t = { + version: string; + base_url: string; + currency: string; + shopping_url: string option; + open_banking_gateway: string option; + bank_compliance_language: string option; + currency_specification: CurrencySpecification.t; + tiny_amount: Amount.t option; + stefan_abs: Amount.t; + stefan_log: Amount.t; + stefan_lin: Float.t; + asset_type: string; + accounts: ExchangeWireAccount.t list; + wire_fees: AggregateTransferFee.t list Stdlib.Map.Make(Stdlib.String).t; + wads: ExchangePartnerListEntry.t list; + rewards_allowed: bool; + kyc_enabled: bool; + disable_direct_deposit: bool; + master_public_key: EddsaPublicKey.t; + reserve_closing_delay: RelativeTime.t; + wallet_balance_limit_without_kyc: Amount.t list option; + hard_limits: AccountLimit.t list; + zero_limits: ZeroLimitedOperation.t list; + denominations: DenomGroup.t list; + (* 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" *) + exchange_sig: ExchangeKeySetPS.t; + exchange_pub: EddsaPublicKey.t; + recoup: RecoupDenoms.t list; + global_fees: GlobalFees.t list; + list_issue_date: Timestamp.t; + auditors: AuditorKeys.t list; + signkeys: SignKey.t list; + extensions: ExtensionManifest.t Stdlib.Map.Make(Stdlib.String).t option; + (* Signature by the exchange master key of the SHA-256 hash of the + normalized JSON-object of field extensions, if it was set. + The signature has purpose TALER_SIGNATURE_MASTER_EXTENSIONS. *) + extensions_sig: EddsaSignature.t option; + } + + let jsont = + let make version base_url currency shopping_url open_banking_gateway + bank_compliance_language currency_specification tiny_amount stefan_abs + stefan_log stefan_lin asset_type accounts wire_fees wads rewards_allowed + kyc_enabled disable_direct_deposit master_public_key + reserve_closing_delay wallet_balance_limit_without_kyc hard_limits + zero_limits denominations exchange_sig exchange_pub recoup global_fees + list_issue_date auditors signkeys extensions extensions_sig = + { + version; + base_url; + currency; + shopping_url; + open_banking_gateway; + bank_compliance_language; + currency_specification; + tiny_amount; + stefan_abs; + stefan_log; + stefan_lin; + asset_type; + accounts; + wire_fees; + wads; + rewards_allowed; + kyc_enabled; + disable_direct_deposit; + master_public_key; + reserve_closing_delay; + wallet_balance_limit_without_kyc; + hard_limits; + zero_limits; + denominations; + exchange_sig; + exchange_pub; + recoup; + global_fees; + list_issue_date; + auditors; + signkeys; + extensions; + extensions_sig; + } + in + + let version v = v.version in + let base_url v = v.base_url in + let currency v = v.currency in + let shopping_url v = v.shopping_url in + let open_banking_gateway v = v.open_banking_gateway in + let bank_compliance_language v = v.bank_compliance_language in + let currency_specification v = v.currency_specification in + let tiny_amount v = v.tiny_amount in + let stefan_abs v = v.stefan_abs in + let stefan_log v = v.stefan_log in + let stefan_lin v = v.stefan_lin in + let asset_type v = v.asset_type in + let accounts v = v.accounts in + let wire_fees v = v.wire_fees in + let wads v = v.wads in + let rewards_allowed v = v.rewards_allowed in + let kyc_enabled v = v.kyc_enabled in + let disable_direct_deposit v = v.disable_direct_deposit in + let master_public_key v = v.master_public_key in + let reserve_closing_delay v = v.reserve_closing_delay in + let wallet_balance_limit_without_kyc v = + v.wallet_balance_limit_without_kyc + in + let hard_limits v = v.hard_limits in + let zero_limits v = v.zero_limits in + let denominations v = v.denominations in + let exchange_sig v = v.exchange_sig in + let exchange_pub v = v.exchange_pub in + let recoup v = v.recoup in + let global_fees v = v.global_fees in + let list_issue_date v = v.list_issue_date in + let auditors v = v.auditors in + let signkeys v = v.signkeys in + let extensions v = v.extensions in + let extensions_sig v = v.extensions_sig in + + let open Jsont.Object in + map ~kind:"ExchangeKeysResponse" make + |> mem "version" Jsont.string ~enc:version + |> mem "base_url" Jsont.string ~enc:base_url + |> mem "currency" Jsont.string ~enc:currency + |> opt_mem "shopping_url" Jsont.string ~enc:shopping_url + |> opt_mem "open_banking_gateway" Jsont.string ~enc:open_banking_gateway + |> opt_mem "bank_compliance_language" Jsont.string + ~enc:bank_compliance_language + |> mem "currency_specification" CurrencySpecification.jsont + ~enc:currency_specification + |> opt_mem "tiny_amount" Amount.jsont ~enc:tiny_amount + |> mem "stefan_abs" Amount.jsont ~enc:stefan_abs + |> mem "stefan_log" Amount.jsont ~enc:stefan_log + |> mem "stefan_lin" Jsont.number ~enc:stefan_lin + |> mem "asset_type" Jsont.string ~enc:asset_type + |> mem "accounts" (Jsont.list ExchangeWireAccount.jsont) ~enc:accounts + |> mem "wire_fees" + (Jsont.Object.as_string_map (Jsont.list AggregateTransferFee.jsont)) + ~enc:wire_fees + |> mem "wads" (Jsont.list ExchangePartnerListEntry.jsont) ~enc:wads + |> mem "rewards_allowed" Jsont.bool ~enc:rewards_allowed + |> mem "kyc_enabled" Jsont.bool ~enc:kyc_enabled + |> mem "disable_direct_deposit" Jsont.bool ~enc:disable_direct_deposit + |> mem "master_public_key" EddsaPublicKey.jsont ~enc:master_public_key + |> mem "reserve_closing_delay" RelativeTime.jsont ~enc:reserve_closing_delay + |> opt_mem "wallet_balance_limit_without_kyc" (Jsont.list Amount.jsont) + ~enc:wallet_balance_limit_without_kyc + |> mem "hard_limits" (Jsont.list AccountLimit.jsont) ~enc:hard_limits + |> mem "zero_limits" + (Jsont.list ZeroLimitedOperation.jsont) + ~enc:zero_limits + |> mem "denominations" (Jsont.list DenomGroup.jsont) ~enc:denominations + |> mem "exchange_sig" ExchangeKeySetPS.jsont ~enc:exchange_sig + |> mem "exchange_pub" EddsaPublicKey.jsont ~enc:exchange_pub + |> mem "recoup" (Jsont.list RecoupDenoms.jsont) ~enc:recoup + |> mem "global_fees" (Jsont.list GlobalFees.jsont) ~enc:global_fees + |> mem "list_issue_date" Timestamp.jsont ~enc:list_issue_date + |> mem "auditors" (Jsont.list AuditorKeys.jsont) ~enc:auditors + |> mem "signkeys" (Jsont.list SignKey.jsont) ~enc:signkeys + |> opt_mem "extensions" + (Jsont.Object.as_string_map ExtensionManifest.jsont) + ~enc:extensions + |> opt_mem "extensions_sig" EddsaSignature.jsont ~enc:extensions_sig + |> finish +end diff --git a/src/bin_signature.ml b/src/bin_signature.ml index 776a1323..b90bc52e 100644 --- a/src/bin_signature.ml +++ b/src/bin_signature.ml @@ -702,6 +702,28 @@ module ExchangeKeyValidityPS = struct include MK (R) end +module ExchangeKeySetPS = struct + module R = struct + (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_KEY_SET *) + type r = { + list_issue_date: TimeAbsoluteNBO.t; + hc: Hash_64.t; + } + + let bin = + let open Bin in + Purpose.make_bin Taler_signatures.exchange_key_set @@ fun _purpose -> + record (fun _purpose list_issue_date hc -> { list_issue_date; hc }) + |+ Purpose.field _purpose + |+ field TimeAbsoluteNBO.bin (fun t -> t.list_issue_date) + |+ field Hash_64.bin (fun t -> t.hc) + |> sealr + end + + include R + include MK (R) +end + (* ### BIN IMPL END ### *) module WithdrawRequestPS = struct @@ -812,14 +834,6 @@ module RefreshMeltConfirmationPS = struct } end -module ExchangeKeySetPS = struct - (* purpose.purpose = TALER_SIGNATURE_EXCHANGE_KEY_SET *) - type t = { - list_issue_date: TimeAbsoluteNBO.t; - hc: Hash_64_cstr.t; - } -end - module DepositTrackPS = struct (* purpose.purpose = TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION *) type t = {