Shielded pool
The shielded pool is the ZK core of Cowl. It is where your assets stop being public numbers and become private notes that only your keys can read.
How it works
When you shield funds, the deposit becomes a note and a commitment — a hash of that note — is added to a Merkle tree on Robinhood Chain. The tree records that some note exists. It reveals nothing about the amount or the owner.
To spend or trade, you publish three things:
- A
nullifierderived from the note, which marks it spent and blocks double-spends. - New commitments for the output notes (your change, the counterparty’s receipt).
- A
ZK proofthat the input note is in the tree and yours — proving membership without revealing which leaf.
What the explorer sees
| On the public ledger | Visible? |
|---|---|
| A commitment was added | Yes — but it is an opaque hash |
| A nullifier was spent | Yes — but it links to no address |
| Amount, asset, cost basis | No |
| Who owns which note | No |
Your shielded portfolio
Your balance is the sum of the notes your viewing keycan decrypt. Cost basis, size, and unrealized P&L are computed client-side from those notes. No wallet-watcher can reconstruct your book, because the book never existed in the clear.
Two in, two out
A spend reads two notes and writes two. That single fact explains most of what you will notice in practice:
- Your ceiling is not your balance. The most you can move in one operation is the sum of your two largest notes. Ten small notes and a big total still means a small maximum.
- Merging fixes it, in rounds. Each round retires two notes and mints one, so n notes settle in n − 2 rounds. Both clients merge the two largest first and show the bill — rounds, fee per round, total — before running anything.
- A merge and a payment look identical on chain. Two nullifiers, two commitments, a proof. Nobody watching can tell which one you just did.
Value cannot leave that did not enter
The pool tracks, per token, exactly what was deposited into it, and refuses any withdrawal past that figure. It is a hard cap in the contract rather than a check the client is trusted to make, so even a broken proof system could not print value out of the pool. It is reconciled against the pool’s real balance continuously, from outside — see monitoring.
Hygiene at the edge
Privacy inside the pool is strong. The one place metadata can leak is the boundary — the moment you shield or unshield. Both clients keep that edge clean by default, and a few habits finish the job:
- Amounts cross the boundary in shared denominations — powers of ten around one whole token — so every 0.1 looks like every other 0.1. That is the default; keep it, and save
--exactfor when you know why. - Let time pass between shielding and your first shielded action.
- Unshield to a fresh address, not the one you deposited from — and hand the spend to a
relayerwith--relay, so the fresh address needs no gas and your wallet never submits a thing.