Skip to content

Instantly share code, notes, and snippets.

Last active December 28, 2022 14:19
What would you like to do?

Coinjoin implementation using nostr

  1. Input registration:

    5 users publish inputs using nostr

import requests
import pexpect

url = ""

headers = {
    'Authorization': 'Basic dXNlcjpwYXNz',
    'Content-Type': 'text/plain'

def publish():
    noscl = pexpect.spawn ('noscl publish "' + input + '"')
    noscl.expect ('Seen ')
    output = str(
    eventid = output.replace('b"','').replace(" on 'wss://'.","").replace('\\r\\n"','')

    return eventid

def listunspent():

    payload = "{\"jsonrpc\": \"1.0\", \"id\": \"joinstr\", \"method\": \"listunspent\"}"
    response = requests.request("POST", url, headers=headers, data=payload)

    i =0
    for i in range(0,len(response.json()['result'])):
        txid = response.json()['result'][i]['txid']
        vout = response.json()['result'][i]['vout']
        amount = response.json()['result'][i]['amount']
        print(txid, ",",vout ,",",amount)
        i = i + 1

if __name__=="__main__":

    utxo_list = listunspent()
    input = input("Enter input for registration (txid,vout): ")
    eventid = publish()
  1. Output registration:

    5 users share a new address for output.

  2. Create and publish tx:

    User that registered the last output creates a PSBT with all inputs, outputs using createpsbt and publishes it.

  3. Sign and broadcast tx:

    All users verify, sign with walletprocesspsbt and publish PSBT. Last user that signs the transaction, combines them with combinepsbt, finalize with finalizepsbt and broadcast with sendrawtransaction.

Example of a coinjoin transaction:


Things that could be improved:

  1. Relay shares a random number with first input and same number with next 4 inputs registered. Clients will mention this number in the request sent for registering outputs to prove they own one registered input in this round. If more than 5 outputs are registered for a round its cancelled.

  2. Use new private key for nostr and a new tor circuit every time soemtihng is published using nostr.

  3. Break UTXOs in pool denominations before coinjoin if amount exceeds pool denomination by more than 200 sats.

  4. Create an Android app that connects with bitcoin core and makes it easier to do coinjoin.

Copy link

Checkout Coinshuffle for a sophisticated decentralized coinjoin coordination scheme.

Single denomintion rounds are very blockspace expensive and create non-private change or loss, so consider multi-standard-denominations [low hamming weight numbers are efficient in decomposition].

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