Concepts
Notes, the commitment tree, nullifiers, and what each one hides.
Sombra holds your money as notes inside a shielded pool. This page explains what a note is, how you spend one privately, and what an observer can still see.
Notes
A note is an amount of one token that belongs to you. Nothing else.
Each note is encrypted to its owner with ML-KEM-768 and AES-256-GCM. The chain never stores the note itself. It stores a commitment: one 32-byte hash that binds the pool, the token, the amount, the owner, and a random value only the owner knows.
Commitments go into one Merkle tree per pool. The tree is public. Its leaves tell you nothing — a commitment is a hash, and the same owner receiving the same amount twice produces two unrelated leaves.
Your wallet finds your notes by trying to decrypt the encrypted payloads published alongside each leaf. The ones that open are yours.
Spending
To spend, your wallet proves four things in zero knowledge:
- You hold the key that owns every input note.
- Every input is a leaf in the tree.
- The outputs add up to the inputs. Nothing is created.
- The outputs are well-formed: the right pool, the right token, and a history you are allowed to pass on.
The proof is public. It publishes one nullifier per input note, one commitment per output, and the action's public fields — which for a withdraw includes where the money went.
One thing the proof does not check is the encrypted payload itself. The sender chooses it, and the proof only carries its hash. So a recipient can tell whether the payload they received is the one the sender published, but a sender who published unopenable bytes would not be caught by the proof.
A nullifier is derived from the note and from a key the note commits to. It reveals nothing about which leaf was spent. But it is the same every time for the same note, so the program records each nullifier once and refuses it a second time. That is how double-spending is stopped.
A transfer produces two outputs: one to the recipient, one back to you as change. A withdraw produces one.
What a spend hides
- The amount. Never published on a transfer.
- Which notes you spent. The proof shows your inputs are somewhere in the tree. It does not say where.
- Who you paid. An output commitment cannot be linked to a recipient.
- The token. A transfer never names the mint. Only a withdraw does, because the program has to pay a real token account.
- Your key. No signature authorises a spend. The proof shows you know the key without using it to sign.
What a spend shows
The chain sees that an action happened, how many inputs and outputs it had, and which verifiers voted for it. A withdraw also shows the destination address, the token, and the amount leaving the pool. That is public by necessity — it is a normal token transfer out.
Deposits and lineage
A deposit moves public tokens into the pool and creates your first note. You deposit your own tokens. Nobody can deposit to you, so the deposit edge is always yours and nobody can plant a note in your history.
Every note carries a blinded label of the deposit it descends from, called its lineage. The label is a hash, and a spend can re-blind it, so notes from one deposit need not look related. A spend that combines several deposits has to re-blind.
You can pay from several deposits at once. When you do, the outputs take a single merged label derived from the labels you spent. Before this, a user who had deposited three times could not combine them in one payment.
Keys
One 24-word recovery phrase produces everything:
- A spend key that owns your notes.
- A nullifier key that marks them spent.
- Weekly ML-KEM-768 keys for encryption. Each week has its own key, published in a tree covering 8192 weeks.
- A small Solana key that pays network fees. It can never move your shielded funds.
Your shielded address is a bech32m string. It carries the key material someone needs to encrypt a note to you, and nothing that lets them spend.
Weekly keys mean you can hand an auditor the keys for one range of weeks without giving up anything outside it.
What you pay
Two fees, both flat, both in one fee token: a protocol fee set by the pool, and a relayer fee you choose and can set to zero.
Neither comes out of the money you are moving. They are paid from separate notes, so paying a fee reveals nothing about the payment it belongs to.
Fees and the relayer covers the prices, who pays Solana's costs, and why you should normally let the relayer submit.
Limits
A single spend can take up to 24 input notes. The limit comes from Solana's cap of 64 cross-program calls in one transaction, measured rather than guessed. If you hold more notes than that, your wallet consolidates them first.
Next: Architecture — the pieces that make this work.