Privacy Pools
The Core Idea
Privacy Pools break the public link between deposits and withdrawals.
Users deposit funds into a shared pool and later withdraw using zero-knowledge proofs that demonstrate:
- they own a valid deposit, and
- the deposit has not been spent before
without revealing which deposit it was.
Key Concepts
| Term | Meaning |
|---|---|
| Commitment | A cryptographic representation of a deposit |
| Nullifier | A value revealed at withdrawal to prevent double-spending |
| Merkle Tree | A structure that allows proving membership without revealing position |
| Zero-Knowledge Proof | A proof that verifies correctness without revealing private data |
A Simple Example
Alice deposits 1 ETH:
- A commitment is added to the pool
- Alice stores a secret locally
Later, Alice withdraws 0.3 ETH:
- She generates a proof: "I own some deposit in the pool"
- She reveals a nullifier (marking that deposit as spent)
- She receives 0.3 ETH
- A new commitment (0.7 ETH) is created as change
On-chain observers see:
- A deposit occurred
- A withdrawal occurred
- A nullifier was spent
They cannot link the withdrawal to the original deposit.
Commitments
When a user deposits, a commitment is created and added to a Merkle tree.
- Commitments are public
- The underlying secret is known only to the depositor
- Commitments cannot be reversed or linked to a future withdrawal
Nullifiers
When withdrawing, the user reveals a nullifier derived from their secret.
- Each deposit has exactly one nullifier
- Once revealed, it is marked as spent
- This prevents double-spending without revealing deposit identity
Zero-Knowledge Proofs
Each withdrawal includes a zero-knowledge proof that verifies:
- The user owns a valid commitment in the pool
- The nullifier is correctly derived and unused
- The deposit belongs to an approved compliance set (via ASP)
The proof reveals nothing about:
- Which deposit was used
- When it was created
- Who created it
Merkle Trees
Shinobi Cash maintains two Merkle trees:
| Tree | Purpose |
|---|---|
| Pool State Tree | Contains all deposit commitments (the full anonymity set) |
| ASP Tree | Contains only commitments approved by an Association Set Provider |
Both trees are referenced inside the withdrawal proof.
Withdrawal Variants
| Type | Description |
|---|---|
| Single note | Same-chain withdrawal from one deposit |
| Two notes | Spend two deposits in one withdrawal |
| Crosschain | Withdrawal to another chain via a solver |
| Crosschain (two notes) | Two-deposit withdrawal delivered crosschain |
All withdrawals:
- Are unlinkable to deposits
- Always create a change commitment with the remaining amount
- Never expose deposit identity
What's Hidden vs Revealed
| Hidden | Revealed |
|---|---|
| Which deposit was spent | That a valid deposit exists |
| Deposit history | The nullifier (once spent) |
| Link to identity | Withdrawal amount |
| Recipient address |
Privacy depends on using the system correctly (e.g., avoiding timing or amount correlation).
Learn More
- Crosschain Architecture — How privacy works across chains
- Compliance — Association Set Providers
- Smart Contracts — Implementation details