Skip to content

Commit

Permalink
Use implicit session initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
DanGould committed Oct 9, 2024
1 parent 66457a0 commit c917eab
Showing 1 changed file with 24 additions and 24 deletions.
48 changes: 24 additions & 24 deletions bip-0077.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -69,31 +69,26 @@ Key:
| Receiver | | Directory | | Sender | | Network |
+----------+ +-----------+ +--------+ +---------+
| | | |
| Request Session subdirectory | | |
+--------------------------------->| | |
| | | |
| Session subdirectory | | |
|<---------------------------------| | |
| | | |
| destination (address, | | |
| subdirectory) | | |
+---------------------------------------------------->| |
| | | |
| Request Original PSBT | | |
+- - - - - - - - - - - - - - - - ->| | |
| GET Request Original PSBT | | |
+- - - - - - - - - - - - - - - - ->| POST Request | |
| | Original PSBT | |
| GET Response Original PSBT |<-----------------| |
|<---------------------------------| GET Request | |
| | Payjoin PSBT | |
| |<- - - - - - - - -| |
| | | |
| | | |
| Original PSBT | | |
|<---------------------------------| | |
| | | |
| | | |
| Payjoin PSBT | | |
+--------------------------------->| | |
| POST Payjoin PSBT | | |
+--------------------------------->| GET Response | |
| | Payjoin PSBT | |
| |----------------->| |
| | | |
| | | Broadcast |
| | | Payjoin |
| | +--------------->|
| | | |
Expand All @@ -104,13 +99,13 @@ Key:

The Payjoin version 2 protocol takes the following steps:

