The ideas you need to use zkSVM well, in plain words. None of it is required reading — the app works without it — but ten minutes here makes everything else in these docs obvious.
Notes
Your shielded balance is not a number stored somewhere. It is a handful of notes, like banknotes in a wallet. Each note has an amount and an owner.
- Shielding 3 SOL gives you one note worth 3.
- Sending 1 SOL from it spends that note and creates two new ones: 1 for the recipient, 2 back to you as change.
- Your balance is the sum of your unspent notes.
This is why the app sometimes talks about notes rather than balances. One transfer can spend at most two notes, and one unshield exactly one. If your balance is spread over many small notes, you merge them by sending to yourself. See Notes and balance.
A balance that earns
A note holds an asset: SOL, or a token. By default the app shields your SOL as jitoSOL — it is staked with Jito in the same transaction — and jitoSOL is worth a little more SOL every epoch. Nothing inside the pool has to track that. The note says 1.15 jitoSOL forever; what 1.15 jitoSOL is worth is what changes.
SOL notes and jitoSOL notes share the same pool, and a transfer never shows which kind it moved. When you unshield, the pool redeems the jitoSOL and the recipient gets SOL. See Earn while shielded.
Commitments and the tree
The chain never sees a note. It sees a commitment — a hash of the note that gives nothing away — and adds it to a Merkle tree. The tree holds up to 2²⁶ notes, about 67 million, in an account that never grows.
Every commitment looks like every other. An observer cannot tell a 0.01 SOL note from a 10,000 SOL note, or yours from anyone else's.
Spending, and why it cannot happen twice
To spend a note you publish its nullifier: a second fingerprint that only the note's owner can compute, and that cannot be linked back to the commitment. The program records the nullifier as a tiny account. If the same nullifier ever shows up again, creating that account fails — that is the whole double-spend check.
The zero-knowledge proof ties it together. It shows that the nullifier belongs to some note in the tree, that you own that note, and that value in equals value out. It does not show which note.
Your keys
Your spending key is derived from one signature by your Solana wallet over a fixed message. Signatures are deterministic, so:
- the same wallet always opens the same shielded balance,
- there is no seed phrase to write down beyond your wallet's own,
- and the signature is the key — only sign the unlock message on the real app.
From the spending key come two public values, which together are your
shielded address (zks…): one names you as an owner, the other lets
senders encrypt a note so that only you can read it.
More in Keys and recovery.
Three kinds of owner
| Owner | Spent by | Used for |
|---|---|---|
| A spending key | a proof that you know the key | your own balance, payments to zks… addresses |
| A Solana address | that address signing the transaction | paying anyone, no setup; programs and multisigs holding shielded value |
| A condition — this address, or the sender after a date | whichever applies | payments that come back |
All three live in the same tree and look identical from outside.
Finding your notes
When someone pays you, the note is encrypted to your key and published next to its commitment. Your wallet tries to decrypt every note in the pool; the ones that open are yours. This is why the app syncs the whole pool: asking a server "which notes are mine?" would tell the server exactly that.
What the chain does see
Going in and coming out are public: a shield shows the depositor and the amount, an unshield shows the recipient and the amount. What is hidden is everything in between, and the link between the two ends. The Privacy model lists it operation by operation, and Staying private turns it into habits.