013-peer-to-peer-payments.rst (54011B)
1 .. _dd-13: 2 3 DD 13: Wallet-to-Wallet Payments 4 ################################ 5 6 :Design status: Accepted 7 :Implementation status: Implemented 8 :DD shepherd: TBD 9 :Historical contributors: Florian Dold, Christian Grothoff, Sebastian 10 :First published: 2021-01-18 11 :Last substantive change: 2022-06-03 12 :Implementation evidence: exchange (2022-03-20, 2022-03-24), taler-typescript-core (2022-07-12, 2022-08-23) 13 :Normative references: :doc:`../core/api-exchange`, :doc:`../wallet/wallet-core`, :doc:`037-wallet-transactions-lifecycle` 14 15 Summary 16 ======= 17 18 .. note:: 19 20 This document includes historical protocol sketches followed by later 21 refinements. The current exchange and wallet APIs are authoritative. 22 23 This design document proposes an extension of the Taler protocol that allows 24 payments from wallet-to-wallet without a merchant. 25 26 27 Motivation 28 ========== 29 30 To be usable as an electronic payment system with cash-like properties, 31 customers should be able to transfer money between themselves without 32 needing to setup anything beyond their wallet(s). 33 34 This will be used for payments via e-mail and other messaging apps, as well as 35 possibly for transfers via NFC/QR code between mobile phones. 36 37 Invoice Flow User Experience 38 ---------------------------- 39 40 .. graphviz:: 41 42 digraph invoice { 43 ranksep="0.5" 44 { rank = same; "inbox"; "begin"; } 45 { rank = same; "sending"; "receiving2"; } 46 { rank = same; "receiving"; "paying"; } 47 { rank = same; "mid"; "midbox"; } 48 { rank = same; "body"; "amount"; } 49 begin [label="Payer Inbox",shape=box]; 50 body [label="compose\nE-mail message"]; 51 amount [label="specify\ninvoice details"]; 52 receiving [label="receiving...",shape=diamond]; 53 sending [label="transmitting...",shape=diamond]; 54 mid [label="Payee Inbox",shape=box]; 55 notified [label="Notification:\npayment received"]; 56 end [label="Payee Inbox",shape=box]; 57 begin -> body [label="(1) new"]; 58 body -> amount [label="(2) attach invoice"]; 59 amount -> body [label="(3) Ok"]; 60 body -> sending [label="(4) send"]; 61 sending -> mid [style=dashed]; 62 mid -> receiving [style=dashed]; 63 receiving -> notified [style=dashed]; 64 notified -> end [label="(9) Acknowledge"]; 65 inbox [label="Payer Inbox",shape=box]; 66 receiving2 [label="receiving...",shape=diamond]; 67 midbox [label="Payer Inbox",shape=box]; 68 open [label="message with\nattached invoice"]; 69 confirm [label="review invoice"]; 70 paying [label="paying...", shape=diamond]; 71 paid [label="message with\npaid invoice"]; 72 finbox [label="Payer Inbox",shape=box]; 73 inbox -> receiving2 [style=dashed]; 74 receiving2 -> sending [label="Internet\n(pEp)",style=dashed,dir=back]; 75 receiving2 -> midbox [style=dashed]; 76 midbox -> open [label="(5) select message"]; 77 open -> confirm [label="(6) view invoice"]; 78 confirm -> paying [label="(7) pay"]; 79 paying -> paid [style=dashed]; 80 paid -> finbox [label="(8) back"]; 81 paying -> receiving [style=dashed, label="Internet\n(Taler)"]; 82 } 83 84 Donation Flow User Experience 85 ----------------------------- 86 87 .. graphviz:: 88 89 digraph donation { 90 ranksep="0.5" 91 { rank = same; "inbox"; "begin"; } 92 { rank = same; "sending"; "receiving2"; } 93 { rank = same; "body"; "amount"; } 94 { rank = same; "mid"; "midbox"; } 95 { rank = same; "accepting"; "timeout"; "receiving"; } 96 begin [label="Donor Inbox",shape=box]; 97 body [label="compose\nE-mail message"]; 98 amount [label="specify\npayment details"]; 99 receiving [label="receiving...",shape=diamond]; 100 timeout [label="timeout...",shape=diamond]; 101 sending [label="transmitting...",shape=diamond]; 102 mid [label="Donor Inbox",shape=box]; 103 notified [label="Notification:\npayment confirmed"]; 104 notified2 [label="Notification:\npayment refunded"]; 105 end [label="Donor Inbox",shape=box]; 106 begin -> body [label="(1) new"]; 107 body -> amount [label="(2) attach payment"]; 108 amount -> body [label="(3) Ok"]; 109 body -> sending [label="(4) send"]; 110 sending -> mid [style=dashed]; 111 mid -> receiving [style=dashed]; 112 receiving -> notified [style=dashed]; 113 mid -> timeout [style=dashed]; 114 timeout -> notified2 [style=dashed]; 115 notified -> end [label="(9a) Acknowledge"]; 116 notified2 -> end [label="(9b) Acknowledge"]; 117 inbox [label="Recipient Inbox",shape=box]; 118 receiving2 [label="receiving...",shape=diamond]; 119 midbox [label="Recipient Inbox",shape=box]; 120 open [label="message with\nattached payment"]; 121 confirm [label="accept payment?"]; 122 accepting [label="accepting...", shape=diamond]; 123 paid [label="message with\naccepted payment"]; 124 finbox [label="Recipient Inbox",shape=box]; 125 inbox -> receiving2 [style=dashed]; 126 receiving2 -> sending [label="Internet\n(pEp)",style=dashed,dir=back]; 127 receiving2 -> midbox [style=dashed]; 128 midbox -> open [label="(5) select message"]; 129 open -> confirm [label="(6) review payment details"]; 130 confirm -> accepting [label="(7) yes"]; 131 accepting -> paid [style=dashed]; 132 paid -> finbox [label="(8) back"]; 133 accepting -> receiving [style=dashed, label="Internet\n(Taler)"]; 134 } 135 136 Requirements 137 ============ 138 139 * The protocol must permit transacting arbitrary amounts in any currency, 140 as long as the exchanges involved support the necessary purse and partner 141 operations. 142 * The control data for wallet-to-wallet payments should be small 143 enough to fit into a QR code or short message (so ideally less than 64 bytes). 144 * No other direct communication channel between payer and payee should 145 be required. 146 * The wallet-to-wallet payment must be possible without trusting the other 147 party beyond the point where the money has been received by the payee. Thus, 148 sharing of coin private keys is not sufficient, we need transactional semantics 149 resulting in exclusive control over the funds by the recipient. 150 * The wallet-to-wallet payment protocol must not allow users to circumvent income 151 transparency. That is, each wallet-to-wallet transaction must be visible 152 on a KYCed transaction ledger (such as a bank account). 153 * The money received via a wallet-to-wallet payment must be usable for 154 further Taler payments with minimal delay (after KYC). 155 * It must still be possible to associate payments with a contract that is 156 effectively (alas not necessarily directly) signed by both parties: 157 the payer with the coin private keys, and the payee with their KYC'ed 158 account private key. 159 * The contract must be able to satisfy laws like the German TSE law, 160 which implies that the payer must be able to obtain a payment receipt. 161 * Two payment scenarios must be possible: (1) one where the payee first 162 transmits a proposal to the payer (request-to-pay) that the payer 163 accepts by making the payment, and (2) completely uni-directional 164 payments where the payer includes a proposal with the payment and the 165 payee accepts the proposal by taking the offered payment. 166 * If the payment fails (i.e. the receiver refuses to accept the money 167 or the message is lost), the payer must automatically recover the 168 funds (minus applicable fees) without the need for further communication. 169 * If funds flow back to the payer due to an aborted payment, it must be 170 provable for the payer that these funds were not income but merely an aborted 171 transaction. Furthermore, in this case, no KYC should be required from the 172 payer. 173 * If a payment would partially succeed, i.e. because the payer inadvertently 174 used some double-spent coins and some valid coins, this must fail before the 175 uni-directional communication and be correctable payer-side. In other words, 176 the actual payment must be atomic. 177 * The usual properties of Taler (everything auditable, unlinkability, 178 high-performance in terms of CPU, bandwidth, latency, storage 179 requirements, and the ability to levy fees on every operation that 180 is costly for the exchange) need to be preserved. 181 * The system must handle the case where a customer no longer intends to 182 use the KYCed account (due to disuse, death, or key compromise). 183 184 185 186 New Terminology 187 =============== 188 189 * An ``account`` is a non-expiring reserve for which entity knowing the 190 reserve private key has completed a KYC procedure sufficient to enable 191 receiving income under that address. 192 * A ``purse`` is a public-private key pair where the public key is 193 an exchange address from which any owners of an account 194 can ``merge`` the amount left at a ``purse`` into their 195 account balance assuming they know the purse private key. 196 * A ``wad`` is an exchange-to-exchange wire transfer that wires money 197 into a group of accounts at the target exchange. 198 199 200 Proposed Solution 201 ================= 202 203 Principles 204 ---------- 205 206 * Purses are ephemeral and only serve for one transaction. 207 * The purse's transaction amount is fixed when the purse is created, and 208 specified together with the maximum deposit fee acceptable to the payee. 209 Deposit fees exceeding this limit must be paid by the payer. 210 * Each purse is associated with a contract terms hash and an expiration date. 211 * The contract is optionally stored encrypted at the exchange. 212 The contract must be encrypted to the purse private key. 213 An additional ephemeral public key (for DH encryption) should be 214 part of the POSTed payload. 215 * The exchange deletes the encrypted contract at this expiration date. 216 * The exchange may limit the encrypted contract size and storage duration. 217 * Either payer or payee can create the purse and associate it with the contract. 218 * By merging the purse into the account, the payee accepts the contract. 219 * By paying the purse to the designated amount, the payer accepts the contract. 220 * Until the purse is fully paid, the payer can abort the payment. 221 * The exchange may charge a **purse fee** for managing the purse, but we 222 want most scenarios to not require it to be effectively charged. 223 * By associating a purse with an account upon creation, the purse fee can be 224 made optional for account holders as long as the number of purses created 225 per account is below a configurable threshold. 226 * By charging the purse fee only in case the payee did **not** merge the 227 purse into their account, the purse fee can be limited for payers to 228 the case where they are receiving a refund --- and here it could be 229 then entirely avoided if the refund fee is non-zero. 230 231 232 W2W Payment Metadata 233 -------------------- 234 235 The standard Taler Customer-to-Merchant payments always use a contract terms 236 JSON object to record the modalities of the payment and the resulting 237 obligations of a successful payment. 238 239 The contract terms concept does not directly carry over to W2W payments, 240 because: 241 242 * Either party may initiate the payment. 243 * The payee does not have a merchant public key, and 244 at the time of payment initiation, the payee account might not yet 245 be known. 246 * There is no nonce that the customer generates and uses to prove that they 247 uniquely "own" the contract terms. 248 * There is no negotiation of trusted auditors / exchanges possible. 249 250 As a result, some of the existing fields of the contract terms no longer apply 251 to wallet-to-wallet payments. 252 253 Contract metadata for W2W payments can be exchanged in three ways: 254 255 1. Inline, as part of the payment request / payment offer. In this case, 256 both parties are already aware of the contract's contents and 257 the exchange's contract exchange facility is simply not used. 258 2. The payee can create a **purse** and immediately associate it with 259 an **account** by sending a signed **merge** request together with 260 the (encrypted) contract. 261 262 a. The purse creation request created by the payee must include a 263 signature with the account private key of the payee signing the purse 264 public key and the hash of the contract, thereby affirming that 265 the contract was pre-approved by the account owner. 266 b. The exchange may wave the purse fee for a certain number of 267 active purses per account. Additional purses can be purchased 268 by paying the **purse fee**. 269 3. The payer can store a contract with the exchange by POSTing 270 an encrypted contract to the exchange as part of creating a **purse**. 271 272 a. The exchange charges the **purse fee** to payers for purses that 273 are refunded after not being **merged**. 274 b. When paying into a purse, the coin signature includes the purse 275 public key, the contract hash and the desired expiration date 276 (how long a merge is allowed). 277 c. Payment offers are not allowed if the amount transacted is below 278 the purse fee. 279 d. The exchange auto-refunds coins in **purses** with deposits 280 matching expired contracts. 281 282 .. note:: 283 284 While the **refund fee** amount can be reused, these types of refunds 285 are not approved by a merchant's signature. Thus, we will need 286 a new message type in the coin history to represent these events. 287 288 289 Account creation 290 ---------------- 291 292 An account is simply a reserve that has been subjected to 293 KYC. A reserve that has seen a purse merged into it must 294 be upgraded to an account before further withdraw (or close) 295 operations are allowed. The usual closure deadline for a 296 reserve is extended to the KYC deadline. 297 298 1. The payee generates a reserve key, which also yields a 299 ``payto://taler/$EXCHANGE_BASE_URL/$RESERVE_PUB`` 300 target address (for which the payee knows the corresponding 301 reserve private key). 302 2. When withdrawing from a reserve that has experienced 303 merge operations and thus must be an account, the exchange 304 first checks if the customer has satisfied the KYC requirements. 305 If not, the customer is redirected to a Web page where they 306 can perform the necessary KYC operation. 307 3. For this, the exchange wire gateway is extended with a request to 308 check the KYC status of a customer based on an ``RESERVE_PUB``. 309 Possible replies are ``in-progress`` and ``succeeded``. 310 An ``in-progress`` status should be accompanied with 311 information how the customer may complete the KYC check. 312 4. A new exchange endpoint ``/reserves/$RESERVE_PUB/kyc`` 313 allows wallets to request a KYC for a 314 ``$RESERVE_PUB``. Such a request may include the requirement to pay 315 a **KYC fee**. 316 The KYC fee may be charged to the reserve (a sufficient 317 balance can be provided by the wallet by creating a purse 318 and merging the purse with the reserve, if needed), 319 or could be waved if the reserve was established via a wire transfer 320 from a partner bank where KYC is free. For this, the Wire 321 gateway API is extended with a flag that informs the exchange 322 that the incoming wire transfer implies a free KYC check. 323 5. If the account owner fails to perform the KYC check, all funds 324 in a reserve remain inaccessible. After a configurable duration, 325 the funds may be considered forfeit and become the property of 326 the exchange where the reserve is located. 327 6. The exchange may charge an annual **account fee**, and can 328 close accounts where the account balance is insufficient to 329 cover the account fee. 330 331 332 Withdrawing from accounts 333 ------------------------- 334 335 1. When requesting an account's history (which can get quite long), 336 the exchange only returns the last 3 months of data. Requesting 337 the full history requires paying an **account history fee** 338 (which is not done via a 402, but simply charged to the account 339 when requested; full account histories for accounts with an 340 insufficient balance cannot be requested -- except of course 341 the wallet could simply top up the account balance first, see below). 342 2. If the exchange has **merged** a **purse** into an account, or 343 received an inbound wire transfer from a **wad** matching the 344 account (see below), it adds the respective amount(s) to the 345 account's balance, allowing the KYC'ed customer to withdraw the funds, 346 similar to withdrawals from a reserve. 347 3. The account history endpoint should also allow long-polling. 348 Note that long-polling should be limited to short durations, 349 as inbound transfers via ``taler-exchange-wirewatch`` cannot cause the long 350 polling to be resumed, only transfers within the same exchange can benefit 351 from long-polling acceleration. 352 353 354 Account deletion 355 ---------------- 356 357 1. A reserve owner can delete a reserve by signing a deletion message 358 with the reserve private key. 359 2. This basically resets the KYC data at the exchange, preventing 360 further use of the account. This is helpful in case a user is 361 concerned about having 362 accidentally disclosed the reserve private key to a third party. 363 3. If funds remain in the reserve, the exchange will close the 364 reserve and wire the funds to the associated bank account. 365 If no bank account is associated with the reserve, 366 an error message is generated instead. The 367 user can pass an extra override parameter to delete reserves 368 even if they still contain funds. 369 4. A related endpoint should exist for the exchange operator, possibly 370 using messages signed with a new exchange management key. 371 This could be useful in case customers die or are otherwise 372 in need for manual intervention that requires an account to 373 be deleted. In this case, 374 remaining funds in the account should be wired to a bank account 375 designated in the message with the management signature. The audit 376 report should contain a special note for all of these types of 377 account deletions. 378 379 380 381 Payment offers 382 -------------- 383 384 In this protocol variant, the payer is initiating the process. 385 386 1. The payer creates a **purse** by computing a public-private key pair. 387 2. The payer POSTs to the ``/purses/$PURSE_PUB/create`` endpoint to create the 388 purse, deposit coins and optionally upload the encrypted contract terms. 389 The deposit signatures should use ``payto://taler/$PURSE_PUB`` 390 as the target address and signing over the ``$CONTRACT_HASH`` as 391 usual in deposit operations. Note that the lack of a hostname 392 indicates that the target address is a local purse. 393 3. The payer shares the contract private key and the base URL 394 of the exchange where the purse was created with the payee. 395 This is represented by a 396 ``taler://pay-push/$BASE_URL/$CONTRACT_PRIV`` URI in the implemented 397 protocol. 398 The chapter on ``Refinements`` below clarifies why this 399 step is not quite OK and was modified when implementing the design. 400 4. The payee uses ``/contracts/$CONTRACT_PUB`` to retrieve the encrypted 401 contract and ``/purses/$PURSE_PUB/deposit`` to retrieve the purse status, 402 including its balance. 403 5. The payee's wallet must ensure that either: 404 405 a. The purse has an attached encrypted contract terms, the contract 406 terms can be decrypted and are valid, and their hash matches the contract 407 terms hash of the purse. 408 b. The wallet received detached contract terms, and their hash matches 409 contract terms of the purse. 410 411 If neither case applies, the payee's wallet must reject the payment. 412 6. The payee can then POST to ``/purses/$PURSE_PUB/merge`` a 413 request signed by the merge private key to **merge** the 414 funds into an account. A second signature must be provided 415 by the account private key, signing the ``$CONTRACT_HASH`` thereby 416 affirming that the payee accepted the contract. 417 The account is of the form ``payto://taler/$EXCHANGE_BASE_URL/$ACCOUNT_PUB``. 418 7. Processing continues depending on the location of the account: 419 420 a. If the ``$EXCHANGE_BASE_URL`` matches the local exchange, then 421 the exchange processes the **merge** request akin to the logic 422 for payments into known accounts, as detailed above. 423 b. If the ``$EXCHANGE_BASE_URL`` does not match the local exchange, 424 a **wad fee** is charged, and the remaining amount is placed into a **wad** 425 to inform the target exchange, as detailed below. Wad fees may be covered 426 by the merchant, just like deposit fees, depending on the contract. 427 8. The exchange confirms the merge (per response to the **merge** request). 428 This allows the payee software to instantly 429 affirm to the users that the transaction is final (even if it may not 430 be instantly available to the payee if the payee did not complete the 431 KYC process for the account). 432 9. The payer uses the GET ``/purses/$PURSE_PUB/merge`` endpoint 433 to obtain the receipt from the payee (in the form of the 434 **merge** signature). Query parameters are used to avoid 435 downloading the (already known) encrypted contract and the 436 deposit operations. Long-polling must also be possible for 437 this request. 438 439 440 441 Payment requests 442 ---------------- 443 444 1. The payee creates a **purse** by computing a public-private key pair. 445 2. The payee POSTs to the ``/reserves/$RESERVE_PUB/purse`` endpoint to 446 create the purse, upload the encrypted contract, associate it with the 447 payee's account and signal its agreement to the contract. The request 448 includes signatures made with the purse, merge and account private keys. 449 3. The payee provides a 450 ``taler://pay-pull/$BASE_URL/$CONTRACT_PRIV`` URI to the payer. 451 4. The payer computes the corresponding public keys and uses 452 ``/contracts/$CONTRACT_PUB`` to retrieve the encrypted contract and 453 ``/purses/$PURSE_PUB/merge`` to retrieve the merge status, which signifies 454 that the payee would agree to the contract. 455 5. The payer software decrypts the encrypted contract using the purse private 456 key and the payer accepts the contract in the user interface. 457 6. Processing continues depending on the source of the coins: 458 459 a. If the payer's coins originate from the same exchange, the 460 payer software POSTs to the ``/purses/$PURSE_PUB/deposit`` endpoint to 461 deposit coins into the purse. The deposit signatures should use 462 ``payto://taler/$PURSE_PUB`` 463 as the target address and signing over the ``$CONTRACT_HASH`` as 464 usual in deposit operations. Note that the lack of a hostname 465 indicates that the target address is a local purse. 466 b. If the payer's coins originate from another exchange, the 467 payer software deposits the coins at the originating exchange 468 using the traditional ``/deposit`` endpoint and a target account of the form 469 ``payto://taler/$EXCHANGE_BASE_URL/$ACCOUNT_PUB``. In this case, 470 the remote exchange charges a **wad fee** and places the remaining 471 amount into a **wad** to inform the target exchange, as detailed below. 472 7. The exchange confirms the deposit. This allows the payer software to instantly 473 affirm to the users that the transaction is final, or to abort or try again 474 in case of errors. 475 8. The payee uses the GET ``/purses/$PURSE_PUB/deposit`` endpoint (possibly with long-polling) 476 to be notified about the successful deposit and subsequent completion of the 477 **merge** request. 478 479 480 Payment into accounts at remote exchanges 481 ----------------------------------------- 482 483 In case the coins and the accounts in the transaction flows above are at 484 different exchanges, an aggregated exchange-to-exchange payment (short 485 **wad**) is used. 486 487 1. Exchanges specify a new **wad fee** that they charge for exchange-to-exchange 488 payments. They also specify their wad policy, that is how often they 489 perform exchange-to-exchange transfers. 490 491 .. note:: 492 493 We may want to consider allowing for different wad-speed levels, where 494 express payments (without aggregation) are allowed in return for higher 495 wad fees. 496 497 2. The payer's exchange creates a **wad** by grouping all wad requests 498 to the same target exchange. It executes 499 the transaction when either the **wad threshold** (maximum number 500 of transactons aggregated per wad) or the **wad delay** (maximum 501 delay for transfers) has been reached. 502 3. If the (aggregated) wire transfer fails (say the 503 ``/wire`` endpoint of the payee exchange does not 504 resolve to a valid bank account), the 505 originating exchange automatically creates a full refund for 506 all involved coins (**refund fees** apply). 507 508 .. note:: 509 510 While the **refund fee** amount can be reused, these types of refunds 511 are not approved by a merchant's signature. Thus, we will need 512 a new message type in the coin history to represent these events. 513 514 4. The payee's exchange observes the wire transfer with a wire transfer 515 subject with the originating exchange base URL and a ``$WATID``, 516 and uses a GET ``/wad/$WATID`` request to obtain 517 details about the target accounts. 518 5. When the payer's exchange is requested to provide information about 519 aggregated transfers under the ``$WATID``, it provides a signed list of 520 account public keys and associated amounts that must add up to an 521 amount below the total amount transferred. If they do not, the 522 payee's exchange does not credit any of the accounts and instead 523 preserves the bogus reply (to justify its inaction with its own 524 auditor) and reports the issue to the auditor of the payer's exchange 525 (keeping the received funds for future manual resolution). 526 6. ``taler-exchange-wirewatch`` and the Taler wire gateway API will 527 need to be extended to allow passing inbound wire transfers with ``$WATID`` 528 and exchange base URL to the exchange. Furthermore, another tool 529 is needed to lookup the **wad** data at remote exchanges. 530 7. If the payee trusts the originating exchange, it may consider the 531 transaction ``final`` once the originating exchange has affirmed the 532 deposit (assuming the payer has a way to submit the evidence of that 533 payment, which may not apply in uni-directional scenarios). 534 Otherwise, the payee may simply only trust its own exchange, 535 resulting in the transfer only being considered final after the 536 receiving exchange has confirmed that the **wad** has arrived. 537 538 539 Examples 540 --------- 541 542 Cross-exchange W2W payment request: 543 544 * Bob borrowed 15 EUR from Alice to buy a train ticket. A few days later, 545 Alice wants her money back. She creates a request for payment in her wallet. 546 The wallet creates a purse for 15 EUR at the only exchange that Alice is currently 547 using. The wallet shows her a 548 ``taler://pay-pull/{EXCHANGE_URL}/{CONTRACT_PRIV}`` 549 link that she can share with Bob. Bob receives the link and opens it with 550 his Taler wallet. Bob is using a different EUR exchange than Alice. Bob's 551 wallet makes a ``/deposit`` request to his own exchange. Shortly after, Alice's 552 exchange receives the wad from Bob's exchange, and credits the money into 553 Alice's purse. 554 555 * Q: How does Bob find out if Alice's exchange supports a wad transfer from 556 Bob's exchange? A: This needs to be part of the wad policy. 557 * Q: How does Bob get a "receipt" to prove that he paid Alice? 558 A: He has Alice's account public key and the associated signature 559 chain leading to her payment request. If he paid someone else by accident, 560 the KYC of Alice's exchange could be used to find out who received the funds. 561 562 Cross-exchange W2W payment offer: 563 564 * Carol wants to send some money to Dave as a birthday gift. Carol knows that 565 Dave is using Taler, but she does not know which exchange he is using. She 566 opens her Taler wallet and initiates a P2P payment. She sends the resulting 567 ``taler://pay-push/{EXCHANGE_URL}/{CONTRACT_PRIV}`` in an e-mail to Dave. 568 Dave opens the link in the e-mail with his Taler wallet. 569 Since Dave is using a different exchange than Carol, Dave's wallet 570 issues a **merge** request to Carol's exchange pointing Carol's exchange 571 to Dave's account at his exchange. Shortly after, 572 Dave's exchange receives a **wad** from Carol's exchange, 573 and credits Dave's account with the money. 574 575 576 State machine for Purses 577 ------------------------ 578 579 .. code-block:: none 580 581 // The "OPEN-ACCOUNT" start state implies that the purse is associated 582 // with an account and a merge request for that account. 583 -> OPEN-ACCOUNT 584 585 // "Partial" means that it is filled with a fraction of the coins 586 // indicated in the creation request. 587 OPEN-ACCOUNT -> PARTIAL 588 589 // The purse was filled with as many coins 590 // as indicated in the creation request, resulting in the transaction to complete. 591 OPEN-ACCOUNT -> ACCEPTED 592 593 // The offer expired before any payment was received. 594 OPEN-ACCOUNT -> CLOSED 595 596 // The purse was filled with as many coins 597 // as indicated in the creation request, resulting in the transaction to complete. 598 PARTIAL -> ACCEPTED 599 600 // During an abort, already deposited coins are being taken out of the purse. 601 PARTIAL -> OPEN-ACCOUNT 602 603 // All coins put into the purse are refunded because the 604 // payer never completed the purchase before the timeout. 605 PARTIAL -> CLOSED 606 607 // The "OPEN-DEPOSIT" start state implies that the purse is filled with 608 // deposited coins. 609 -> OPEN-DEPOSIT 610 611 // Paid and merged with an account (locally or via a wad) 612 OPEN-DEPOSIT -> ACCEPTED 613 614 // The offer expired without a merge request. 615 OPEN-DEPOSIT -> CLOSED 616 617 618 Additional considerations 619 ------------------------- 620 621 * Creation of additional accounts per customer can 622 be discouraged by asking for higher fees. 623 * The global transaction volume of one customer can be easily 624 determined by authorities, which can then trigger further audits 625 of the customer 626 * As a technically expensive but more water-tight measure, normal 627 withdrawals from reserves could be disallowed. Instead, 628 a modified refresh protocol could ensure that whoever has knowledge 629 of the account private key can also learn the private keys 630 of coins withdrawn from that account, thereby removing 631 Taler's "one-hop withdrawal loophole". 632 633 634 Exchange database schema changes 635 -------------------------------- 636 637 We need to exchange the existing reserves table to include bits for KYC-needed 638 and KYC-passed. Also, we need to store the payto://-URI of the bank account. 639 640 Finally, we may need to keep some link to the KYC data, even though the 641 exchange technically does not need it, but likely there might be regulatory 642 reasons to have that association for legal inquiries. (However, it would 643 also be possible to keep that link only in the external KYC service's 644 database.) 645 646 .. sourcecode:: sql 647 648 -- Everything in one big transaction 649 BEGIN; 650 -- Check patch versioning is in place. 651 SELECT _v.register_patch('exchange-TBD', NULL, NULL); 652 -- 653 CREATE TABLE IF NOT EXISTS partners 654 (partner_serial_id BIGSERIAL UNIQUE 655 ,partner_master_pub BYTEA NOT NULL CHECK(LENGTH(partner_master_pub)=32) 656 ,start_date INT8 NOT NULL 657 ,end_date INT8 NOT NULL 658 ,wad_frequency INT8 NOT NULL 659 ,wad_fee_val INT8 NOT NULL 660 ,wad_fee_frac INT4 NOT NULL 661 ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)) 662 ,partner_base_url TEXT NOT NULL 663 ); 664 COMMENT ON TABLE partners 665 IS 'exchanges we do wad transfers to'; 666 COMMENT ON COLUMN partners.partner_master_pub 667 IS 'offline master public key of the partner'; 668 COMMENT ON COLUMN partners.start_date 669 IS 'starting date of the partnership'; 670 COMMENT ON COLUMN partners.end_date 671 IS 'end date of the partnership'; 672 COMMENT ON COLUMN partners.wad_frequency 673 IS 'how often do we promise to do wad transfers'; 674 COMMENT ON COLUMN partners.wad_fee_val 675 IS 'how high is the fee for a wallet to be added to a wad to this partner'; 676 COMMENT ON COLUMN partners.partner_base_url 677 IS 'base URL of the REST API for this partner'; 678 COMMENT ON COLUMN partners.master_sig 679 IS 'signature of our master public key affirming the partnership, of purpose TALER_SIGNATURE_MASTER_PARTNER_DETAILS'; 680 -- 681 ALTER TABLE reserves 682 ADD COLUMN kyc_needed BOOLEAN NOT NULL DEFAULT (false) 683 ADD COLUMN kyc_passed BOOLEAN NOT NULL DEFAULT (false) 684 ADD COLUMN payto_uri TEXT DEFAULT (NULL) 685 ADD COLUMN kyc_link TEXT DEFAULT (NULL); 686 COMMENT ON COLUMN reserves.kyc_needed 687 IS 'set to true once a reserve was merged with a purse'; 688 COMMENT ON COLUMN reserves.kyc_passed 689 IS 'set to true once the user performed the KYC check'; 690 COMMENT ON COLUMN reserves.payto_uri 691 IS 'bank account details to use in case reserve is closed'; 692 COMMENT ON COLUMN reserves.kyc_link 693 IS 'optional link to KYC data'; 694 -- 695 CREATE TABLE IF NOT EXISTS kyc_requests 696 (kyc_request_serial_id BIGSERIAL UNIQUE 697 ,reserve_uuid INT8 NOT NULL REFERENCES reserves (reserve_uuid) ON DELETE CASCADE 698 ,kyc_date INT8 NOT NULL 699 ,kyc_retry INT8 NOT NULL 700 ,kyc_fee_val INT8 NOT NULL 701 ,kyc_fee_frac INT4 NOT NULL 702 ,reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)) 703 ,kyc_id TEXT NOT NULL 704 ,PRIMARY KEY (reserve_uuid, kyc_date) 705 ); 706 COMMENT ON TABLE kyc_requests 707 IS 'KYC processes initiated by the owner of a reserve'; 708 COMMENT ON COLUMN kyc_requests.reserve_uuid 709 IS 'Reserve for which the KYC request was triggered.'; 710 COMMENT ON COLUMN kyc_requests.reserve_sig 711 IS 'Signature affirming the KYC request'; 712 COMMENT ON COLUMN kyc_requests.kyc_fee_val 713 IS 'Amount paid by the reserve for the KYC process.'; 714 COMMENT ON COLUMN kyc_requests.kyc_date 715 IS 'When was the KYC process originally initiated.'; 716 COMMENT ON COLUMN kyc_requests.kyc_retry 717 IS 'Timestamp when we should next query the KYC backend for the KYC status. The maximum possible numeric value indicates that we do not need to ever check the status of this KYC process again.'; 718 COMMENT ON COLUMN kyc_requests.kyc_id 719 IS 'ID of the KYC process, used to compute the URL returned to the client as well as for the exchange to check if the KYC has completed. Format depends on the KYC process of the bank.'; 720 -- 721 CREATE TABLE IF NOT EXISTS mergers 722 (merge_request_serial_id BIGSERIAL UNIQUE 723 ,reserve_uuid BYTEA NOT NULL REFERENCES reserves (reserve_uuid) ON DELETE CASCADE 724 ,partner_serial_id INT8 REFERENCES partners(partner_serial_id) ON DELETE CASCADE, 725 ,reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32), 726 ,purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32), 727 ,reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)) 728 ,purse_sig BYTEA NOT NULL CHECK (LENGTH(purse_sig)=64)) 729 ,merge_timestamp INT8 NOT NULL 730 ,purse_expiration INT8 NOT NULL 731 ,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)) 732 ,purse_val INT8 NOT NULL 733 ,purse_frac INT4 NOT NULL 734 ,PRIMARY KEY (purse_pub) 735 ); 736 COMMENT ON TABLE mergers 737 IS 'Merge requests where a purse- and account-owner requested merging the purse into the account'; 738 COMMENT ON COLUMN mergers.reserve_uuid 739 IS 'identifies the reserve'; 740 COMMENT ON COLUMN mergers.partner_serial_id 741 IS 'identifies the partner exchange, NULL in case the target reserve lives at this exchange'; 742 COMMENT ON COLUMN mergers.reserve_pub 743 IS 'public key of the target reserve'; 744 COMMENT ON COLUMN mergers.purse_pub 745 IS 'public key of the purse'; 746 COMMENT ON COLUMN mergers.reserve_sig 747 IS 'signature by the reserve private key affirming the merge'; 748 COMMENT ON COLUMN mergers.purse_sig 749 IS 'signature by the purse private key affirming the merge'; 750 COMMENT ON COLUMN mergers.merge_timestamp 751 IS 'when was the merge message signed'; 752 COMMENT ON COLUMN mergers.purse_expiration 753 IS 'when is the purse set to expire'; 754 COMMENT ON COLUMN mergers.h_contract_terms 755 IS 'hash of the contract terms both sides are to agree upon'; 756 COMMENT ON COLUMN mergers.purse_val 757 IS 'amount to be transferred from the purse to the reserve (excludes deposit fees)'; 758 CREATE INDEX IF NOT EXISTS mergers_reserve_uuid 759 ON mergers (reserve_uuid); 760 COMMENT ON INDEX mergers_reserve_uuid 761 IS 'needed in reserve history computation'; 762 -- 763 CREATE TABLE IF NOT EXISTS contracts 764 (contract_serial_id BIGSERIAL UNIQUE 765 ,purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32), 766 ,pub_ckey BYTEA NOT NULL CHECK (LENGTH(pub_ckey)=32)), 767 ,e_contract BYTEA NOT NULL, 768 ,PRIMARY KEY (purse_pub) 769 ); 770 COMMENT ON TABLE contracts 771 IS 'encrypted contracts associated with purses'; 772 COMMENT ON COLUMN contracts.purse_pub 773 IS 'public key of the purse that the contract is associated with'; 774 COMMENT ON COLUMN contracts.pub_ckey 775 IS 'Public ECDH key used to encrypt the contract, to be used with the purse private key for decryption'; 776 COMMENT ON COLUMN contracts.e_contract 777 IS 'AES-GCM encrypted contract terms (contains gzip compressed JSON after decryption)'; 778 -- 779 CREATE TABLE IF NOT EXISTS history_requests 780 (reserve_uuid INT8 NOT NULL REFERENCES reserves(reserve_uuid) ON DELETE CASCADE, 781 ,request_timestamp INT8 NOT NULL 782 ,reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)) 783 ,history_fee_val INT8 NOT NULL 784 ,history_fee_frac INT4 NOT NULL 785 ,PRIMARY KEY (reserve_uuid,request_timestamp) 786 ); 787 COMMENT ON TABLE history_requests 788 IS 'Paid history requests issued by a client against a reserve'; 789 COMMENT ON COLUMN history_requests.request_timestamp 790 IS 'When was the history request made'; 791 COMMENT ON COLUMN history_requests.reserve_sig 792 IS 'Signature approving payment for the history request'; 793 COMMENT ON COLUMN history_requests.history_fee_val 794 IS 'History fee approved by the signature'; 795 -- 796 CREATE TABLE IF NOT EXISTS close_requests 797 (reserve_uuid INT8 NOT NULL REFERENCES reserves(reserve_uuid) ON DELETE CASCADE, 798 ,close_timestamp INT8 NOT NULL 799 ,reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)) 800 ,close_val INT8 NOT NULL 801 ,close_frac INT4 NOT NULL 802 ,PRIMARY KEY (reserve_uuid,close_timestamp) 803 ); 804 COMMENT ON TABLE close_requests 805 IS 'Explicit requests by a reserve owner to close a reserve immediately'; 806 COMMENT ON COLUMN close_requests.close_timestamp 807 IS 'When the request was created by the client'; 808 COMMENT ON COLUMN close_requests.reserve_sig 809 IS 'Signature affirming that the reserve is to be closed'; 810 COMMENT ON COLUMN close_requests.close_val 811 IS 'Balance of the reserve at the time of closing, to be wired to the associated bank account (minus the closing fee)'; 812 813 -- 814 CREATE TABLE IF NOT EXISTS purse_requests 815 (purse_deposit_serial_id BIGSERIAL UNIQUE 816 ,purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32), 817 ,purse_expiration INT8 NOT NULL 818 ,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64) 819 ,amount_with_fee_val INT8 NOT NULL 820 ,amount_with_fee_frac INT4 NOT NULL 821 ,purse_sig BYTEA NOT NULL CHECK(LENGTH(purse_sig)=64) 822 ,PRIMARY KEY (purse_pub,coin_pub) 823 ); 824 COMMENT ON TABLE purse_requests 825 IS 'Requests establishing purses, associating them with a contract but without a target reserve'; 826 COMMENT ON COLUMN purse_requests.purse_pub 827 IS 'Public key of the purse'; 828 COMMENT ON COLUMN purse_requests.purse_expiration 829 IS 'When the purse is set to expire'; 830 COMMENT ON COLUMN purse_requests.h_contract_terms 831 IS 'Hash of the contract the parties are to agree to'; 832 COMMENT ON COLUMN purse_requests.amount_with_fee_val 833 IS 'Total amount expected to be in the purse'; 834 COMMENT ON COLUMN purse_requests.purse_sig 835 IS 'Signature of the purse affirming the purse parameters, of type TALER_SIGNATURE_PURSE_REQUEST'; 836 -- 837 CREATE TABLE IF NOT EXISTS purse_deposits 838 (purse_deposit_serial_id BIGSERIAL UNIQUE 839 ,purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32), 840 ,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE 841 ,amount_with_fee_val INT8 NOT NULL 842 ,amount_with_fee_frac INT4 NOT NULL 843 ,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64) 844 ,PRIMARY KEY (purse_pub,coin_pub) 845 ); 846 COMMENT ON TABLE purse_deposits 847 IS 'Requests depositing coins into a purse'; 848 COMMENT ON COLUMN purse_deposits.purse_pub 849 IS 'Public key of the purse'; 850 COMMENT ON COLUMN purse_deposits.coin_pub 851 IS 'Public key of the coin being deposited'; 852 COMMENT ON COLUMN purse_deposits.amount_with_fee_val 853 IS 'Total amount being deposited'; 854 COMMENT ON COLUMN purse_deposits.coin_sig 855 IS 'Signature of the coin affirming the deposit into the purse, of type TALER_SIGNATURE_PURSE_DEPOSIT'; 856 -- 857 CREATE TABLE IF NOT EXISTS wads_out 858 (wad_out_serial_id BIGSERIAL UNIQUE 859 ,wad_id BYTEA PRIMARY KEY CHECK (LENGTH(wad_id)=24) 860 ,partner_serial_id INT8 NOT NULL REFERENCES partners(partner_serial_id) ON DELETE CASCADE, 861 ,amount_val INT8 NOT NULL 862 ,amount_frac INT4 NOT NULL 863 ,execution_time INT8 NOT NULL 864 ,UNIQUE (exchange_url, execution_time) 865 ); 866 COMMENT ON TABLE wads_out 867 IS 'Wire transfers made to another exchange to transfer purse funds'; 868 COMMENT ON COLUMN wads_out.wad_id 869 IS 'Unique identifier of the wad, part of the wire transfer subject'; 870 COMMENT ON COLUMN wads_out.partner_serial_id 871 IS 'target exchange of the wad'; 872 COMMENT ON COLUMN wads_out.amount_val 873 IS 'Amount that was wired'; 874 COMMENT ON COLUMN wads_out.execution_time 875 IS 'Time when the wire transfer was scheduled'; 876 -- 877 CREATE TABLE IF NOT EXISTS wad_out_entries 878 (wad_out_entry_serial_id BIGSERIAL UNIQUE 879 ,wad_out_serial_id INT8 REFERENCES wads_out (wad_out_serial_id) ON DELETE CASCADE 880 ,reserve_pub BYTEA NOT NULL CHECK(LENGTH(reserve_pub)=32) 881 ,purse_pub BYTEA PRIMARY KEY CHECK(LENGTH(purse_pub)=32) 882 ,h_contract BYTEA NOT NULL CHECK(LENGTH(h_contract)=64) 883 ,purse_expiration INT8 NOT NULL 884 ,merge_timestamp INT8 NOT NULL 885 ,amount_with_fee_val INT8 NOT NULL 886 ,amount_with_fee_frac INT4 NOT NULL 887 ,wad_fee_val INT8 NOT NULL 888 ,wad_fee_frac INT4 NOT NULL 889 ,deposit_fees_val INT8 NOT NULL 890 ,deposit_fees_frac INT4 NOT NULL 891 ,reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)) 892 ,purse_sig BYTEA NOT NULL CHECK (LENGTH(purse_sig)=64)) 893 ); 894 CREATE INDEX IF NOT EXISTS wad_out_entries_index_by_wad 895 ON wad_out_entries (wad_out_serial_id); 896 COMMENT ON TABLE wad_out_entries 897 IS 'Purses combined into a wad'; 898 COMMENT ON COLUMN wad_out_entries.wad_out_serial_id 899 IS 'Wad the purse was part of'; 900 COMMENT ON COLUMN wad_out_entries.reserve_pub 901 IS 'Target reserve for the purse'; 902 COMMENT ON COLUMN wad_out_entries.purse_pub 903 IS 'Public key of the purse'; 904 COMMENT ON COLUMN wad_out_entries.h_contract 905 IS 'Hash of the contract associated with the purse'; 906 COMMENT ON COLUMN wad_out_entries.purse_expiration 907 IS 'Time when the purse expires'; 908 COMMENT ON COLUMN wad_out_entries.merge_timestamp 909 IS 'Time when the merge was approved'; 910 COMMENT ON COLUMN wad_out_entries.amount_with_fee_val 911 IS 'Total amount in the purse'; 912 COMMENT ON COLUMN wad_out_entries.wad_fee_val 913 IS 'Wat fee charged to the purse'; 914 COMMENT ON COLUMN wad_out_entries.deposit_fees_val 915 IS 'Total deposit fees charged to the purse'; 916 COMMENT ON COLUMN wad_out_entries.reserve_sig 917 IS 'Signature by the receiving reserve, of purpose TALER_SIGNATURE_ACCOUNT_MERGE'; 918 COMMENT ON COLUMN wad_out_entries.purse_sig 919 IS 'Signature by the purse of purpose TALER_SIGNATURE_PURSE_MERGE'; 920 -- 921 CREATE TABLE IF NOT EXISTS wads_in 922 (wad_in_serial_id BIGSERIAL UNIQUE 923 ,wad_id BYTEA PRIMARY KEY CHECK (LENGTH(wad_id)=24) 924 ,origin_exchange_url TEXT NOT NULL 925 ,amount_val INT8 NOT NULL 926 ,amount_frac INT4 NOT NULL 927 ,arrival_time INT8 NOT NULL 928 ,UNIQUE (wad_id, origin_exchange_url) 929 ); 930 COMMENT ON TABLE wads_in_entries 931 IS 'Incoming exchange-to-exchange wad wire transfers'; 932 COMMENT ON COLUMN wads_in.wad_id 933 IS 'Unique identifier of the wad, part of the wire transfer subject'; 934 COMMENT ON COLUMN wads_in.origin_exchange_url 935 IS 'Base URL of the originating URL, also part of the wire transfer subject'; 936 COMMENT ON COLUMN wads_in.amount_val 937 IS 'Actual amount that was received by our exchange'; 938 COMMENT ON COLUMN wads_in.arrival_time 939 IS 'Time when the wad was received'; 940 -- 941 CREATE TABLE IF NOT EXISTS wad_in_entries 942 (wad_in_entry_serial_id BIGSERIAL UNIQUE 943 ,wad_in_serial_id INT8 REFERENCES wads_in (wad_serial_id) ON DELETE CASCADE 944 ,reserve_pub BYTEA NOT NULL CHECK(LENGTH(reserve_pub)=32) 945 ,purse_pub BYTEA PRIMARY KEY CHECK(LENGTH(purse_pub)=32) 946 ,h_contract BYTEA NOT NULL CHECK(LENGTH(h_contract)=64) 947 ,purse_expiration INT8 NOT NULL 948 ,merge_timestamp INT8 NOT NULL 949 ,amount_with_fee_val INT8 NOT NULL 950 ,amount_with_fee_frac INT4 NOT NULL 951 ,wad_fee_val INT8 NOT NULL 952 ,wad_fee_frac INT4 NOT NULL 953 ,deposit_fees_val INT8 NOT NULL 954 ,deposit_fees_frac INT4 NOT NULL 955 ,reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)) 956 ,purse_sig BYTEA NOT NULL CHECK (LENGTH(purse_sig)=64)) 957 ); 958 COMMENT ON TABLE wad_in_entries 959 IS 'list of purses aggregated in a wad according to the sending exchange'; 960 COMMENT ON COLUMN wad_in_entries.wad_in_serial_id 961 IS 'wad for which the given purse was included in the aggregation'; 962 COMMENT ON COLUMN wad_in_entries.reserve_pub 963 IS 'target account of the purse (must be at the local exchange)'; 964 COMMENT ON COLUMN wad_in_entries.purse_pub 965 IS 'public key of the purse that was merged'; 966 COMMENT ON COLUMN wad_in_entries.h_contract 967 IS 'hash of the contract terms of the purse'; 968 COMMENT ON COLUMN wad_in_entries.purse_expiration 969 IS 'Time when the purse was set to expire'; 970 COMMENT ON COLUMN wad_in_entries.merge_timestamp 971 IS 'Time when the merge was approved'; 972 COMMENT ON COLUMN wad_in_entries.amount_with_fee_val 973 IS 'Total amount in the purse'; 974 COMMENT ON COLUMN wad_in_entries.wad_fee_val 975 IS 'Total wad fees paid by the purse'; 976 COMMENT ON COLUMN wad_in_entries.deposit_fees_val 977 IS 'Total deposit fees paid when depositing coins into the purse'; 978 COMMENT ON COLUMN wad_in_entries.reserve_sig 979 IS 'Signature by the receiving reserve, of purpose TALER_SIGNATURE_ACCOUNT_MERGE'; 980 COMMENT ON COLUMN wad_in_entries.purse_sig 981 IS 'Signature by the purse of purpose TALER_SIGNATURE_PURSE_MERGE'; 982 CREATE INDEX IF NOT EXISTS wad_in_entries_wad_in_serial 983 ON wad_in_entries (wad_in_serial_id); 984 CREATE INDEX IF NOT EXISTS wad_in_entries_reserve_pub 985 ON wad_in_entries (reserve_pub); 986 COMMENT ON INDEX wad_in_entries_wad_in_serial 987 IS 'needed to lookup all transfers associated with a wad'; 988 COMMENT ON INDEX wad_in_entries_reserve_pub 989 IS 'needed to compute reserve history'; 990 -- 991 CREATE TABLE IF NOT EXISTS p2pfees 992 (p2pfees_serial_id BIGSERIAL UNIQUE 993 ,start_date INT8 NOT NULL 994 ,end_date INT8 NOT NULL 995 ,kyc_timeout INT8 NOT NULL 996 ,purse_timeout INT8 NOT NULL 997 ,history_retention INT8 NOT NULL 998 ,purse_account_limit INT NOT NULL 999 ,kyc_fee_val INT8 NOT NULL 1000 ,kyc_fee_frac INT4 NOT NULL 1001 ,history_fee_val INT8 NOT NULL 1002 ,history_fee_frac INT4 NOT NULL 1003 ,account_fee_val INT8 NOT NULL 1004 ,account_fee_frac INT4 NOT NULL 1005 ,purse_fee_val INT8 NOT NULL 1006 ,purse_fee_frac INT4 NOT NULL 1007 ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)) 1008 ); 1009 -- 1010 CREATE TABLE IF NOT EXISTS partner_accounts 1011 (payto_uri VARCHAR PRIMARY KEY 1012 ,partner_serial_id INT8 REFERENCES partners(partner_serial_id) ON DELETE CASCADE, 1013 ,partner_master_sig BYTEA CHECK (LENGTH(partner_master_sig)=64) 1014 ,last_seen INT8 NOT NULL 1015 ); 1016 CREATE INDEX IF NOT EXISTS partner_accounts_index_by_partner_and_time 1017 ON partner_accounts (partner_serial_id,last_seen); 1018 COMMENT ON TABLE partner_accounts 1019 IS 'Table with bank accounts of the partner exchange. Entries never expire as we need to remember the signature for the auditor.'; 1020 COMMENT ON COLUMN wire_accounts.payto_uri 1021 IS 'payto URI (RFC 8905) with the bank account of the partner exchange.'; 1022 COMMENT ON COLUMN wire_accounts.partner_master_sig 1023 IS 'Signature of purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS by the partner master public key'; 1024 COMMENT ON COLUMN wire_accounts.last_seen 1025 IS 'Last time we saw this account as being active at the partner exchange. Used to select the most recent entry, and to detect when we should check again.'; 1026 -- Complete transaction 1027 COMMIT; 1028 1029 1030 1031 Alternatives 1032 ============ 1033 1034 * The payer could directly give deposit permissions to the payee. 1035 This has two problems: 1036 1037 1. The payer does not know the wire details of the payee. 1038 Thus we would need to introduce some "wildcard deposit permission", 1039 where the exchange allows any wire details on ``/deposit``. 1040 2. The payment information would be rather large, making it difficult 1041 to transfer via a QR code or short text message. 1042 1043 * Account history exceeding a configurable time limit (like 6 years) 1044 could be subject to garbage collection. However, doing so may be difficult to 1045 square with onboarding new auditors in the presence of existing 1046 accounts, as the auditors could then not reconstruct the account 1047 balances from cryptographic proofs. 1048 1049 * Accounts without KYC check could be eventually closed. However, 1050 even if the coins used to fill the account are refunded, it 1051 would be difficult to inform the originating wallet that the 1052 coins have received a refund. This applies even more strongly 1053 in case of accounts filled via wads, where in theory the 1054 originating exchange may not even be in business anymore. 1055 Thus, it is cleaner and simpler to declare such funds forfeit. 1056 1057 1058 Drawbacks 1059 ========= 1060 1061 The overall changes required are not small: 1062 1063 * New **KYC fee**, **wad fee** and **account history fee** 1064 required in ``/keys`` endpoint (similar to closing and wire fees), 1065 requires some work across toolchain (offline signature, etc.) 1066 * New ``taler`` wire method needs special case to possibly bypass 1067 (same exchange scenario, with long-poll trigger) the usual aggregation logic. 1068 * New exchange table(s) required to store inbound amounts by account. 1069 Likely two tables, one for local exchange p2p and one for remote exchange p2p 1070 payments. 1071 * New exchange table for purses required (for remote p2p payments). 1072 * New exchange logic required to make ``transfers`` requests for purses 1073 (another separate process). 1074 * New ``/account/$ACCOUNT_PUB/kyc`` endpoint required. 1075 * New ``/purses/$PURSE_PUB/merge`` endpoint required. 1076 * Additional tables to be verified by the auditor. 1077 * ``taler-exchange-wirewatch`` needs to support receiving purses closures 1078 and exchange-to-exchange wire transfers with WTIDs. 1079 1080 Aside from implementation complexity, the solution has the following drawbacks: 1081 1082 * If a W2W payment failed (say the receiver lost the account private key), 1083 the customer's money can be forfeit. Alas, this should be very, very rare 1084 as the wallet software can trivially ensure that a backup was made of the 1085 account private key before initiating the KYC process. 1086 1087 1088 Refinements 1089 =========== 1090 1091 In the original design, a payer making a payment offer sends the purse private 1092 key to the payee, so that the payee can sign the merge request with it. This 1093 creates a security issue, as theoretically the payee could sign a different 1094 contract with the purse private key, and conspire with the exchange to replace 1095 the original contract. In this case, the payer would be making a payment to 1096 the "wrong" contract, and have no proof of the exchange and payee conspiring 1097 against it. 1098 1099 A simple fix seems possible: instead of having simply one public-private key 1100 pair for a purse, we have a PayerContractKey and a PurseMergeKey pair. The payer 1101 would pay into a purse identified by the PayerContractKey and associate a 1102 PurseMergeKey with the purse. The payer can then safely share the 1103 PayeeMergeKey with the payee, as it is ONLY useful for the merge and not to 1104 sign the contract. Payments would be made into a purse identified by the 1105 PurseContractKey. 1106 1107 When payments flow in the other direction, the split of the keys seems 1108 unnecessary (as only a public key is transmitted anyway. However, schema-wise, 1109 signing the contract with the PurseContractKey and the merge with the 1110 PurseMergeKey would still work. Only the public PurseContractKey would need 1111 to be sent to the payer. 1112 1113 1114 1115 Q / A 1116 ===== 1117 1118 * Q: Why are direct payments into accounts allowed? 1119 1120 * A: Direct payments into accounts may be used by the customer 1121 to fund the expenses for using the account. They should not 1122 be used for payments between customers, as contract terms for 1123 the ``/deposit`` of coins cannot be negotiated. Furthermore, 1124 the sender of the payment cannot be sure that the account of 1125 the sender is still valid. 1126 1127 * Q: Who "owns" a purse? The payer or payee? 1128 1129 * Both. Ownership is shared. Either the payer issues 1130 a refund on the purse, or the payee claims it by merging 1131 it with one of their accounts. 1132 1133 * Q: Are purses created with a pre-determined "capacity"? 1134 1135 * A: Yes. Otherwise there would be weird failure modes when the payee 1136 merges the purse before the payer fully deposited into it. 1137 1138 * Q: Are account public keys considered private or public data? 1139 1140 * A: Public. The payer needs a signature from the payee affirming 1141 that they accepted the contract, and this requires a key that 1142 is linked to the KYC process to be meaningful. However, the 1143 software should NOT permit direct payments into foreign accounts 1144 because it would be too easy to accidentally send payments that 1145 nobody can receive, because the account public key is wrong/lost. 1146 1147 * Q: Why do traditional merchant payments not use purses? 1148 1149 * Refunds are not possible with purses after they are closed. 1150 * The customer cannot prove that they own the contract terms 1151 (Contract terms claiming requires interactivity that is not 1152 possible in all W2W scenarios.) Thus, while payers can prove 1153 that they paid, the payee may claim someone else also 1154 bought the same product. A secure channel must thus be used to 1155 exchange the purchase offer. 1156 1157 * Q: What determines when a wad transfer can happen between two exchanges? 1158 1159 * Exchanges explicitly state which other exchanges they are willing 1160 to do wad transfers with (and how often, at what cost). This may involve 1161 abstract policies like sharing an auditor, using the same currency and the 1162 same (banking) protocol, or other constraints (like a specific list of 1163 exchanges). 1164 1165 * Q: What happens if the owner of a reserve never drains it? 1166 1167 * Reserves are eventually closed. If the reserve is associated 1168 with a bank account, the remaining funds are sent to that bank 1169 account. If the reserve was created via a merge, and the owner 1170 failed to associate a bank account with it (say because the 1171 KYC step never happened), then the reserve balance is forfeit 1172 to the exchange upon expiration.