diff options
authorChristian Grothoff <>2021-01-20 22:19:11 +0100
committerChristian Grothoff <>2021-01-20 22:19:11 +0100
commit2746d09ef06cc06581f5448727ed8bd8d47706ed (patch)
parent93a3b61d241b20e36f7303bbba90c82f609ce1f6 (diff)
working on DD13
1 files changed, 145 insertions, 9 deletions
diff --git a/design-documents/013-peer-to-peer-payments.rst b/design-documents/013-peer-to-peer-payments.rst
index c5e529d..8921644 100644
--- a/design-documents/013-peer-to-peer-payments.rst
+++ b/design-documents/013-peer-to-peer-payments.rst
@@ -11,8 +11,8 @@ Motivation
To be usable as an electronic payment system with cash-like properties,
-customers should be able to transfer money between themselves without any
-external provider.
+customers should be able to transfer money between themselves without
+needing to setup anything beyond their wallet(s).
@@ -23,15 +23,109 @@ Requirements
direct communication channel between payer and payee should be required.
* This customer-to-customer payment must be possible without trusting the other
party beyond the point where the money has been received by the payee. Thus,
- sharing of coin private keys is not sufficient.
+ sharing of coin private keys is not sufficient, we need transactional semantics
+ resulting in exclusive control over the funds by the recipient.
* The P2P payment protocol must not allow users to circumvent income
transparency. That is, each P2P transaction must be visible
on a KYCed transaction ledger (such as a bank account).
* The money received via a P2P payment must be usable for
further Taler payments with minimal delay.
-Proposed Solution
+Proposed Solution (CG)
+.. note::
+ 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
+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::
+ 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
+ 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
+ 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,
+ 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:
@@ -39,8 +133,8 @@ 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 must have undergone a KYC check.
-3. If more than once exchange should be supported, there must be a real-time
+ 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.
@@ -122,9 +216,51 @@ Alternatives
to transfer via a QR code or short text message.
+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
+* 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)?
+Drawbacks (Grothoff)
+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 ``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
+ 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``).
+* 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.