miden_crypto/merkle/smt/large/
mod.rs

1//! Large-scale Sparse Merkle Tree backed by pluggable storage.
2//!
3//! `LargeSmt` stores the top of the tree (depths 0–23) in memory and persists the lower
4//! depths (24–64) in storage as fixed-size subtrees. This hybrid layout scales beyond RAM
5//! while keeping common operations fast. With the `rocksdb` feature enabled, the lower
6//! subtrees and leaves are stored in RocksDB. On reopen, the in-memory top is reconstructed
7//! from cached depth-24 subtree roots.
8//!
9//! Examples below require the `rocksdb` feature.
10//!
11//! Open an existing RocksDB-backed tree:
12//! ```no_run
13//! use miden_crypto::merkle::{LargeSmt, RocksDbConfig, RocksDbStorage};
14//!
15//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
16//! let storage = RocksDbStorage::open(RocksDbConfig::new("/path/to/db"))?;
17//! let smt = LargeSmt::new(storage)?; // reconstructs in-memory top if data exists
18//! let _root = smt.root()?;
19//! # Ok(())
20//! # }
21//! ```
22//!
23//! Initialize an empty RocksDB-backed tree and bulk-load entries using mutations:
24//! ```no_run
25//! use miden_crypto::{
26//!     Felt, Word,
27//!     merkle::{LargeSmt, RocksDbConfig, RocksDbStorage},
28//! };
29//!
30//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
31//! let path = "/path/to/new-db";
32//! if std::path::Path::new(path).exists() {
33//!     std::fs::remove_dir_all(path)?;
34//! }
35//! std::fs::create_dir_all(path)?;
36//!
37//! let storage = RocksDbStorage::open(RocksDbConfig::new(path))?;
38//! let mut smt = LargeSmt::new(storage)?; // empty tree
39//!
40//! // Prepare initial entries
41//! let entries = vec![
42//!     (
43//!         Word::new([Felt::new(1), Felt::new(0), Felt::new(0), Felt::new(0)]),
44//!         Word::new([Felt::new(10), Felt::new(20), Felt::new(30), Felt::new(40)]),
45//!     ),
46//!     (
47//!         Word::new([Felt::new(2), Felt::new(0), Felt::new(0), Felt::new(0)]),
48//!         Word::new([Felt::new(11), Felt::new(22), Felt::new(33), Felt::new(44)]),
49//!     ),
50//! ];
51//!
52//! // Compute and atomically apply the initial bulk load
53//! let mutations = smt.compute_mutations(entries)?;
54//! smt.apply_mutations(mutations)?;
55//! # Ok(())
56//! # }
57//! ```
58//!
59//! Compute and apply a batch of updates atomically:
60//! ```no_run
61//! use miden_crypto::{
62//!     EMPTY_WORD, Felt, Word,
63//!     merkle::{LargeSmt, RocksDbConfig, RocksDbStorage},
64//! };
65//!
66//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
67//! let storage = RocksDbStorage::open(RocksDbConfig::new("/path/to/db"))?;
68//! let mut smt = LargeSmt::new(storage)?;
69//!
70//! let k1 = Word::new([Felt::new(101), Felt::new(0), Felt::new(0), Felt::new(0)]);
71//! let v1 = Word::new([Felt::new(1), Felt::new(2), Felt::new(3), Felt::new(4)]);
72//! let k2 = Word::new([Felt::new(202), Felt::new(0), Felt::new(0), Felt::new(0)]);
73//! let k3 = Word::new([Felt::new(303), Felt::new(0), Felt::new(0), Felt::new(0)]);
74//! let v3 = Word::new([Felt::new(7), Felt::new(7), Felt::new(7), Felt::new(7)]);
75//!
76//! // EMPTY_WORD marks deletions.
77//! let updates = vec![(k1, v1), (k2, EMPTY_WORD), (k3, v3)];
78//! let mutations = smt.compute_mutations(updates)?;
79//! smt.apply_mutations(mutations)?;
80//! # Ok(())
81//! # }
82//! ```
83//!
84//! Quick initialization with `with_entries` (best for modest datasets/tests):
85//! ```no_run
86//! use miden_crypto::{
87//!     Felt, Word,
88//!     merkle::{LargeSmt, RocksDbConfig, RocksDbStorage},
89//! };
90//!
91//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
92//! // Note: `with_entries` expects an EMPTY storage and performs an all-at-once build.
93//! // Prefer `compute_mutations` + `apply_mutations` for very large/bulk loads.
94//! let path = "/path/to/new-db";
95//! if std::path::Path::new(path).exists() {
96//!     std::fs::remove_dir_all(path)?;
97//! }
98//! std::fs::create_dir_all(path)?;
99//!
100//! let storage = RocksDbStorage::open(RocksDbConfig::new(path))?;
101//! let entries = vec![
102//!     (
103//!         Word::new([Felt::new(1), Felt::new(0), Felt::new(0), Felt::new(0)]),
104//!         Word::new([Felt::new(10), Felt::new(20), Felt::new(30), Felt::new(40)]),
105//!     ),
106//!     (
107//!         Word::new([Felt::new(2), Felt::new(0), Felt::new(0), Felt::new(0)]),
108//!         Word::new([Felt::new(11), Felt::new(22), Felt::new(33), Felt::new(44)]),
109//!     ),
110//! ];
111//! let _smt = LargeSmt::with_entries(storage, entries)?;
112//! # Ok(())
113//! # }
114//! ```
115use alloc::{boxed::Box, vec::Vec};
116use core::mem;
117
118use num::Integer;
119use rayon::prelude::*;
120
121use super::{
122    EMPTY_WORD, EmptySubtreeRoots, InnerNode, InnerNodeInfo, InnerNodes, LeafIndex, MerkleError,
123    MutationSet, NodeIndex, Rpo256, SMT_DEPTH, Smt, SmtLeaf, SmtLeafError, SmtProof,
124    SparseMerklePath, SparseMerkleTree, Word,
125};
126use crate::merkle::smt::{
127    Map, NodeMutation, NodeMutations,
128    full::concurrent::{
129        MutatedSubtreeLeaves, PairComputations, SUBTREE_DEPTH, SubtreeLeaf, SubtreeLeavesIter,
130        build_subtree, fetch_sibling_pair, process_sorted_pairs_to_leaves,
131    },
132};
133
134mod error;
135pub use error::LargeSmtError;
136
137#[cfg(test)]
138mod tests;
139
140mod subtree;
141pub use subtree::{Subtree, SubtreeError};
142
143mod storage;
144pub use storage::{MemoryStorage, SmtStorage, StorageError, StorageUpdateParts, StorageUpdates};
145#[cfg(feature = "rocksdb")]
146pub use storage::{RocksDbConfig, RocksDbStorage};
147
148// CONSTANTS
149// ================================================================================================
150
151/// Number of levels of the tree that are stored in memory
152const IN_MEMORY_DEPTH: u8 = 24;
153
154/// Number of nodes that are stored in memory (including the unused index 0)
155const NUM_IN_MEMORY_NODES: usize = 1 << (IN_MEMORY_DEPTH + 1);
156
157/// Number of subtree levels below in-memory depth (24-64 in steps of 8)
158const NUM_SUBTREE_LEVELS: usize = 5;
159
160/// How many subtrees we buffer before flushing them to storage **during the
161/// SMT construction phase**.
162///
163/// * This constant is **only** used while building a fresh tree; incremental updates use their own
164///   per-batch sizing.
165/// * Construction is all-or-nothing: if the write fails we abort and rebuild from scratch, so we
166///   allow larger batches that maximise I/O throughput instead of fine-grained rollback safety.
167const CONSTRUCTION_SUBTREE_BATCH_SIZE: usize = 10_000;
168
169// TYPES
170// ================================================================================================
171
172type Leaves = super::Leaves<SmtLeaf>;
173// LargeSmt
174// ================================================================================================
175
176/// A large-scale Sparse Merkle tree mapping 256-bit keys to 256-bit values, backed by pluggable
177/// storage. Both keys and values are represented by 4 field elements.
178///
179/// Unlike the regular `Smt`, this implementation is designed for very large trees by using external
180/// storage (such as RocksDB) for the bulk of the tree data, while keeping only the upper levels (up
181/// to depth 24) in memory. This hybrid approach allows the tree to scale beyond memory limitations
182/// while maintaining good performance for common operations.
183///
184/// All leaves sit at depth 64. The most significant element of the key is used to identify the leaf
185/// to which the key maps.
186///
187/// A leaf is either empty, or holds one or more key-value pairs. An empty leaf hashes to the empty
188/// word. Otherwise, a leaf hashes to the hash of its key-value pairs, ordered by key first, value
189/// second.
190///
191/// The tree structure:
192/// - Depths 0-23: Stored in memory as a flat array for fast access
193/// - Depths 24-64: Stored in external storage organized as subtrees for efficient batch operations
194#[derive(Debug)]
195pub struct LargeSmt<S: SmtStorage> {
196    storage: S,
197    /// Flat vector representation of in-memory nodes.
198    /// Index 0 is unused; index 1 is root.
199    /// For node at index i: left child at 2*i, right child at 2*i+1.
200    in_memory_nodes: Vec<Word>,
201}
202
203impl<S: SmtStorage> LargeSmt<S> {
204    // CONSTANTS
205    // --------------------------------------------------------------------------------------------
206    /// The default value used to compute the hash of empty leaves.
207    pub const EMPTY_VALUE: Word = <Self as SparseMerkleTree<SMT_DEPTH>>::EMPTY_VALUE;
208
209    /// Subtree depths for the subtrees stored in storage.
210    pub const SUBTREE_DEPTHS: [u8; 5] = [56, 48, 40, 32, 24];
211
212    // CONSTRUCTORS
213    // --------------------------------------------------------------------------------------------
214
215    /// Returns a new [LargeSmt] backed by the provided storage.
216    ///
217    /// The SMT's root is fetched from the storage backend. If the storage is empty the SMT is
218    /// initialized with the root of an empty tree. Otherwise, materializes in-memory nodes from
219    /// the top subtrees.
220    ///
221    /// # Errors
222    /// Returns an error if fetching the root or initial in-memory nodes from the storage fails.
223    pub fn new(storage: S) -> Result<Self, LargeSmtError> {
224        let root = storage.get_root()?.unwrap_or(*EmptySubtreeRoots::entry(SMT_DEPTH, 0));
225
226        let is_empty = !storage.has_leaves()?;
227
228        // Initialize in-memory nodes
229        let mut in_memory_nodes: Vec<Word> = vec![EMPTY_WORD; NUM_IN_MEMORY_NODES];
230
231        for depth in 0..IN_MEMORY_DEPTH {
232            let child_empty_hash = *EmptySubtreeRoots::entry(SMT_DEPTH, depth + 1);
233            let start = 2 * (1 << depth);
234            let end = 2 * (1 << (depth + 1));
235            in_memory_nodes[start..end].fill(child_empty_hash);
236        }
237
238        // No leaves, return empty tree
239        if is_empty {
240            return Ok(Self { storage, in_memory_nodes });
241        }
242
243        let subtree_roots = storage.get_depth24()?;
244
245        // convert subtree roots to SubtreeLeaf
246        let mut leaf_subtrees: Vec<SubtreeLeaf> = subtree_roots
247            .into_iter()
248            .map(|(index, hash)| SubtreeLeaf { col: index, hash })
249            .collect();
250        leaf_subtrees.sort_by_key(|leaf| leaf.col);
251
252        let mut subtree_leaves: Vec<Vec<SubtreeLeaf>> =
253            SubtreeLeavesIter::from_leaves(&mut leaf_subtrees).collect();
254
255        // build in-memory top of the tree
256        for current_depth in (SUBTREE_DEPTH..=IN_MEMORY_DEPTH).step_by(SUBTREE_DEPTH as usize).rev()
257        {
258            let (nodes, mut subtree_roots): (Vec<Map<_, _>>, Vec<SubtreeLeaf>) = subtree_leaves
259                .into_par_iter()
260                .map(|subtree| {
261                    debug_assert!(subtree.is_sorted());
262                    debug_assert!(!subtree.is_empty());
263                    let (nodes, subtree_root) = build_subtree(subtree, SMT_DEPTH, current_depth);
264                    (nodes, subtree_root)
265                })
266                .unzip();
267            subtree_leaves = SubtreeLeavesIter::from_leaves(&mut subtree_roots).collect();
268            debug_assert!(!subtree_leaves.is_empty());
269
270            for subtree_nodes in nodes {
271                for (index, node) in subtree_nodes {
272                    let memory_index = to_memory_index(&index);
273                    // Store left and right children in flat layout
274                    in_memory_nodes[memory_index * 2] = node.left;
275                    in_memory_nodes[memory_index * 2 + 1] = node.right;
276                }
277            }
278        }
279
280        // Check that the calculated root matches the root in storage
281        // Root is at index 1, with children at indices 2 and 3
282        let calculated_root = Rpo256::merge(&[in_memory_nodes[2], in_memory_nodes[3]]);
283        assert_eq!(calculated_root, root, "Tree reconstruction failed - root mismatch");
284
285        Ok(Self { storage, in_memory_nodes })
286    }
287
288    /// Returns a new [Smt] instantiated with leaves set as specified by the provided entries.
289    ///
290    /// If the `concurrent` feature is enabled, this function uses a parallel implementation to
291    /// process the entries efficiently, otherwise it defaults to the sequential implementation.
292    ///
293    /// All leaves omitted from the entries list are set to [Self::EMPTY_VALUE].
294    ///
295    /// # Errors
296    /// Returns an error if the provided entries contain multiple values for the same key.
297    pub fn with_entries(
298        storage: S,
299        entries: impl IntoIterator<Item = (Word, Word)>,
300    ) -> Result<Self, LargeSmtError> {
301        let entries: Vec<(Word, Word)> = entries.into_iter().collect();
302
303        if storage.has_leaves()? {
304            return Err(StorageError::Unsupported(
305                "Cannot create SMT with non-empty storage".into(),
306            )
307            .into());
308        }
309        let mut tree = LargeSmt::new(storage)?;
310        if entries.is_empty() {
311            return Ok(tree);
312        }
313        tree.build_subtrees(entries)?;
314        Ok(tree)
315    }
316
317    // PUBLIC ACCESSORS
318    // --------------------------------------------------------------------------------------------
319
320    /// Returns the depth of the tree
321    pub const fn depth(&self) -> u8 {
322        SMT_DEPTH
323    }
324
325    /// Returns the root of the tree
326    pub fn root(&self) -> Result<Word, LargeSmtError> {
327        Ok(self.storage.get_root()?.unwrap_or(Self::EMPTY_ROOT))
328    }
329
330    /// Returns the number of non-empty leaves in this tree.
331    ///
332    /// Note that this may return a different value from [Self::num_entries()] as a single leaf may
333    /// contain more than one key-value pair.
334    ///
335    /// # Errors
336    /// Returns an error if there is a storage error when retrieving the leaf count.
337    pub fn num_leaves(&self) -> Result<usize, LargeSmtError> {
338        Ok(self.storage.leaf_count()?)
339    }
340
341    /// Returns the number of key-value pairs with non-default values in this tree.
342    ///
343    /// Note that this may return a different value from [Self::num_leaves()] as a single leaf may
344    /// contain more than one key-value pair.
345    ///
346    /// Also note that this is currently an expensive operation is counting the number of entries
347    /// requires iterating over all leaves of the tree.
348    ///
349    /// # Errors
350    /// Returns an error if there is a storage error when retrieving the entry count.
351    pub fn num_entries(&self) -> Result<usize, LargeSmtError> {
352        Ok(self.storage.entry_count()?)
353    }
354
355    /// Returns the leaf to which `key` maps
356    pub fn get_leaf(&self, key: &Word) -> SmtLeaf {
357        <Self as SparseMerkleTree<SMT_DEPTH>>::get_leaf(self, key)
358    }
359
360    /// Returns the value associated with `key`
361    pub fn get_value(&self, key: &Word) -> Word {
362        <Self as SparseMerkleTree<SMT_DEPTH>>::get_value(self, key)
363    }
364
365    /// Returns an opening of the leaf associated with `key`. Conceptually, an opening is a Merkle
366    /// path to the leaf, as well as the leaf itself.
367    pub fn open(&self, key: &Word) -> SmtProof {
368        <Self as SparseMerkleTree<SMT_DEPTH>>::open(self, key)
369    }
370
371    /// Returns a boolean value indicating whether the SMT is empty.
372    ///
373    /// # Errors
374    /// Returns an error if there is a storage error when retrieving the root or leaf count.
375    pub fn is_empty(&self) -> Result<bool, LargeSmtError> {
376        let root = self.storage.get_root()?.unwrap_or(Self::EMPTY_ROOT);
377        debug_assert_eq!(self.num_leaves()? == 0, root == Self::EMPTY_ROOT);
378        Ok(root == Self::EMPTY_ROOT)
379    }
380
381    // ITERATORS
382    // --------------------------------------------------------------------------------------------
383
384    /// Returns an iterator over the leaves of this [Smt].
385    /// Note: This iterator returns owned SmtLeaf values.
386    ///
387    /// # Errors
388    /// Returns an error if the storage backend fails to create the iterator.
389    pub fn leaves(
390        &self,
391    ) -> Result<impl Iterator<Item = (LeafIndex<SMT_DEPTH>, SmtLeaf)>, LargeSmtError> {
392        let iter = self.storage.iter_leaves()?;
393        Ok(iter.map(|(idx, leaf)| (LeafIndex::new_max_depth(idx), leaf)))
394    }
395
396    /// Returns an iterator over the key-value pairs of this [Smt].
397    /// Note: This iterator returns owned (Word, Word) tuples.
398    ///
399    /// # Errors
400    /// Returns an error if the storage backend fails to create the iterator.
401    pub fn entries(&self) -> Result<impl Iterator<Item = (Word, Word)>, LargeSmtError> {
402        let leaves_iter = self.leaves()?;
403        Ok(leaves_iter.flat_map(|(_, leaf)| {
404            // Collect the (Word, Word) tuples into an owned Vec
405            // This ensures they outlive the 'leaf' from which they are derived.
406            let owned_entries: Vec<(Word, Word)> = leaf.entries().to_vec();
407            // Return an iterator over this owned Vec
408            owned_entries.into_iter()
409        }))
410    }
411
412    /// Returns an iterator over the inner nodes of this [Smt].
413    ///
414    /// # Errors
415    /// Returns an error if the storage backend fails during iteration setup.
416    pub fn inner_nodes(&self) -> Result<impl Iterator<Item = InnerNodeInfo> + '_, LargeSmtError> {
417        // Pre-validate that storage is accessible
418        let _ = self.storage.iter_subtrees()?;
419        Ok(LargeSmtInnerNodeIterator::new(self))
420    }
421
422    // STATE MUTATORS
423    // --------------------------------------------------------------------------------------------
424
425    /// Inserts a value at the specified key, returning the previous value associated with that key.
426    /// Recall that by definition, any key that hasn't been updated is associated with
427    /// [`Self::EMPTY_VALUE`].
428    ///
429    /// This also recomputes all hashes between the leaf (associated with the key) and the root,
430    /// updating the root itself.
431    ///
432    /// # Errors
433    /// Returns an error if inserting the key-value pair would exceed
434    /// [`MAX_LEAF_ENTRIES`](super::MAX_LEAF_ENTRIES) (1024 entries) in the leaf.
435    pub fn insert(&mut self, key: Word, value: Word) -> Result<Word, MerkleError> {
436        <Self as SparseMerkleTree<SMT_DEPTH>>::insert(self, key, value)
437    }
438
439    /// Computes what changes are necessary to insert the specified key-value pairs into this Merkle
440    /// tree, allowing for validation before applying those changes.
441    ///
442    /// This method returns a [`MutationSet`], which contains all the information for inserting
443    /// `kv_pairs` into this Merkle tree already calculated, including the new root hash, which can
444    /// be queried with [`MutationSet::root()`]. Once a mutation set is returned,
445    /// [`Smt::apply_mutations()`] can be called in order to commit these changes to the Merkle
446    /// tree, or [`drop()`] to discard them.
447    ///
448    /// # Example
449    /// ```
450    /// # use miden_crypto::{Felt, Word};
451    /// # use miden_crypto::merkle::{Smt, EmptySubtreeRoots, SMT_DEPTH};
452    /// let mut smt = Smt::new();
453    /// let pair = (Word::default(), Word::default());
454    /// let mutations = smt.compute_mutations(vec![pair]).expect("compute_mutations ok");
455    /// assert_eq!(mutations.root(), *EmptySubtreeRoots::entry(SMT_DEPTH, 0));
456    /// smt.apply_mutations(mutations);
457    /// assert_eq!(smt.root(), *EmptySubtreeRoots::entry(SMT_DEPTH, 0));
458    /// ```
459    pub fn compute_mutations(
460        &self,
461        kv_pairs: impl IntoIterator<Item = (Word, Word)>,
462    ) -> Result<MutationSet<SMT_DEPTH, Word, Word>, LargeSmtError>
463    where
464        Self: Sized + Sync,
465    {
466        // Collect and sort key-value pairs by their corresponding leaf index
467        let mut sorted_kv_pairs: Vec<_> = kv_pairs.into_iter().collect();
468        sorted_kv_pairs.par_sort_unstable_by_key(|(key, _)| Self::key_to_leaf_index(key).value());
469
470        // Collect the unique leaf indices
471        let mut leaf_indices: Vec<u64> = sorted_kv_pairs
472            .iter()
473            .map(|(key, _)| Self::key_to_leaf_index(key).value())
474            .collect();
475        leaf_indices.dedup();
476        leaf_indices.sort_unstable();
477
478        // Get leaves from storage
479        let leaves_from_storage = self.storage.get_leaves(&leaf_indices)?;
480
481        // Map leaf indices to their corresponding leaves
482        let leaf_map: Map<u64, SmtLeaf> = leaf_indices
483            .into_iter()
484            .zip(leaves_from_storage)
485            .filter_map(|(index, maybe_leaf)| maybe_leaf.map(|leaf| (index, leaf)))
486            .collect();
487
488        // Convert sorted pairs into mutated leaves and capture any new pairs
489        let (mut leaves, new_pairs) =
490            self.sorted_pairs_to_mutated_leaves_with_preloaded_leaves(sorted_kv_pairs, leaf_map);
491
492        // If no mutations, return an empty mutation set
493        let old_root = self.root()?;
494        if leaves.is_empty() {
495            return Ok(MutationSet {
496                old_root,
497                new_root: old_root,
498                node_mutations: NodeMutations::default(),
499                new_pairs,
500            });
501        }
502
503        let mut node_mutations = NodeMutations::default();
504
505        // Process each depth level in reverse, stepping by the subtree depth
506        for subtree_root_depth in
507            (0..=SMT_DEPTH - SUBTREE_DEPTH).step_by(SUBTREE_DEPTH as usize).rev()
508        {
509            // Parallel processing of each subtree to generate mutations and roots
510            let (mutations_per_subtree, mut subtree_roots): (Vec<_>, Vec<_>) = leaves
511                .into_par_iter()
512                .map(|subtree_leaves| {
513                    let subtree: Option<Subtree> = if subtree_root_depth < IN_MEMORY_DEPTH {
514                        None
515                    } else {
516                        // Compute subtree root index
517                        let subtree_root_index = NodeIndex::new_unchecked(
518                            subtree_root_depth,
519                            subtree_leaves[0].col >> SUBTREE_DEPTH,
520                        );
521                        self.storage
522                            .get_subtree(subtree_root_index)
523                            .expect("Storage error getting subtree in compute_mutations")
524                    };
525                    debug_assert!(subtree_leaves.is_sorted() && !subtree_leaves.is_empty());
526                    self.build_subtree_mutations(
527                        subtree_leaves,
528                        SMT_DEPTH,
529                        subtree_root_depth,
530                        subtree,
531                    )
532                })
533                .unzip();
534
535            // Prepare leaves for the next depth level
536            leaves = SubtreeLeavesIter::from_leaves(&mut subtree_roots).collect();
537
538            // Aggregate all node mutations
539            node_mutations.extend(mutations_per_subtree.into_iter().flatten());
540
541            debug_assert!(!leaves.is_empty());
542        }
543
544        let new_root = leaves[0][0].hash;
545
546        // Create mutation set
547        let mutation_set = MutationSet {
548            old_root: self.root()?,
549            new_root,
550            node_mutations,
551            new_pairs,
552        };
553
554        // There should be mutations and new pairs at this point
555        debug_assert!(
556            !mutation_set.node_mutations().is_empty() && !mutation_set.new_pairs().is_empty()
557        );
558
559        Ok(mutation_set)
560    }
561
562    /// Applies the prospective mutations computed with [`Smt::compute_mutations()`] to this tree.
563    ///
564    /// # Errors
565    /// If `mutations` was computed on a tree with a different root than this one, returns
566    /// [`MerkleError::ConflictingRoots`] with a two-item [`Vec`]. The first item is the root hash
567    /// the `mutations` were computed against, and the second item is the actual current root of
568    /// this tree.
569    pub fn apply_mutations(
570        &mut self,
571        mutations: MutationSet<SMT_DEPTH, Word, Word>,
572    ) -> Result<(), LargeSmtError> {
573        use NodeMutation::*;
574        use rayon::prelude::*;
575        let MutationSet {
576            old_root,
577            node_mutations,
578            new_pairs,
579            new_root,
580        } = mutations;
581
582        // Guard against accidentally trying to apply mutations that were computed against a
583        // different tree, including a stale version of this tree.
584        let expected_root = self.root()?;
585        if old_root != expected_root {
586            return Err(LargeSmtError::Merkle(MerkleError::ConflictingRoots {
587                expected_root,
588                actual_root: old_root,
589            }));
590        }
591
592        // Sort mutations
593        let mut sorted_mutations: Vec<_> = Vec::from_iter(node_mutations);
594        sorted_mutations.par_sort_unstable_by_key(|(index, _)| Subtree::find_subtree_root(*index));
595
596        // Collect all unique subtree root indexes needed
597        let mut subtree_roots_indices: Vec<NodeIndex> = sorted_mutations
598            .iter()
599            .filter_map(|(index, _)| {
600                if index.depth() < IN_MEMORY_DEPTH {
601                    None
602                } else {
603                    Some(Subtree::find_subtree_root(*index))
604                }
605            })
606            .collect();
607        subtree_roots_indices.dedup();
608
609        // Read all subtrees at once
610        let subtrees_from_storage = self.storage.get_subtrees(&subtree_roots_indices)?;
611
612        // Map the subtrees
613        let mut loaded_subtrees: Map<NodeIndex, Option<Subtree>> = subtree_roots_indices
614            .into_iter()
615            .zip(subtrees_from_storage)
616            .map(|(root_index, subtree_opt)| {
617                (root_index, Some(subtree_opt.unwrap_or_else(|| Subtree::new(root_index))))
618            })
619            .collect();
620
621        // Process mutations
622        for (index, mutation) in sorted_mutations {
623            if index.depth() < IN_MEMORY_DEPTH {
624                match mutation {
625                    Removal => self.remove_inner_node(index),
626                    Addition(node) => self.insert_inner_node(index, node),
627                };
628            } else {
629                let subtree_root_index = Subtree::find_subtree_root(index);
630                let subtree = loaded_subtrees
631                    .get_mut(&subtree_root_index)
632                    .expect("Subtree map entry must exist")
633                    .as_mut()
634                    .expect("Subtree must exist as it was either fetched or created");
635
636                match mutation {
637                    Removal => subtree.remove_inner_node(index),
638                    Addition(node) => subtree.insert_inner_node(index, node),
639                };
640            }
641        }
642
643        // Go through subtrees, see if any are empty, and if so remove them
644        for (_index, subtree) in loaded_subtrees.iter_mut() {
645            if subtree.as_ref().is_some_and(|s| s.is_empty()) {
646                *subtree = None;
647            }
648        }
649
650        // Collect and sort key-value pairs by their corresponding leaf index
651        let mut sorted_kv_pairs: Vec<_> = new_pairs.iter().map(|(k, v)| (*k, *v)).collect();
652        sorted_kv_pairs.par_sort_by_key(|(key, _)| Self::key_to_leaf_index(key).value());
653
654        // Collect the unique leaf indices
655        let mut leaf_indices: Vec<u64> = sorted_kv_pairs
656            .iter()
657            .map(|(key, _)| Self::key_to_leaf_index(key).value())
658            .collect();
659        leaf_indices.par_sort_unstable();
660        leaf_indices.dedup();
661
662        // Get leaves from storage
663        let leaves = self.storage.get_leaves(&leaf_indices)?;
664
665        // Map leaf indices to their corresponding leaves
666        let mut leaf_map: Map<u64, Option<SmtLeaf>> =
667            leaf_indices.into_iter().zip(leaves).collect();
668
669        let mut leaf_count_delta = 0isize;
670        let mut entry_count_delta = 0isize;
671
672        for (key, value) in new_pairs {
673            let idx = Self::key_to_leaf_index(&key).value();
674            // Get leaf
675            let entry = leaf_map.entry(idx).or_insert(None);
676
677            // New values is empty, handle deletion
678            if value == Self::EMPTY_VALUE {
679                if let Some(leaf) = entry {
680                    // Leaf exists, handle deletion
681                    if leaf.remove(key).1 {
682                        // Key had previous value, decrement entry count
683                        entry_count_delta -= 1;
684                        if leaf.is_empty() {
685                            // Leaf is now empty, remove it and decrement leaf count
686                            *entry = None;
687                            leaf_count_delta -= 1;
688                        }
689                    }
690                }
691            } else {
692                // New value is not empty, handle update or create
693                match entry {
694                    Some(leaf) => {
695                        // Leaf exists, handle update
696                        if leaf.insert(key, value).expect("Failed to insert value").is_none() {
697                            // Key had no previous value, increment entry count
698                            entry_count_delta += 1;
699                        }
700                    },
701                    None => {
702                        // Leaf does not exist, create it
703                        *entry = Some(SmtLeaf::Single((key, value)));
704                        // Increment both entry and leaf count
705                        entry_count_delta += 1;
706                        leaf_count_delta += 1;
707                    },
708                }
709            }
710        }
711
712        let updates = StorageUpdates::from_parts(
713            leaf_map,
714            loaded_subtrees,
715            new_root,
716            leaf_count_delta,
717            entry_count_delta,
718        );
719        self.storage.apply(updates)?;
720        Ok(())
721    }
722
723    /// Applies the prospective mutations computed with [`Smt::compute_mutations()`] to this tree
724    /// and returns the reverse mutation set.
725    ///
726    /// Applying the reverse mutation sets to the updated tree will revert the changes.
727    ///
728    /// # Errors
729    /// If `mutations` was computed on a tree with a different root than this one, returns
730    /// [`MerkleError::ConflictingRoots`] with a two-item [`Vec`]. The first item is the root hash
731    /// the `mutations` were computed against, and the second item is the actual current root of
732    /// this tree.
733    pub fn apply_mutations_with_reversion(
734        &mut self,
735        mutations: MutationSet<SMT_DEPTH, Word, Word>,
736    ) -> Result<MutationSet<SMT_DEPTH, Word, Word>, LargeSmtError>
737    where
738        Self: Sized,
739    {
740        use NodeMutation::*;
741        let MutationSet {
742            old_root,
743            node_mutations,
744            new_pairs,
745            new_root,
746        } = mutations;
747
748        let mut reverse_mutations = NodeMutations::new();
749        for (index, mutation) in node_mutations {
750            match mutation {
751                Removal => {
752                    if let Some(node) = self.remove_inner_node(index) {
753                        reverse_mutations.insert(index, Addition(node));
754                    }
755                },
756                Addition(node) => {
757                    if let Some(old_node) = self.insert_inner_node(index, node) {
758                        reverse_mutations.insert(index, Addition(old_node));
759                    } else {
760                        reverse_mutations.insert(index, Removal);
761                    }
762                },
763            }
764        }
765
766        let mut reverse_pairs = Map::new();
767        for (key, value) in new_pairs {
768            if let Some(old_value) = self.insert_value(key, value)? {
769                reverse_pairs.insert(key, old_value);
770            } else {
771                reverse_pairs.insert(key, Self::EMPTY_VALUE);
772            }
773        }
774
775        self.set_root(new_root);
776
777        Ok(MutationSet {
778            old_root: new_root,
779            node_mutations: reverse_mutations,
780            new_pairs: reverse_pairs,
781            new_root: old_root,
782        })
783    }
784
785    // HELPERS
786    // --------------------------------------------------------------------------------------------
787
788    fn build_subtrees(&mut self, mut entries: Vec<(Word, Word)>) -> Result<(), MerkleError> {
789        entries.par_sort_unstable_by_key(|item| {
790            let index = Self::key_to_leaf_index(&item.0);
791            index.value()
792        });
793        self.build_subtrees_from_sorted_entries(entries)?;
794        Ok(())
795    }
796
797    fn build_subtrees_from_sorted_entries(
798        &mut self,
799        entries: Vec<(Word, Word)>,
800    ) -> Result<(), MerkleError> {
801        let PairComputations {
802            leaves: mut leaf_subtrees,
803            nodes: initial_leaves,
804        } = Smt::sorted_pairs_to_leaves(entries)?;
805
806        if initial_leaves.is_empty() {
807            return Ok(());
808        }
809
810        // Store the initial leaves
811        self.storage.set_leaves(initial_leaves).expect("Failed to store initial leaves");
812
813        // build deep (disk-backed) subtrees
814        leaf_subtrees = std::thread::scope(|scope| {
815            let (sender, receiver) = flume::bounded(CONSTRUCTION_SUBTREE_BATCH_SIZE);
816            let storage: &S = &self.storage;
817
818            scope.spawn(move || -> Result<(), MerkleError> {
819                let mut subtrees: Vec<Subtree> =
820                    Vec::with_capacity(CONSTRUCTION_SUBTREE_BATCH_SIZE);
821                for subtree in receiver.iter() {
822                    subtrees.push(subtree);
823                    if subtrees.len() == CONSTRUCTION_SUBTREE_BATCH_SIZE {
824                        let subtrees_clone = mem::take(&mut subtrees);
825                        storage
826                            .set_subtrees(subtrees_clone)
827                            .expect("Writer thread failed to set subtrees");
828                    }
829                }
830                storage.set_subtrees(subtrees).expect("Writer thread failed to set subtrees");
831                Ok(())
832            });
833
834            for bottom_depth in (IN_MEMORY_DEPTH + SUBTREE_DEPTH..=SMT_DEPTH)
835                .step_by(SUBTREE_DEPTH as usize)
836                .rev()
837            {
838                let mut subtree_roots: Vec<SubtreeLeaf> = leaf_subtrees
839                    .into_par_iter()
840                    .map(|subtree_leaves| {
841                        debug_assert!(subtree_leaves.is_sorted());
842                        debug_assert!(!subtree_leaves.is_empty());
843                        let (nodes, subtree_root) =
844                            build_subtree(subtree_leaves, SMT_DEPTH, bottom_depth);
845
846                        let subtree_root_index =
847                            NodeIndex::new(bottom_depth - SUBTREE_DEPTH, subtree_root.col).unwrap();
848                        let mut subtree = Subtree::new(subtree_root_index);
849                        for (index, node) in nodes {
850                            subtree.insert_inner_node(index, node);
851                        }
852                        sender.send(subtree).expect("Flume channel disconnected unexpectedly");
853                        subtree_root
854                    })
855                    .collect();
856                leaf_subtrees = SubtreeLeavesIter::from_leaves(&mut subtree_roots).collect();
857                debug_assert!(!leaf_subtrees.is_empty());
858            }
859
860            drop(sender);
861            leaf_subtrees
862        });
863
864        // build top of the tree (in-memory only, normal insert)
865        for bottom_depth in (SUBTREE_DEPTH..=IN_MEMORY_DEPTH).step_by(SUBTREE_DEPTH as usize).rev()
866        {
867            let (nodes, mut subtree_roots): (Vec<Map<_, _>>, Vec<SubtreeLeaf>) = leaf_subtrees
868                .into_par_iter()
869                .map(|subtree| {
870                    debug_assert!(subtree.is_sorted());
871                    debug_assert!(!subtree.is_empty());
872                    let (nodes, subtree_root) = build_subtree(subtree, SMT_DEPTH, bottom_depth);
873                    (nodes, subtree_root)
874                })
875                .unzip();
876            leaf_subtrees = SubtreeLeavesIter::from_leaves(&mut subtree_roots).collect();
877            debug_assert!(!leaf_subtrees.is_empty());
878
879            for subtree_nodes in nodes {
880                self.insert_inner_nodes_batch(subtree_nodes.into_iter());
881            }
882        }
883        self.set_root(self.get_inner_node(NodeIndex::root()).hash());
884        Ok(())
885    }
886
887    // MUTATIONS
888    // --------------------------------------------------------------------------------------------
889
890    /// Computes leaves from a set of key-value pairs and current leaf values.
891    /// Derived from `sorted_pairs_to_leaves`
892    fn sorted_pairs_to_mutated_leaves_with_preloaded_leaves(
893        &self,
894        pairs: Vec<(Word, Word)>,
895        leaf_map: Map<u64, SmtLeaf>,
896    ) -> (MutatedSubtreeLeaves, Map<Word, Word>) {
897        // Map to track new key-value pairs for mutated leaves
898        let mut new_pairs = Map::new();
899
900        let accumulator = process_sorted_pairs_to_leaves(pairs, |leaf_pairs| {
901            let leaf_index = LeafIndex::<SMT_DEPTH>::from(leaf_pairs[0].0);
902            let mut leaf = leaf_map
903                .get(&leaf_index.value())
904                .cloned()
905                .unwrap_or_else(|| SmtLeaf::new_empty(leaf_pairs[0].0.into()));
906
907            let mut leaf_changed = false;
908            for (key, value) in leaf_pairs {
909                // Check if the value has changed
910                let old_value = new_pairs.get(&key).cloned().unwrap_or_else(|| {
911                    // Safe to unwrap: `leaf_pairs` contains keys all belonging to this leaf.
912                    // `SmtLeaf::get_value()` only returns `None` if the key does not belong to the
913                    // leaf, which cannot happen due to the sorting/grouping
914                    // logic in `process_sorted_pairs_to_leaves()`.
915                    leaf.get_value(&key).unwrap()
916                });
917
918                if value != old_value {
919                    // Update the leaf and track the new key-value pair
920                    leaf = self
921                        .construct_prospective_leaf(leaf, &key, &value)
922                        .expect("Failed to construct prospective leaf");
923                    new_pairs.insert(key, value);
924                    leaf_changed = true;
925                }
926            }
927
928            if leaf_changed {
929                // Only return the leaf if it actually changed
930                Ok(Some(leaf))
931            } else {
932                // Return None if leaf hasn't changed
933                Ok(None)
934            }
935        });
936        // The closure is the only possible source of errors.
937        // Since it never returns an error - only `Ok(Some(_))` or `Ok(None)` - we can safely assume
938        // `accumulator` is always `Ok(_)`.
939        (
940            accumulator.expect("process_sorted_pairs_to_leaves never fails").leaves,
941            new_pairs,
942        )
943    }
944
945    /// Computes the node mutations and the root of a subtree
946    fn build_subtree_mutations(
947        &self,
948        mut leaves: Vec<SubtreeLeaf>,
949        tree_depth: u8,
950        subtree_root_depth: u8,
951        subtree: Option<Subtree>,
952    ) -> (NodeMutations, SubtreeLeaf)
953    where
954        Self: Sized,
955    {
956        let bottom_depth = subtree_root_depth + SUBTREE_DEPTH;
957
958        debug_assert!(bottom_depth <= tree_depth);
959        debug_assert!(Integer::is_multiple_of(&bottom_depth, &SUBTREE_DEPTH));
960        debug_assert!(leaves.len() <= usize::pow(2, SUBTREE_DEPTH as u32));
961
962        let mut node_mutations: NodeMutations = Default::default();
963        let mut next_leaves: Vec<SubtreeLeaf> = Vec::with_capacity(leaves.len() / 2);
964
965        for current_depth in (subtree_root_depth..bottom_depth).rev() {
966            debug_assert!(current_depth <= bottom_depth);
967
968            let next_depth = current_depth + 1;
969            let mut iter = leaves.drain(..).peekable();
970
971            while let Some(first_leaf) = iter.next() {
972                // This constructs a valid index because next_depth will never exceed the depth of
973                // the tree.
974                let parent_index = NodeIndex::new_unchecked(next_depth, first_leaf.col).parent();
975                let parent_node = if let Some(ref sub) = subtree {
976                    sub.get_inner_node(parent_index).unwrap_or_else(|| {
977                        EmptySubtreeRoots::get_inner_node(SMT_DEPTH, parent_index.depth())
978                    })
979                } else if subtree_root_depth >= IN_MEMORY_DEPTH {
980                    EmptySubtreeRoots::get_inner_node(SMT_DEPTH, parent_index.depth())
981                } else {
982                    self.get_inner_node(parent_index)
983                };
984                let combined_node = fetch_sibling_pair(&mut iter, first_leaf, parent_node);
985                let combined_hash = combined_node.hash();
986
987                let &empty_hash = EmptySubtreeRoots::entry(tree_depth, current_depth);
988
989                // Add the parent node even if it is empty for proper upward updates
990                next_leaves.push(SubtreeLeaf {
991                    col: parent_index.value(),
992                    hash: combined_hash,
993                });
994
995                node_mutations.insert(
996                    parent_index,
997                    if combined_hash != empty_hash {
998                        NodeMutation::Addition(combined_node)
999                    } else {
1000                        NodeMutation::Removal
1001                    },
1002                );
1003            }
1004            drop(iter);
1005            leaves = mem::take(&mut next_leaves);
1006        }
1007
1008        debug_assert_eq!(leaves.len(), 1);
1009        let root_leaf = leaves.pop().unwrap();
1010        (node_mutations, root_leaf)
1011    }
1012
1013    // STORAGE
1014    // --------------------------------------------------------------------------------------------
1015
1016    // Inserts batch of upper inner nodes
1017    fn insert_inner_nodes_batch(
1018        &mut self,
1019        nodes: impl IntoIterator<Item = (NodeIndex, InnerNode)>,
1020    ) {
1021        for (index, node) in nodes {
1022            if index.depth() < IN_MEMORY_DEPTH {
1023                let memory_index = to_memory_index(&index);
1024                // Store in flat layout: left at 2*i, right at 2*i+1
1025                self.in_memory_nodes[memory_index * 2] = node.left;
1026                self.in_memory_nodes[memory_index * 2 + 1] = node.right;
1027            }
1028        }
1029    }
1030
1031    // TEST HELPERS
1032    // --------------------------------------------------------------------------------------------
1033
1034    #[cfg(test)]
1035    pub(crate) fn in_memory_nodes(&self) -> &Vec<Word> {
1036        &self.in_memory_nodes
1037    }
1038}
1039
1040impl<S: SmtStorage> SparseMerkleTree<SMT_DEPTH> for LargeSmt<S> {
1041    type Key = Word;
1042    type Value = Word;
1043    type Leaf = SmtLeaf;
1044    type Opening = SmtProof;
1045
1046    const EMPTY_VALUE: Self::Value = EMPTY_WORD;
1047    const EMPTY_ROOT: Word = *EmptySubtreeRoots::entry(SMT_DEPTH, 0);
1048
1049    fn from_raw_parts(
1050        _inner_nodes: InnerNodes,
1051        _leaves: Leaves,
1052        _root: Word,
1053    ) -> Result<Self, MerkleError> {
1054        // This method is not supported
1055        panic!("LargeSmt::from_raw_parts is not supported");
1056    }
1057
1058    fn root(&self) -> Word {
1059        self.storage.get_root().ok().flatten().unwrap_or(Self::EMPTY_ROOT)
1060    }
1061
1062    fn set_root(&mut self, root: Word) {
1063        self.storage.set_root(root).expect("Failed to set root");
1064    }
1065
1066    fn get_inner_node(&self, index: NodeIndex) -> InnerNode {
1067        if index.depth() < IN_MEMORY_DEPTH {
1068            let memory_index = to_memory_index(&index);
1069            // Reconstruct InnerNode from flat layout: left at 2*i, right at 2*i+1
1070            return InnerNode {
1071                left: self.in_memory_nodes[memory_index * 2],
1072                right: self.in_memory_nodes[memory_index * 2 + 1],
1073            };
1074        }
1075
1076        self.storage
1077            .get_inner_node(index)
1078            .expect("Failed to get inner node")
1079            .unwrap_or_else(|| EmptySubtreeRoots::get_inner_node(SMT_DEPTH, index.depth()))
1080    }
1081
1082    fn insert_inner_node(&mut self, index: NodeIndex, inner_node: InnerNode) -> Option<InnerNode> {
1083        if index.depth() < IN_MEMORY_DEPTH {
1084            let i = to_memory_index(&index);
1085            // Get the old node before replacing
1086            let old_left = self.in_memory_nodes[i * 2];
1087            let old_right = self.in_memory_nodes[i * 2 + 1];
1088
1089            // Store new node in flat layout
1090            self.in_memory_nodes[i * 2] = inner_node.left;
1091            self.in_memory_nodes[i * 2 + 1] = inner_node.right;
1092
1093            // Check if the old node was empty
1094            if is_empty_parent(old_left, old_right, index.depth() + 1) {
1095                return None;
1096            }
1097
1098            return Some(InnerNode { left: old_left, right: old_right });
1099        }
1100        self.storage
1101            .set_inner_node(index, inner_node)
1102            .expect("Failed to store inner node")
1103    }
1104
1105    fn remove_inner_node(&mut self, index: NodeIndex) -> Option<InnerNode> {
1106        if index.depth() < IN_MEMORY_DEPTH {
1107            let memory_index = to_memory_index(&index);
1108            // Get the old node before replacing with empty hashes
1109            let old_left = self.in_memory_nodes[memory_index * 2];
1110            let old_right = self.in_memory_nodes[memory_index * 2 + 1];
1111
1112            // Replace with empty hashes
1113            let child_depth = index.depth() + 1;
1114            let empty_hash = *EmptySubtreeRoots::entry(SMT_DEPTH, child_depth);
1115            self.in_memory_nodes[memory_index * 2] = empty_hash;
1116            self.in_memory_nodes[memory_index * 2 + 1] = empty_hash;
1117
1118            // Return the old node if it wasn't already empty
1119            if is_empty_parent(old_left, old_right, child_depth) {
1120                return None;
1121            }
1122
1123            return Some(InnerNode { left: old_left, right: old_right });
1124        }
1125        self.storage.remove_inner_node(index).expect("Failed to remove inner node")
1126    }
1127
1128    fn insert(&mut self, key: Self::Key, value: Self::Value) -> Result<Self::Value, MerkleError> {
1129        let old_value = self.get_value(&key);
1130        // if the old value and new value are the same, there is nothing to update
1131        if value == old_value {
1132            return Ok(value);
1133        }
1134
1135        let mutations = self
1136            .compute_mutations([(key, value)])
1137            .expect("Failed to compute mutations in insert");
1138        self.apply_mutations(mutations).expect("Failed to apply mutations in insert");
1139
1140        Ok(old_value)
1141    }
1142
1143    fn insert_value(
1144        &mut self,
1145        key: Self::Key,
1146        value: Self::Value,
1147    ) -> Result<Option<Self::Value>, MerkleError> {
1148        // inserting an `EMPTY_VALUE` is equivalent to removing any value associated with `key`
1149        let index = Self::key_to_leaf_index(&key).value();
1150        if value != Self::EMPTY_VALUE {
1151            match self.storage.insert_value(index, key, value) {
1152                Ok(prev) => Ok(prev),
1153                Err(StorageError::Leaf(SmtLeafError::TooManyLeafEntries { actual })) => {
1154                    Err(MerkleError::TooManyLeafEntries { actual })
1155                },
1156                Err(_) => {
1157                    panic!("Storage error during insert_value");
1158                },
1159            }
1160        } else {
1161            Ok(self.storage.remove_value(index, key).expect("Failed to remove value"))
1162        }
1163    }
1164
1165    fn get_value(&self, key: &Self::Key) -> Self::Value {
1166        let leaf_pos = LeafIndex::<SMT_DEPTH>::from(*key);
1167        match self.storage.get_leaf(leaf_pos.value()) {
1168            Ok(Some(leaf)) => leaf.get_value(key).unwrap_or_default(),
1169            Ok(None) => EMPTY_WORD,
1170            Err(_) => {
1171                panic!("Storage error during get_leaf in get_value");
1172            },
1173        }
1174    }
1175
1176    fn get_leaf(&self, key: &Word) -> Self::Leaf {
1177        let leaf_pos = LeafIndex::<SMT_DEPTH>::from(*key).value();
1178        match self.storage.get_leaf(leaf_pos) {
1179            Ok(Some(leaf)) => leaf,
1180            Ok(None) => SmtLeaf::new_empty((*key).into()),
1181            Err(_) => {
1182                panic!("Storage error during get_leaf in get_leaf");
1183            },
1184        }
1185    }
1186
1187    fn hash_leaf(leaf: &Self::Leaf) -> Word {
1188        leaf.hash()
1189    }
1190
1191    fn construct_prospective_leaf(
1192        &self,
1193        mut existing_leaf: SmtLeaf,
1194        key: &Word,
1195        value: &Word,
1196    ) -> Result<SmtLeaf, SmtLeafError> {
1197        debug_assert_eq!(existing_leaf.index(), Self::key_to_leaf_index(key));
1198
1199        match existing_leaf {
1200            SmtLeaf::Empty(_) => Ok(SmtLeaf::new_single(*key, *value)),
1201            _ => {
1202                if *value != EMPTY_WORD {
1203                    existing_leaf.insert(*key, *value)?;
1204                } else {
1205                    existing_leaf.remove(*key);
1206                }
1207
1208                Ok(existing_leaf)
1209            },
1210        }
1211    }
1212
1213    fn open(&self, key: &Self::Key) -> Self::Opening {
1214        let leaf = self.get_leaf(key);
1215
1216        let mut idx: NodeIndex = LeafIndex::from(*key).into();
1217
1218        let subtree_roots: Vec<NodeIndex> = (0..NUM_SUBTREE_LEVELS)
1219            .scan(idx.parent(), |cursor, _| {
1220                let subtree_root = Subtree::find_subtree_root(*cursor);
1221                *cursor = subtree_root.parent();
1222                Some(subtree_root)
1223            })
1224            .collect();
1225        // cache subtrees in memory
1226        let mut cache = Map::<NodeIndex, Subtree>::new();
1227        for &root in &subtree_roots {
1228            let subtree =
1229                match self.storage.get_subtree(root).expect("storage error fetching subtree") {
1230                    Some(st) => st,
1231                    None => Subtree::new(root),
1232                };
1233            cache.insert(root, subtree);
1234        }
1235        let mut path = Vec::with_capacity(idx.depth() as usize);
1236        while idx.depth() > 0 {
1237            let is_right = idx.is_value_odd();
1238            idx = idx.parent();
1239
1240            let sibling_hash = if idx.depth() < IN_MEMORY_DEPTH {
1241                // top levels in memory
1242                let InnerNode { left, right } = self.get_inner_node(idx);
1243                if is_right { left } else { right }
1244            } else {
1245                // deep levels come from our 5 preloaded subtrees
1246                let root = Subtree::find_subtree_root(idx);
1247                let subtree = &cache[&root];
1248                let InnerNode { left, right } = subtree
1249                    .get_inner_node(idx)
1250                    .unwrap_or_else(|| EmptySubtreeRoots::get_inner_node(SMT_DEPTH, idx.depth()));
1251                if is_right { left } else { right }
1252            };
1253
1254            path.push(sibling_hash);
1255        }
1256
1257        let merkle_path =
1258            SparseMerklePath::from_sized_iter(path).expect("failed to convert to SparseMerklePath");
1259        Self::path_and_leaf_to_opening(merkle_path, leaf)
1260    }
1261
1262    fn key_to_leaf_index(key: &Word) -> LeafIndex<SMT_DEPTH> {
1263        let most_significant_felt = key[3];
1264        LeafIndex::new_max_depth(most_significant_felt.as_int())
1265    }
1266
1267    fn path_and_leaf_to_opening(path: SparseMerklePath, leaf: SmtLeaf) -> SmtProof {
1268        SmtProof::new_unchecked(path, leaf)
1269    }
1270}
1271
1272impl<S: SmtStorage> PartialEq for LargeSmt<S> {
1273    /// Compares two LargeSmt instances based on their root hash and metadata.
1274    ///
1275    /// Note: This comparison only checks the root hash and counts, not the underlying
1276    /// storage contents. Two SMTs with the same root should be cryptographically
1277    /// equivalent, but this doesn't verify the storage backends are identical.
1278    fn eq(&self, other: &Self) -> bool {
1279        self.root().unwrap() == other.root().unwrap()
1280            && self.num_leaves().unwrap() == other.num_leaves().unwrap()
1281            && self.num_entries().unwrap() == other.num_entries().unwrap()
1282    }
1283}
1284
1285impl<S: SmtStorage> Eq for LargeSmt<S> {}
1286
1287// Note: Clone is intentionally not implemented for LargeSmt because:
1288// 1. Cloning would only clone the in-memory portion and share storage via Arc
1289// 2. This doesn't actually clone the underlying disk data, which is misleading
1290// 3. Users should be explicit about sharing LargeSmt instances via Arc if needed
1291
1292/// Converts a NodeIndex to a flat vector index using 1-indexed layout.
1293/// Index 0 is unused, index 1 is root.
1294/// For a node at index i: left child at 2*i, right child at 2*i+1.
1295fn to_memory_index(index: &NodeIndex) -> usize {
1296    debug_assert!(index.depth() < IN_MEMORY_DEPTH);
1297    debug_assert!(index.value() < (1 << index.depth()));
1298    (1usize << index.depth()) + index.value() as usize
1299}
1300
1301/// Checks if a node with the given children is empty.
1302/// A node is considered empty if both children equal the empty hash for that depth.
1303fn is_empty_parent(left: Word, right: Word, child_depth: u8) -> bool {
1304    let empty_hash = *EmptySubtreeRoots::entry(SMT_DEPTH, child_depth);
1305    left == empty_hash && right == empty_hash
1306}
1307
1308// ITERATORS
1309// ================================================================================================
1310
1311enum InnerNodeIteratorState<'a> {
1312    InMemory {
1313        current_index: usize,
1314        large_smt_in_memory_nodes: &'a Vec<Word>,
1315    },
1316    Subtree {
1317        subtree_iter: Box<dyn Iterator<Item = Subtree> + 'a>,
1318        current_subtree_node_iter: Option<Box<dyn Iterator<Item = InnerNodeInfo> + 'a>>,
1319    },
1320    Done,
1321}
1322
1323pub struct LargeSmtInnerNodeIterator<'a, S: SmtStorage> {
1324    large_smt: &'a LargeSmt<S>,
1325    state: InnerNodeIteratorState<'a>,
1326}
1327
1328impl<'a, S: SmtStorage> LargeSmtInnerNodeIterator<'a, S> {
1329    fn new(large_smt: &'a LargeSmt<S>) -> Self {
1330        // in-memory nodes should never be empty
1331        Self {
1332            large_smt,
1333            state: InnerNodeIteratorState::InMemory {
1334                current_index: 0,
1335                large_smt_in_memory_nodes: &large_smt.in_memory_nodes,
1336            },
1337        }
1338    }
1339}
1340
1341impl<S: SmtStorage> Iterator for LargeSmtInnerNodeIterator<'_, S> {
1342    type Item = InnerNodeInfo;
1343
1344    /// Returns the next inner node info in the tree.
1345    ///
1346    /// The iterator operates in three phases:
1347    /// 1. InMemory: Iterates through the in-memory nodes (depths 0-IN_MEMORY_DEPTH-1)
1348    /// 2. Subtree: Iterates through nodes in storage subtrees (depths IN_MEMORY_DEPTH-SMT_DEPTH)
1349    /// 3. Done: No more nodes to iterate
1350    fn next(&mut self) -> Option<Self::Item> {
1351        loop {
1352            match &mut self.state {
1353                // Phase 1: Process in-memory nodes (depths 0-23)
1354                InnerNodeIteratorState::InMemory { current_index, large_smt_in_memory_nodes } => {
1355                    // Iterate through nodes at depths 0 to IN_MEMORY_DEPTH-1
1356                    // Start at index 1 (root), max node index is (1 << IN_MEMORY_DEPTH) - 1
1357                    if *current_index == 0 {
1358                        *current_index = 1;
1359                    }
1360
1361                    let max_node_idx = (1 << IN_MEMORY_DEPTH) - 1;
1362
1363                    while *current_index <= max_node_idx {
1364                        let node_idx = *current_index;
1365                        *current_index += 1;
1366
1367                        // Get children from flat layout: left at 2*i, right at 2*i+1
1368                        let left = large_smt_in_memory_nodes[node_idx * 2];
1369                        let right = large_smt_in_memory_nodes[node_idx * 2 + 1];
1370
1371                        // Skip empty nodes
1372                        let depth = node_idx.ilog2() as u8;
1373                        let child_depth = depth + 1;
1374
1375                        if !is_empty_parent(left, right, child_depth) {
1376                            return Some(InnerNodeInfo {
1377                                value: Rpo256::merge(&[left, right]),
1378                                left,
1379                                right,
1380                            });
1381                        }
1382                    }
1383
1384                    // All in-memory nodes processed. Transition to Phase 2: Subtree iteration
1385                    match self.large_smt.storage.iter_subtrees() {
1386                        Ok(subtree_iter) => {
1387                            self.state = InnerNodeIteratorState::Subtree {
1388                                subtree_iter,
1389                                current_subtree_node_iter: None,
1390                            };
1391                            continue; // Start processing subtrees immediately
1392                        },
1393                        Err(_e) => {
1394                            // Storage error occurred - we should propagate this properly
1395                            // For now, transition to Done state to avoid infinite loops
1396                            self.state = InnerNodeIteratorState::Done;
1397                            return None;
1398                        },
1399                    }
1400                },
1401                // Phase 2: Process storage subtrees (depths 25-64)
1402                InnerNodeIteratorState::Subtree { subtree_iter, current_subtree_node_iter } => {
1403                    loop {
1404                        // First, try to get the next node from current subtree
1405                        if let Some(node_iter) = current_subtree_node_iter
1406                            && let Some(info) = node_iter.as_mut().next()
1407                        {
1408                            return Some(info);
1409                        }
1410
1411                        // Current subtree exhausted, move to next subtree
1412                        match subtree_iter.next() {
1413                            Some(next_subtree) => {
1414                                let infos: Vec<InnerNodeInfo> =
1415                                    next_subtree.iter_inner_node_info().collect();
1416                                *current_subtree_node_iter = Some(Box::new(infos.into_iter()));
1417                            },
1418                            None => {
1419                                self.state = InnerNodeIteratorState::Done;
1420                                return None; // All subtrees processed
1421                            },
1422                        }
1423                    }
1424                },
1425                InnerNodeIteratorState::Done => {
1426                    return None; // Iteration finished.
1427                },
1428            }
1429        }
1430    }
1431}