Expand description
§Unified Binary Tree (UBT)
Implementation of EIP-7864: Ethereum state using a unified binary tree.
This crate provides a binary tree structure intended to replace the hexary patricia trees used in Ethereum. Key features:
- Single tree: Account and storage tries are merged into a single tree with 32-byte keys
- Code chunking: Contract bytecode is chunked and stored in the tree
- Data co-location: Related data (nonce, balance, first storage slots, first code chunks) are grouped together in 256-value subtrees to reduce branch openings
- ZK-friendly: Designed for efficient proving in ZK circuits
- Parallel hashing: Uses rayon for concurrent stem hash computation (default feature)
- Incremental updates: O(D*C) root updates instead of O(S log S) rebuilds
§Tree Structure
The tree uses 32-byte keys where:
- First 31 bytes: stem (defines the subtree)
- Last byte: subindex (position within the 256-value subtree)
Node types:
InternalNode: Has left_hash and right_hashStemNode: Has stem (31 bytes), left_hash and right_hash for its 256-value subtreeLeafNode: Contains a 32-byte value or emptyEmptyNode: Represents an empty node/subtree (hash = 0)
§Quick Start
use ubt::{UnifiedBinaryTree, TreeKey, Blake3Hasher, B256};
let mut tree: UnifiedBinaryTree<Blake3Hasher> = UnifiedBinaryTree::new();
let key = TreeKey::from_bytes(B256::repeat_byte(0x01));
tree.insert(key, B256::repeat_byte(0x42));
let root = tree.root_hash();§Features
parallel(default): Enables parallel stem hashing via rayon. Provides significant speedup for trees with many dirty stems per rebuild cycle.serde: Enables serialization support for tree types.
§Performance Modes
§Parallel Hashing (default)
When the parallel feature is enabled (default), stem hashes are computed concurrently
using rayon’s parallel iterators. This is beneficial when many stems are modified
between root_hash() calls.
§Incremental Updates
For block-by-block state updates where only a small subset of stems change, enable incremental mode to cache intermediate node hashes:
use ubt::{UnifiedBinaryTree, Blake3Hasher};
let mut tree: UnifiedBinaryTree<Blake3Hasher> = UnifiedBinaryTree::new();
// ... initial inserts ...
tree.root_hash(); // Initial full build
// Enable incremental mode for subsequent updates
tree.enable_incremental_mode();
// Future updates only recompute affected paths: O(D*C) vs O(S log S)
// where D=248 (tree depth) and C=changed stems per block§Hash Function
Note: The hash function is not final per EIP-7864. This implementation uses BLAKE3 as a reference. Candidates include Keccak and Poseidon2.
The Hasher trait is Send + Sync to support parallel hashing contexts.
Structs§
- Account
Stem - Helper struct for computing account keys.
- Address
- Re-export alloy primitives for convenience An Ethereum address, 20 bytes in length.
- Basic
Data Leaf - Basic account data packed into a single 32-byte leaf.
- Blake3
Hasher - BLAKE3-based hasher (reference implementation).
- Code
Chunk - A code chunk with leading PUSHDATA count.
- Internal
Node - Internal branching node.
- Leaf
Node - Leaf node containing a 32-byte value.
- Multi
Proof - A multi-proof for multiple keys.
- Proof
- A Merkle proof for a value in the UBT.
- Sha256
Hasher - SHA256-based hasher (go-ethereum compatible).
- Stem
- A 31-byte stem that identifies a subtree of 256 values.
- Stem
Node - Stem node that roots a 256-value subtree.
- Streaming
Tree Builder - A streaming tree builder that computes root hash with minimal memory.
- TreeKey
- A complete 32-byte tree key (stem + subindex).
- Unified
Binary Tree - The Unified Binary Tree.
- Witness
- Witness data for stateless execution.
Enums§
- Direction
- Direction in the tree (for proof paths)
- Node
- A node in the UBT.
- Proof
Node - A node in a Merkle proof path.
- UbtError
- Errors that can occur during UBT operations.
Constants§
- BASIC_
DATA_ BALANCE_ OFFSET - Offset in basic data leaf for balance (bytes 16-31)
- BASIC_
DATA_ CODE_ SIZE_ OFFSET - Offset in basic data leaf for code size (bytes 5-7)
- BASIC_
DATA_ LEAF_ KEY - Subindex for basic account data (nonce, balance, code size)
- BASIC_
DATA_ NONCE_ OFFSET - Offset in basic data leaf for nonce (bytes 8-15)
- CODE_
HASH_ LEAF_ KEY - Subindex for code hash
- CODE_
OFFSET - Offset for first 128 code chunks within account stem (subindexes 128-255)
- HEADER_
STORAGE_ OFFSET - Offset for first 64 storage slots within account stem (subindexes 64-127)
- STEM_
LEN - Length of a stem in bytes (31 bytes = 248 bits)
- STEM_
SUBTREE_ WIDTH - Width of a stem subtree (256 values)
- SUBINDEX_
BITS - Number of bits in the subindex (8 bits = 256 possible values)
Traits§
- Hasher
- Trait for hash functions used in the UBT.
Functions§
- chunkify_
code - Chunkify bytecode into 31-byte chunks with PUSHDATA tracking.
- dechunkify_
code - Reconstruct bytecode from chunks.
- generate_
stem_ proof - Generate a proof for a key in a stem node.
- get_
basic_ data_ key - Get the tree key for basic account data (nonce, balance, code size).
- get_
binary_ tree_ key - Derive a tree key using the go-ethereum algorithm.
- get_
code_ chunk_ key - Get the tree key for a code chunk.
- get_
code_ hash_ key - Get the tree key for code hash.
- get_
storage_ slot_ key - Get the tree key for a storage slot.
- get_
storage_ slot_ key_ u256 - Get the tree key for a storage slot from U256.
Type Aliases§
- B256
- Re-export alloy primitives for convenience 32-byte fixed byte-array type.
- SubIndex
- Subindex within a stem’s subtree (0-255).
- U256
- Re-export alloy primitives for convenience 256-bit unsigned integer type, consisting of 4, 64-bit limbs.