summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-08-11 02:47:12 +0200
committerChristian Grothoff <christian@grothoff.org>2023-08-11 02:47:18 +0200
commit36e78aa674264ca1c6e37ebabd653faa08dd6026 (patch)
tree8d08ee058cc1f1e23968f45bf30921ce5e9e8d2b
parenta980dfed1cc026d944924f9d2fef1090d2a0e137 (diff)
downloaddocs-36e78aa674264ca1c6e37ebabd653faa08dd6026.tar.gz
docs-36e78aa674264ca1c6e37ebabd653faa08dd6026.tar.bz2
docs-36e78aa674264ca1c6e37ebabd653faa08dd6026.zip
contract v1 DD draft
-rw-r--r--design-documents/045-mumimo-contracts.rst448
-rw-r--r--manpages/taler-bank-benchmark.1.rst4
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.