Skip to content

Instantly share code, notes, and snippets.

  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Author: Kukks

New protocol design: Discrete Payments through Wabisabi coinjoins and Nostr ecnrypted communication

  1. Merchant creates invoice of 0.1BTC
  2. Merchant generates a unique key for invoice
  3. Merchant shows the pubkey of (2), a recommended nostr relay uri
  4. Customer generates a unique key for this invoice payment
  5. Customer posts an encrypted event addressed to pubkey of (3) with a message stating intent to pay invoice of 0.1BTC using a specific wabisabi coordinator
  6. Merchant replies with an encrypted event with acknowledgement (or rejects)
  7. Customer joins next round, adds inputs >0.1 BTC, gets credentials
  8. Customer reissues credentials, gets one credential of 0.1BTC
  9. Customer posts an encrypted event addressed to pubkey of (3) with the credential in a text format
  10. Merchant reissues credentials
  11. Merchant replies with an encrypted event with acknowledgement (or rejects)
  12. Round enters output registration stage
  13. Merchant registers outputs
  14. Round enters tx signing stage
  15. Merchant verifies output is there
  16. Merchant replies with an encrypted event stating payment is present in tx hash
  17. Customer verifies round tx equals hash
  18. Customer signs


  • a pseudo nostr relay will connect to multiple relays and retrieve all relelavnt events and aggregate. This will then serve them in a unified entrypoint, allowing users to not leak their ip to a dedicated nostr relay for private payments
  • Customer specifies which coordinator to use, not tied to only one
  • Merchant can provide own coins to same coinjoin to increase anonymity
  • Can theoretically chain the payments to other hops within the same coinjoin, serves as a trustless, private layer 3 equivalent to ecash systems, without the custodians (but with a much stricter time horizon)
Copy link

Kukks commented Jan 10, 2023

Pros over normal payjoin:

  • don't need to start a web server (because of nostr, I think we can do the same for payjoin though)
  • Sender does not reveal his coins to the receiver
  • Receiver does not reveal where he received his coins
  • Dos protection included in coinjoin protocol itself
  • You can do multiple hops of payments between different users, as long as the round hasn't ended yet.
  • Cost can actually be decent. Entering a coinjoin with readymixed coins is free. Coins under 1m sats are also free to join a round. Coins one hop away from a previous coinjoin are also free. You pay for your inputs and output mining cost but in payjoin you pay for those plus tx body and at least one of the receivers input cost

Copy link

Kukks commented Jul 21, 2023

Receiver creates payment link bip21: bitcoin:address?amount=1&ws="npub1..." (BIP21)
Share payment link to Sender
Sender parses the ws value, extracting a public key (KEYRECEIVER1) and a set of relay uris

Sender creates a new ephemeral key (KEYSENDER1) and creates a dedicated tor circuit
Sender connects to nostr relays using previously created tor circuit
Sender sends a NIP4 event (EVT1) using key KEYSENDER1 as author, addressed to KEYRECEIVER1, with contents:

coordinatorsSupported: ["", "zyx.onion"]

Receiver chooses a coordinator from list CHOSENCOORD
Receiver replies to EVT1 with a new event (EVT2), with contents:


Sender waits for a round to be present that has at least X minutes remaining in input registration, ROUNDX
Sender replies to EVT2 with a new event (EVT3), with contents:


Sender joins round ROUNDX, registers utxos and receives credentials, then reissues into 2 credentials: CREDENTIALPAY and CREDENTIALCHANGE
Sender replies to EVT3 with new event (EVT4) with contents:


Receiver joins round {ROUNDX}, reissues {CREDENTIALPAY}, registers additional UTXOs
When Round switches to ReadyToSign, RECEIVER sends a new event (EVT5) to Sender with contents:


Sender signs coinjoin
Receiver signs coinjoin
Receiver marks payment as received (but not settled)
On successful round and transaction confirmation, mark payment as settled

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment