Lose the thread
in the crowd.
Swirlpool lets you feel how a mixer-style pool works: drop equal notes into a shared pool, wait, withdraw to fresh addresses — and watch the crowd size k grow, shrink and collapse as you make the classic mistakes.
Watch the anonymity set move.
Every deposit creates a real random nullifier and secret and a SHA-256 commitment via crypto.subtle. Withdrawals check a real Merkle proof and burn a real nullifier hash. The observer analysis below the graph is computed live from the public ledger.
1 · Deposit
2 · Wait
3 · Withdraw
Observer model
Private notes (what holders keep)
| # | owner | amt | commitment |
|---|
Public ledger (what an observer sees)
| time | event | amt | address | hash | k / eff. |
|---|
Hidden vs. public.
The privacy of a pool is the size of the crowd that looks identical from the outside. Everything else in this demo is about the ways that crowd gets thinned out.
Commit
You pick a random nullifier and secret and publish only SHA-256(nullifier ‖ secret). That commitment becomes a leaf in a Merkle tree.
Let the crowd grow
Each extra equal-sized deposit is one more candidate source. Waiting also spreads timing, so "just deposited" stops being a clue.
Prove & burn
You show a leaf is in the tree and publish SHA-256(nullifier), which can be used only once — that stops double-spends.
Fresh address
Funds go to an address never used before. If that address already touched your deposit, the pool did nothing for you.
Public on the ledger
- every commitment, its time, amount and depositing address
- every nullifier hash, its time, amount and destination address
- the Merkle root at each moment
- how many equal notes exist (that is k)
Hidden by the design
- which commitment a given nullifier hash belongs to
- the nullifier and secret themselves
- who controls which note
- the true deposit→withdrawal links (the amber lines)
Known limitations — please read
- It is a simulation. There is no pool contract, no chain, and no funds. Nothing you do here moves value, and the addresses are random bytes, not wallets.
- Not zero-knowledge. The demo checks a Merkle path in the clear, which reveals the leaf position to the verifier. A real mixer proves membership in a zk-SNARK without revealing it. The "hidden" link here is hidden by the interface, not by cryptography.
- Privacy scales with set size. With k = 3 you are one of three; that is weak. A big k only helps if the notes in it are genuinely indistinguishable.
- Unequal amounts re-link you. The "Odd amount" button shows it: a note nobody else matches has k = 1. Real pools use fixed denominations for this reason.
- Timing re-links you. Withdrawing soon after depositing collapses effective k. The observer model here is a toy (power-law weight on recency, adjustable); real analysts use more signals than this.
- Address reuse and funding re-link you. Sending to an address that already touched the pool, funding the exit address with gas from your own wallet, or trading from it in a recognisable pattern all reconnect you off-pool.
- It models one attack family. It does not model intersection attacks over many rounds, network-level metadata (IP, RPC), relayers, or off-chain leaks.
- Unaudited toy code. SHA-256 and a binary Merkle tree are used for clarity, not the zk-friendly primitives a production system needs. The numbers on this page are for the session you generate; no real-world statistics are claimed.
- Use lawfully. Mixing services are restricted in some jurisdictions. You are responsible for following the laws and tax rules that apply to you.
What exists, what doesn't.
If it isn't live, it says Coming Soon. There is no token, no deployed program and no audit.