diff options
author | Christian Grothoff <christian@grothoff.org> | 2023-08-11 02:47:12 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2023-08-11 02:47:18 +0200 |
commit | 36e78aa674264ca1c6e37ebabd653faa08dd6026 (patch) | |
tree | 8d08ee058cc1f1e23968f45bf30921ce5e9e8d2b | |
parent | a980dfed1cc026d944924f9d2fef1090d2a0e137 (diff) | |
download | docs-36e78aa674264ca1c6e37ebabd653faa08dd6026.tar.gz docs-36e78aa674264ca1c6e37ebabd653faa08dd6026.tar.bz2 docs-36e78aa674264ca1c6e37ebabd653faa08dd6026.zip |
contract v1 DD draft
-rw-r--r-- | design-documents/045-mumimo-contracts.rst | 448 | ||||
-rw-r--r-- | manpages/taler-bank-benchmark.1.rst | 4 |
2 files changed, 448 insertions, 4 deletions
diff --git a/design-documents/045-mumimo-contracts.rst b/design-documents/045-mumimo-contracts.rst new file mode 100644 index 00000000..f93d99d1 --- /dev/null +++ b/design-documents/045-mumimo-contracts.rst @@ -0,0 +1,448 @@ +Contract Format v1 +################## + +Summary +======= + +The contract v1 format enables a multitude of advanced interactions between +merchants and wallets, including donations, subscriptions, coupons, currency +exchange and more. + +Motivation +========== + +The existing v0 contract format is too simplistic to +support many frequenly requested types of contracts. + +Requirements +============ + +We want Taler to support various interesting use-cases: + + - Unlinkable, uncopyable subscriptions without accounts (reader can pay with + Taler to subscribe to online publication, read unlimited number of + articles during a certain period, transfer subscription to other devices, + maintain unlinkability / full anonymity amongst all anonymous + subscribers). + + - Coupons, discounts and stamps -- like receiving a discount on a product, + product basket or subscription -- based on previous purchase(s). Again, + with unlinkability and anonymity (modulo there being other users eligible + for the discount). + + - Currency conversion, that is exchanging one currency for another. + + - Donations, including privacy-preserving tax receipts that prove that the + user donated to an entity that is eligible for tax-deductions but without + revealing which entity the user donated to. At the same time, the entity + issuing the tax receipt must be transparent (to the state) with respect to + the amount of tax-deductable donations it has received. + + - Throttled political donations where each individual is only allowed to + donate anonymously up to a certain amount per year or election cycle. + +TODO: add more use-cases here! + + +Proposed Solution +================= + +Merchants will also blindly sign tokens (not coins) to indicate the +eligibility of a user for certain special offers. Contracts will be modified +to allow requiring multiple inputs (to be *provisioned*" to the merchant) and +multiple outputs (to be *yielded* by the merchant). Contracts will also +include multiple options for how a user may pay or what they might want to +purchase. The wallet will then allow the user to select between the choices +that the user could pay for, or possibly make an automatic choice if the +correct choice is obvious. One output option is blindly signed coins from +another exchange, possibly in a different currency. Another output option is +blindly signed donation receipts from a DONation AUthority (DONAU). +Subscriptions can be modeled by requiring the wallet to provision a token of +the same type that is also yielded by the contract. For security, payments +using subscription tokens (and possibly certain other special tokens?) will be +limited to a list of domains explicitly defined as trusted by the token +issuer. When paying for a contract, the wallet must additionally sign over +the selected sub-contract index and a hash committing it to the blinded +envelopes (if any). The merchant backend will (probably?) need to be changed +to truly support multiple currencies (ugh). + + +.. _contract-terms-v1: + +The contract terms v1 will have the following structure: + +.. ts:def:: ContractTermsV1 + + interface ContractTermsV1 { + + // This is version 1, the previous contract terms SHOULD + // be indicated using "0", but in v0 specifying the version + // is optional. + version: "1"; + + // Unique, free-form identifier for the proposal. + // Must be unique within a merchant instance. + // For merchants that do not store proposals in their DB + // before the customer paid for them, the ``order_id`` can be used + // by the frontend to restore a proposal from the information + // encoded in it (such as a short product identifier and timestamp). + order_id: string; + + // URL where the same contract could be ordered again (if + // available). Returned also at the public order endpoint + // for people other than the actual buyer (hence public, + // in case order IDs are guessable). + public_reorder_url?: string; + + // Time when this contract was generated. + timestamp: Timestamp; + + // After this deadline, the merchant won't accept payments for the contract. + pay_deadline: Timestamp; + + // Transfer deadline for the exchange. Must be in the + // deposit permissions of coins used to pay for this order. + wire_transfer_deadline: Timestamp; + + // Merchant's public key used to sign this proposal; this information + // is typically added by the backend. Note that this can be an ephemeral key. + merchant_pub: EddsaPublicKey; + + // Base URL of the (public!) merchant backend API. + // Must be an absolute URL that ends with a slash. + merchant_base_url: string; + + // More info about the merchant (same as in v0). + merchant: Merchant; + + // After this deadline has passed, no refunds will be accepted. + refund_deadline: Timestamp; + + // Specifies for how long the wallet should try to get an + // automatic refund for the purchase. If this field is + // present, the wallet should wait for a few seconds after + // the purchase and then automatically attempt to obtain + // a refund. The wallet should probe until "delay" + // after the payment was successful (i.e. via long polling + // or via explicit requests with exponential back-off). + // + // In particular, if the wallet is offline + // at that time, it MUST repeat the request until it gets + // one response from the merchant after the delay has expired. + // If the refund is granted, the wallet MUST automatically + // recover the payment. This is used in case a merchant + // knows that it might be unable to satisfy the contract and + // desires for the wallet to attempt to get the refund without any + // customer interaction. Note that it is NOT an error if the + // merchant does not grant a refund. + auto_refund?: RelativeTime; + + // Delivery location for (all!) products (same as in v0). + delivery_location?: Location; + + // Time indicating when the order should be delivered. + // May be overwritten by individual products. + delivery_date?: Timestamp; + + // Nonce generated by the wallet and echoed by the merchant + // in this field when the proposal is generated. + // Note: required in contract, absent in order! + nonce: string; + + // Array of possible specific contracts the wallet/customer + // may choose from by selecting the respective index when + // signing the deposit confirmation. + choices: ContractChoice[]; + + // Extra data that is only interpreted by the merchant frontend. + // Useful when the merchant needs to store extra information on a + // contract without storing it separately in their database. + extra?: any; + + // Fee limits and wire account details by currency. + limits: { [currency:string] : CurrencyLimit }; + } + +.. ts:def:: CurrencyLimit + + interface CurrencyLimit { + + // The hash of the merchant instance's wire details. + h_wire: HashCode; + + // Wire transfer method identifier for the wire method associated with ``h_wire``. + // The wallet may only select exchanges via a matching auditor if the + // exchange also supports this wire method. + // The wire transfer fees must be added based on this wire transfer method. + wire_method: string; + + // Maximum total deposit fee accepted by the merchant for this contract. + max_fee: Amount; + + // Maximum wire fee accepted by the merchant (customer share to be + // divided by the ``wire_fee_amortization`` factor, and further reduced + // if deposit fees are below ``max_fee``). Default if missing is zero. + max_wire_fee: Amount; + + // Over how many customer transactions does the merchant expect to + // amortize wire fees on average? If the exchange's wire fee is + // above ``max_wire_fee``, the difference is divided by this number + // to compute the expected customer's contribution to the wire fee. + // The customer's contribution may further be reduced by the difference + // between the ``max_fee`` and the sum of the actual deposit fees. + // Optional, default value if missing is 1. 0 and negative values are + // invalid and also interpreted as 1. + wire_fee_amortization: number; + + // Exchanges that the merchant accepts for this currency. + exchanges: Exchange[]; + + } + + +.. ts:def:: ContractChoice + + interface ContractChoice { + + // Human-readable description of the choice. + summary: string; + + // Map from IETF BCP 47 language tags to localized summaries. + summary_i18n?: { [lang_tag: string]: string }; + + // URL that will show that the order was successful after + // it has been paid for. Optional. When POSTing to the + // merchant, the placeholder "${ORDER_ID}" will be + // replaced with the actual order ID (useful if the + // order ID is generated server-side and needs to be + // in the URL). + // Note that this placeholder can only be used once. + // Either fulfillment_url or fulfillment_message must be specified. + fulfillment_url?: string; + + // Message shown to the customer after paying for the order. + // Either fulfillment_url or fulfillment_message must be specified. + fulfillment_message?: string; + + // Map from IETF BCP 47 language tags to localized fulfillment + // messages. + fulfillment_message_i18n?: { [lang_tag: string]: string }; + + // List of products that are part of the purchase (see `Product`). + products: Product[]; + + // List of inputs the wallet must provision (all of them) to + // satisfy the conditions for the contract. + inputs: ContractInput[]; + + // List of outputs the merchant promises to yield (all of them) + // once the contract is paid. + outputs: ContractOutput[]; + + // Map from authority labels to meta data abou the + // respective token authority. + token_types: { [authority_label: TokenAuthority }; + + } + +.. ts:def:: ContractInput + + type ContractInput = + | ContractInputCurrency + | ContractInputToken; + +.. ts:def:: ContractInputCurrency + + interface ContractInputCurrency { + + type: "currency"; + + // Price to be paid for the transaction. + // The exchange will subtract deposit fees from that amount + // before transferring it to the merchant. + price: Amount; + + }; + +.. ts:def:: ContractInputToken + + interface ContractInputToken { + + type: "token"; + + // Hash over the public key used to sign the + // type of subscription token required. + h_issuer: HashCode; + + // Number of tokens of this type required. + // Defaults to one if the field is not provided. + number?: integer; + + }; + +.. ts:def:: ContractOutput + + type ContractOutput = + | ContractOutputCurrency + | ContractOutputTaxReceipt + | ContractOutputToken; + +.. ts:def:: ContractOutputCurrency + + interface ContractOutputCurrency { + + type: "currency"; + + // Amount of currency that will be yielded. + // This excludes any applicable withdraw fees. + brutto_yield: Amount; + + // Base URL of the exchange that will issue the + // coins. + exchange_url: string; + + }; + +.. ts:def:: ContractOutputTaxReceipt + + interface ContractOutputTaxReceipt { + + type: "tax-receipt"; + + // Base URL of the donation authority that will + // issue the tax receipt. + donau_url: string; + + }; + +.. ts:def:: ContractOutputToken + + interface ContractOutputToken { + + type: "token"; + + // Label of the token authority in the + // 'token_types' map on the top-level. + authority_label: string; + + // Must a wallet understand this token type to + // process contracts that consume or yield it? + critical: boolean; + + // Information about the class of token that will + // be yielded. + details: OutputTokenClass; + } + + type OutputTokenClass = + | OutputTokenClassSubscription + | OutputTokenClassDiscount + +.. ts:def::OutputTokenClassSubscription + + interface OutputTokenClassSubscription { + + class: "subscription"; + + // When does the subscription period start? + start_date: Timestamp; + + // Array of domain names where this subscription + // can be safely used (e.g. the issuer warrants that + // these sites will re-issue tokens of this type + // if the respective contract says so). + trusted_domains: string[]; + + }; + +.. ts:def:: OutputTokenClassDiscount + + interface OutputTokenClassDiscount { + + class: "discount"; + + }; + + +.. ts:def:: TokenAuthority + + interface TokenAuthority { + + // Human-readable description of the semantics of + // the tokens issued by this authority (for display). + summary: string; + + // Map from IETF BCP 47 language tags to localized summaries. + summary_i18n?: { [lang_tag: string]: string }; + + // Public key used to validate tokens issued + // by this token authority (merchant backend). + key: TokenSignerPublicKey; + + // When will tokens signed by this key expire? + // (also the expiration for 'subscriptions'). + token_expiration: Timestamp; + + // Number of tokens issued according to ASS authority + // FIXME: this is still rather speculative in the design... + ass?: integer; + + // Signature affirming sum of token issuance deposit (?) fees + // collected by an exchange according to the ASS authority. + // FIXME: this is still rather speculative in the design... + ass_cost?: Amount; + + // Signature affirming the ass by the ASS authority. + // FIXME: this is still rather speculative in the design... + ass_sig?: EddsaSignature; + + }; + + +.. ts:def:: TokenSignerPublicKey + + type TokenSignerPublicKey = + | DenomGroupRsa + | DenomGroupCs; + +TODO: may want to do a deep copy and rename +DenomGroup* to TokenSignerPublicKey* here. + + + +Definition of Done +================== + + - Merchant backend support for multiple currencies + - Merchant backend support for consuming and issuing tokens + - Merchant SPA support for configuring new tokens of different types + - Wallet-core support for various new contract types + - Wallet-core filters for feasible contracts and possibly auto-executes subscriptions + - Wallet-GUIs (WebEx, Android, iOS) render new contract types + - Wallet-GUIs (WebEx, Android, iOS) allow user to select between multiple contracts + - Documentation for developers is up-to-date + - Token anonymity set size (ASS) authority implemented, documented + - Merchants report anonymity set size increases to ASS authority + - Wallets process anonymity set size reports from ASS authority + - Bachelor thesis written on applications and design + - Academic paper written on DONAU (requirements, design, implementation) + - DONAU implemented, documented + - Integration tests exist in wallet-core + - Deliverables accepted by EC + + +Alternatives +============ + +None. + +Drawbacks +========= + +Significant change, but actually good ratio compared to use-cases covered. + + +Discussion / Q&A +================ + +(This should be filled in with results from discussions on mailing lists / personal communication.) diff --git a/manpages/taler-bank-benchmark.1.rst b/manpages/taler-bank-benchmark.1.rst index eaf1c542..be7aceb1 100644 --- a/manpages/taler-bank-benchmark.1.rst +++ b/manpages/taler-bank-benchmark.1.rst @@ -18,7 +18,6 @@ Synopsis [**-L** *LOGLEVEL* | **--loglevel=**\ \ *LOGLEVEL*] [**-l** *FILENAME* | **--logfile=**\ \ *FILENAME*] [**-p** *NPROCS* | **--worker-parallelism=**\ \ *NPROCS*] -[**-P** *NTHREADS* | **--service-parallelism=**\ \ *NTHREADS*] [**-r** *NRESERVES* | **--reserves=**\ \ *NRESERVES*] [**-u** *SECTION* | **--exchange-account-section=**\ \ *SECTION*] [**-V** | **--verbose**] @@ -55,9 +54,6 @@ The options for **taler-bank-benchmark** are: Run as ``bank``, ``client`` or ``both``. If unspecified, *MODE* defaults to ``both``. -**-P** *NTHREADS** \| **--service-parallelism=**\ \ *NTHREADS* - Run with *NTHREADS* service threads. - **-p** *NPROCS* \| **--worker-parallelism=**\ \ *NPROCS* Run with *NPROCS* client processes. |