N is one of the most important parameters in RotorTree. It determines how many children each internal node can have, fundamentally affecting tree depth, proof size, and performance characteristics.
Overview
RotorTree implements an n-ary Lean Incremental Merkle Tree whereN is the branching factor:
N must be at least 2. Common values are 2, 4, 8, and 16.Depth vs Width Tradeoff
The branching factor creates a fundamental tradeoff: Higher N (wider trees):- ✅ Shallower trees (fewer hash layers)
- ✅ Shorter Merkle proofs
- ✅ Better cache locality (more children per node)
- ❌ More children to hash per node
- ❌ Larger memory per node update
- ✅ Fewer children to hash per node
- ✅ Smaller individual hash operations
- ❌ Deeper trees (more hash layers)
- ❌ Longer Merkle proofs
- ❌ More levels to traverse
Capacity Calculations
The maximum number of leaves a tree can hold is determined by:L, the actual depth is:
Common Configurations
N=2 (Binary)
Classic binary Merkle tree
- MAX_DEPTH=20: 1,048,576 leaves
- MAX_DEPTH=25: 33,554,432 leaves
- MAX_DEPTH=30: 1,073,741,824 leaves
N=4 (Quaternary)
Balanced performance
- MAX_DEPTH=10: 1,048,576 leaves
- MAX_DEPTH=13: 67,108,864 leaves
- MAX_DEPTH=16: 4,294,967,296 leaves (~4.3B)
N=8 (Octonary)
Wide trees, shallow depth
- MAX_DEPTH=7: 2,097,152 leaves
- MAX_DEPTH=10: 1,073,741,824 leaves (~1B)
- MAX_DEPTH=13: 549,755,813,888 leaves
N=16 (Hexadecimal)
Maximum width
- MAX_DEPTH=5: 1,048,576 leaves
- MAX_DEPTH=8: 4,294,967,296 leaves (~4.3B)
- MAX_DEPTH=10: 1,099,511,627,776 leaves (~1T)
Storage Examples from README
With thestorage feature enabled:
N=4, MAX_DEPTH=16:
- Capacity: ~4.3 billion nullifiers
- Disk usage: 41 GiB
- Capacity: ~1 billion nullifiers
- Disk usage: 37 GiB
Proof Size Impact
Merkle proof size is directly affected by tree depth:L leaves:
| N | Depth for 1M leaves | Depth for 1B leaves | Proof size (1M) | Proof size (1B) |
|---|---|---|---|---|
| 2 | 20 | 30 | ~640 bytes | ~960 bytes |
| 4 | 10 | 15 | ~960 bytes | ~1440 bytes |
| 8 | 7 | 10 | ~1344 bytes | ~1920 bytes |
| 16 | 5 | 8 | ~1920 bytes | ~3072 bytes |
Actual proof size depends on the Merkle proof format and includes additional metadata.
ZK Prover Circuit Costs
From the README, circuit costs scale with bothN and depth d = ⌈log_N(num_leaves)⌉:
Jolt Execution Cycles
Noir Circuit Size (UltraHonk)
N reduces d but increases the per-level cost. Optimal N depends on your prover and constraint system.
Choosing N for Your Use Case
Privacy Protocols (Low to Medium Throughput)
Recommended: N=2 or N=4- Proof compatibility with existing binary tree circuits
- Reasonable depth for proof generation
- Good balance for verification
High-Throughput Nullifier Databases
Recommended: N=8 or N=16- Minimizes depth for faster insertions
- Better parallelization with wider nodes
- Reduces tree traversal overhead
ZK Circuit Compatibility
Recommended: N=2 or N=4- Easier to prove in constraint systems
- Better support in existing ZK libraries
- Lower per-node circuit complexity
In-Memory Only (No Persistence)
Recommended: N=4 or N=8- Optimize for insertion throughput
- Cache-friendly chunk sizes
- Good structural sharing characteristics
Empirical Guidance
Based on the README benchmark notes:The pure in-memory benchmark (tree_bench_parallel) exhibits lesser variance and achieves peak throughput up to ~190M leaves/sec with parallel features enabled.For predictability under load:
- Use single-threaded mode
- Choose N=4 or N=8
- Trade raw throughput for consistent latency
- Enable
parallelfeature - Choose N=8 or N=16
- Accept higher variance
Example Calculations
Let’s say you need to support 10 million nullifiers:N=4, MAX_DEPTH=16 for headroom and good balance.
Runtime Behavior
The tree depth grows dynamically as leaves are inserted:Related Topics
- Configuration - Tuning compile-time constants
- Batch Operations - Optimizing bulk insertions
- Benchmarks - Performance data for different configurations
