A SeedSigner seed already produces the silent-payment address other wallets expect. We paid that address on Bitsaga Signet, the receiver side recomputed the same output from the scan key, and we spent it. The payment confirmed in block 79148, the spend in 79149. What is still missing is a menu on the device, and a simulator firmware that shows the address.
This is the first half of a world-first we have been aiming at: silent payment receiving on a signing device. No released hardware wallet can do that today. The second half is the screen. This sitting did the maths and the chain, not the firmware.
I wrote this overnight with an AI, then checked every claim against source or against a live signet proof. The test seeds are published on purpose. They hold no real bitcoin. Do not type a real seed into any of this.
What this is and is not
It is a working receive and spend of a BIP-352 output, derived the way SeedSigner pull request #769 would derive it. It is not a SeedSigner release, not a simulator menu, and not a design for who should hold the scan key.
The gap this is trying to close
A silent payment address is one string you can publish once. Each payer derives a fresh taproot output that only you can spend. Two people who paid you cannot tell they paid the same person. I wrote the usable-name half of that story in I replaced my bitcoin address with a name.
The hardware half is stuck on send. Coldcard, Krux, Passport and SeedSigner all have work in flight for paying an sp1 address. Receiving means deriving the address, scanning the chain, and spending what arrives. No released signer does that.
SeedSigner is the right first device. The seed never lives on the board. The code is public. We already run the real Python in a browser simulator. And pull request #769 already generates the address, plus the spscan watch key Sparrow wants. It has been quiet since June 2026. The author, notTanveer, said address generation only really makes sense once you can also spend, and moved to send-side work (SeedSigner #949, blocked on embit #145).
So the unfinished SeedSigner receive work is sitting there, with published test seeds, and nobody has taken it through a real payment.
The address matches the published answers
BIP-352 puts two keys under the seed:
scan m/352h/{coin}'/0h/1h/0
spend m/352h/{coin}'/0h/0h/0
Coin type 0 is mainnet (sp1). Coin type 1 is testnet and signet (tsp1). Encode those two public keys and you have the address a payer types.
earthdiver published four test seeds on #769 on 23 May 2026, with unlabeled addresses, labels 0, 1 and 2, and the spscan watch key. We derive them the same way #769 does, through notTanveer's embit branch feat/silent-payments-V2. All four seeds match on every field we check.
| Seed (first words) | Network | Unlabeled address starts |
|---|---|---|
| initial tilt corn… | signet | tsp1qqfvn9pmv…ph7a |
| tongue vanish post… | mainnet | sp1qq2c4jvrj…ty23x |
| index today witness… | signet | tsp1qqvdcq76j…824hd6 |
| fold cotton pipe… | mainnet | sp1qq25f3laf…k2w7lh |
Label 0 is reserved for change in BIP-352. embit's generate_silent_payment_address refuses it. The test set still publishes it, so we apply the label and encode it ourselves. Labels 1 and 2 go through the normal helper. All three match.
That is the proof a future SeedSigner screen would show the same string Sparrow already understands. If the vectors stay green, the device is not inventing a private dialect.
Then we paid it
Matching a string is not receiving. Receiving is: someone pays, you find the coin, you spend it.
We used the first published seed as the receiver, on Bitsaga Signet. The sender is the well-known throwaway BIP39 line (abandon eleven times, then about), first receive address tb1q6rz28mcfaxtmd6v789l9rrlrusdprr9pqcpvkl. The faucet paid it. The sender built a BIP-352 output from its own key and the outpoint it was about to spend. The receiver, holding only the scan key and that same outpoint, derived the same output key.
The derived taproot address was:
tb1p7ta63uxzdyzszfc3t7ryfueydhnd6skhspkhsss3l78lvnaje56qnxszp6
400,000 sat landed there. The send transaction is 71fb91163c8723b9e2ffe7c53c2981258c736ae18338d69a9cd35a215ffc7fdf. The spend went to a different address, tb1qd7spv5q28348xl4myc8zmh983w5jx32cjhkn97, as c7b0913eb3fac782989101a5054f8dbb2e3aa40e6a930fa7a1f7293c58c78083. Both return 200 from /tx-proof, with a merkle branch you can check in a browser the same way the signet page already does for blocks.
The shared secret tweak was 75fccaf2f0ab0a332ff98c99ae0a02776bea15ccf8b279ab3a3199f5881af9b3. The output x-only key was f2fba8f0c269050127115f8644f3246de6dd42d7806d784211ff8ff64fb2cd34. Anyone with the published test seed and the sender outpoint can recompute both.
The easy way to get this wrong
embit's p2tr() applies BIP-341's TapTweak on top of the key you hand it. A silent payment output is already the tweaked key: B_spend + t_k·G. Script is OP_1 plus that x-only key, nothing else. If you wrap it in p2tr(), you pay a different address, the receiver cannot see the coin, and a spend of the key you thought you had will not match the chain.
Spend is the spend private key plus the same tweak, forced to even Y, then a Schnorr signature with SIGHASH_DEFAULT. That is what confirmed in 79149.
What we did not finish
The SeedSigner menu in #769 is real work: address screen, label entry, scan-key warning, spscan export. We did not port that onto a device, and we did not load it into the browser simulator. The simulator firmware zips are built in a separate repo. They are not in this one.
We also did not solve the scan-key problem. The scan private key sees every payment you will ever receive. Handing it to a server is how most wallets make silent payments usable today, and it is a strange price for privacy. The earlier piece covers that. This sitting ignored it on purpose, so the receive path could be proven at all.
An earlier loop paid the same address and spent it in block 79138. That spend went back to the sender's change address, so a naive "wait until that address has a coin" returned the leftover change, not the spend. The spend itself still confirmed. The run above pays a different address and waits for that exact txid.
How to replay it
The code lives in this repo under research/seedsigner-sp. Published test seeds only.
cd research/seedsigner-sp
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python test_vectors.py
.venv/bin/python loop.py
test_vectors.py is the address proof. loop.py is the signet send, detect, and spend. It writes RESULT.json with the txids. The faucet and the scanner are the public Bitsaga Signet API. Nothing here talks to mainnet.
Every mnemonic in this article and in that folder was published so other people can check the arithmetic. If a later SeedSigner screen shows you an sp1 address from your own seed, compare it to an independent wallet. Do not paste your seed into a script on a laptop to "just check".
What happens next
The remaining work is firmware. Take #769, keep the derivation that already matches, put the address on a SeedSigner screen, and load that build into the simulator so someone can see it without a Pi. Then spend from the device, not from a script. That is the world-first. This page is the proof that the address you would show is already the right one, and that a coin sent to it can be found and spent.
If you want a name that points at an address like this, that part is already live at silentpayments.net. The constraint was never the name. It was a signer that can receive.