Skip to main content

Feature Flags

RotorTree provides a modular feature system allowing you to enable only the functionality you need. The core algorithm has zero dependencies by default.

Quick Reference

blake3

Default. Provides Blake3Hasher adapter

std

Standard library support (default via blake3)

concurrent

Thread-safe &self methods with RwLock

parallel

Rayon-parallelized batch insertions

storage

WAL persistence and checkpointing

wincode

Fast Solana-style serialization

serde

Standard serde serialization

test-helpers

Testing utilities (dev only)

Feature Combinations

Minimal (No Dependencies)

[dependencies]
rotortree = { version = "0.15", default-features = false }
Provides:
  • LeanIMT in-memory tree
  • no_std compatible
  • Zero dependencies
  • Bring your own hasher (implement Hasher trait)
Best for:
  • Embedded systems
  • WASM targets
  • ZK circuits (with custom field-aware hasher)
  • Minimal binary size

Default (Blake3 + std)

[dependencies]
rotortree = "0.15"
Provides:
  • Blake3Hasher adapter
  • Standard library support
  • In-memory LeanIMT only
Dependencies: blake3 (1 crate) Best for:
  • Most use cases
  • Quick prototyping
  • When you don’t need persistence

Concurrent (Thread-Safe)

[dependencies]
rotortree = { version = "0.15", features = ["concurrent"] }
Changes:
  • LeanIMT methods take &self instead of &mut self
  • Internal RwLock synchronization via parking_lot
  • Multiple threads can hold snapshots while one thread inserts
Dependencies: blake3, parking_lot (5 crates total) API Difference:
let mut tree = LeanIMT::new(Blake3Hasher);
tree.insert([1u8; 32]).unwrap();
tree.insert([2u8; 32]).unwrap();
Performance Impact:
  • ~5-10% overhead on single-threaded insertions
  • Worthwhile if you need concurrent snapshots + insertions

Parallel (Rayon-Powered)

[dependencies]
rotortree = { version = "0.15", features = ["parallel"] }
Provides:
  • Automatic parallelization of insert_many for large batches
  • Uses rayon work-stealing for optimal CPU utilization
Dependencies: blake3, rayon (~15 crates total) Behavior:
  • Parallelism kicks in when parent count exceeds ROTORTREE_PARALLEL_THRESHOLD (default: 1024)
  • Work is split into chunks of PAR_CHUNK_SIZE parents (default: 64)
  • Linear speedup up to ~8 cores, then diminishing returns
Configuration:
# Increase threshold for smaller workloads
export ROTORTREE_PARALLEL_THRESHOLD=4096

# Run your application
cargo run --release
Performance:
  • Single-threaded: ~1-2M leaves/sec
  • Parallel (8 cores): ~10-20M leaves/sec
  • Parallel (14 cores): ~190M leaves/sec peak
Parallel mode has higher variance in latency. Use single-threaded for predictable performance under load.

Storage (Persistence)

[dependencies]
rotortree = { version = "0.15", features = ["storage", "blake3"] }
Provides:
  • RotorTree type with WAL persistence
  • Crash recovery via WAL replay
  • Checkpointing to data files
  • Memory-mapped storage tiers
  • Durability tokens
Dependencies: ~20 crates (includes parking_lot, arc-swap, fs4, memmap2, crc-fast, wincode) API:
use rotortree::{
    RotorTree, RotorTreeConfig,
    FlushPolicy, CheckpointPolicy, TieringConfig,
};

let config = RotorTreeConfig {
    path: PathBuf::from("/tmp/tree"),
    flush_policy: FlushPolicy::Interval(Duration::from_millis(10)),
    checkpoint_policy: CheckpointPolicy::Manual,
    tiering: TieringConfig::default(),
    verify_checkpoint: true,
};

let tree = RotorTree::<Blake3Hasher, 4, 20>::open(Blake3Hasher, config)?;
See the Persistent Storage guide for details.

Serialization

Wincode (Solana-Style)

[dependencies]
rotortree = { version = "0.15", features = ["wincode"] }
Provides:
  • wincode derives on NaryProof and ConsistencyProof
  • Compatible with Solana’s wincode format
  • Fastest serialization option
Usage:
let proof = snap.generate_proof(0).unwrap();

// Serialize
let bytes = wincode::serialize(&proof).unwrap();

// Deserialize
let decoded: NaryProof<4, 20> = wincode::deserialize(&bytes).unwrap();
The storage feature automatically includes wincode since it’s used internally for WAL frames.

Serde (Standard)

