🔗Reusable Payment Codes (BIP47)

Publish one code on your website. Anyone — forever — can send you unlimited unlinkable stealth payments without ever asking for a fresh address.

The problem

Stealth addresses are great, but for an ongoing relationship — a vendor, a donation address, a paying client — the sender needs your stealth address each time, or has to maintain a contact channel. BIP47 fixes this with a one-time notification transaction that establishes a permanent shared secret.

Activation Available from genesis. No height gate.

How it works

  1. Alice generates a single payment code she can publish anywhere
  2. Bob sends a tiny notification TX to Alice's notification address — it carries Bob's payment code, blinded with an ECDH shared secret, in OP_RETURN
  3. Now Bob (or anyone with the same payment code relationship) can derive infinite unique stealth addresses for Alice without further interaction
  4. Each subsequent payment is a fresh stealth output. The notification TX itself reveals only that some notification happened — not the payment code relationship

Step-by-step

  1. Get your payment code

    $ MaryJaneCoind getpaymentcode
    {
      "payment_code": "PM8TJJvP5XPvcn4oy75XBydTpZrZxtKSYBqRtj7WuVywEYaWJmWcnpPyCi2AZVhbtZudqu4Go2fGQeFdeyRFtqtwkjRkmFPPWFDkLYvtpGPBeipi8nG4",
      "notification_address": "MPNLrBVBYYWKpSNdKJ3ABipZEUC8aDvsYZ",
      "scan_pubkey": "0209683bcb222d6f8f8d0c9d13432a...",
      "spend_pubkey": "0328c613cd05ba604e049acfc5cdf1..."
    }

    Publish the payment_code string anywhere — Twitter bio, website, QR code, business card.

  2. Sender: establish a payment channel

    To send Alice money the first time, Bob runs:

    $ MaryJaneCoind sendtonotify "PM8TJJvP5XP..."
    {
      "txid": "abc123...",
      "notification_address": "MPNLrBVBYY...",
      "status": "notification_sent"
    }
  3. Receiver: scan for incoming notifications

    $ MaryJaneCoind scannotifications
    2   # found 2 inbound payment-code notifications
  4. Send unlimited payments — no more interaction

    Once the channel exists, Bob can derive any address index for Alice:

    $ MaryJaneCoind deriveaddress "PM8TJJvP5XP..." 0
    {"index": 0, "address": "MQx7k9f..."}
    
    $ MaryJaneCoind deriveaddress "PM8TJJvP5XP..." 1
    {"index": 1, "address": "MRy8l0g..."}

    Each address is a fresh DKSAP destination — same privacy as standard stealth.

  5. List all your payment relationships

    $ MaryJaneCoind listpaymentcodes
    [
      {
        "payment_code": "PM8TJKx...",
        "label": "Bob",
        "notification_sent": true,
        "notification_received": true,
        "next_send_index": 3,
        "next_recv_index": 1
      }
    ]

Notification blinding

The 80-byte payment-code payload is XOR-masked with ECDH(sender_scan_priv, receiver_scan_pub). Only the recipient can unblind it. Observers see a notification TX exists, but cannot identify which payment code it carries — preventing attackers from building a directory of "who knows whose code".

Use cases Donation pages, vendor checkouts, recurring subscriptions, podcast tip jars — anywhere you want a single permanent identifier without sacrificing per-payment privacy.