summaryrefslogtreecommitdiff
path: root/design-documents/013-peer-to-peer-payments.rst
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-01-29 21:05:15 +0100
committerChristian Grothoff <christian@grothoff.org>2021-01-29 21:05:15 +0100
commit03eeb79192ceb55e01737640d0d59502b3c74ca0 (patch)
treea2d90a7af3dcae3d75736028fe9ae301e54bd5ce /design-documents/013-peer-to-peer-payments.rst
parenta4fd71e5e7c07b9b0f7ffbdee268e897e6091ead (diff)
downloaddocs-03eeb79192ceb55e01737640d0d59502b3c74ca0.tar.gz
docs-03eeb79192ceb55e01737640d0d59502b3c74ca0.tar.bz2
docs-03eeb79192ceb55e01737640d0d59502b3c74ca0.zip
merge Dold/Grothoff proposals for D13 into something coherent
Diffstat (limited to 'design-documents/013-peer-to-peer-payments.rst')
-rw-r--r--design-documents/013-peer-to-peer-payments.rst342
1 files changed, 162 insertions, 180 deletions
diff --git a/design-documents/013-peer-to-peer-payments.rst b/design-documents/013-peer-to-peer-payments.rst
index 89216449..64fe8a7f 100644
--- a/design-documents/013-peer-to-peer-payments.rst
+++ b/design-documents/013-peer-to-peer-payments.rst
@@ -31,177 +31,169 @@ Requirements
* The money received via a P2P payment must be usable for
further Taler payments with minimal delay.
-Proposed Solution (CG)
-======================
+New Terminology
+===============
-.. note::
+* An ``account`` is a non-expiring reserve for which entity knowing the
+ reserve private key has completed a KYC procedure sufficient to enable
+ receiving income under that address.
+* A ``pouch`` is a public-private key pair where the public key is
+ an exchange address from which any owners of an account
+ can pick up an amount left at a ``pouch`` assuming they know the pouches
+ private key.
+* A ``wad`` is an exchange-to-exchange wire transfer that wires money
+ into a group of accounts at the target exchange.
- The notion of ``pouch`` used in this proposal differs completely from
- the notion of ``pouch`` in the Dold approach. In this proposal,
- pouches are used to represent aggregated wire transfers combining
- multiple p2p payments between pairs of exchanges. WE NEED A BETTER
- WORD.
-A complete solution for customer-to-customer payments consists of three
-separate parts:
-
-1. The payee generates a ``payto://taler/$EXCHANGE_BASE_URL/$RESERVE_PUB``
- target address for which the payee knows the corresponding reserve
- private key. The parties must also create a fixed-form contract.
- The the contract must specify the amount, a nonce, the reserve public key,
- and may include further a **forgettable** details like a subject.
- The required information should still be sufficiently compact for a
- small QR code or NFC transmission.
-2. The payer then performs an ordinary ``/deposit`` operation.
-3. The exchange detects the use of the ``taler`` wire method, and if the base
- URL of the target exchange differs, initiates a wire transfer to the
- ``/wire`` endpoint of the target exchange. For this wire transfer,
- the wire transfer subject is set to provide the exchange base URL and
- a WTID as with other outgoing wire transfers. Aggregation is possible.
- An inbound wire transfer of this type creates a **pouch**.
-4. If the (aggregated) wire transfer fails (say the
- ``/wire`` endpoint does not resolve to a valid bank account, or
- the target exchange closed the pouch), the originating exchange
- automatically creates a full refund for the deposit (refund fees still
- apply).
-
- .. note::
+Proposed Solution
+=================
- While the refund **fee** can be reused, these types of refunds
- are not approved by a merchant's signature. Thus, we will need
- a new message type in the coin history to represent these events.
-
-5. When the exchange is requested to provide information about
- aggregated transfers under the WTID, it provides the contract's
- 512-bit hash and the amount.
-6. The exchange wire gateway is extended with a request to check the KYC
- status of a customer based on a RESERVE_PUB. Possible replies are
- in-progress, failed and succeeded. Failed KYCs ultimately result in
- pouches being closed. An in-progress status should be accompanied with
+A complete solution for customer-to-customer payments consists of three
+possible operational flows.
+
+
+Account creation and withdrawal
+-------------------------------
+
+1. The payee generates an account key, which also yields a
+ ``payto://taler/$EXCHANGE_BASE_URL/$ACCOUNT_PUB``
+ target address (for which the payee knows the corresponding
+ account private key).
+2. When withdrawing from an account, the exchange first checks if the
+ customer has satisfied the KYC requirements. If not, the consumer
+ is redirected to a Web page where they can perform the necessary
+ KYC operation.
+3. For this, the exchange wire gateway is extended with a request to
+ check the KYC status of a customer based on an ACCOUNT_PUB.
+ Possible replies are in-progress and succeeded. An in-progress
+ status should be accompanied with
information how the customer may complete the KYC check.
-
- .. note::
-
- If a target exchange closes a pouch, the closing fee
- applies for every non-merged contract hash associated with the pouch.
- Closing a pouch requires the target exchange to perform
- a wire transfer for each (non-merged) contract hash, using
- a truncated 256-bit contract hash for the wire transfer subject.
- That way, the originating exchange can refund the respective
- coins.
-
-7. A new exchange endpoint allows wallets to request a KYC for a
- RESERVE_PUB. Such a request may include the requirement to pay
- a KYC fee. The KYC fee may be charged to that reserve (if it exists),
- or could be waved if the reserve was established via a wire transfer
+4. A new exchange endpoint ``/account/$ACCOUNT_PUB/kyc``
+ allows wallets to request a KYC for an
+ ACCOUNT_PUB. Such a request may include the requirement to pay
+ a **KYC fee**. The KYC fee may be charged to that account (if it exists),
+ or could be waved if the account was established via a wire transfer
from a partner bank.
-8. When an exchange receives a wire transfer with an exchange base URL
- and a WTID (instead of a RESERVE_PUB), it performs a request to the
- ``/transfers/$WTID`` API of the originating exchange to obtain a
- list of contract hashes.
-9. The payee can try to merge incoming payments into a KYC'ed reserve by
- POSTing to a new ``/reserve/$RESERVE_PUB/merge`` endpoint.
- The POSTing must include a signature by the reserve private key
- over the 512-bit contract hash and the (maximally ``forgotten``)
- contract (so only nonce, amount and RESERVE_PUB are in the clear).
- By doing so, the receiver demonstrates knowledge of the full contract
- (the ``forgotten`` fields provide privacy for details irrelevant to
- the exchange).
-
- .. note::
-
- A possible optimization is to forgo including the reserve public key
- field in the transmitted exchange contract, as it is already in the URL;
- however, the RESERVE_PUB MUST be in a well-defined
- field of the contract when hashing the contract.
-
-10. If the exchange has received a matching inbound wire transfer, it adds the
- respective balance to the reserve's balance, allowing the KYC'ed customer
- to withdraw the funds. The new ``merge`` endpoint should also allow
- long-polling. Note that long-polling should be limited to short durations,
+5. If the account owner fails to perform the KYC check, the funds
+ in an account remain inaccessible. After a configurable duration,
+ the funds may be considered forfeit and become the property of
+ the exchange where the account is located.
+6. When requesting an account's history (which can get quite long),
+ the exchange only returns the last 3 months of data. Requesting
+ the full history requires paying an **account history fee**
+ (which is not done via a 402, but simply charged to the account
+ when requested; full account histories for accounts with an
+ insufficient balance cannot be requested -- except of course
+ the wallet could simply top up the account balance first, see below).
+
+7. If the exchange has received a **deposit** or **merge** into an
+ account, or received an inbound wire transfer from a **wad**
+ matching the account (see below), it adds the respective amount(s)
+ to the account's balance, allowing the KYC'ed customer to withdraw
+ the funds.
+8. The account history endpoint should also allow long-polling.
+ Note that long-polling should be limited to short durations,
as inbound transfers via ``taler-exchange-wirewatch`` cannot cause the long
polling to be resumed, only transfers within the same exchange can benefit
from long polling acceleration.
-Proposed Solution (Dold)
-========================
-
-A complete solution for customer-to-customer payments consists of three
-separate parts:
-
-1. The mechanism whereby coins are deposited into some address
- associated with the receiver.
-2. A mechanism to ensure that the receiver of a customer-to-customer
- payment has undergone a KYC check.
-3. If more than once exchange is involved, there must be a real-time
- settlement layer between involved exchanges.
+Payment into an unknown account
+-------------------------------
+
+1. If the payer does not know the payee's account, they can create
+ a **purse** by computing a public-private key pair.
+2. The payer then uses the ``/depost`` API to deposit coins into
+ the purse, using ``payto://taler/$PURSE_PUB`` as the target
+ address. Note that the lack of a hostname indicates that the
+ target address is a purse.
+3. The payer shares the purse's private key and the base URL
+ of the exchange where the purse was created with the payee.
+ This can be done using a ``taler://purse/BASE_URL/$PURSE_PRIV`` URL.
+4. The payee uses the new ``/purse/$PURSE_PUB`` endpoint to retrieve
+ the purse history, which includes all deposits and withdrawals
+ involving the purse.
+5. The payee can then POST to ``/purse/$PURSE_PUB/merge`` a
+ request signed by the purse's private key to **merge** the
+ funds into an account. The signature is only over a salted
+ hash of the account public key, thus avoiding disclosure of
+ the account public key in the purse history. The exchange
+ processes the merge request akin to the logic for payments
+ into known accounts, as detailed below, except that no
+ **deposit fees** are charged at this time. The exchange
+ confirms the merge, allowing the payee to instantly affirm
+ to the user that the amount is inbound (even if it may not
+ be instantly available).
+
+
+Payment directly into a known account at the same exchange
+----------------------------------------------------------
+
+1. If the payer knows the payee's account and uses the same exchange,
+ they may perform an ordinary ``/deposit`` operation, paying
+ the usual **deposit fee**.
+2. The exchange detects the use of the ``taler`` wire method, and
+ directly credits the target account.
+
+
+Payment into known account at a remote exchange
+-----------------------------------------------
+
+1. If the payer knows the payee's account and uses a different exchange,
+ they POST the coins to a new ``/wad/MASTER_PUB`` endpoint using the master
+ public key of the target exchange, including a deposit permission,
+ the base URL of the target exchange, and the target account,
+ paying a **deposit fee** and a new **wad fee**. The **wad fees** can
+ be used to cover the cost of the exchange-to-exchange wire transfer.
+2. The payer's exchange creates a **wad** grouping all wad requests, executing
+ the transaction when either the **wad threshold** (maximum number
+ of transactons aggregated per wad) or the **wad delay** (maximum
+ delay for transfers) has been reached.
+3. If the (aggregated) wire transfer fails (say the
+ ``/wire`` endpoint of the payee exchange does not
+ resolve to a valid bank account), the
+ originating exchange automatically creates a full refund for
+ all aggregated deposits and **purses** (**refund fees** apply).
-Customer-to-customer Deposits
------------------------------
-
-The payer deposits coins (via the existing /deposit protocol) into a
-``payto://taler-p2p-pouch/$POUCH_PUB`` address. The exchange handles this
-deposit by internally transfering the money to a "pouch" identified by the
-pouch public key (``$POUCH_PUB``).
-
-Once a pouch has been funded, the payer can additionally attach some meta-data
-(e.g. remittance information) to the pouch.
-
-The payee claims the payment by transfering funds from the (anonymous) pouch
-into a KYCed reserve (also called a "bound reserve", as it is bound to
-personally identifying information of the owner") that belongs to the payee.
-
-Alternatively the payee can also choose to receive the funds on their bank
-account, simply by providing their bank account (as a payto URI) in the pouch
-claiming request.
-
-The exchange needs a new endpoint for this:
-
-::
-
- POST {exchangeBaseUrl}/pouches/$POUCH_PUB/claim
- Request:
- {
- bound_reserve_exchange: "..."
- bound_reserve_pub: "..."
- }
- Response:
- {
- amount: "...",
- }
-
-Note that the bound reserve might exist at a different exchange.
-
-Bound Reserves
---------------
-
-A bound reserve is a reserve that is associated with personally identifyable
-information of the customer.
-
-A bound reserve is created by depositing small cover fee into it and then going
-through an exchange-specific KYC process. If an exchange is operated by a bank
-that a customer already has a business relationship with, the bank might
-automatically provide a bound reserve for that customer.
+ .. note::
-To prevent abuse of bound reserves (in the form of multiple parties exchanging
-funds via shared access to a bound reserve), the following measures can be
-taken:
+ While the **refund fee** amount can be reused, these types of refunds
+ are not approved by a merchant's signature. Thus, we will need
+ a new message type in the coin history to represent these events.
-* Creation of additional bound reserves per customer can
+4. The payee's exchange observes the wire transfer and uses a GET
+ ``/wad/{MASTER_PUB}/{WTID}`` request to obtain details about the target
+ accounts.
+5. When the payer's exchange is requested to provide information about
+ aggregated transfers under the WTID, it provides a signed list of
+ account public keys and associated amounts that must add up to an
+ amount below the total amount transferred. If they do not, the
+ payee's exchange does not credit any of the accounts and instead
+ preserves the bogus reply (to justify its inaction with its own
+ auditor) and reports the issue to the auditor of the payer's exchange
+ (keeping the received funds for future manual resolution).
+6. ``taler-exchange-wirewatch`` and the Taler wire gateway API will
+ need to be extended to allow passing inbound wire transfers with WTID
+ and exchange base URL to the exchange. Furthermore, another tool
+ is needed to lookup the **wad** data at remote exchanges.
+
+
+Additional considerations
+-------------------------
+
+* Creation of additional accounts per customer can
be discouraged by asking for higher fees.
* The global transaction volume of one customer can be easily
determined by authorities, which can then trigger further audits
of the customer
* As a technically expensive but more water-tight measure, normal
- withdrawals from bound reserves could be disallowed. Instead,
+ withdrawals from reserves could be disallowed. Instead,
a modified refresh protocol could ensure that whoever has knowledge
- of the reserve private key can also learn the private keys
- of coins withdrawn from that reserve.
+ of the account private key can also learn the private keys
+ of coins withdrawn from that account, thereby removing
+ Taler's "one-hop withdrawal loohole".
-Bound reserves could also be used to remove Taler's "one-hop withdrawal
-loohole".
Alternatives
============
@@ -215,52 +207,42 @@ Alternatives
2. The payment information would be rather large, making it difficult
to transfer via a QR code or short text message.
+* Account history exceeding a configurable time limit (like 6 years)
+ could be subject to garbage collection. However, doing so may be difficult to
+ square with onboarding new auditors in the presence of existing
+ accounts, as the auditors could then not reconstruct the account
+ balances from cryptographic proofs.
-Drawbacks (Dold)
-================
-
-* pouches introduce new 'pouch' loophole, which could allow a customer
- to collect 'income' into a pouch and then 'pay' a merchant by allowing
- the merchant to empty the pouches.
-* The exchange needs to be extended with customer-to-customer pouches (probably
- the easy part) and bound reserves (possibly falls into the responsibility of
- LibEuFin).
-* error handling (failure in exchange-to-exchange wire transfer,
- failure to drain reserve, etc) is unclear from the proposal. Can money get
- lost in the case of failures (bad keys, failed KYC)?
-
+* Accounts without KYC check could be eventually closed. However,
+ even if the coins used to fill the account are refunded, it
+ would be difficult to inform the originating wallet that the
+ coins have received a refund. Thus, it is likely simpler to
+ declare the funds forfeit.
-Drawbacks (Grothoff)
-====================
+Drawbacks
+=========
The overall changes required are not small:
-* New KYC fee required in ``/keys`` endpoint (similar to closing and wire fees),
- requires extensive work across toolchain (offline signature, etc.)
+* New **KYC fee**, **wad fee** and **account history fee**
+ required in ``/keys`` endpoint (similar to closing and wire fees),
+ requires some work across toolchain (offline signature, etc.)
* New ``taler`` wire method needs special case to possibly bypass
(same exchange scenario, with long-poll trigger) the usual aggregation logic.
-* New exchange table(s) required to store inbound amounts by contract hash.
- Maybe two tables, one for local exchange p2p and one for remote exchange p2p
+* New exchange table(s) required to store inbound amounts by account.
+ Likely two tables, one for local exchange p2p and one for remote exchange p2p
payments.
* New exchange table for pouches required (for remote p2p payments).
* New exchange logic required to make ``transfers`` requests for pouches
(another separate process).
-* New ``/reserve/$RESERVE_PUB/kyc`` endpoint required.
-* New ``/reserve/$RESERVE_PUB/merge`` endpoint required.
-* New type of reserve history entries required (``merge``).
+* New ``/account/$ACCOUNT_PUB/kyc`` endpoint required.
+* New ``/purse/$PURSE_PUB/merge`` endpoint required.
* Additional tables to be verified by the auditor.
-* ``taler-exchange-closer`` needs additional logic to ``close`` pouches.
* ``taler-exchange-wirewatch`` needs to support receiving pouch closures
and exchange-to-exchange wire transfers with WTIDs.
-* A new type of ``refund`` (better name needed) is required to handle
- coins re-gaining value from closed pouches.
Aside from implementation complexity, the solution has the following drawbacks:
-* We have no good way to determine that a p2p payment failed and that the
- wallets should try to refresh the spent coin to get the ``refund``.
- Wallets will have to basically 'probe' for a plausible time period to
- recover funds from failed p2p payments. Alternatively, we may create a
- special URI that the payee wallet will generate to inform the payer
- about failed p2p payments. Alas, that seems to not be very user-friendly.
+* If a p2p payment failed (say the receiver lost the account private key),
+ the customer's money can be forfeit.