[dependencies]
rotortree = { version = "0.15", features = ["serde"] }
Provides:
  • Standard serde derives on proof types
  • Compatible with serde_json, bincode, postcard, etc.
  • Better ecosystem compatibility than wincode
Usage:
// JSON
let json = serde_json::to_string(&proof).unwrap();
let decoded: NaryProof<4, 20> = serde_json::from_str(&json).unwrap();

// Bincode
let bytes = bincode::serialize(&proof).unwrap();
let decoded: NaryProof<4, 20> = bincode::deserialize(&bytes).unwrap();
You can enable both wincode and serde simultaneously for maximum flexibility.

Complete Feature Matrix

FeatureDependenciesBinary SizeUse Case
default-features = false0MinimalEmbedded, WASM, ZK circuits
blake3 (default)1+50 KBStandard hashing
stdvia blake3+0 KBStandard library support
concurrent+4+100 KBMulti-threaded access
parallel+14+500 KBBatch insertion speedup
storage+19+800 KBCrash recovery
wincode+1+50 KBSolana compatibility
serde+2+100 KBEcosystem serialization
Binary sizes are approximate and include transitive dependencies. Actual size depends on target and optimization level.

Common Configurations

Web Application (High Throughput)

[dependencies]
rotortree = { version = "0.15", features = [
    "storage",
    "blake3",
    "parallel",
    "serde",
] }
Use case: Web server with persistence, fast batch insertions, and JSON API

Blockchain Full Node

[dependencies]
rotortree = { version = "0.15", features = [
    "storage",
    "blake3",
    "concurrent",
    "parallel",
] }
Use case: High-throughput state tree with multiple readers

Light Client

[dependencies]
rotortree = { version = "0.15", features = ["blake3", "serde"] }
Use case: No persistence needed, just proof verification

ZK Circuit (Custom Field)

[dependencies]
rotortree = { version = "0.15", default-features = false }
Use case: Implement Hasher trait for field-aware hashing
use rotortree::{Hasher, Hash, HashState};

#[derive(Clone, Copy)]
struct FieldHasher;

impl Hasher for FieldHasher {
    fn hash_state(&self) -> HashState {
        // Return hasher-specific state
        HashState::new()
    }
    
    fn hash_children(&self, children: &[Hash]) -> Hash {
        // Implement field-aware Poseidon/Pedersen/etc
        todo!()
    }
}

let tree = LeanIMT::<FieldHasher, 2, 20>::new(FieldHasher);

Embedded System

[dependencies]
rotortree = { version = "0.15", default-features = false }
Use case: no_std environment with custom hasher

Feature Dependencies

Some features automatically enable others:
Enabling storage automatically gives you std, wincode, and several other dependencies.

Runtime Configuration

Some features expose runtime configuration:

Parallel Threshold

# Default: 1024 parents
export ROTORTREE_PARALLEL_THRESHOLD=2048
Controls when parallelism kicks in for insert_many. Higher values = less parallelism overhead for smaller batches.

Rayon Thread Pool

rayon::ThreadPoolBuilder::new()
    .num_threads(8)
    .build_global()
    .unwrap();

// Now insert_many will use 8 threads max

Compile-Time Constants

These require source modification and recompilation:
ConstantDefaultLocationEffect
CHUNK_SIZE128src/tree.rsHashes per chunk (affects snapshot cost)
CHUNKS_PER_SEGMENT256src/tree.rsChunks per immutable segment
PAR_CHUNK_SIZE64src/tree.rsParents per rayon work unit
MAX_FRAME_PAYLOAD128 MBsrc/storage/frame.rsMax WAL frame size
CHUNKS_PER_SHARD65,536src/storage/checkpoint.rsChunks per data file
See the Performance Tuning guide for details.

Feature Recommendations

Enable storage feature:
rotortree = { version = "0.15", features = ["storage", "blake3"] }
Enable storage, parallel, and serde:
rotortree = { version = "0.15", features = ["storage", "parallel", "serde"] }
Enable concurrent feature:
rotortree = { version = "0.15", features = ["concurrent"] }
Enable parallel and tune ROTORTREE_PARALLEL_THRESHOLD:
rotortree = { version = "0.15", features = ["parallel"] }
export ROTORTREE_PARALLEL_THRESHOLD=512
Disable default features:
rotortree = { version = "0.15", default-features = false }
Implement custom hasher if needed.
Enable wincode feature:
rotortree = { version = "0.15", features = ["wincode"] }

Next Steps

Performance Tuning

Optimize compile-time and runtime parameters

In-Memory Trees

Learn the basics of LeanIMT

Persistent Storage

Set up WAL-based persistence

Proof Generation

Generate and verify proofs

Build docs developers (and LLMs) love