forked from btcpayserver/BTCPayServer.BIP78
/
README.md
57 lines (46 loc) · 4.41 KB
/
README.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# BIP78 Addendum: Payjoin over Nostr
This addendum describes a variant of BIP78 Payjoin that uses the Nostr protocol to negotiate the transaction instead of an HTTP endpoint operated by the receiver.
## Motivation
The main motivation for this addendum is to allow Payjoin to be used in a peer-to-peer fashion, without requiring the receiver to operate a server. This is useful for mobile wallets, which are often not always online, and for privacy reasons may not want to reveal their IP address to the sender.
## Protocol
The protocol is identical to the [BIP78 Payjoin protocol], except that instead of specifying an HTTP endpoint in the `pj` query string of BIP21, the receiver provides a Nostr NIP21 URI, containing either an `npub` or `nprofile`.
The public key encoded in the `npub` or `nprofile` is recommended to be generated as a one-time use keypair, and not reused for any other purpose. An expiry can be explicitly specified and added as a query string to the uri with the key `expiry`, so that senders would know if it is too late to attempt connection.
The receiver must be connected to the relays they specify, and for every new payment request generated, must adapt their subscription to listen for events with the `p` tag matching the public key specified in `npub` or `nprofile`.
A sender then connects to the relays specified in the `nprofile` (if `npub`, the sender connects to relays that the receiver is most likely connected to), and publishes an event with the following criteria:
* a `p` tag with value of the public key specified in `nprofile` or `npub`
* a `kind` with value 4, and also following NIP4's message encryption protocol.
* a `created_at` with a value of the current time in UTC
* a json object stringified as the content of the event (before encryption) with the following format (note that all parameters are defined in BIP78)
```json
{
"psbt:": "base64 encoded psbt",
"parameters": {
"version": 1,
"maxAdditionalFeeContribution": 1000,
"additionalFeeOutputIndex": 0,
"minFeeRate": 10,
"disableOutputSubstitution": false
}
}
```
* the private key used to sign the event is a unique one-time key generated by the sender, and is not reused for any other purpose.
Once published, a receiver is notified through their Nostr subscriptions, and can decrypt the PSBT. Once the PSBT is received, the BIP78 flow continues as normal.
If there is an error, the receiver should publish an event with the following criteria:
* a `p` tag with value of the public key used by the sender
* an `e` tag with the event id of the event that the sender published
* a `kind` with value 4, and also following NIP4's message encryption protocol.
* a `created_at` with a value of the current time in UTC
* a json object stringified as the content of the event (before encryption) with the format as specified by the BIP78 protocol
If the proposal PSBT was successfully computed, the receiver should publish an event with the following criteria:
* a `p` tag with value of the public key used by the sender
* an `e` tag with the event id of the event that the sender published
* a `kind` with value 4, and also following NIP4's message encryption protocol.
* a `created_at` with a value of the current time in UTC
* the PSBT in base64 format as the content of the event (before encryption)
## Reasoning for design choices
* NIP04 messages are used to encrypt the contents, and are indistinguishable from other non-payjoin related messages sent over the Nostr network.
* A new key is used for every request sent to a payjoin endpoint, to prevent correlation between requests.
* The receiver is not required to be online at the time of the request, and can receive the request at a later time when they are online to process.
* Nprofile, npub and hex representations of the nostr public key are supported, but nprofile is recommended as it allows the receiver to tell the sender which relays the receiver is directly connected to (one can still have relay proxies that provide a bridge).
* A new key for every payment request is desirable, to prevent correlation between requests. However, it is not required, and the sender can reuse the same key for multiple requests if they wish to do so.
* A wallet is able to create a static nostr endpoint that is not intended to process receiving transactions, but instead act as a public, transaction enhancement endpoint. This allows wallets that support payjoin to still use payjoin, even if the receiving wallet does not.