* The receiver sends their Payjoin Session public key and optional authentication credential according to the [[#session-initiation|Session initiation]] protocol to receive a Payjoin Session subdirectory. The receiver may go offline and replay Session initiation to come back online.
* The receiver generates a Payjoin Session public key.
* Out of band, the receiver shares a bitcoin URI with the sender, including a <code>pj=</code> query parameter where the subdirectory is the compressed Payjoin Session public key. The key is encoded in [[https://datatracker.ietf.org/doc/html/rfc4648#section-5| base64url]] encoding. To support version 1 senders, the directory acts as an unsecured Payjoin server, so <code>pjos=0</code> must be specified in the URI. Version 2 senders may safely allow output substitution regardless. An <code>ohttp=</code> fragment parameter containing the directory's base64url encoded [[https://www.ietf.org/rfc/rfc9458.html#name-key-configuration| Oblivious HTTP Key Configuration]] must also be provided. It should also include an <code>exp=</code> parameter with a Unix timestamp after which the receiver will broadcast the Original PSBT and stop polling the session.
* The sender creates a valid version 0 PSBT satisfying the [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#receivers-original-psbt-checklist| the receiver checklist]]. We call this the <code>Original PSBT</code>. This <code>Original PSBT</code>, and optional sender parameters, are wrapped in HPKE authenticated encryption, and encapsulated in OHTTP. This [[#send-messaging|Original PSBT Request send message]] is made to the directory's OHTTP Gateway.
* The sender continues to replay this request in order to await a response from the directory containing a <code>Payjoin PSBT</code>. It stops after expiry.
* The sender creates a valid version 0 PSBT satisfying the [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#receivers-original-psbt-checklist| the receiver checklist]]. We call this the <code>Original PSBT</code>. This <code>Original PSBT</code>, and optional sender parameters, are wrapped in HPKE authenticated encryption, including a sender session public key as associated data, and encapsulats it all as OHTTP. This [[#send-messaging|Original PSBT Request send message]] is made to the directory's OHTTP Gateway.
* The sender polls GET requests to the subdirectory defined by the sender's Payjoin Session public key in order to await a response from the directory containing a <code>Payjoin PSBT</code>. It stops polling after expiry.
* The request is stored in the subdirectory.
* Once the receiver is online, it sends [[#receive-messaging|<code>GET</code>]] requests to the subdirectory. The receiver decrypts and authenticates the response, which it checks according to [[https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki#receivers-original-psbt-checklist| the receiver checklist]]. The receiver updates the Original PSBT to include new signed inputs and outputs, invalidating sender signatures, and may adjust the fee. The result is called the <code>Payjoin PSBT</code>.
* The <code>Payjoin PSBT</code> and HPKE keys are encrypted, authenticated, encapsulated in OHTTP, and sent to the directory's OHTTP Gateway.
* The <code>Payjoin PSBT</code> and HPKE keys are encrypted, authenticated, encapsulated in OHTTP, and POSTed to the directory's OHTTP Gateway.
* The directory awaits a request from the sender if it goes offline. Upon request, the directory relays the encrypted <code>Payjoin PSBT</code>.
* The sender validates the <code>Payjoin PSBT</code> according to [[#senders-payjoin-psbt-checklist|the sender checklist]], signs its inputs and broadcasts the transaction to the Bitcoin network.
Expand Down Expand Up @@ -152,16 +147,21 @@ If a directory is subject to denial of service attacks, it may require [[https:/

====Send Messaging====

The Original PSBT is serialized in base64, followed by the query parameter string on a new line. This plaintext string is encrypted according to the HPKE using a shared secret derived from a newly generated Payjoin Session keypair public key combined with the receiver's subdirectory Payjoin Session public key. The resulting HPKE payload body is then encapsulated according to Oblivious HTTP as a POST request to the directory's OHTTP Gateway.
The Original PSBT is serialized in base64, followed by the query parameter string on a new line. This plaintext string is encrypted according to HPKE using a shared secret derived from the sender's Payjoin Session public key combined with the receiver's subdirectory Payjoin Session public key. The resulting HPKE payload body is then encapsulated according to Oblivious HTTP as a POST request to the directory's OHTTP Gateway to the receiver's payjoin session subdirectory.

Upon receipt, the directory's OHTTP Gateway decapsulates the OHTTP request and handles the inner POST request at the Payjoin Session subdirectory endpoint, which stores the HPKE encrypted payload to be forwarded to the receiver. The directory's OHTTP Gateway awaits a request from the receiver to the Payjoin Session subdirectory endpoint and responds with the HPKE encrypted Original PSBT payload acording to OHTTP.
Upon receipt, the directory's OHTTP Gateway decapsulates the OHTTP request and handles the inner POST request at the receiver's Payjoin Session subdirectory endpoint, which stores the HPKE encrypted payload to be forwarded to the receiver.

The sender then polls GET requests to the receiver's Payjoin Session subdirectory endpoint in order to await a response from the directory containing a <code>Payjoin PSBT</code>. It stops polling after expiry.

====Receive Messaging====

The receiver sends a GET request to the path of the subdirectory. This request is encapsulated in OHTTP.
The receiver then awaits an OHTTP response from the directory encapsulating a request from the sender with status code 200 OK, and otherwise continues to poll by sending a new OHTTP request after receiving an encapsulated 202 ACCEPTED response notifying the receiver that the directory has not yet received a request from the sender.
After sharing the Payjoin URI with the sender, the receiver sends a GET request to the path of the receiver's Payjoin Session subdirectory. This request is encapsulated in OHTTP. It continues to poll by sending a new OHTTP request after receiving an encapsulated 202 ACCEPTED response notifying the receiver that the directory has not yet received a request from the sender.

Upon receiving OHTTP response from the directory encapsulating a request from the sender with status code 200 OK, the receiver decrypts the payload and checks the <code>Payjoin PSBT</code> according to the [[#receivers-payjoin-psbt-checklist|checklist]].

The receiver then updates the <code>Original PSBT</code> to include new signed inputs and outputs, invalidating sender signatures, and may adjust the fee. The result is called the <code>Payjoin PSBT</code>.

Once an Original PSBT Payload is decrypted and checked according to the [[#receivers-payjoin-psbt-checklist|checklist]], the receiver should respond with a Payjoin PSBT or an error. The receiver encrypts the PSBT according to the HPKE protocol, generating an ephemeral keypair from which it derives a shared secret with the sender's key <code>e</code> from the payload. It generates a nonce from sufficient randomness, and constructs a ciphertext containing the Payjoin PSBT and serialized receiver ephemeral key <code>e</code>'s public key as associated data using ChaCha20Poly1305. A payload is constructed by concatenating the ephemeral public key, the nonce, and the ciphertext. This Payjoin PSBT payload is then sent to the directory in an OHTTP request encapsulating the binary payload as a PUT message to the subdirectory.
The receiver encrypts the <code>Payjoin PSBT</code> according to the HPKE protocol, generating an ephemeral keypair from which it derives a shared secret with the sender's Payjoin Session public key from the payload. It generates a nonce from sufficient randomness, and constructs a ciphertext containing the Payjoin PSBT and serialized receiver ephemeral key <code>e</code>'s public key as associated data using ChaCha20Poly1305. A payload is constructed by concatenating the ephemeral public key, the nonce, and the ciphertext. This Payjoin PSBT payload is then sent as a POST message to the directory in an OHTTP request encapsulating the binary payload to the sender's Payjoin Session subdirectory.

===Receiver's Payjoin PSBT checklist===

Expand All @@ -177,7 +177,7 @@ The Payjoin Directory provides a rendezvous point for sender and receiver to mee

===Subdirectories===

Each Payjoin Session subdirectory allocated on the directory has one buffer for requests and one for responses. Each buffer updates listeners through awaitable events so that updates are immediately apparent upon client request.
Each Payjoin Session subdirectory allocated on the directory has one buffer for a PSBT payload. The buffer updates listeners through awaitable events so that updates are immediately apparent upon client request.

===Receiver fragment parameters===

Expand All @@ -196,7 +196,7 @@ Using the fragment for Payjoin URI parameters makes for more compact QR codes to

===Optional sender parameters===

When a Payjoin sender posts an Original PSBT to the receiver, the sender should specify the following HTTP query string parameters:
When a Payjoin sender POSTs an Original PSBT to the receiver, the sender should specify the following HTTP query string parameters:

* <code>v</code>: represents the version number of the Payjoin protocol that the sender is using. This version is <code>2</code>.
Expand Down

0 comments on commit c917eab

Please sign in to comment.