The UTXO Model
Privacy Boost uses a UTXO (Unspent Transaction Output) model. Instead of maintaining account balances, the system tracks individual notes — each representing a specific amount of a specific token owned by a specific user. Think of it like cash. You don’t have a “balance of $47” — you have a $20 bill, a $20 bill, a $5 bill, and two $1 bills. To pay someone $15, you hand over the $20 and get $5 back as change. In Privacy Boost:- Spending a note publishes a nullifier (marks it as consumed)
- Receiving creates new notes (adds commitments to the Merkle tree)
- A transfer consumes input notes and creates output notes, with the ZK circuit enforcing that inputs = outputs + fees
Notes and Commitments
What’s Inside a Note
A note contains three fields:| Field | Description |
|---|---|
| NPK (Note Public Key) | Unique per-note key derived from the owner’s identity + randomness |
| Token ID | Which ERC-20 token (compact ID from the TokenRegistry) |
| Value | Amount of tokens |
Commitments
A commitment is the Poseidon2 hash of a note’s contents:Nullifiers
A nullifier is a one-time-use tag that marks a specific note as spent. It prevents double-spending without revealing which note was consumed.How Nullifiers Work
Each nullifier is derived from the user’s secret nullifying key and the note’s position in the Merkle tree:How Ownership Is Proven
To spend a note, you prove three things inside the ZK circuit:- You know the note’s secrets: The circuit verifies your private fields hash to the correct commitment.
- Your auth key is registered: You sign with your EdDSA auth key, and the circuit proves it exists in the AuthRegistry.
- The note exists: The circuit verifies a Merkle proof for your commitment.
Merkle Trees
LeanIMT (Lean Incremental Merkle Tree)
All note commitments are stored in an append-only Merkle tree using Poseidon2 hashing. Privacy Boost uses LeanIMT — a Lean Incremental Merkle Tree optimized for efficient onchain appends, minimizing the number of hash computations per insert. Each tree has a maximum depth of 20 (~1M leaves). Leaves are never modified or deleted.Multi-Tree Architecture
When the active tree fills up, a new tree is created (rollover). Input notes can reference commitments in any historical tree, so old notes remain spendable indefinitely. Each tree maintains a ring buffer of recent roots, allowing proofs to reference slightly stale roots. This accommodates the delay between proof construction and onchain submission.Tree Transitions in Circuits
When new notes are created, the ZK circuit proves that the tree state transition is valid — the contract just verifies the proof and updates the stored root. This means the contract never has to compute Poseidon2 hashes onchain for leaf insertions.Transaction Lifecycle
Deposit (Public → Shielded)
Deposits are a 2-step process:- User locks tokens: The user computes note commitments, encrypts the metadata using the dual-path ECDH scheme, and submits everything to the contract. The contract transfers the ERC-20 tokens and stores the pending deposit with replay protection.
- TEE processes the batch: The TEE detects pending deposits, generates a Groth16 proof verifying that commitments are correctly computed and the tree state transition is valid, then submits it onchain.
Transfer (Shielded → Shielded)
Transfers move value between shielded notes. Sender identity, recipient identity, token type, and amounts are all hidden from onchain observers.- User prepares: Select input notes to spend, construct output notes for the recipient (and change for yourself), sign with your EdDSA auth key, and encrypt the output metadata using dual-path ECDH
- User submits to TEE: The TEE verifies the signature and ciphertext integrity, then batches the transfer into an epoch
- TEE submits epoch: The TEE generates a Groth16 proof covering signature validity, note existence, nullifier correctness, value conservation, and tree state transition — then submits it onchain
- Contract verifies: Checks the proof, marks nullifiers as spent, updates the tree root
Withdrawal (Shielded → Public)
Withdrawals use the same mechanism as transfers. The difference: instead of creating an output note, the contract sends ERC-20 tokens to a public address. Withdrawals are batched alongside transfers in the same epoch.Forced Withdrawal (Emergency Exit)
Forced withdrawal is the self-custody escape hatch — exit the shielded pool without any TEE involvement.- Reconstruct your notes: Scan onchain events and decrypt metadata with your viewing key
- Generate a ZK proof locally: Prove you own the notes and derive correct nullifiers — this runs on consumer hardware
- Submit to the contract: The contract verifies the proof and starts a configurable delay period
- Execute after the delay: The contract transfers your tokens
Epoch Batching
Multiple user transactions are aggregated into a single epoch — one Groth16 proof covering the entire batch. This is a key design choice for throughput:- Groth16 verification costs ~200K gas, regardless of batch size
- Batching amortizes this cost across all participants
- At Base’s gas target, this enables 300+ sustained TPS; at the gas limit, 1,800+ TPS
Fee Model
- Deposits are fee-free
- Transfers and withdrawals charge configurable fees (in basis points)
- The ZK circuit enforces conservation: inputs = outputs + fees
- Forced withdrawal fees are deducted at execution time
Smart Contracts
| Contract | Role |
|---|---|
| PrivacyBoost | Core shielded pool: Merkle trees, nullifier registry, deposits, epochs, forced withdrawals |
| AuthRegistry | Binds account IDs to EdDSA signing keys. Supports multi-device, rotation, and revocation. Maintains its own Poseidon2 Merkle tree with snapshots for epoch proofs. |
| TokenRegistry | Maps compact token IDs to ERC-20 addresses (append-only) |
| AuditGateway | Auditor registry and onchain audit logging (see Compliance) |
| Groth16 Verifiers | Proof verification for each circuit type (Epoch, Deposit, ForcedWithdraw) |
Next Steps
- Keys & Encryption — How keys are derived and how the dual-path ECDH encryption scheme works
- Trust & Security — TEE guarantees and the full trust model
- Glossary — Technical terminology reference