Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Lightprotocol/light-protocol/llms.txt
Use this file to discover all available pages before exploring further.
What are State Trees?
State trees are specialized Merkle trees that store compressed account hashes in Light Protocol. They enable efficient cryptographic verification of state while keeping the full account data off-chain.State trees are the backbone of ZK Compression - they provide the cryptographic guarantee that compressed state is valid while dramatically reducing storage costs.
State Tree Architecture
A state tree consists of multiple components working together:Core Components
- Merkle Tree Account: Stores roots and metadata
- Nullifier Queue: Buffers accounts being spent/updated
- Output Queue: Buffers new account hashes
- Root History: Circular buffer of recent roots
- Bloom Filters: Prevent double-spending during batch
State Tree Metadata
Metadata Fields Explained
sequence_number:- Increments with each batch update (append or nullify)
- Used to track when roots can be safely removed
- Critical for bloom filter zeroing logic
- Position where next new leaf will be inserted
- Increments by batch size on each append
- Used in compressed account hash computation
- Tracks nullification progress for indexers
- Not used in on-chain logic
- Helps indexers maintain consistent state
Tree Initialization
Creating a new state tree:Initialization Parameters
Choosing Good Parameters
Choosing Good Parameters
Tree Height:
- 26 (default): 67M capacity, ~0.005 SOL rent
- 30: 1B capacity, ~0.02 SOL rent
- Larger = more capacity but higher rent
- 100 (default): ~10 seconds of validity at 10 updates/sec
- 1000: ~100 seconds validity
- Larger = longer validity window but more storage
- Input (nullifier): Smaller (500-2000) for faster nullification
- Output (append): Larger (10k-50k) for better throughput
- ZKP batch: Balance between proof time and tree update frequency
- Capacity: 10-20x batch size to minimize false positives
- Iterations: 3-5 for good false positive rate (~0.1%)
State Transitions
Appending New Accounts
When programs create compressed accounts: Insertion Flow:-
Insert into Output Queue
-
Batch Fills Up
- Current batch reaches
batch_size - State transitions: Fill → Full
- Switches to alternate batch for new insertions
- Full batch ready for tree update
- Current batch reaches
-
Forester Submits Proof
-
Tree Update
- Verify ZK proof
- Increment sequence number
- Update next_index (old + batch_size)
- Push new root to root history
- Mark batch as Inserted
Nullifying Existing Accounts
When programs update or close compressed accounts: Nullification Flow:-
Create Nullifier
-
Insert into Nullifier Queue
-
Bloom Filter Check
- Insert
compressed_account_hashinto current bloom filter - Check non-inclusion in other bloom filter
- Prevents double-spending within queue
- Insert
-
Forester Nullifies Batch
-
Tree Update
- Verify ZK proof
- Overwrite leaves with nullifiers
- Increment sequence number
- Push new root to root history
- Mark batch as Inserted
Nullification doesn’t change next_index - we’re updating existing leaves, not appending new ones.
Root History Management
The root history is a circular buffer:Root Validity Window
Transactions must reference a root that’s still in history:- Created by tree update
- Pushed to root history
- Valid for ~capacity updates
- Eventually overwritten by newer roots
- May be zeroed early (see Bloom Filter Zeroing)
Bloom Filter Zeroing
Bloom filters must be cleared before batch reuse:When to Zero
Filters are zeroed when:- Previous batch is fully inserted
- Current batch is 50% full
- All roots containing previous batch values are invalid
Root Zeroing Logic
Root Zeroing Example
Why Zero Roots?
Why Zero Roots?
Security Requirement:Once a bloom filter is zeroed, we must ensure no valid roots exist that could prove inclusion of values from that batch.Example Timeline:
- Batch 0 inserted over 4 tree updates → roots R0, R1, R2, R3
- Batch 0 finished at sequence_number=13, root_index=3
- Current sequence_number=8
- Difference: 13-8=5 overlapping roots
Proof Methods
Proof by Index
Fast proof for accounts in output queue:- O(1) lookup in value array
- Only works while in queue (before tree insertion)
- Fails if account already nullified
- No ZK proof required
Proof by Merkle
Cryptographic proof for accounts in tree:- Works for any historical state (within root history)
- Requires Merkle proof from leaf to root
- Requires ZK proof for state transitions
- Higher CU cost than proof by index
Queue Overflow Prevention
Queues have limited capacity:Overflow Scenarios
Output Queue:- Fills faster than foresters can process
- Both batches full, can’t accept new accounts
- Prevents any new compressed account creation
- Fills faster than foresters can nullify
- Both batches full, can’t accept nullifications
- Prevents any compressed account updates/closes
Mitigation
- Forester Incentives: Economic rewards for consistent processing
- Multiple Foresters: Redundancy prevents single point of failure
- Monitoring: Alert when queue usage > 80%
- Rollover: Automatic tree rollover before capacity reached
Tree Rollover
When tree reaches capacity:Rollover Process
- Trigger Condition:
next_index + batch_size >= capacity - Create New Tree: Same configuration as old tree
- Link Trees:
old_tree.next_merkle_tree = new_tree_pubkey - Redirect Traffic: New accounts go to new tree
- Old Tree: Remains readable forever
Rollover Fees
Performance Characteristics
Throughput
| Operation | Cost | Throughput |
|---|---|---|
| Insert to queue | 5k-10k CU | 10k-50k TPS |
| Batch append | 200k-400k CU | 100-500 accounts/update |
| Batch nullify | 200k-400k CU | 100-500 accounts/update |
| Proof by index | 5k CU | 100k TPS |
| Proof by Merkle | 100k-200k CU | 1k TPS |
Latency
Time to Readable:- Insert to queue: Immediate (same transaction)
- Proof by index: Immediate (queue lookup)
- Proof by Merkle: ~10-60 seconds (forester processing + 1 slot finality)
- Depends on batch size and transaction volume
- Typical: 1-10 updates per minute per tree
- High traffic: Up to 100 updates per minute
Next Steps
Build a Program
Create compressed accounts in your program
Forester Guide
Run a forester to maintain state trees
Compressed Accounts
Deep dive into account structure
Merkle Trees
Learn about Merkle tree fundamentals