-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BIP 77: Payjoin Version 2 — Async Payjoin #1483
base: master
Are you sure you want to change the base?
Conversation
Let's call this BIP 77 |
Hi @DanGould, the first comment on this PR seems to indicate that this proposal is still WIP. Is that an accurate understanding? If this PR is not yet ready to be merged, perhaps it should be changed to "Draft". If I misunderstood the status of this PR, please respond below so someone may review to assess whether this is ready for merge. |
The main changes from the last review are that
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NACK
This BIP is bad for privacy and lacks details in "attack vectors" section. Please be careful while implementing.
Can you provide the reasoning, please? |
Risks with accepting donations using payjoin:
|
Example: https://hrf.org/payjoin |
@1440000bytes Your first point has already been addressed and he has added a link to the attack vectors section on BIP-78. No one is "not accepting" anything. Are you asking that the full explanation given on probing attacks in BIP-78 be redundantly added here? What exactly is your criticism? Your second point has already been addressed in BIP-78, here is what the link that you suggested be added says:
BIP-78 already explains what can be done to mitigate this, and fully acknowledges this tradeoff. |
The sender could first register an additional session subdirectory for the response, and include the associated public key along with the original PSBT when posting to the receiver's subdirectory. The sender would then respond in the sender's subdirectory. Eliminating the request/response distinction would avoid a metadata leak, namely whether or not the payjoin flow was completed, since requests and responses would be indistinguishable. A followup suggestion would be removing explicit session initialization. Incidentally in the reference directory it appears that since Timing analysis of subdirectory polling could still leak information about which payjoin requests were responded to, but aggressive clients could mitigate this by maintaining a pool of pre-allocated and randomly polled subdirectories ahead of time, and by responding to themselves in some of them with dummy payloads to generate random cover traffic. |
@nothingmuch I'll write up your suggestions to simplify the protocol. It makes the directory implementation simpler, requires fewer protocol message types, and even reduces bandwidth. wowza
HPKE E2EE deployed in this application in Authenticated mode (akin to Noise Framework's IK model) already requires the sender to include their session public key as associated data, so this is an pretty darn easy change to make. The change not only simplifies the protocol messaging, but as you say eliminates a metadata leak. I'm a big fan.
This makes sense too. Creating separate subdirectory resources for either sender or receiver on POST then GETting updates to replace the repeated sender POST polling reduces bandwidth too, since the GET request doesn't contain that repeat POST body. Even without aggressive client mitigation of the remaining client leaks subject to timing analysis assuming this suggestion is put in place, your new design deletes complexity and improves efficiency. I'll update the BIP to the best of my understanding based on your comment and link it to a Edit: Is there a potential authorization issue now that the sender POSTs first? In the current design of the protocol, only the receiver might need authorization from the directory in order to initialize a session subdirectory, and having knowledge of a session public key was sufficient for the sender to use an initialized subdirectory. Now, the sender would also need to obtain authorization somehow, since the directory doesn't yet know about the session the receiver has implicitly initiated by communicating directly with the sender, out of band from the directory. We'll have to work out how this might affect the expiration mechanic as well. |
The specifics of a credential issuance are left out, however
Co-authored-by: Yuval Kogman <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor clarifications following the "original"/"proposal" payjoin PSBT terminology established in BIP78.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I struggled a bit to grok the new messaging flow. After reading through the implementation I think I get it now and left some corrections/clarification suggestions throughout.
Co-authored-by: spacebear <[email protected]>
===Receiver's Proposal PSBT checklist=== | ||
|
||
The receiver checklist is the same as the [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#receivers-original-psbt-checklist| the BIP 78 receiver checklist]], except for the "Verify that the payjoin proposal did not introduce mixed input's type" step, which may be ignored. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
===Receiver's Proposal PSBT checklist=== | |
The receiver checklist is the same as the [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#receivers-original-psbt-checklist| the BIP 78 receiver checklist]], except for the "Verify that the payjoin proposal did not introduce mixed input's type" step, which may be ignored. | |
===Receiver's Original PSBT checklist=== | |
The receiver checklist is the same as the [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#receivers-original-psbt-checklist| the BIP 78 receiver checklist]], except for the "If the sender's inputs are all from the same scriptPubKey type, the receiver must match the same type" step, which may be ignored. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use "output script" instead of "scriptPubKey" since this document also uses "input script" elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great. I did not notice any blocking formatting issues, and it appears to fulfill all formal criteria to get merged. Please let me know when you have concluded addressing the outstanding review comments and are ready for it to get merged.
Would it be viable to provide test vectors for this proposal? If so, I would suggest that some be added before this proposal is advanced to "Proposed".
|
||
The message payloads in this version parallel those used in BIP 78, while being encapsulated in authenticated encryption. TLS and Tor security, which depend on third-party authorities, are replaced with Hybrid Public Key Encryption ([[https://www.rfc-editor.org/rfc/rfc9180| HPKE]]). The synchronous HTTP client-server model is replaced with an asynchronous store-and-forward mechanism. | ||
|
||
The BIP 78 standard allows for an [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#unsecured-payjoin-server| unsecured Payjoin server|]] to operate separately from the so-called "payment server" responsible for generating [[https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki| BIP 21]] request URIs. Because BIP 78 messages relayed over an unsecured server are neither end-to-end authenticated nor encrypted between sender and receiver, a malicious unsecured Payjoin server is able to modify the Proposal PSBT in flight, thus requiring payment output substitution to be disabled. Output substitution is useful for a number of block space optimizations, including payment batching and transaction cut-through. This proposal introduces authentication and encryption to secure output substitution by using a directory server without compromising sender or receiver privacy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This extraneous pipe character doesn’t seem to show up anywhere, but still seems to be a syntax error.
The BIP 78 standard allows for an [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#unsecured-payjoin-server| unsecured Payjoin server|]] to operate separately from the so-called "payment server" responsible for generating [[https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki| BIP 21]] request URIs. Because BIP 78 messages relayed over an unsecured server are neither end-to-end authenticated nor encrypted between sender and receiver, a malicious unsecured Payjoin server is able to modify the Proposal PSBT in flight, thus requiring payment output substitution to be disabled. Output substitution is useful for a number of block space optimizations, including payment batching and transaction cut-through. This proposal introduces authentication and encryption to secure output substitution by using a directory server without compromising sender or receiver privacy. | |
The BIP 78 standard allows for an [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#unsecured-payjoin-server| unsecured Payjoin server]] to operate separately from the so-called "payment server" responsible for generating [[https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki| BIP 21]] request URIs. Because BIP 78 messages relayed over an unsecured server are neither end-to-end authenticated nor encrypted between sender and receiver, a malicious unsecured Payjoin server is able to modify the Proposal PSBT in flight, thus requiring payment output substitution to be disabled. Output substitution is useful for a number of block space optimizations, including payment batching and transaction cut-through. This proposal introduces authentication and encryption to secure output substitution by using a directory server without compromising sender or receiver privacy. |
Status: Draft | ||
Type: Standards Track | ||
Created: 2023-08-08 | ||
License: BSD-2-Clause |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds like this proposal builds on BIP 21 URI Scheme, BIP 174 PSBT, and expands on BIP 78, so perhaps those should be listed as requirements:
License: BSD-2-Clause | |
License: BSD-2-Clause | |
Requires: 21, 78, 174 |
or even replacement:
License: BSD-2-Clause | |
License: BSD-2-Clause | |
Requires: 21, 174 | |
Replaces: 78 |
* Exclude unnecessary fields such as global xpubs or keypath information. | ||
* Be broadcastable. | ||
|
||
The Original PSBT MAY: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering, is this proposal only compatible with PSBT v0, or also PSBT v2?
Perhaps it would make sense for this proposal to consider whether this proposal will be compatible with the efforts in "Bip Draft: Sending Silent Payments in PSBTs #1687" to ensure that it will be possible in the future to create Silent Payments-based Payjoins?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the point of view of the BIP 77 Sender & Receiver roles, there are three relevant settings we might consider, whether the receiver knows b_scan
or only B_scan
(relevant for cut-through payments when the receiver's intended recipient is a 3rd party), or whether the sender knows B_scan
at the time of sending the original PSBT.
When the receiver only knows B_scan
, they they know the corresponding a
values of their inputs, but since the BIP 77 sender does not necessarily know B_scan
yet, this requires another round of communication. The receiver can provide the ECDH_SHARE values a*B_scan
for their inputs, and SP_V0_INFO values for their outputs as per BIP-PSBT-SP. Unfortunately, although the sender can complete compute the output scripts, they cannot sign for the receiver's inputs, nor can the receiver sign before the sender's ECDH_SHARE values are given because their output scripts are not finalized, which deviates from BIP 77.
Conversely, since BIP 77 specifies that the receiver modify the Original PSBT, which is already signed, the proposal PSBT can't be considered "the same" in line with BIP 370, as that requires that inputs and outputs no longer be modifiable to ensure signatures are invalidated, and BIP 352 requires that signatures commit to the input set to ensure output scripts are spendable. Therefore for BIP-PSBT-SP to be compatible with this use case it would need to relax BIP 370's rules for input/output modifiability as well, and introduce non-monotonicity to the Signer and Combiner roles.
However, the other two settings don't require any modifications for compatibility:
When the receiver knows b_scan
, they can use the Original PSBT's witnesses to compute A as per BIP 352, adjust it to account for their own inputs, and use b_scan
to derive their own output addresses before sending the proposal PSBT back to the sender, and the sender doesn't need to support silent payments in any way (also compatible with BIP 78 if output substitution is not disallowed). This allows a BIP 352 aware BIP 77 receiver receiver to statelessly avoid address reuse, and does not require state or growing the BIP 44 address gap limit even if BIP 77 sessions fail, so potentially quite valuable.
Secondly, the case where the sender knows B_scan a priori (e.g. from the BIP 21 URI) is also independently interesting, but does not require any changes WRT the BIP-PSBT-SP.
If silent payments transactions are hypothetically used for sender initiated BIP 77 compatible payjoins (arguably topic of a separate BIP than BIP 77 anyway), the receiver can reply with a proposal PSBT as in BIP 77, with the silent payments transaction taking the place of the original PSBT. The sender's reply public key can be implicit, e.g. the BIP 352 A
point (or arguably better yet, the sum of the R points?). This sort of assumes payjoin/rust-payjoin#364. If also assuming payjoin/rust-payjoin#386, the BIP 352 ECDH shared secret could be used to derive a tweak for the HPKE reply key, precluding the directory from censoring payjoins associated with a specific SP transaction.
In this situation, the sender already provided their ECDH secrets, which allows the receiver to dividing out the original PSBT's input set hash, add their own private keys, and the input hash of the modified input set, only requiring the sender to provide new signatures for the proposal PSBT.
Unfortunately this final variant is not as useful as it might appears, because it assumes the sender won't do another round of input addition, which implies the transaction replacement will leak information about the payment amount and potentially violate the unnecessary input heuristics if the additional round of communication is to be avoided. If the sender is allowed to reply to the receiver, then it would need to provide ECDH_SHARE values as per BIP-PSBT-SP, in line with the case where receiver only knowing B_scan
.
|
||
* Include all inputs from the Original PSBT. | ||
* Include all outputs which do not belong to the receiver from the Original PSBT. | ||
* Include complete UTXO data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Include complete UTXO data. | |
* Include complete UTXO data. | |
* Insert additional outputs or additional inputs at random indices while retaining the order of existing inputs and outputs. |
|
||
The Proposal PSBT MUST NOT: | ||
|
||
* Shuffle the order of inputs or outputs; the additional outputs or additional inputs must be inserted at a random index. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me that the latter should also be mentioned in the "MUST" block above (see above) and then this could be reduced to the MUST NOT part:
* Shuffle the order of inputs or outputs; the additional outputs or additional inputs must be inserted at a random index. | |
* Shuffle the order of existing inputs or outputs. |
|
||
==Reference implementation== | ||
|
||
An production reference implementation client can be found at [[https://crates.io/crates/payjoin-cli]]. Source code for the clients, the Payjoin Directory, and development kit may be found here: [[https://github.com/payjoin/rust-payjoin]]. Source code for an Oblivous HTTP relay implementation may be found here [[https://github.com/payjoin/ohttp-relay]]. The reference implementation may be configured to the following independent production relays as of 24/09/26: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo:
An production reference implementation client can be found at [[https://crates.io/crates/payjoin-cli]]. Source code for the clients, the Payjoin Directory, and development kit may be found here: [[https://github.com/payjoin/rust-payjoin]]. Source code for an Oblivous HTTP relay implementation may be found here [[https://github.com/payjoin/ohttp-relay]]. The reference implementation may be configured to the following independent production relays as of 24/09/26: | |
An production reference implementation client can be found at [[https://crates.io/crates/payjoin-cli]]. Source code for the clients, the Payjoin Directory, and development kit may be found here: [[https://github.com/payjoin/rust-payjoin]]. Source code for an Oblivious HTTP relay implementation may be found here [[https://github.com/payjoin/ohttp-relay]]. The reference implementation may be configured to the following independent production relays as of 24/09/26: |
|
||
==Reference implementation== | ||
|
||
An production reference implementation client can be found at [[https://crates.io/crates/payjoin-cli]]. Source code for the clients, the Payjoin Directory, and development kit may be found here: [[https://github.com/payjoin/rust-payjoin]]. Source code for an Oblivous HTTP relay implementation may be found here [[https://github.com/payjoin/ohttp-relay]]. The reference implementation may be configured to the following independent production relays as of 24/09/26: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m not sure whether specifying "production relays" in the BIP makes sense as that information will almost inevitably outdate.
I also think that "production relays" synonymously refers to what was previously called "Payjoin Directory". Please do not use synonyms but settle on one term.
via https://courses.lumenlearning.com/olemiss-technicalwriting/chapter/unit-3-using-appropiate-language-and-tone-avoiding-confusing-terms-lecture-2/
|
||
==Abstract== | ||
|
||
This document proposes a backwards-compatible second version of the Payjoin protocol described in [[bip-0078.mediawiki|BIP 78]], allowing complete Payjoin receiver functionality, including payment output substitution, without requiring one to host a secure public endpoint. This requirement is replaced with an untrusted third-party directory accessed via HTTP clients that communicate using an asynchronous protocol and authenticated, encrypted payloads. Authenticated encryption depends only on cryptographic primitives available in Bitcoin Core. Requests use [[https://www.ietf.org/rfc/rfc9458.html| Oblivious HTTP]] to prevent the directory and Payjoin peers from linking requests to client IP addresses. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is clearer to repeat the active agent by name:
This document proposes a backwards-compatible second version of the Payjoin protocol described in [[bip-0078.mediawiki|BIP 78]], allowing complete Payjoin receiver functionality, including payment output substitution, without requiring one to host a secure public endpoint. This requirement is replaced with an untrusted third-party directory accessed via HTTP clients that communicate using an asynchronous protocol and authenticated, encrypted payloads. Authenticated encryption depends only on cryptographic primitives available in Bitcoin Core. Requests use [[https://www.ietf.org/rfc/rfc9458.html| Oblivious HTTP]] to prevent the directory and Payjoin peers from linking requests to client IP addresses. | |
This document proposes a backwards-compatible second version of the Payjoin protocol described in [[bip-0078.mediawiki|BIP 78]], allowing complete Payjoin receiver functionality, including payment output substitution, without requiring the receiver to host a secure public endpoint. This requirement is replaced with an untrusted third-party directory accessed via HTTP clients that communicate using an asynchronous protocol and authenticated, encrypted payloads. Authenticated encryption depends only on cryptographic primitives available in Bitcoin Core. Requests use [[https://www.ietf.org/rfc/rfc9458.html| Oblivious HTTP]] to prevent the directory and Payjoin peers from linking requests to client IP addresses. |
Status: Draft | ||
Type: Standards Track | ||
Created: 2023-08-08 | ||
License: BSD-2-Clause |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also link to all relevant mailing list threads via the Post-History header.
<pre> | ||
BIP: 77 | ||
Layer: Applications | ||
Title: Payjoin Version 2 — Async Payjoin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many visitors of the BIPs repository may first become aware of this proposal per the title. Does writing out "version 2" provide the biggest bang for the buck?
What do you think about:
Title: Payjoin Version 2 — Async Payjoin | |
Title: Payjoin v2—Async Payjoin |
Or even:
Title: Payjoin Version 2 — Async Payjoin | |
Title: Async Payjoin |
This document proposes an asynchronous, backwards-compatible second version of the payjoin protocol described in BIP 78, enabling complete payjoin receiver functionality including payment output substitution with only an HTTP client rather than server. The former requirement for receivers to run HTTP servers is replaced with an untrusted third-party "payjoin directory" store-and-forward server accessed by polling clients which communicate using an asynchronous protocol and authenticated, encrypted payloads. It was originally proposed to the mailing list here.
The protocol design has received rounds of review elsewhere on the bitcoin-dev mailing list as well.
Feedback from that list post has been incorporated into this draft.
Proposing this as an Standards Track BIP to ensure wallets across the ecosystem can come to rough consensus on a single asynchronous payjoin standard and correctly implement it widely.