diff options
author | Christian Grothoff <christian@grothoff.org> | 2021-01-29 21:05:15 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2021-01-29 21:05:15 +0100 |
commit | 03eeb79192ceb55e01737640d0d59502b3c74ca0 (patch) | |
tree | a2d90a7af3dcae3d75736028fe9ae301e54bd5ce /design-documents/013-peer-to-peer-payments.rst | |
parent | a4fd71e5e7c07b9b0f7ffbdee268e897e6091ead (diff) | |
download | docs-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.rst | 342 |
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. |