The win for today: after this lesson you can explain what a Cashu token is made of, and trace the full life of a sat through the system: mint → send → swap → melt. Everything else in Cashu — every API endpoint you'll ever debug — hangs off this skeleton.
You know onchain: global consensus, everyone verifies everything, slow and public. You know Lightning: channels, invoices, fast and cheaper. Cashu is a third layer with a very different trust model:
A mint is a server. You pay it over Lightning; it hands you back ecash tokens — bearer IOUs it has signed. Later, anyone holding those tokens can redeem them at the same mint. The trade you're making is explicit: the mint custodies the bitcoin and can rug you, but in exchange you get something neither onchain nor Lightning gives you: the mint cannot see who pays whom, and payments are instant, offline-transferable strings of text.
Why can't the mint see anything? That's the 1982 David Chaum trick that gives "Chaumian mint" its name — the blind signature.
Imagine you write a serial number on a slip of paper, seal it in an envelope lined with carbon paper, and hand it to a bank. The bank stamps the outside of the envelope; the carbon paper presses the stamp through onto your slip. You take the envelope home, open it, and now hold a slip that carries a valid bank stamp — but the bank has never seen your serial number.
Later, someone shows up at the bank with that slip. The stamp checks out, so the bank honors it. But the bank cannot connect this slip to any particular stamping visit — it stamped only sealed envelopes. That's unlinkability: the bank knows how much it issued and redeemed, but not who paid whom.
In Cashu, the actual mechanism is elliptic-curve math called BDHKE (we'll do it properly, with real variables, in the next lesson). For today, map the story to the protocol words:
| Story | Cashu term | JSON model |
|---|---|---|
| Serial number on the slip | the secret x — a random string your wallet generates | "secret" field |
| Sealed envelope | BlindedMessage B_ — the secret, hidden by a blinding factor | {"amount", "id", "B_"} |
| Stamp on the envelope | BlindSignature C_ — mint signs the blinded thing | {"amount", "id", "C_"} |
| Opened slip with stamp | Proof — secret + unblinded signature C. This is the token. | {"amount", "id", "secret", "C"} |
The one thing to internalize: a Cashu token is a Proof — just data: an amount, a keyset id, a random secret, and the mint's signature over that secret. Whoever knows it, owns it. Copying the JSON is stealing the money. There is no ledger of accounts anywhere; your wallet's "balance" is literally a local database of Proofs.
Two consequences you'll use constantly when building wallets:
cashuB… string and gives it to Carol. Any channel works — QR, DM, paper.Note the symmetry with Lightning at the edges: mint = sats flow in via LN, melt = sats flow out via LN. In between, the mint's Lightning node holds the actual bitcoin while tokens circulate off-ledger.
Step 3 is the non-obvious one. Why must Carol swap? Because Alice still has a copy — she sent Carol a copy of data, not a physical object. Until Carol swaps, both of them can redeem those Proofs, and it's a race: first secret to hit the mint's spent-list wins. Swapping (POST /v1/swap: old proofs in, new blind signatures out) invalidates Alice's copy and gives Carol proofs whose secrets only she has ever seen. The same endpoint doubles as the "make change" operation — swap a 32-sat proof for 16+8+8 when you need to pay 24.
Debugging instinct #1 (you'll build many): almost every "my payment is stuck / my token is invalid" report resolves to one question — is this proof's secret already on the mint's spent list? Unspent, spent, or pending is the first thing to check (there's an endpoint for it: NUT-07 /v1/checkstate).
From memory — no scrolling up. Retrieval is the point.
Primary source: read NUT-00: Cryptography and models — it's short, and after this lesson every model in it (BlindedMessage, BlindSignature, Proof) should feel familiar. The math section will be the subject of the next lesson, so a first skim is enough.
Keep the protocol cheat sheet open whenever you work — it compresses this lesson plus the endpoints and BDHKE variables into one page.