taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

046-mumimo-contracts.rst (27564B)


      1 DD 46: Contract Format v1
      2 #########################
      3 
      4 :Design status: Accepted
      5 :Implementation status: Partial
      6 :DD shepherd: TBD
      7 :Historical contributors: Christian Blättler, Stefan Kügel, Florian Dold, Christian Grothoff
      8 :First published: 2023-08-11
      9 :Last substantive change: 2026-08-04
     10 :Implementation evidence: merchant (2025-03-05), taler-typescript-core (2026-07-06)
     11 :Normative references: ``core/api-merchant.rst``, ``wallet/wallet-core.md``
     12 
     13 .. note::
     14 
     15    The REST API specifications are normative for the implemented wire format.
     16    Future-work and rationale sections in this DD do not extend those APIs.
     17 
     18 Summary
     19 =======
     20 
     21 The contract v1 format enables a multitude of advanced interactions between
     22 merchants and wallets, including donations, subscriptions, coupons, currency
     23 exchange and more.
     24 
     25 Motivation
     26 ==========
     27 
     28 The existing v0 contract format is too simplistic to
     29 support many frequenly requested types of contracts.
     30 
     31 Requirements
     32 ============
     33 
     34 We want Taler to support various interesting use-cases:
     35 
     36   - Unlinkable, uncopyable subscriptions without accounts (reader can pay with
     37     Taler to subscribe to online publication, read unlimited number of
     38     articles during a certain period, transfer subscription to other devices,
     39     maintain unlinkability / full anonymity amongst all anonymous
     40     subscribers).
     41 
     42   - Coupons, discounts and stamps -- like receiving a discount on a product,
     43     product basket or subscription -- based on previous purchase(s). Again,
     44     with unlinkability and anonymity (modulo there being other users eligible
     45     for the discount).
     46 
     47   - Subscription tokens lost (due to loss of device without backup) should
     48     be recoverable from any previous backup of the subscription.
     49 
     50   - Currency conversion, that is exchanging one currency for another.
     51 
     52   - Donations, including privacy-preserving tax receipts that prove that the
     53     user donated to an entity that is eligible for tax-deductions but without
     54     revealing which entity the user donated to. At the same time, the entity
     55     issuing the tax receipt must be transparent (to the state) with respect to
     56     the amount of tax-deductable donations it has received.
     57 
     58   - Throttled political donations where each individual is only allowed to
     59     donate anonymously up to a certain amount per year or election cycle.
     60 
     61   - Unlinkable gifts -- enabling the purchase of digital goods (such as
     62     articles, albums, etc.) to be consumed by a third party. For example, a
     63     newspaper subscription may include a fixed number of articles that can be
     64     gifted to others each week, all while maintaining unlinkability and
     65     anonymity between the giver and the recipient.
     66 
     67   - Temporally-constrained, unlinkable event ticketing. Allowing visitors to
     68     use Taler to purchase a ticket for an event. This ticket grants entry and
     69     exit privileges to the event location during a specified time window, while
     70     preserving the anonymity of the ticket holder (within the group of all the
     71     ticket holders).
     72 
     73   - Event deposit systems. A deposit mechanism for events where customers
     74     receive a token alongside their cup or plate, which they are expected to
     75     return. This system validates that the cup or plate was legitimately
     76     acquired (i.e., not brought from home or stolen from a stack of dirty items)
     77     and incentivizes return after use.
     78 
     79 
     80 Proposed Solution
     81 =================
     82 
     83 Merchants will also blindly sign tokens (not coins) to indicate the
     84 eligibility of a user for certain special offers. Contracts will be modified
     85 to allow requiring multiple inputs (to be *provisioned* to the merchant) and
     86 multiple outputs (to be *yielded* by the merchant).  The wallet will then allow
     87 the user to select between the choices that the user could pay for, or possibly
     88 make an automatic choice if the correct choice is obvious. One output option is
     89 blindly signed coins from another exchange, possibly in a different currency.
     90 Another output option is blindly signed donation receipts from a DONation
     91 AUthority (DONAU). Subscriptions can be modeled by requiring the wallet to
     92 provision a token of the same type that is also yielded by the contract. For
     93 security, payments using subscription tokens (and possibly certain other special
     94 tokens?) will be limited to a list of domains explicitly defined as trusted by
     95 the token issuer.  When paying for a contract, the wallet must additionally sign
     96 over the selected sub-contract index and a hash committing it to the blinded
     97 envelopes (if any).  The merchant backend will (probably?) need to be changed
     98 to truly support multiple currencies (ugh).
     99 
    100 .. _contract-terms-v1:
    101 
    102 New Contract Terms Format
    103 -------------------------
    104 
    105 The contract terms v1 will have the following structure:
    106 
    107 .. ts:def:: DDContractTermsV1
    108 
    109   interface DDContractTermsV1 {
    110     // This is version 1, the previous contract terms SHOULD
    111     // be indicated using "0", but in v0 specifying the version
    112     // is optional.
    113     version: 1;
    114 
    115     // Unique, free-form identifier for the proposal.
    116     // Must be unique within a merchant instance.
    117     // For merchants that do not store proposals in their DB
    118     // before the customer paid for them, the ``order_id`` can be used
    119     // by the frontend to restore a proposal from the information
    120     // encoded in it (such as a short product identifier and timestamp).
    121     order_id: Slug;
    122 
    123     // URL where the same contract could be ordered again (if
    124     // available). Returned also at the public order endpoint
    125     // for people other than the actual buyer (hence public,
    126     // in case order IDs are guessable).
    127     public_reorder_url?: WebURL;
    128 
    129     // Time when this contract was generated.
    130     timestamp: Timestamp;
    131 
    132     // After this deadline, the merchant won't accept payments for the contract.
    133     pay_deadline: Timestamp;
    134 
    135     // Transfer deadline for the exchange.  Must be in the
    136     // deposit permissions of coins used to pay for this order.
    137     wire_transfer_deadline: Timestamp;
    138 
    139     // Merchant's public key used to sign this proposal; this information
    140     // is typically added by the backend. Note that this can be an ephemeral key.
    141     merchant_pub: EddsaPublicKey;
    142 
    143     // Base URL of the (public!) merchant backend API.
    144     // Must be an absolute URL that ends with a slash.
    145     merchant_base_url: WebURL;
    146 
    147     // More info about the merchant (same as in v0).
    148     merchant: Merchant;
    149 
    150     // Human-readable description of the contract.
    151     summary: string;
    152 
    153     // Map from IETF BCP 47 language tags to localized summaries.
    154     summary_i18n?: { [lang_tag: string]: string };
    155 
    156     // URL that will show that the order was successful after
    157     // it has been paid for.  Optional. When POSTing to the
    158     // merchant, the placeholder "${ORDER_ID}" will be
    159     // replaced with the actual order ID (useful if the
    160     // order ID is generated server-side and needs to be
    161     // in the URL).
    162     // Note that this placeholder can only be used once.
    163     // Because of that placeholder, the value given here is merely a
    164     // string and not yet a `WebURL`; only after the substitution has
    165     // been performed is the result a `WebURL`.
    166     // Either fulfillment_url or fulfillment_message must be specified.
    167     fulfillment_url?: string;
    168 
    169     // Message shown to the customer after paying for the order.
    170     // Either fulfillment_url or fulfillment_message must be specified.
    171     fulfillment_message?: string;
    172 
    173     // Map from IETF BCP 47 language tags to localized fulfillment
    174     // messages.
    175     fulfillment_message_i18n?: { [lang_tag: string]: string };
    176 
    177     // List of products that are part of the purchase (see `ProductSold`).
    178     products: ProductSold[];
    179 
    180     // After this deadline has passed, no refunds will be accepted.
    181     refund_deadline: Timestamp;
    182 
    183     // Specifies for how long the wallet should try to get an
    184     // automatic refund for the purchase. If this field is
    185     // present, the wallet should wait for a few seconds after
    186     // the purchase and then automatically attempt to obtain
    187     // a refund.  The wallet should probe until "delay"
    188     // after the payment was successful (i.e. via long polling
    189     // or via explicit requests with exponential back-off).
    190     //
    191     // In particular, if the wallet is offline
    192     // at that time, it MUST repeat the request until it gets
    193     // one response from the merchant after the delay has expired.
    194     // If the refund is granted, the wallet MUST automatically
    195     // recover the payment.  This is used in case a merchant
    196     // knows that it might be unable to satisfy the contract and
    197     // desires for the wallet to attempt to get the refund without any
    198     // customer interaction.  Note that it is NOT an error if the
    199     // merchant does not grant a refund.
    200     auto_refund?: RelativeTime;
    201 
    202     // Delivery location for (all!) products (same as in v0).
    203     delivery_location?: Location;
    204 
    205     // Time indicating when the order should be delivered.
    206     // May be overwritten by individual products.
    207     delivery_date?: Timestamp;
    208 
    209     // Nonce generated by the wallet and echoed by the merchant
    210     // in this field when the proposal is generated.
    211     // Note: required in contract, absent in order!
    212     nonce: string;
    213 
    214     // Array of possible specific contracts the wallet/customer
    215     // may choose from by selecting the respective index when
    216     // signing the deposit confirmation.
    217     choices: DDContractChoice[];
    218 
    219     // Map from token family slugs to meta data about the
    220     // respective token family.
    221     token_families: { [token_family_slug: Slug]: ContractTokenFamily };
    222 
    223     // Extra data that is only interpreted by the merchant frontend.
    224     // Useful when the merchant needs to store extra information on a
    225     // contract without storing it separately in their database.
    226     extra?: any;
    227 
    228     // Exchanges that the merchant accepts for this currency.
    229     exchanges: Exchange[];
    230   }
    231 
    232 .. ts:def:: DDContractChoice
    233 
    234   interface DDContractChoice {
    235     // Price to be paid for this choice. Could be 0.
    236     // The price is in addition to other instruments,
    237     // such as rations and tokens.
    238     // The exchange will subtract deposit fees from that amount
    239     // before transferring it to the merchant.
    240     amount: Amount;
    241 
    242     // List of inputs the wallet must provision (all of them) to
    243     // satisfy the conditions for the contract.
    244     inputs: DDContractInput[];
    245 
    246     // List of outputs the merchant promises to yield (all of them)
    247     // once the contract is paid.
    248     outputs: DDContractOutput[];
    249 
    250     // Maximum total deposit fee accepted by the merchant for this contract.
    251     max_fee: Amount;
    252   }
    253 
    254 .. ts:def:: DDContractInput
    255 
    256   type DDContractInput =
    257     | DDContractInputRation
    258     | DDContractInputToken;
    259 
    260 .. ts:def:: DDContractInputRation
    261 
    262   interface DDContractInputRation {
    263     type: "coin";
    264 
    265     // Price to be paid for the transaction.
    266     price: Amount;
    267 
    268     // FIXME-DOLD: do we want to move this into a 'details'
    269     // sub-structure as done with tokens below?
    270     class: "ration";
    271 
    272     // Base URL of the ration authority.
    273     ration_authority_url: WebURL;
    274   };
    275 
    276 .. ts:def:: DDContractInputToken
    277 
    278   interface DDContractInputToken {
    279     type: "token";
    280 
    281     // Slug of the token family in the
    282     // 'token_families' map on the order.
    283     token_family_slug: Slug;
    284 
    285     // Start of the validity period of the token. This is used to find the
    286     // matching public key within the token family.
    287     valid_after: Timestamp;
    288 
    289     // Number of tokens of this type required.
    290     // Defaults to one if the field is not provided.
    291     number?: Integer;
    292   };
    293 
    294 .. ts:def:: DDContractOutput
    295 
    296   type DDContractOutput =
    297     | DDContractOutputCoin
    298     | DDContractOutputTaxReceipt
    299     | DDContractOutputToken;
    300 
    301 .. ts:def:: DDContractOutputCoin
    302 
    303   interface DDContractOutputCoin {
    304     type: "coins";
    305 
    306     // Amount of coins that will be yielded.
    307     // This excludes any applicable withdraw fees.
    308     brutto_yield: Amount;
    309 
    310     // Base URL of the exchange that will issue the
    311     // coins.
    312     exchange_url: WebURL;
    313   };
    314 
    315 .. ts:def:: DDContractOutputTaxReceipt
    316 
    317   interface DDContractOutputTaxReceipt {
    318     type: "tax-receipt";
    319 
    320     // Base URL of the donation authority that will
    321     // issue the tax receipt.
    322     donau_url: WebURL;
    323   };
    324 
    325 .. ts:def:: DDContractOutputToken
    326 
    327   interface DDContractOutputToken {
    328     type: "token";
    329 
    330     // Slug of the token family in the
    331     // 'token_families' map on the top-level.
    332     token_family_slug: Slug;
    333 
    334     // Start of the validity period of the token. This is used to find the
    335     // matching public key within the token family.
    336     valid_after: Timestamp;
    337 
    338     // Number of tokens to be issued.
    339     // Defaults to one if the field is not provided.
    340     number?: Integer;
    341   }
    342 
    343 .. ts:def:: DDContractTokenDetails
    344 
    345   type DDContractTokenDetails =
    346     | DDContractSubscriptionTokenDetails
    347     | DDContractDiscountTokenDetails
    348 
    349 .. ts:def:: DDContractSubscriptionTokenDetails
    350 
    351   interface DDContractSubscriptionTokenDetails {
    352     class: "subscription";
    353 
    354     // Array of domain names where this subscription
    355     // can be safely used (e.g. the issuer warrants that
    356     // these sites will re-issue tokens of this type
    357     // if the respective contract says so).  May contain
    358     // "*" for any domain or subdomain.
    359     trusted_domains: string[];
    360   };
    361 
    362 .. ts:def:: DDContractDiscountTokenDetails
    363 
    364   interface DDContractDiscountTokenDetails {
    365     class: "discount";
    366 
    367     // Array of domain names where this discount token
    368     // is intended to be used.  May contain "*" for any
    369     // domain or subdomain.  Users should be warned about
    370     // sites proposing to consume discount tokens of this
    371     // type that are not in this list that the merchant
    372     // is accepting a coupon from a competitor and thus
    373     // may be attaching different semantics (like get 20%
    374     // discount for my competitors 30% discount token).
    375     expected_domains: string[];
    376   };
    377 
    378 .. ts:def:: DDContractTokenFamily
    379 
    380   interface DDContractTokenFamily {
    381     // Human-readable name of the token family.
    382     name: string;
    383 
    384     // Human-readable description of the semantics of
    385     // this token family (for display).
    386     description: string;
    387 
    388     // Map from IETF BCP 47 language tags to localized descriptions.
    389     description_i18n?: { [lang_tag: string]: string };
    390 
    391     // Public keys used to validate tokens issued by this token family.
    392     keys: TokenIssuePublicKey[];
    393 
    394     // Class-specific information of the token
    395     details: ContractTokenDetails;
    396 
    397     // Must a wallet understand this token type to
    398     // process contracts that consume or yield it?
    399     critical: boolean;
    400 
    401     // Number of tokens issued according to ASS authority
    402     // FIXME: this is still rather speculative in the design...
    403     ass?: Integer;
    404 
    405     // Signature affirming sum of token issuance deposit (?) fees
    406     // collected by an exchange according to the ASS authority.
    407     // FIXME: this is still rather speculative in the design...
    408     ass_cost?: Amount;
    409 
    410     // Signature affirming the ass by the ASS authority.
    411     // FIXME: this is still rather speculative in the design...
    412     ass_sig?: EddsaSignature;
    413   };
    414 
    415 .. ts:def:: DDTokenIssuePublicKey
    416 
    417   type DDTokenIssuePublicKey =
    418     | DDTokenIssueRsaPublicKey
    419     | DDTokenIssueCsPublicKey;
    420 
    421 .. ts:def:: DDTokenIssueRsaPublicKey
    422 
    423   interface DDTokenIssueRsaPublicKey {
    424     cipher: "RSA";
    425 
    426     // RSA public key.
    427     rsa_pub: RsaPublicKey;
    428 
    429     // Start time of this key's validity period.
    430     valid_after: Timestamp;
    431 
    432     // End time of this key's validity period.
    433     valid_before: Timestamp;
    434   }
    435 
    436 .. ts:def:: DDTokenIssueCsPublicKey
    437 
    438   interface DDTokenIssueCsPublicKey {
    439     cipher: "CS";
    440 
    441     // CS public key.
    442     cs_pub: Cs25519Point;
    443 
    444     // Start time of this key's validity period.
    445     valid_after: Timestamp;
    446 
    447     // End time of this key's validity period.
    448     valid_before: Timestamp;
    449   }
    450 
    451 
    452 Alternative Contracts
    453 ---------------------
    454 
    455 The contract terms object may contain any number of alternative contracts that
    456 the user must choose between. The alternatives can differ by inputs, outputs
    457 or other details. The wallet must filter the contracts by those that the user
    458 can actually pay for, and move those that the user could currently not pay for
    459 to the end of the rendered list.  Similarly, the wallet must move up the
    460 cheaper contracts, so if a contract has a definitively lower price and
    461 consumes an available discount token, that contract should be moved up in the
    462 list.
    463 
    464 Which specific alternative contract was chosen by the user is indicated in the
    465 ``choice_index`` field of the :ref:`TALER_DepositRequestPS <taler_depositrequestps>`.
    466 
    467 
    468 Output Commitments
    469 ------------------
    470 
    471 When a contract has outputs, the wallet must send an array of blinded tokens,
    472 coins or tax receipts together with the payment request.  The order in the
    473 array must match the order in the outputs field of the contract.  For currency
    474 outputs, one array element must include all of the required planchets for a
    475 batch withdrawal, but of course not the reserve signature.
    476 
    477   .. note::
    478 
    479      We can probably spec this rather nicely if we first change the
    480      batch-withdraw API to only use a single reserve signature.
    481 
    482 This array of blinded values is hashed to create the output commitment hash
    483 (``h_outputs``) in the :ref:`TALER_DepositRequestPS <taler_depositrequestps>`.
    484 
    485 
    486 
    487 Subscriptions
    488 -------------
    489 
    490 The user buys a subscription (and possibly at the same time an article) using
    491 currency and the contract yields an additional subscription token as an
    492 output.  Active subscriptions are listed below the currencies in the wallet
    493 under a new heading.  Subscriptions are never auto-renewing, if the user wants
    494 to extend the subscription they can trivially pay for it with one click.
    495 
    496 When a contract consumes and yields exactly one subscription
    497 token of the same type in a trusted domain, the wallet may automatically
    498 approve the transaction without asking the user for confirmation (as it is free).
    499 
    500 The token expiration for a subscription can be past the "end date" to enable a
    501 previous subscription to be used to get a discount on renewing the
    502 subscription.  The wallet should show applicable contracts with a lower price
    503 that only additionally consume subscription tokens after their end date before
    504 higher-priced alternative offers.
    505 
    506 Subscription tokens are "critical" in that a wallet implementation must
    507 understand them before allowing a user to interact with this class of token.
    508 Subscription token secrets should be derived from a master secret associated
    509 with the subscription, so that the private keys are recoverable from backup.
    510 To obtain the blind signatures, a merchant must offer an endpoint where
    511 one can submit the public key of the N-1 subscription token and obtain the
    512 blinded signature over the N-th subscription token.  The wallet can then
    513 effectively recover the subscription from backup using a binary search.
    514 
    515 The merchant SPA should allow the administrator to create (maybe update) and
    516 delete subscriptions. Each subscription is identified by a subscription
    517 label and includes a validity period.
    518 
    519 The merchant backend must then automatically manage (create, use, delete) the
    520 respective signing keys.  When creating an order, the frontend can just refer
    521 to the subscription label (and possibly a start date) in the inputs or
    522 outputs. The backend should then automatically substitute this with the
    523 respective cryptographic fields for the respective time period and
    524 subscription label.
    525 
    526 
    527 
    528 
    529 Discounts
    530 ---------
    531 
    532 To offer a discount based on one or more previous purchases, a merchant must
    533 yield some discount-specific token as an output with the previous purchase,
    534 and then offer an alternative contract with a lower price that consumes currency
    535 and the discount token.  The wallet should show contracts with a lower price that
    536 only additionally consume discount tokens
    537 
    538 The merchant SPA should allow the administrator to create (maybe update) and
    539 delete discount tokens. Each discount token is identified by a discount
    540 label and includes an expiration time or validity duration.
    541 
    542 The merchant backend must then automatically manage (create, use, delete) the
    543 respective signing keys.  When creating an order, the frontend can just refer
    544 to the discount token label in the inputs or outputs. The backend should then
    545 automatically substitute this with the respective cryptographic fields for the
    546 respective discount token.
    547 
    548 
    549 Donation Authority
    550 ------------------
    551 
    552 A donation authority (DONAU) implements a service that is expected to be run
    553 by a government authority that determines eligibility for tax deduction.  A
    554 DONAU blindly signs tax receipts using a protocol very close to that of the
    555 Taler exchange's withdraw protocol, except that the reserves are not filled
    556 via wire transfers but instead represent accounts of the organizations
    557 eligible to issue tax deduction receipts. These accounts are basically
    558 expected to have only negative balances, but the DONAU can set a negative
    559 balance threshold per organization to limit the creation of tax deduction
    560 receipts to a plausible amount. DONAU administrators are expected to be
    561 able to add, update or remove these accounts using a SPA. Tax receipts are
    562 blindly signed by keys that always have a usage period of one calendar year.
    563 
    564 A stand-alone app for tax authorities can scan QR codes representing DONAU
    565 signatures to validate that a given tax payer has donated a certain amount.
    566 As RSA signatures are typically very large and a single donation may require
    567 multiple blind signatures, CS blind signatures must also be supported.  To
    568 avoid encoding the public keys, QR codes with tax receipts should reference
    569 the DONAU, the year and the amount, but not the specific public key.  A
    570 single donation may nevertheless be rendered using multiple QR codes.
    571 
    572 Revocations, refresh, deposits, age-restrictions and other exchange features
    573 are not applicable for a DONAU.
    574 
    575 The merchant SPA should allow the administrator to manage DONAU accounts in
    576 the merchant backend. Each DONAU account includes a base URL and a private
    577 signing key for signing the requests to the DONAU on behalf of the eligible
    578 organization.
    579 
    580 When creating an order, the frontend must specify a configured DONAU base URL
    581 in the outputs. The backend should then automatically interact with the DONAU
    582 when the wallet supplies the payment request with the blinded tax receipts.
    583 The DONAU interaction must only happen after the exchange confirmed that the
    584 contract was successfully paid.  A partial error must be returned if the
    585 exchange interaction was successful but the DONAU interaction failed. In this
    586 case, the fulfillment action should still be triggered, but the wallet should
    587 display a warning that the donation receipt could not be obtained. The wallet
    588 should then re-try the payment (in the background with an exponential
    589 back-off) to possibly obtain the tax receipt at a later time.
    590 
    591 
    592 Tax Receipts
    593 ------------
    594 
    595 Tax receipts differ from coins and tokens in that what is blindly signed over
    596 should be the taxpayer identification number of the tax payer.  The format of
    597 the taxpayer identification number should simply be a string, with the rest
    598 being defined by the national authority. The DONAU should indicate in its
    599 ``/config`` response what format this string should have, using possibly both
    600 an Anastasis-style regex and an Anastasis-style function name (to check things
    601 like checksums that cannot be validated using a regex).  Wallets must then
    602 validate the regex (if given) and if possible should implement the
    603 Anastasis-style logic.
    604 
    605 Wallets should collect tax receipts by year and offer an
    606 export functionality.  The export should generate either
    607 
    608     (a) a JSON file,
    609     (b) a PDF (with QR codes), or
    610     (c) a series of screens with QR codes.
    611 
    612 Wallets may only implement some of the above options due to resource
    613 constraints.
    614 
    615 The documents should encode the taxpayer ID, the amount and the DONAU
    616 signature (including the year, excluding the exact public key as there should
    617 only be one possible).
    618 
    619 
    620 Rationing (future work)
    621 -----------------------
    622 
    623 If per-capita rationing must be imposed on certain transactions, a rationing
    624 authority (RA) must exist that identifies each eligible human and issues that
    625 human a number of ration coins for the respective rationing period.  An RA
    626 largely functions like a regular exchange, except that eligible humans will
    627 need to authenticate directly to withdraw rations (instead of transferring
    628 fiat to an exchange).  Merchants selling rationed goods will be (legally)
    629 required to collect deposit confirmations in proportion to the amount of
    630 rationed goods sold.  A difference to regular exchanges is that RAs do not
    631 charge any fees.  RAs may or may not allow refreshing rations that are about
    632 to expire for ration coins in the next period.
    633 
    634 Once an RA is added to a wallet, it should automatically try to withdraw the
    635 maximum amount of ration coins it is eligible for. Available rations should be
    636 shown below the subscriptions by RA (if any).
    637 
    638   ..note::
    639 
    640     RAs are considered an idea for future work and not part of our current timeline.
    641 
    642 
    643 Limited Donations per Capita (future work)
    644 ------------------------------------------
    645 
    646 If per-capita limitations must be imposed on anonymous donations (for example
    647 for donations to political parties), an RA can be used to issue donation
    648 rations that limit the amount of donations that can be made for the respective
    649 period.
    650 
    651   ..note::
    652 
    653     RAs are considered an idea for future work and not part of our current timeline.
    654 
    655 
    656 
    657 Definition of Done
    658 ==================
    659 
    660   - [ ] Merchant backend support for multiple currencies
    661   - [x] Merchant backend support for consuming and issuing tokens
    662   - [ ] Merchant SPA support for configuring new tokens of different types
    663   - [x] Wallet-core support for contract format v1
    664   - [ ] Wallet-core filters for feasible contracts and automatic subscription execution
    665   - [ ] Wallet-GUIs (WebEx, Android, iOS) render all new contract types
    666   - [ ] Wallet-GUIs (WebEx, Android, iOS) allow users to select between multiple contracts
    667   - [x] Implemented wire formats documented in the normative API specifications
    668   - [ ] Token anonymity set size (ASS) authority implemented and documented
    669   - [ ] Merchants report anonymity set size increases to ASS authority
    670   - [ ] Wallets process anonymity set size reports from ASS authority
    671   - [x] Bachelor thesis written on applications and design
    672   - [x] Academic paper written on DONAU (requirements, design, implementation)
    673   - [x] DONAU implemented and documented
    674   - [ ] DONAU receipt-validation application completed
    675   - [x] Integration tests exist in wallet-core
    676   - [ ] Deliverables accepted by EC
    677 
    678 While rationing is part of the design, we expect the actual implementation to
    679 be done much later and thus should not consider it part of the "DONE" part.
    680 Rationing is complex, especially as a refunded contract should probably also
    681 refund the ration.
    682 
    683 
    684 Alternatives
    685 ============
    686 
    687 The first draft of this DD included the capability of paying with multiple
    688 currencies for the same contract (for example, USD:1 and EUR:5) plus tokens
    689 and rations. However, this is very complex, both for wallets (how to display),
    690 for other merchant APIs (does the refund API have to become multi-currency as
    691 well?) and there does not seem to be a good business case for it. So for now,
    692 the price is always only in one currency.
    693 
    694 
    695 Drawbacks
    696 =========
    697 
    698 Significant change, but actually good ratio compared to use-cases covered.
    699 
    700 
    701 Discussion / Q&A
    702 ================
    703 
    704 (This should be filled in with results from discussions on mailing lists / personal communication.)