diff options
author | Nicolas Dorier <nicolas.dorier@gmail.com> | 2020-05-17 04:46:35 +0900 |
---|---|---|
committer | bitcoindev <bitcoindev@gnusha.org> | 2020-05-16 19:46:51 +0000 |
commit | d2d8e449da1e8bac5ac52ff452f122961a2a5924 (patch) | |
tree | df92ec8affa167c356dd5a84642c3ea4a3be7fc3 | |
parent | a3aa3bc29120dfd9dad27dde197ecef35e7c2807 (diff) | |
download | pi-bitcoindev-d2d8e449da1e8bac5ac52ff452f122961a2a5924.tar.gz pi-bitcoindev-d2d8e449da1e8bac5ac52ff452f122961a2a5924.zip |
[bitcoin-dev] BIP Number request for a simple payjoin proposal
-rw-r--r-- | 1a/bf24659abef9f0b2ffb4999088cab1181cea82 | 1123 |
1 files changed, 1123 insertions, 0 deletions
diff --git a/1a/bf24659abef9f0b2ffb4999088cab1181cea82 b/1a/bf24659abef9f0b2ffb4999088cab1181cea82 new file mode 100644 index 000000000..fbdee0296 --- /dev/null +++ b/1a/bf24659abef9f0b2ffb4999088cab1181cea82 @@ -0,0 +1,1123 @@ +Return-Path: <slashene@gmail.com> +Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) + by lists.linuxfoundation.org (Postfix) with ESMTP id A7850C016F + for <bitcoin-dev@lists.linuxfoundation.org>; + Sat, 16 May 2020 19:46:51 +0000 (UTC) +Received: from localhost (localhost [127.0.0.1]) + by hemlock.osuosl.org (Postfix) with ESMTP id C8A1C885C3 + for <bitcoin-dev@lists.linuxfoundation.org>; + Sat, 16 May 2020 19:46:50 +0000 (UTC) +X-Virus-Scanned: amavisd-new at osuosl.org +Received: from hemlock.osuosl.org ([127.0.0.1]) + by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id U9lyh8CAoEvD + for <bitcoin-dev@lists.linuxfoundation.org>; + Sat, 16 May 2020 19:46:48 +0000 (UTC) +X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 +Received: from mail-oi1-f196.google.com (mail-oi1-f196.google.com + [209.85.167.196]) + by hemlock.osuosl.org (Postfix) with ESMTPS id E84C78859B + for <bitcoin-dev@lists.linuxfoundation.org>; + Sat, 16 May 2020 19:46:47 +0000 (UTC) +Received: by mail-oi1-f196.google.com with SMTP id w4so1594247oia.1 + for <bitcoin-dev@lists.linuxfoundation.org>; + Sat, 16 May 2020 12:46:47 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; + h=mime-version:from:date:message-id:subject:to; + bh=vjjYuNfFYlE5i1C+9CT12Ges/37qM+Q8jtRzzQNltak=; + b=qaMHcgtEL5FiPkajP74dVVs8KTopj7LF1ZPZ/0kiJd/n7PUWWiX1XZYeswSnWKmKzP + 21JrMQffm7iiBvSW3XYAXVsxF0bx12TV1Zi60INxbGkBcAa+BmhVXQgCWyapKrYkyvJk + M1w+i5nzAXjc1EojlUk0wVF+SyInooSES39Pc9/BbR+5xF9zYEHenLOneHGEoUBYVWrx + 7bLmaRdUxNfnOeWL0W9f/6W05jZejW5XyedF9exp//A328t1vzgAUHEBkzGrw1ziZzOv + NhW4SHsrbgv0fJbaBz3APJw+AdthAGs0+No2+U8/dq4Lz6DFaG681zLmiqk1jMWX8bWo + hJFA== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20161025; + h=x-gm-message-state:mime-version:from:date:message-id:subject:to; + bh=vjjYuNfFYlE5i1C+9CT12Ges/37qM+Q8jtRzzQNltak=; + b=Sl18WTyopSLUGzWioe+MAdmgBHQ1PQ+IJcOGy3bCB1jkgOw3LZS3IyKp7W8aVNrnKe + b31qyt9My+wMWSrwEvTqOscFhUCOy56BFzq9pHUJFZelxnESn2HSjwx54yENrBagHXye + lsrFfkFz9b2EBUpr9wH5fH0OW5x2QTBBwUet/xK1EQQdaxb0/v22pA84tnYbeauEJTwL + 6y+q+3i5ADrPRFn4NZGLL0Qg69zGtErJCL+tJKoXSwHSb1VwDdmJrFZvR8x4f5K4PtKN + d7vFHXQ+fTs1Iq+FvjSBaKsGyMLV96oVMeIB4hdhffO97pTHMse3Dypc1B7zsTBR65kO + vcfQ== +X-Gm-Message-State: AOAM531Tq7m6iQ+idCH7x8pui68ekMvR/yZSE2/8QXhzqE9NniZKYF5r + W4uBfvpfabBah0x09yMcLzi2SCokHhoNvyHk7+fQUt7lHv0= +X-Google-Smtp-Source: ABdhPJyhOp7BCcnSiNFX8+RwAB30YUBRqkIwLrVW1/F/98bKZXu6LBP243TwV63+1zwg9tdVxQFqVh94OYorSXFwRCI= +X-Received: by 2002:aca:c4cf:: with SMTP id u198mr6250330oif.17.1589658406106; + Sat, 16 May 2020 12:46:46 -0700 (PDT) +MIME-Version: 1.0 +From: Nicolas Dorier <nicolas.dorier@gmail.com> +Date: Sun, 17 May 2020 04:46:35 +0900 +Message-ID: <CA+1nnrkq2zq_PFoUyNadE7KMncbv30M=Kr-Ek4nDfnJvgDHrfQ@mail.gmail.com> +To: Bitcoin Dev <bitcoin-dev@lists.linuxfoundation.org> +Content-Type: multipart/alternative; boundary="0000000000009c395605a5c930a9" +X-Mailman-Approved-At: Sat, 16 May 2020 19:50:49 +0000 +Subject: [bitcoin-dev] BIP Number request for a simple payjoin proposal +X-BeenThere: bitcoin-dev@lists.linuxfoundation.org +X-Mailman-Version: 2.1.15 +Precedence: list +List-Id: Bitcoin Protocol Discussion <bitcoin-dev.lists.linuxfoundation.org> +List-Unsubscribe: <https://lists.linuxfoundation.org/mailman/options/bitcoin-dev>, + <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=unsubscribe> +List-Archive: <http://lists.linuxfoundation.org/pipermail/bitcoin-dev/> +List-Post: <mailto:bitcoin-dev@lists.linuxfoundation.org> +List-Help: <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=help> +List-Subscribe: <https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev>, + <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=subscribe> +X-List-Received-Date: Sat, 16 May 2020 19:46:51 -0000 + +--0000000000009c395605a5c930a9 +Content-Type: text/plain; charset="UTF-8" + +I am requesting a BIP number to be allocated for this simple payjoin proposal. +This proposal is already being implemented by several service and +wallets and incorporate the feedback of the community at +https://github.com/NicolasDorier/bips/pull/3 + +I opened a pull request at: https://github.com/bitcoin/bips/pull/923 + +I am not checking my mail very often, so I suggest give me feedback +directly on the opened pull request. + + +<pre> + BIP: ? + Layer: Applications + Title: A Simple Payjoin Proposal + Author: Nicolas Dorier <nicolas.dorier@gmail.com> + Comments-Summary: No comments yet. + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-X + Status: Draft + Type: Standards Track + Created: 2019-05-01 + License: BSD-2-Clause +</pre> + +==Introduction== + +===Abstract=== + +This document proposes a protocol for two parties +to negotiate a coinjoin transaction during a payment between them. + +===Copyright=== + +This BIP is licensed under the 2-clause BSD license. + +===Motivation=== + +When two parties (later referred to as sender and receiver) want to transact, +most of the time, the sender creates a transaction spending their own +Unspent Transaction Outputs (UTXOs), signs +it and broadcasts it on the network. + +This simple model gave birth to several heuristics impacting the +privacy of the parties and of the network as a whole. + +* Common input ownership heuristic: In most transactions, all the +inputs belong to the same party. +* Change identification from scriptPubKey type: If all inputs are +spending UTXOs of a certain scriptPubKey type, then the change output +is likely to have the same scriptPubKey type, too. +* Change identification from round amount: If an output in the +transaction has a round amount, it is likely an output belonging to +the receiver. + +We will designate these three heuristics as <code>common-input</code>, +<code>change-scriptpubkey</code>, <code>change-round-amount</code>. + +The problems we aim to solve are: +* For the receiver, there is a missed opportunity to consolidate their +own UTXOs or making payment in the sender's transaction. +* For the sender, there are privacy leaks regarding their wallet that +happen when someone applies the heuristics detailed above to their +transaction. + +Our proposal gives an opportunity for the receiver to consolidate +their UTXOs while also batching their own payments, without creating a +new transaction. (Saving fees in the process) +For the sender, it allows them to invalidate the three heuristics +above. With the receiver's involvement, the heuristics can even be +poisoned. (ie, using the heuristics to intentionally mislead +blockchain analysis) + +Note that the existence of this proposal is also improving the privacy +of parties who are not using it by making the three heuristics +unreliable to the network as a whole. + +=== Relation to BIP79 (Bustapay) === + +Another implementation proposal has been written: +[[https://github.com/bitcoin/bips/blob/master/bip-0079.mediawiki|BIP79 +Bustapay]]. + +We decided to deviate from it for several reasons: +* It was not using PSBT, so if the receiver wanted to bump the fee, +they would need the full UTXO set. +* The receiver was responsible to pay the additional fee, not the sender. +* It was requiring at least one input to be contributed by the receiver. +* Inability to change the payment output to match scriptPubKey type. +* Lack of basic versioning negotiation if the protocol evolves. +* No standardization of error condition for proper feedback to the sender. + +Other than that, our proposal is very similar. + +==Specification== + +===Protocol=== + +In a payjoin payment, the following steps happen: + +* The receiver of the payment, presents a [[bip-021.mediawiki|BIP 21 +URI]] to the sender with a parameter <code>pj</code> describing an +https (or http if it is a Tor hidden service) link to the payjoin +endpoint. +* The sender creates a signed, finalized PSBT with witness UTXO or +previous transactions of the inputs. We call this PSBT the +<code>original</code>. +* The receiver replies back with a signed PSBT containing his own +signed inputs/outputs and those of the sender. We call this PSBT +<code>Payjoin proposal</code>. +* The sender verifies the proposal, re-signs his inputs and broadcasts +the transaction to the Bitcoin network. We call this transaction +<code>Payjoin transaction</code>. +<pre> ++----------+ +--------+ +-----------------+ +| Receiver | | Sender | | Bitcoin Network | ++----+-----+ +---+----+ +-------+---------+ + | +-----------------+ | | + +-------+ BIP21 with ?pj= +------->+ | + | +-----------------+ | | + | | | + | +---------------+ | | + +<-------+ Original PSBT +---------+ | + | +---------------+ | | + | | | + | +------------------+ | | + | | Payjoin Proposal | | | + +-------+ PSBT +------>+ | + | +------------------+ | | + | | +--------------+ | + | |---+ Payjoin | | + | | | transaction +-->+ + | | +--------------+ | + + + + +</pre> +The original PSBT is sent in the HTTP POST request body, base64 +serialized, with <code>text/plain</code> in the +<code>Content-Type</code> HTTP header and <code>Content-Length</code> +set correctly. +The payjoin proposal PSBT is sent in the HTTP response body, base64 +serialized with HTTP code 200. + +To ensure compatibility with web-wallets and browser-based-tools, all +responses (including errors) must contain the HTTP header +<code>Access-Control-Allow-Origin: *</code>. + +The sender must ensure that the url refers to a scheme or protocol +using authenticated encryption, for example TLS with certificate +validation, or a .onion link to a hidden service whose public key +identifier has already been communicated via a TLS connection. Senders +MUST NOT accept a url representing an unencrypted or unauthenticated +connection. + +===Receiver's well known errors=== + +If for some reason the receiver is unable to create a payjoin +proposal, it will reply with a HTTP code different than 200. +The receiver is not constrained to specific set of errors, some are +specified in this proposal. + +The errors have the following format: +<pre> +{ + "errorCode": "leaking-data", + "message": "Key path information or GlobalXPubs should not be +included in the original PSBT." +} +</pre> + +The well-known error codes are: +{| class="wikitable" +!Error code +!Meaning +|- +|leaking-data +|Key path information or GlobalXPubs should not be included in the +original PSBT. +|- +|psbt-not-finalized +|The original PSBT must be finalized. +|- +|unavailable +|The payjoin endpoint is not available for now. +|- +|out-of-utxos +|The receiver does not have any UTXO to contribute in a payjoin proposal. +|- +|not-enough-money +|The receiver added some inputs but could not bump the fee of the +payjoin proposal. +|- +|insane-psbt +|Some consistency check on the PSBT failed. +|- +|version-unsupported +|This version of payjoin is not supported. +|- +|need-utxo-information +|The witness UTXO or non witness UTXO is missing +|- +|invalid-transaction +|The original transaction is invalid for payjoin +|} + +The receiver is allowed to return implementation specific errors which +may assist the sender to diagnose any issue. + +However, it is important that error codes that are not well-known and +that the message do not appear on the sender's software user +interface. +Such error codes or messages could be used maliciously to phish a non +technical user. +Instead those errors or messages can only appear in debug logs. + +It is advised to hard code the description of the error codes into the +sender's software. + +===Receiver's original PSBT checklist=== + +The receiver needs to do some check on the original PSBT before proceeding: + +* Non-interactive receivers (like a payment processor) need to check +that the original PSBT is broadcastable. <code>*</code> +* If the sender included inputs in the original PSBT owned by the +receiver, the receiver must either return error +<code>invalid-transaction</code> or make sure they do not sign those +inputs in the payjoin proposal. +* If the sender's inputs are all from the same scriptPubKey type, the +receiver must match the same type. If the receiver can't match the +type, they must return error <code>out-of-utxos</code>. + +<code>*</code>: Interactive receivers are not required to validate the +original PSBT because they are not exposed to probing attacks. + +===Sender's payjoin proposal checklist=== + +The sender should check the payjoin proposal before signing it to +prevent a malicious receiver from stealing money. + +* Check that all the spent outpoints in the original PSBT still exist +in the coinjoin PSBT. +* Check that all the spent outpoints in the original PSBT do not have +any partial signature. +* If the sender is not using inputs with mixed types, check that the +receiver inputs type match the inputs type of the sender. (ie. both +using P2SH-P2WPKH or both using P2WPKH) +* Check that any inputs added by the receiver are finalized. +* Check that the transaction version, and nLockTime are unchanged. +* Check that the sender's inputs' sequence numbers are unchanged. +* If the sender's inputs' sequence numbers the homogenous, check that +the receiver's contributed inputs match those. +* Check that the sender's outputs have not been modified (but +potentially shuffled), except for paying increased fee +* If sender specified <code>feebumpindex=</code> (see later), the fee +should have been subtracted from the output at the same index in the +original PSBT. +* Check that the sent amount in the payjoin proposal is less than or +equal to the sent amount of the original transaction. + +If the sent amount in the payjoin proposal is above the amount sent in +the original PSBT +* Check that the additional paid amount has been add paid to the fee. +* Check that the estimated fee rate of the payjoin proposal is not +more than the fee rate of the original PSBT. (fee estimation is hard, +so we should allow ~2 satoshi per inputs as margin of error) +* If <code>maxfeebumpcontribution=</code> was specified, check the +additional paid amount is less than or equal to this amount. +* If <code>maxfeebumpcontribution=</code> was not specified, the +sender's software should ask an interactive confirmation to the user. + +The sender must be careful to only sign the inputs that were present +in the original PSBT and nothing else. + +Note: +* The sender should allow the payment output to be modified by the +receiver (The receiver may substitute a P2WPKH payment to P2SH payment +to increase privacy) +* The sender must allow the receiver to add outputs. +* The sender must allow the receiver to not add any input. Useful for +the receiver to change the paymout output scriptPubKey type. +* If no input has been added, the sender's wallet should accept the +payjoin proposal, but should not mark the transaction as an actual +payjoin in the user interface. + +Our method of checking the fee allows the receiver and the sender to +batch payments in the payjoin transaction. +It also allows the receiver to pay the fee for batching adding his own outputs. + +===Optional parameters=== + +When the payjoin sender posts the original PSBT to the receiver, he +can optionally specify the following HTTP query string parameters: + +* <code>v=</code>, the version number of the payjoin protocol that the +sender is using. The current version is <code>1</code>. + +This can be used in the future so the receiver can reject a payjoin if +the sender is using a version which is not supported via an error HTTP +400, <code>version-unsupported</code>. +If not specified, the receiver will assume the sender is <code>v=1</code>. + +If the receiver does not support the version of the sender, they +should send an error with the list of supported versions: +<pre> +{ + "errorCode": "version-unsupported", + "supported" : [ 2, 3, 4 ], + "message": "The version is not supported anymore" +} +</pre> + +* <code>feebumpindex=</code>, the preferred output from which to +increase the fee for the added inputs. (default: <code>-1</code>) + +If the <code>feebumpindex</code> is out of bounds or pointing to the +payment ouptut meant for the receiver, the receiver should ignore the +parameter. + +* <code>maxfeebumpcontribution=</code>, an integer defining the +maximum amount in satoshis that the sender is willing to contribute +towards fees for the additional inputs. +<code>maxfeebumpcontribution</code> must be ignored if set to less +than zero. (default: -1) + +Note that if <code>maxfeebumpcontribution</code> is too low, the +sender should create a transaction with RBF disabled, as the original +transaction could replace the payjoin transaction. + +==Rationale== + +There is several consequences of our proposal: + +* The receiver can bump the fee of the original transaction. +* The receiver can modify the outputs of the original PSBT. +* The sender must provide the UTXO information (Witness or previous +transaction) in the PSBT. + +===Respecting the minimum relay fee policy=== + +To be properly relayed, a Bitcoin transaction needs to pay at least 1 +satoshi per virtual byte. +When fees are low, the original transaction is already 1 satoshi per +virtual byte, so if the receiver adds their own input, they need to +make sure the fee is increased such that the rate does not drop below +1 satoshi per virtual byte. + +===Preventing mempool replacement=== + +A safe way to implement payjoin, is for both the sender and receiver +to try broadcasting the original transaction at some fixed interval +period regardless of the state of the payjoin. + +If the receiver was not properly adding fees to the payjoin +transaction, the original transaction would end up replacing the +payjoin transaction in the mempool. + +===Defeating heuristics based on the fee calculation=== + +Most wallets are creating a round fee rate (like 2 sat/b). +If the payjoin transaction's fee was not increased by the added size, +then those payjoin transactions could easily be identifiable on the +blockchain. + +Not only would those transactions stand out by not having a round fee +(like 1.87 sat/b), but any suspicion of payjoin could be confirmed by +checking if removing one input would create a round fee rate. + +===Receiver does not need to be a full node=== + +Because the receiver needs to bump the fee to keep the same fee rate +as the original PSBT, it needs the input's UTXO information to know +what is the original fee rate. Without PSBT, light wallets like Wasabi +Wallet would not be able to receive a payjoin transaction. + +The validation (policy and consensus) of the original transaction is +optional: a receiver without a full node can decide to create the +payjoin transaction and automatically broadcast the original +transaction after a timeout of 1 minute, and only verify that it has +been propagated in the network. + +However, non-interactive receivers (like a payment processor) need to +verify the transaction to prevent UTXO probing attacks. + +This is not a concern for interactive receivers like Wasabi Wallet, +because those receivers can just limit the number of original PSBT +proposals of a specific address to one. With such wallets, the +attacker has no way to generate new deposit addresses to probe the +UTXOs. + +===Spare change donation=== + +Small change inside wallets are detrimental to privacy. Mixers like +Wasabi wallet, because of its protocol, eventually generate such +[[https://docs.wasabiwallet.io/using-wasabi/ChangeCoins.html#first-round-coinjoin-change|small +change]]. + +A common way to protect your privacy is to donate those spare changes, +to deposit them in an exchange or on your favorite merchant's store +account. Those kind of transactions can easily be spotted on the +blockchain: There is only one output. + +However, if you donate via payjoin, it will look like a normal transaction. + +On top of this the receiver can poison analysis by randomly faking a +round amount of satoshi for the additional output. + +===Payment output substitution=== + +The receiver is free to change the output paying to himself. +For example, if the sender's scriptPubKey type is P2WPKH while the +receiver's payment output in the original PSBT is P2SH, then the +receiver can substitute the payment output to be P2WPKH to match the +sender's scriptPubKey type. + +===Impacted heuristics=== + +Our proposal of payjoin is breaking the following blockchain heuristics: + +* Common inputs heuristics. + +Because payjoin is mixing the inputs of the sender and receiver, this +heuristic becomes unreliable. + +* Change identification from scriptPubKey type heuristics + +When Alice pays Bob, if Alice is using P2SH but Bob's deposit address +is P2WPKH, the heuristic would assume that the P2SH output is the +change address of Alice. +This is now however a broken assumption, as the payjoin receiver has +the freedom to mislead analytics by purposefully changing the +invoice's address in the payjoin transaction. + +Alternatively, if the original address of Bob is P2WPKH and Alice's +address is also P2WPKH, Bob can change the receiving address in the +payjoin to P2SH. The heuristic would wrongfully identify the payjoin's +receiving address as the change address of the transaction. + +See payment output substitution above. + +* Change identification from round change amount + +If Alice pays Bob, she might be tempted to pay him a round amount, +like <code>1.23000000 BTC</code>. When this happens, blockchain +analysis often identifies the output without the round amount as the +change of the transaction. + +For this reason, during a [spare +change](Payjoin-spec.md#spare-change-donation) situation, we randomly +round the amount in the output added by the receiver to the payjoin +transaction. + +==Attack vectors== + +===On the receiver side: UTXO probing attack=== + +When the receiver creates a payjoin proposal, they expose one or more +inputs belonging to them. + +An attacker could create multiple original transactions in order to +learn the UTXOs of the receiver, while not broadcasting the payjoin +proposal. + +While we cannot prevent this type of attack entirely, we implemented +the following mitigations: + +* When the receiver detects an original transaction being broadcast, +or if the receiver detects that the original transaction has been +double spent, then they will reuse the UTXO that was exposed for the +next payjoin. +* While the exposed UTXO will be reused in priority to not leak other +UTXOs, there is no strong guarantee about it. This prevents the +attacker from detecting with certainty the next payjoin of the +merchant to another peer. + +Note that probing attacks are only a problem for automated payment +systems such as BTCPay Server. End-user wallets with payjoin +capabilities are not affected, as the attacker can't create multiple +invoices to force the receiver to expose their UTXOs. + +===On the sender side: Double payment risk for hardware wallets=== + +For a successful payjoin to happen, the sender needs to sign two +transactions double spending each other: The original transaction and +the payjoin proposal. + +The sender's software wallet can verify that the payjoin proposal is +legitimate by the sender's checklist. + +However, a hardware wallet can't verify that this is indeed the case. +This means that the security guarantee of the hardware wallet is +decreased. If the sender's software is compromised, the hardware +wallet would sign two valid transactions, thus sending two payments. + +Without payjoin, the maximum amount of money that could be lost by a +compromised software is equal to one payment (via address +substitution). + +With payjoin, the maximum amount of money that can be lost is equal to +two payments. + +==Implementations== + +* [[https://github.com/BlueWallet/BlueWallet|BlueWallet]] is in the +process of implementing the protocol. +* [[https://github.com/btcpayserver/btcpayserver|BTCPay Server]] has +implemented sender and receiver side of this protocol. +* [[https://github.com/zkSNACKs/WalletWasabi/|Wasabi Wallet]] has +merged sender's support. +* [[https://github.com/JoinMarket-Org/joinmarket-clientserver|Join +Market]] is in the process of implementing the protocol. +* [[https://github.com/junderw/payjoin-client-js|JavaScript sender +implementation]]. + +==Special thanks== + +Special thanks to Kukks for developing the initial support to BTCPay +Server, to junderw, AdamISZ, lukechilds, ncoelho, nopara73, yahiheb +for all the feedback we received since our first implementation. +Thanks also to RHavar who wrote the +[[https://github.com/bitcoin/bips/blob/master/bip-0079.mediawiki|BIP79 +Bustapay]] proposal, this gave a good starting point for our proposal. + +--0000000000009c395605a5c930a9 +Content-Type: text/html; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable + +<div dir=3D"ltr"> +<pre>I am requesting a BIP number to be allocated for this simple payjoin p= +roposal.<br>This proposal is already being implemented by several service a= +nd wallets and incorporate the feedback of the community at <a href=3D"http= +s://github.com/NicolasDorier/bips/pull/3">https://github.com/NicolasDorier/= +bips/pull/3</a><br><br>I opened a pull request at: <a href=3D"https://githu= +b.com/bitcoin/bips/pull/923">https://github.com/bitcoin/bips/pull/923</a><b= +r></pre><pre>I am not checking my mail very often, so I suggest give me fee= +dback directly on the opened pull request.<br></pre><pre><br><pre> + BIP: ? + Layer: Applications + Title: A Simple Payjoin Proposal + Author: Nicolas Dorier <<a href=3D"mailto:nicolas.dorier@gmail.com">ni= +colas.dorier@gmail.com</a>> + Comments-Summary: No comments yet. + Comments-URI: <a href=3D"https://github.com/bitcoin/bips/wiki/Comments:BI= +P-X">https://github.com/bitcoin/bips/wiki/Comments:BIP-X</a> + Status: Draft + Type: Standards Track + Created: 2019-05-01 + License: BSD-2-Clause +</pre> + +=3D=3DIntroduction=3D=3D + +=3D=3D=3DAbstract=3D=3D=3D + +This document proposes a protocol for two parties +to negotiate a coinjoin transaction during a payment between them. + +=3D=3D=3DCopyright=3D=3D=3D + +This BIP is licensed under the 2-clause BSD license. + +=3D=3D=3DMotivation=3D=3D=3D + +When two parties (later referred to as sender and receiver) want to transac= +t, +most of the time, the sender creates a transaction spending their own Unspe= +nt Transaction Outputs (UTXOs), signs +it and broadcasts it on the network. + +This simple model gave birth to several heuristics impacting the privacy of= + the parties and of the network as a whole. + +* Common input ownership heuristic: In most transactions, all the inputs be= +long to the same party. +* Change identification from scriptPubKey type: If all inputs are spending = +UTXOs of a certain scriptPubKey type, then the change output is likely to h= +ave the same scriptPubKey type, too. +* Change identification from round amount: If an output in the transaction = +has a round amount, it is likely an output belonging to the receiver. + +We will designate these three heuristics as <code>common-input</co= +de>, <code>change-scriptpubkey</code>, <code>change-ro= +und-amount</code>. + +The problems we aim to solve are: +* For the receiver, there is a missed opportunity to consolidate their own = +UTXOs or making payment in the sender's transaction. +* For the sender, there are privacy leaks regarding their wallet that happe= +n when someone applies the heuristics detailed above to their transaction. + +Our proposal gives an opportunity for the receiver to consolidate their UTX= +Os while also batching their own payments, without creating a new transacti= +on. (Saving fees in the process) +For the sender, it allows them to invalidate the three heuristics above. Wi= +th the receiver's involvement, the heuristics can even be poisoned. (ie= +, using the heuristics to intentionally mislead blockchain analysis) + +Note that the existence of this proposal is also improving the privacy of p= +arties who are not using it by making the three heuristics unreliable to th= +e network as a whole. + +=3D=3D=3D Relation to BIP79 (Bustapay) =3D=3D=3D + +Another implementation proposal has been written: [[<a href=3D"https://gith= +ub.com/bitcoin/bips/blob/master/bip-0079.mediawiki|BIP79">https://github.co= +m/bitcoin/bips/blob/master/bip-0079.mediawiki|BIP79</a> Bustapay]]. + +We decided to deviate from it for several reasons: +* It was not using PSBT, so if the receiver wanted to bump the fee, they wo= +uld need the full UTXO set. +* The receiver was responsible to pay the additional fee, not the sender. +* It was requiring at least one input to be contributed by the receiver. +* Inability to change the payment output to match scriptPubKey type. +* Lack of basic versioning negotiation if the protocol evolves. +* No standardization of error condition for proper feedback to the sender. + +Other than that, our proposal is very similar. + +=3D=3DSpecification=3D=3D + +=3D=3D=3DProtocol=3D=3D=3D + +In a payjoin payment, the following steps happen: + +* The receiver of the payment, presents a [[bip-021.mediawiki|BIP 21 URI]] = +to the sender with a parameter <code>pj</code> describing an ht= +tps (or http if it is a Tor hidden service) link to the payjoin endpoint. +* The sender creates a signed, finalized PSBT with witness UTXO or previous= + transactions of the inputs. We call this PSBT the <code>original<= +/code>. +* The receiver replies back with a signed PSBT containing his own signed in= +puts/outputs and those of the sender. We call this PSBT <code>Payjoin= + proposal</code>. +* The sender verifies the proposal, re-signs his inputs and broadcasts the = +transaction to the Bitcoin network. We call this transaction <code>Pa= +yjoin transaction</code>. +<pre> ++----------+ +--------+ +-----------------+ +| Receiver | | Sender | | Bitcoin Network | ++----+-----+ +---+----+ +-------+---------+ + | +-----------------+ | | + +-------+ BIP21 with ?pj=3D +------->+ | + | +-----------------+ | | + | | | + | +---------------+ | | + +<-------+ Original PSBT +---------+ | + | +---------------+ | | + | | | + | +------------------+ | | + | | Payjoin Proposal | | | + +-------+ PSBT +------>+ | + | +------------------+ | | + | | +--------------+ | + | |---+ Payjoin | | + | | | transaction +-->+ + | | +--------------+ | + + + + +</pre> +The original PSBT is sent in the HTTP POST request body, base64 serialized,= + with <code>text/plain</code> in the <code>Content-Type&l= +t;/code> HTTP header and <code>Content-Length</code> set cor= +rectly. +The payjoin proposal PSBT is sent in the HTTP response body, base64 seriali= +zed with HTTP code 200. + +To ensure compatibility with web-wallets and browser-based-tools, all respo= +nses (including errors) must contain the HTTP header <code>Access-Con= +trol-Allow-Origin: *</code>. + +The sender must ensure that the url refers to a scheme or protocol using au= +thenticated encryption, for example TLS with certificate validation, or a .= +onion link to a hidden service whose public key identifier has already been= + communicated via a TLS connection. Senders MUST NOT accept a url represent= +ing an unencrypted or unauthenticated connection. + +=3D=3D=3DReceiver's well known errors=3D=3D=3D + +If for some reason the receiver is unable to create a payjoin proposal, it = +will reply with a HTTP code different than 200. +The receiver is not constrained to specific set of errors, some are specifi= +ed in this proposal. + +The errors have the following format: +<pre> +{ + "errorCode": "leaking-data", + "message": "Key path information or GlobalXPubs should n= +ot be included in the original PSBT." +} +</pre> + +The well-known error codes are: +{| class=3D"wikitable" +!Error code +!Meaning +|- +|leaking-data +|Key path information or GlobalXPubs should not be included in the original= + PSBT. +|- +|psbt-not-finalized +|The original PSBT must be finalized. +|- +|unavailable +|The payjoin endpoint is not available for now. +|- +|out-of-utxos +|The receiver does not have any UTXO to contribute in a payjoin proposal. +|- +|not-enough-money +|The receiver added some inputs but could not bump the fee of the payjoin p= +roposal. +|- +|insane-psbt +|Some consistency check on the PSBT failed. +|- +|version-unsupported +|This version of payjoin is not supported. +|- +|need-utxo-information +|The witness UTXO or non witness UTXO is missing +|- +|invalid-transaction +|The original transaction is invalid for payjoin +|} + +The receiver is allowed to return implementation specific errors which may = +assist the sender to diagnose any issue. + +However, it is important that error codes that are not well-known and that = +the message do not appear on the sender's software user interface. +Such error codes or messages could be used maliciously to phish a non techn= +ical user. +Instead those errors or messages can only appear in debug logs. + +It is advised to hard code the description of the error codes into the send= +er's software. + +=3D=3D=3DReceiver's original PSBT checklist=3D=3D=3D + +The receiver needs to do some check on the original PSBT before proceeding: + +* Non-interactive receivers (like a payment processor) need to check that t= +he original PSBT is broadcastable. <code>*</code> +* If the sender included inputs in the original PSBT owned by the receiver,= + the receiver must either return error <code>invalid-transaction</= +code> or make sure they do not sign those inputs in the payjoin proposal= +. +* If the sender's inputs are all from the same scriptPubKey type, the r= +eceiver must match the same type. If the receiver can't match the type,= + they must return error <code>out-of-utxos</code>. + +<code>*</code>: Interactive receivers are not required to valid= +ate the original PSBT because they are not exposed to probing attacks. + +=3D=3D=3DSender's payjoin proposal checklist=3D=3D=3D + +The sender should check the payjoin proposal before signing it to prevent a= + malicious receiver from stealing money. + +* Check that all the spent outpoints in the original PSBT still exist in th= +e coinjoin PSBT. +* Check that all the spent outpoints in the original PSBT do not have any p= +artial signature. +* If the sender is not using inputs with mixed types, check that the receiv= +er inputs type match the inputs type of the sender. (ie. both using P2SH-P2= +WPKH or both using P2WPKH) +* Check that any inputs added by the receiver are finalized. +* Check that the transaction version, and nLockTime are unchanged. +* Check that the sender's inputs' sequence numbers are unchanged. +* If the sender's inputs' sequence numbers the homogenous, check th= +at the receiver's contributed inputs match those. +* Check that the sender's outputs have not been modified (but potential= +ly shuffled), except for paying increased fee +* If sender specified <code>feebumpindex=3D</code> (see later),= + the fee should have been subtracted from the output at the same index in t= +he original PSBT. +* Check that the sent amount in the payjoin proposal is less than or equal = +to the sent amount of the original transaction. + +If the sent amount in the payjoin proposal is above the amount sent in the = +original PSBT +* Check that the additional paid amount has been add paid to the fee. +* Check that the estimated fee rate of the payjoin proposal is not more tha= +n the fee rate of the original PSBT. (fee estimation is hard, so we should = +allow ~2 satoshi per inputs as margin of error) +* If <code>maxfeebumpcontribution=3D</code> was specified, chec= +k the additional paid amount is less than or equal to this amount. +* If <code>maxfeebumpcontribution=3D</code> was not specified, = +the sender's software should ask an interactive confirmation to the use= +r. + +The sender must be careful to only sign the inputs that were present in the= + original PSBT and nothing else. + +Note: +* The sender should allow the payment output to be modified by the receiver= + (The receiver may substitute a P2WPKH payment to P2SH payment to increase = +privacy) +* The sender must allow the receiver to add outputs. +* The sender must allow the receiver to not add any input. Useful for the r= +eceiver to change the paymout output scriptPubKey type. +* If no input has been added, the sender's wallet should accept the pay= +join proposal, but should not mark the transaction as an actual payjoin in = +the user interface. + +Our method of checking the fee allows the receiver and the sender to batch = +payments in the payjoin transaction. +It also allows the receiver to pay the fee for batching adding his own outp= +uts. + +=3D=3D=3DOptional parameters=3D=3D=3D + +When the payjoin sender posts the original PSBT to the receiver, he can opt= +ionally specify the following HTTP query string parameters: + +* <code>v=3D</code>, the version number of the payjoin protocol= + that the sender is using. The current version is <code>1</code>= +;. + +This can be used in the future so the receiver can reject a payjoin if the = +sender is using a version which is not supported via an error HTTP 400, <= +;code>version-unsupported</code>. +If not specified, the receiver will assume the sender is <code>v=3D1&= +lt;/code>. + +If the receiver does not support the version of the sender, they should sen= +d an error with the list of supported versions: +<pre> +{ + "errorCode": "version-unsupported", + "supported" : [ 2, 3, 4 ], + "message": "The version is not supported anymore" +} +</pre> + +* <code>feebumpindex=3D</code>, the preferred output from which= + to increase the fee for the added inputs. (default: <code>-1</cod= +e>) + +If the <code>feebumpindex</code> is out of bounds or pointing t= +o the payment ouptut meant for the receiver, the receiver should ignore the= + parameter. + +* <code>maxfeebumpcontribution=3D</code>, an integer defining t= +he maximum amount in satoshis that the sender is willing to contribute towa= +rds fees for the additional inputs. <code>maxfeebumpcontribution</= +code> must be ignored if set to less than zero. (default: -1) + +Note that if <code>maxfeebumpcontribution</code> is too low, th= +e sender should create a transaction with RBF disabled, as the original tra= +nsaction could replace the payjoin transaction. + +=3D=3DRationale=3D=3D + +There is several consequences of our proposal: + +* The receiver can bump the fee of the original transaction. +* The receiver can modify the outputs of the original PSBT. +* The sender must provide the UTXO information (Witness or previous transac= +tion) in the PSBT. + +=3D=3D=3DRespecting the minimum relay fee policy=3D=3D=3D + +To be properly relayed, a Bitcoin transaction needs to pay at least 1 satos= +hi per virtual byte. +When fees are low, the original transaction is already 1 satoshi per virtua= +l byte, so if the receiver adds their own input, they need to make sure the= + fee is increased such that the rate does not drop below 1 satoshi per virt= +ual byte. + +=3D=3D=3DPreventing mempool replacement=3D=3D=3D + +A safe way to implement payjoin, is for both the sender and receiver to try= + broadcasting the original transaction at some fixed interval period regard= +less of the state of the payjoin. + +If the receiver was not properly adding fees to the payjoin transaction, th= +e original transaction would end up replacing the payjoin transaction in th= +e mempool. + +=3D=3D=3DDefeating heuristics based on the fee calculation=3D=3D=3D + +Most wallets are creating a round fee rate (like 2 sat/b). +If the payjoin transaction's fee was not increased by the added size, t= +hen those payjoin transactions could easily be identifiable on the blockcha= +in. + +Not only would those transactions stand out by not having a round fee (like= + 1.87 sat/b), but any suspicion of payjoin could be confirmed by checking i= +f removing one input would create a round fee rate. + +=3D=3D=3DReceiver does not need to be a full node=3D=3D=3D + +Because the receiver needs to bump the fee to keep the same fee rate as the= + original PSBT, it needs the input's UTXO information to know what is t= +he original fee rate. Without PSBT, light wallets like Wasabi Wallet would = +not be able to receive a payjoin transaction. + +The validation (policy and consensus) of the original transaction is option= +al: a receiver without a full node can decide to create the payjoin transac= +tion and automatically broadcast the original transaction after a timeout o= +f 1 minute, and only verify that it has been propagated in the network. + +However, non-interactive receivers (like a payment processor) need to verif= +y the transaction to prevent UTXO probing attacks.=20 + +This is not a concern for interactive receivers like Wasabi Wallet, because= + those receivers can just limit the number of original PSBT proposals of a = +specific address to one. With such wallets, the attacker has no way to gene= +rate new deposit addresses to probe the UTXOs. + +=3D=3D=3DSpare change donation=3D=3D=3D + +Small change inside wallets are detrimental to privacy. Mixers like Wasabi = +wallet, because of its protocol, eventually generate such [[<a href=3D"http= +s://docs.wasabiwallet.io/using-wasabi/ChangeCoins.html#first-round-coinjoin= +-change|small">https://docs.wasabiwallet.io/using-wasabi/ChangeCoins.html#f= +irst-round-coinjoin-change|small</a> change]]. + +A common way to protect your privacy is to donate those spare changes, to d= +eposit them in an exchange or on your favorite merchant's store account= +. Those kind of transactions can easily be spotted on the blockchain: There= + is only one output. + +However, if you donate via payjoin, it will look like a normal transaction. + +On top of this the receiver can poison analysis by randomly faking a round = +amount of satoshi for the additional output. + +=3D=3D=3DPayment output substitution=3D=3D=3D + +The receiver is free to change the output paying to himself. +For example, if the sender's scriptPubKey type is P2WPKH while the rece= +iver's payment output in the original PSBT is P2SH, then the receiver c= +an substitute the payment output to be P2WPKH to match the sender's scr= +iptPubKey type. + +=3D=3D=3DImpacted heuristics=3D=3D=3D + +Our proposal of payjoin is breaking the following blockchain heuristics: + +* Common inputs heuristics. + +Because payjoin is mixing the inputs of the sender and receiver, this heuri= +stic becomes unreliable. + +* Change identification from scriptPubKey type heuristics + +When Alice pays Bob, if Alice is using P2SH but Bob's deposit address i= +s P2WPKH, the heuristic would assume that the P2SH output is the change add= +ress of Alice. +This is now however a broken assumption, as the payjoin receiver has the fr= +eedom to mislead analytics by purposefully changing the invoice's addre= +ss in the payjoin transaction. + +Alternatively, if the original address of Bob is P2WPKH and Alice's add= +ress is also P2WPKH, Bob can change the receiving address in the payjoin to= + P2SH. The heuristic would wrongfully identify the payjoin's receiving = +address as the change address of the transaction. + +See payment output substitution above. + +* Change identification from round change amount + +If Alice pays Bob, she might be tempted to pay him a round amount, like <= +;code>1.23000000 BTC</code>. When this happens, blockchain analysi= +s often identifies the output without the round amount as the change of the= + transaction. + +For this reason, during a [spare change](Payjoin-spec.md#spare-change-donat= +ion) situation, we randomly round the amount in the output added by the rec= +eiver to the payjoin transaction. + +=3D=3DAttack vectors=3D=3D + +=3D=3D=3DOn the receiver side: UTXO probing attack=3D=3D=3D + +When the receiver creates a payjoin proposal, they expose one or more input= +s belonging to them. + +An attacker could create multiple original transactions in order to learn t= +he UTXOs of the receiver, while not broadcasting the payjoin proposal. + +While we cannot prevent this type of attack entirely, we implemented the fo= +llowing mitigations: + +* When the receiver detects an original transaction being broadcast, or if = +the receiver detects that the original transaction has been double spent, t= +hen they will reuse the UTXO that was exposed for the next payjoin. +* While the exposed UTXO will be reused in priority to not leak other UTXOs= +, there is no strong guarantee about it. This prevents the attacker from de= +tecting with certainty the next payjoin of the merchant to another peer. + +Note that probing attacks are only a problem for automated payment systems = +such as BTCPay Server. End-user wallets with payjoin capabilities are not a= +ffected, as the attacker can't create multiple invoices to force the re= +ceiver to expose their UTXOs. + +=3D=3D=3DOn the sender side: Double payment risk for hardware wallets=3D=3D= +=3D + +For a successful payjoin to happen, the sender needs to sign two transactio= +ns double spending each other: The original transaction and the payjoin pro= +posal. + +The sender's software wallet can verify that the payjoin proposal is le= +gitimate by the sender's checklist. + +However, a hardware wallet can't verify that this is indeed the case. T= +his means that the security guarantee of the hardware wallet is decreased. = +If the sender's software is compromised, the hardware wallet would sign= + two valid transactions, thus sending two payments. + +Without payjoin, the maximum amount of money that could be lost by a compro= +mised software is equal to one payment (via address substitution). + +With payjoin, the maximum amount of money that can be lost is equal to two = +payments. + +=3D=3DImplementations=3D=3D + +* [[<a href=3D"https://github.com/BlueWallet/BlueWallet|BlueWallet">https:/= +/github.com/BlueWallet/BlueWallet|BlueWallet</a>]] is in the process of imp= +lementing the protocol. +* [[<a href=3D"https://github.com/btcpayserver/btcpayserver|BTCPay">https:/= +/github.com/btcpayserver/btcpayserver|BTCPay</a> Server]] has implemented s= +ender and receiver side of this protocol. +* [[<a href=3D"https://github.com/zkSNACKs/WalletWasabi/|Wasabi">https://gi= +thub.com/zkSNACKs/WalletWasabi/|Wasabi</a> Wallet]] has merged sender's= + support. +* [[<a href=3D"https://github.com/JoinMarket-Org/joinmarket-clientserver|Jo= +in">https://github.com/JoinMarket-Org/joinmarket-clientserver|Join</a> Mark= +et]] is in the process of implementing the protocol. +* [[<a href=3D"https://github.com/junderw/payjoin-client-js|JavaScript">htt= +ps://github.com/junderw/payjoin-client-js|JavaScript</a> sender implementat= +ion]]. + +=3D=3DSpecial thanks=3D=3D + +Special thanks to Kukks for developing the initial support to BTCPay Server= +, to junderw, AdamISZ, lukechilds, ncoelho, nopara73, yahiheb for all the f= +eedback we received since our first implementation. +Thanks also to RHavar who wrote the [[<a href=3D"https://github.com/bitcoin= +/bips/blob/master/bip-0079.mediawiki|BIP79">https://github.com/bitcoin/bips= +/blob/master/bip-0079.mediawiki|BIP79</a> Bustapay]] proposal, this gave a = +good starting point for our proposal. +</pre> + +</div> + +--0000000000009c395605a5c930a9-- + |