Skip to main content

miden_crypto/merkle/smt/
mod.rs

1//! Sparse Merkle Tree (SMT) data structures.
2
3use alloc::{string::ToString, vec::Vec};
4use core::{
5    fmt::{self, Display},
6    hash::Hash,
7};
8
9use super::{EmptySubtreeRoots, InnerNodeInfo, MerkleError, NodeIndex, SparseMerklePath};
10use crate::{
11    EMPTY_WORD, Map, Set, Word,
12    hash::poseidon2::Poseidon2,
13    utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
14};
15
16mod full;
17pub use full::{MAX_LEAF_ENTRIES, SMT_DEPTH, Smt, SmtLeaf, SmtLeafError, SmtProof, SmtProofError};
18
19#[cfg(feature = "concurrent")]
20mod large;
21#[cfg(feature = "internal")]
22pub use full::concurrent::{SubtreeLeaf, build_subtree_for_bench};
23#[cfg(feature = "concurrent")]
24pub use large::{
25    LargeSmt, LargeSmtError, LargeSmtResult, MemoryStorage, MemoryStorageSnapshot, SmtStorage,
26    SmtStorageReader, StorageError, StorageResult, StorageUpdateParts, StorageUpdates, Subtree,
27    SubtreeError, SubtreeUpdate,
28};
29#[cfg(feature = "rocksdb")]
30pub use large::{
31    RocksDbBloomFilterBitsPerKey, RocksDbConfig, RocksDbDurabilityMode, RocksDbMemoryBudget,
32    RocksDbSnapshotStorage, RocksDbStorage, RocksDbTuningOptions, RocksDbWriteBufferManagerBudget,
33};
34
35mod large_forest;
36pub use large_forest::{
37    AppliedLineageMutation, Backend, BackendError, BackendReader, Config as ForestConfig,
38    DEFAULT_MAX_HISTORY_VERSIONS as FOREST_DEFAULT_MAX_HISTORY_VERSIONS,
39    InMemoryBackend as ForestInMemoryBackend,
40    InMemoryBackendSnapshot as ForestInMemoryBackendReader, LargeSmtForest, LargeSmtForestError,
41    LineageId, LineageMutation, LineageMutationKind,
42    MIN_HISTORY_VERSIONS as FOREST_MIN_HISTORY_VERSIONS, RootInfo, SmtForestMutationSet,
43    SmtForestOperation, SmtForestUpdateBatch, SmtUpdateBatch, TreeEntry, TreeId, TreeWithRoot,
44    VersionId,
45};
46#[cfg(feature = "persistent-forest")]
47pub use large_forest::{
48    PersistentBackend as ForestPersistentBackend, PersistentBackendConfig,
49    PersistentBackendReader as ForestPersistentBackendReader,
50};
51
52mod simple;
53pub use simple::{SimpleSmt, SimpleSmtProof};
54
55mod partial;
56use miden_field::Felt;
57pub use partial::{PartialSmt, UniqueNodes};
58// CONSTANTS
59// ================================================================================================
60
61/// Minimum supported depth.
62pub const SMT_MIN_DEPTH: u8 = 1;
63
64/// Maximum supported depth.
65pub const SMT_MAX_DEPTH: u8 = 64;
66
67/// The felt used as a domain separator when hashing leaves in merkle trees.
68pub const LEAF_DOMAIN: Felt = Felt::new_unchecked(0x13af);
69
70// SPARSE MERKLE TREE
71// ================================================================================================
72
73type InnerNodes = Map<NodeIndex, InnerNode>;
74type Leaves<T> = Map<u64, T>;
75type NodeMutations = Map<NodeIndex, NodeMutation>;
76
77/// The read-only view of a sparse Merkle tree.
78///
79/// This trait contains all methods that require only read access to the tree, including querying
80/// values, generating proofs/openings, and computing prospective mutations. Splitting this from
81/// [`SparseMerkleTree`] allows types like `LargeSmt` to implement read-only operations with
82/// weaker generic bounds (e.g., `SmtStorageReader` instead of `SmtStorage`).
83pub(crate) trait SparseMerkleTreeReader<const DEPTH: u8> {
84    /// The type for a key
85    type Key: Clone + Ord + Eq + Hash;
86    /// The type for a value
87    type Value: Clone + PartialEq;
88    /// The type for a leaf
89    type Leaf: Clone;
90    /// The type for an opening (i.e. a "proof") of a leaf
91    type Opening;
92
93    /// The default value used to compute the hash of empty leaves
94    const EMPTY_VALUE: Self::Value;
95
96    /// The root of the empty tree with provided DEPTH
97    const EMPTY_ROOT: Word;
98
99    // PROVIDED METHODS
100    // ---------------------------------------------------------------------------------------------
101
102    /// Returns a [SparseMerklePath] to the specified key.
103    ///
104    /// Mostly this is an implementation detail of [`Self::open()`].
105    fn get_path(&self, key: &Self::Key) -> SparseMerklePath {
106        let index = NodeIndex::from(Self::key_to_leaf_index(key));
107
108        // SAFETY: this is guaranteed to have depth <= SMT_MAX_DEPTH
109        SparseMerklePath::from_sized_iter(
110            index.proof_indices().map(|index| self.get_node_hash(index)),
111        )
112        .expect("failed to convert to SparseMerklePath")
113    }
114
115    /// Get the hash of a node at an arbitrary index, including the root or leaf hashes.
116    ///
117    /// The root index simply returns [`Self::root()`]. Other hashes are retrieved by calling
118    /// [`Self::get_inner_node()`] on the parent, and returning the respective child hash.
119    fn get_node_hash(&self, index: NodeIndex) -> Word {
120        if index.is_root() {
121            return self.root();
122        }
123
124        let InnerNode { left, right } = self.get_inner_node(index.parent());
125
126        let index_is_right = index.is_position_odd();
127        if index_is_right { right } else { left }
128    }
129
130    /// Returns an opening of the leaf associated with `key`. Conceptually, an opening is a sparse
131    /// Merkle path to the leaf, as well as the leaf itself.
132    fn open(&self, key: &Self::Key) -> Self::Opening {
133        let leaf = self.get_leaf(key);
134        let merkle_path = self.get_path(key);
135
136        Self::path_and_leaf_to_opening(merkle_path, leaf)
137    }
138
139    /// Computes what changes are necessary to insert the specified key-value pairs into this Merkle
140    /// tree, allowing for validation before applying those changes.
141    ///
142    /// This method returns a [`MutationSet`], which contains all the information for inserting
143    /// `kv_pairs` into this Merkle tree already calculated, including the new root hash, which can
144    /// be queried with [`MutationSet::root()`]. Once a mutation set is returned,
145    /// [`SparseMerkleTree::apply_mutations()`] can be called in order to commit these changes to
146    /// the Merkle tree, or [`drop()`] to discard them.
147    ///
148    /// # Errors
149    /// - Returns [`MerkleError::DuplicateValuesForIndex`] if `kv_pairs` contains duplicate keys.
150    /// - If mutations would exceed [`crate::merkle::smt::MAX_LEAF_ENTRIES`] (1024 entries) in a
151    ///   leaf, returns [`MerkleError::TooManyLeafEntries`].
152    fn compute_mutations(
153        &self,
154        kv_pairs: impl IntoIterator<Item = (Self::Key, Self::Value)>,
155    ) -> Result<MutationSet<DEPTH, Self::Key, Self::Value>, MerkleError> {
156        self.compute_mutations_sequential(kv_pairs)
157    }
158
159    /// Sequential version of [`SparseMerkleTreeReader::compute_mutations()`].
160    /// This is the default implementation.
161    ///
162    /// # Errors
163    ///
164    /// - [`MerkleError::DuplicateValuesForIndex`] if `kv_pairs` contains multiple pairs with the
165    ///   same key.
166    /// - [`MerkleError::TooManyLeafEntries`] if the mutations would cause the tree to exceed
167    ///   [`crate::merkle::smt::MAX_LEAF_ENTRIES`] in a single leaf.
168    fn compute_mutations_sequential(
169        &self,
170        kv_pairs: impl IntoIterator<Item = (Self::Key, Self::Value)>,
171    ) -> Result<MutationSet<DEPTH, Self::Key, Self::Value>, MerkleError> {
172        use NodeMutation::*;
173
174        let mut new_root = self.root();
175        let mut new_pairs: Map<Self::Key, Self::Value> = Default::default();
176        let mut node_mutations: NodeMutations = NodeMutations::new();
177        let mut seen_keys: Set<Self::Key> = Set::new();
178
179        for (key, value) in kv_pairs {
180            // Reject duplicate keys.
181            if !seen_keys.insert(key.clone()) {
182                return Err(MerkleError::DuplicateValuesForIndex(
183                    Self::key_to_leaf_index(&key).position(),
184                ));
185            }
186
187            // If the old value and the new value are the same, there is nothing to update.
188            let old_value = new_pairs.get(&key).cloned().unwrap_or_else(|| self.get_value(&key));
189            if value == old_value {
190                continue;
191            }
192
193            let leaf_index = Self::key_to_leaf_index(&key);
194            let mut node_index = NodeIndex::from(leaf_index);
195
196            // We need the current leaf's hash to calculate the new leaf, but in the rare case that
197            // `kv_pairs` has multiple pairs that go into the same leaf, then those pairs are also
198            // part of the "current leaf".
199            let old_leaf = {
200                let pairs_at_index = new_pairs
201                    .iter()
202                    .filter(|&(new_key, _)| Self::key_to_leaf_index(new_key) == leaf_index);
203
204                pairs_at_index.fold(self.get_leaf(&key), |acc, (k, v)| {
205                    // Most of the time `pairs_at_index` should only contain a single entry (or
206                    // none at all), as multi-leaves should be really rare.
207                    let existing_leaf = acc;
208                    self.construct_prospective_leaf(existing_leaf, k, v)
209                        .expect("current leaf should be valid")
210                })
211            };
212
213            let new_leaf =
214                self.construct_prospective_leaf(old_leaf, &key, &value).map_err(|e| match e {
215                    SmtLeafError::TooManyLeafEntries { actual } => {
216                        MerkleError::TooManyLeafEntries { actual }
217                    },
218                    other => panic!("unexpected SmtLeaf::insert error: {other:?}"),
219                })?;
220
221            let mut new_child_hash = Self::hash_leaf(&new_leaf);
222
223            for node_depth in (0..node_index.depth()).rev() {
224                // Whether the node we're replacing is the right child or the left child.
225                let is_right = node_index.is_position_odd();
226                node_index.move_up();
227
228                let old_node = node_mutations
229                    .get(&node_index)
230                    .map(|mutation| match mutation {
231                        Addition(node) => node.clone(),
232                        Removal => EmptySubtreeRoots::get_inner_node(DEPTH, node_depth),
233                    })
234                    .unwrap_or_else(|| self.get_inner_node(node_index));
235
236                let new_node = if is_right {
237                    InnerNode {
238                        left: old_node.left,
239                        right: new_child_hash,
240                    }
241                } else {
242                    InnerNode {
243                        left: new_child_hash,
244                        right: old_node.right,
245                    }
246                };
247
248                // The next iteration will operate on this new node's hash.
249                new_child_hash = new_node.hash();
250
251                let &equivalent_empty_hash = EmptySubtreeRoots::entry(DEPTH, node_depth);
252                let is_removal = new_child_hash == equivalent_empty_hash;
253                let new_entry = if is_removal { Removal } else { Addition(new_node) };
254                node_mutations.insert(node_index, new_entry);
255            }
256
257            // Once we're at depth 0, the last node we made is the new root.
258            new_root = new_child_hash;
259            // And then we're done with this pair; on to the next one.
260            new_pairs.insert(key, value);
261        }
262
263        Ok(MutationSet {
264            old_root: self.root(),
265            new_root,
266            node_mutations,
267            new_pairs,
268        })
269    }
270
271    // REQUIRED METHODS
272    // ---------------------------------------------------------------------------------------------
273
274    /// The root of the tree
275    fn root(&self) -> Word;
276
277    /// Retrieves an inner node at the given index
278    fn get_inner_node(&self, index: NodeIndex) -> InnerNode;
279
280    /// Returns the value at the specified key. Recall that by definition, any key that hasn't been
281    /// updated is associated with [`Self::EMPTY_VALUE`].
282    fn get_value(&self, key: &Self::Key) -> Self::Value;
283
284    /// Returns the leaf at the specified index.
285    fn get_leaf(&self, key: &Self::Key) -> Self::Leaf;
286
287    /// Returns the hash of a leaf
288    fn hash_leaf(leaf: &Self::Leaf) -> Word;
289
290    /// Returns what a leaf would look like if a key-value pair were inserted into the tree, without
291    /// mutating the tree itself. The existing leaf can be empty.
292    ///
293    /// To get a prospective leaf based on the current state of the tree, use `self.get_leaf(key)`
294    /// as the argument for `existing_leaf`. The return value from this function can be chained back
295    /// into this function as the first argument to continue making prospective changes.
296    ///
297    /// # Invariants
298    /// Because this method is for a prospective key-value insertion into a specific leaf,
299    /// `existing_leaf` must have the same leaf index as `key` (as determined by
300    /// [`SparseMerkleTreeReader::key_to_leaf_index()`]), or the result will be meaningless.
301    ///
302    /// # Errors
303    /// If inserting the key-value pair would exceed
304    /// [`crate::merkle::smt::MAX_LEAF_ENTRIES`] (1024 entries) in a leaf,
305    /// returns [`SmtLeafError::TooManyLeafEntries`].
306    fn construct_prospective_leaf(
307        &self,
308        existing_leaf: Self::Leaf,
309        key: &Self::Key,
310        value: &Self::Value,
311    ) -> Result<Self::Leaf, SmtLeafError>;
312
313    /// Checks a slice of key-value pairs (assumed sorted by key) for duplicate keys.
314    ///
315    /// The input `sorted_kv_pairs` must be sorted for this function to return correct results, as
316    /// it only performs checks of adjacent elements.
317    ///
318    /// # Errors
319    ///
320    /// - [`MerkleError::DuplicateValuesForIndex`] at the first duplicate key found in
321    ///   `sorted_kv_pairs`.
322    #[cfg(feature = "concurrent")] // Currently only used in concurrent contexts
323    fn check_for_duplicate_keys(
324        sorted_kv_pairs: &[(Self::Key, Self::Value)],
325    ) -> Result<(), MerkleError> {
326        if let Some(window) = sorted_kv_pairs.windows(2).find(|w| w[0].0 == w[1].0) {
327            return Err(MerkleError::DuplicateValuesForIndex(
328                Self::key_to_leaf_index(&window[0].0).position(),
329            ));
330        }
331        Ok(())
332    }
333
334    /// Maps a key to a leaf index
335    fn key_to_leaf_index(key: &Self::Key) -> LeafIndex<DEPTH>;
336
337    /// Maps a (SparseMerklePath, Self::Leaf) to an opening.
338    ///
339    /// The length `path` is guaranteed to be equal to `DEPTH`
340    fn path_and_leaf_to_opening(path: SparseMerklePath, leaf: Self::Leaf) -> Self::Opening;
341}
342
343/// An abstract description of a sparse Merkle tree with write capabilities.
344///
345/// A sparse Merkle tree is a key-value map which also supports proving that a given value is indeed
346/// stored at a given key in the tree. It is viewed as always being fully populated. If a leaf's
347/// value was not explicitly set, then its value is the default value. Typically, the vast majority
348/// of leaves will store the default value (hence it is "sparse"), and therefore the internal
349/// representation of the tree will only keep track of the leaves that have a different value from
350/// the default.
351///
352/// All leaves sit at the same depth. The deeper the tree, the more leaves it has; but also the
353/// longer its proofs are - of exactly `log(depth)` size. A tree cannot have depth 0, since such a
354/// tree is just a single value, and is probably a programming mistake.
355///
356/// Every key maps to one leaf. If there are as many keys as there are leaves, then
357/// [Self::Leaf] should be the same type as [Self::Value], as is the case with
358/// [`SimpleSmt`]. However, if there are more keys than leaves, then [`Self::Leaf`]
359/// must accommodate all keys that map to the same leaf.
360///
361/// [SparseMerkleTree] currently doesn't support optimizations that compress Merkle proofs.
362pub(crate) trait SparseMerkleTree<const DEPTH: u8>: SparseMerkleTreeReader<DEPTH> {
363    // PROVIDED METHODS
364    // ---------------------------------------------------------------------------------------------
365
366    /// Inserts a value at the specified key, returning the previous value associated with that key.
367    /// Recall that by definition, any key that hasn't been updated is associated with
368    /// [`Self::EMPTY_VALUE`].
369    ///
370    /// This also recomputes all hashes between the leaf (associated with the key) and the root,
371    /// updating the root itself.
372    fn insert(&mut self, key: Self::Key, value: Self::Value) -> Result<Self::Value, MerkleError> {
373        let old_value = self.insert_value(key.clone(), value.clone())?.unwrap_or(Self::EMPTY_VALUE);
374
375        // if the old value and new value are the same, there is nothing to update
376        if value == old_value {
377            return Ok(value);
378        }
379
380        let leaf = self.get_leaf(&key);
381        let node_index = {
382            let leaf_index: LeafIndex<DEPTH> = Self::key_to_leaf_index(&key);
383            leaf_index.into()
384        };
385
386        self.recompute_nodes_from_index_to_root(node_index, Self::hash_leaf(&leaf));
387
388        Ok(old_value)
389    }
390
391    /// Recomputes the branch nodes (including the root) from `index` all the way to the root.
392    /// `node_hash_at_index` is the hash of the node stored at index.
393    fn recompute_nodes_from_index_to_root(
394        &mut self,
395        mut index: NodeIndex,
396        node_hash_at_index: Word,
397    ) {
398        let mut node_hash = node_hash_at_index;
399        for node_depth in (0..index.depth()).rev() {
400            let is_right = index.is_position_odd();
401            index.move_up();
402            let InnerNode { left, right } = self.get_inner_node(index);
403            let (left, right) = if is_right {
404                (left, node_hash)
405            } else {
406                (node_hash, right)
407            };
408            node_hash = Poseidon2::merge(&[left, right]);
409
410            if node_hash == *EmptySubtreeRoots::entry(DEPTH, node_depth) {
411                // If a subtree is empty, then can remove the inner node, since it's equal to the
412                // default value
413                self.remove_inner_node(index);
414            } else {
415                self.insert_inner_node(index, InnerNode { left, right });
416            }
417        }
418        self.set_root(node_hash);
419    }
420
421    /// Applies the prospective mutations computed with [`SparseMerkleTree::compute_mutations()`] to
422    /// this tree.
423    ///
424    /// # Errors
425    /// If `mutations` was computed on a tree with a different root than this one, returns
426    /// [`MerkleError::ConflictingRoots`] with a two-item [`Vec`]. The first item is the root hash
427    /// the `mutations` were computed against, and the second item is the actual current root of
428    /// this tree.
429    /// If mutations would exceed [`crate::merkle::smt::MAX_LEAF_ENTRIES`] (1024 entries) in a leaf,
430    /// returns
431    /// [`MerkleError::TooManyLeafEntries`].
432    fn apply_mutations(
433        &mut self,
434        mutations: MutationSet<DEPTH, Self::Key, Self::Value>,
435    ) -> Result<(), MerkleError>
436    where
437        Self: Sized,
438    {
439        use NodeMutation::*;
440        let MutationSet {
441            old_root,
442            node_mutations,
443            new_pairs,
444            new_root,
445        } = mutations;
446
447        // Guard against accidentally trying to apply mutations that were computed against a
448        // different tree, including a stale version of this tree.
449        if old_root != self.root() {
450            return Err(MerkleError::ConflictingRoots {
451                expected_root: self.root(),
452                actual_root: old_root,
453            });
454        }
455
456        for (index, mutation) in node_mutations {
457            match mutation {
458                Removal => {
459                    self.remove_inner_node(index);
460                },
461                Addition(node) => {
462                    self.insert_inner_node(index, node);
463                },
464            }
465        }
466
467        for (key, value) in new_pairs {
468            self.insert_value(key, value)?;
469        }
470
471        self.set_root(new_root);
472
473        Ok(())
474    }
475
476    /// Applies the prospective mutations computed with [`SparseMerkleTree::compute_mutations()`] to
477    /// this tree and returns the reverse mutation set. Applying the reverse mutation sets to the
478    /// updated tree will revert the changes.
479    ///
480    /// # Errors
481    /// If `mutations` was computed on a tree with a different root than this one, returns
482    /// [`MerkleError::ConflictingRoots`] with a two-item [`Vec`]. The first item is the root hash
483    /// the `mutations` were computed against, and the second item is the actual current root of
484    /// this tree.
485    fn apply_mutations_with_reversion(
486        &mut self,
487        mutations: MutationSet<DEPTH, Self::Key, Self::Value>,
488    ) -> Result<MutationSet<DEPTH, Self::Key, Self::Value>, MerkleError>
489    where
490        Self: Sized,
491    {
492        use NodeMutation::*;
493        let MutationSet {
494            old_root,
495            node_mutations,
496            new_pairs,
497            new_root,
498        } = mutations;
499
500        // Guard against accidentally trying to apply mutations that were computed against a
501        // different tree, including a stale version of this tree.
502        if old_root != self.root() {
503            return Err(MerkleError::ConflictingRoots {
504                expected_root: self.root(),
505                actual_root: old_root,
506            });
507        }
508
509        let mut reverse_mutations = NodeMutations::new();
510        for (index, mutation) in node_mutations {
511            match mutation {
512                Removal => {
513                    if let Some(node) = self.remove_inner_node(index) {
514                        reverse_mutations.insert(index, Addition(node));
515                    }
516                },
517                Addition(node) => {
518                    if let Some(old_node) = self.insert_inner_node(index, node) {
519                        reverse_mutations.insert(index, Addition(old_node));
520                    } else {
521                        reverse_mutations.insert(index, Removal);
522                    }
523                },
524            }
525        }
526
527        let mut reverse_pairs = Map::new();
528        for (key, value) in new_pairs {
529            match self.insert_value(key.clone(), value)? {
530                Some(old_value) => {
531                    reverse_pairs.insert(key, old_value);
532                },
533                None => {
534                    reverse_pairs.insert(key, Self::EMPTY_VALUE);
535                },
536            }
537        }
538
539        self.set_root(new_root);
540
541        Ok(MutationSet {
542            old_root: new_root,
543            node_mutations: reverse_mutations,
544            new_pairs: reverse_pairs,
545            new_root: old_root,
546        })
547    }
548
549    // REQUIRED METHODS
550    // ---------------------------------------------------------------------------------------------
551
552    /// Sets the root of the tree
553    fn set_root(&mut self, root: Word);
554
555    /// Inserts an inner node at the given index
556    fn insert_inner_node(&mut self, index: NodeIndex, inner_node: InnerNode) -> Option<InnerNode>;
557
558    /// Removes an inner node at the given index
559    fn remove_inner_node(&mut self, index: NodeIndex) -> Option<InnerNode>;
560
561    /// Inserts a leaf node, and returns the value at the key if already exists
562    fn insert_value(
563        &mut self,
564        key: Self::Key,
565        value: Self::Value,
566    ) -> Result<Option<Self::Value>, MerkleError>;
567}
568
569// INNER NODE
570// ================================================================================================
571
572/// This struct is public so functions returning it can be used in `benches/`, but is otherwise not
573/// part of the public API.
574#[doc(hidden)]
575#[derive(Debug, Default, Clone, PartialEq, Eq)]
576pub struct InnerNode {
577    pub left: Word,
578    pub right: Word,
579}
580
581impl InnerNode {
582    pub fn hash(&self) -> Word {
583        Poseidon2::merge(&[self.left, self.right])
584    }
585}
586
587// LEAF INDEX
588// ================================================================================================
589
590/// The index of a leaf, at a depth known at compile-time.
591#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
592pub struct LeafIndex<const DEPTH: u8> {
593    index: NodeIndex,
594}
595
596impl<const DEPTH: u8> LeafIndex<DEPTH> {
597    /// Creates a new `LeafIndex` with the specified value.
598    ///
599    /// # Errors
600    ///
601    /// Returns an error if the provided depth is less than the minimum supported depth.
602    pub fn new(value: u64) -> Result<Self, MerkleError> {
603        if DEPTH < SMT_MIN_DEPTH {
604            return Err(MerkleError::DepthTooSmall(DEPTH));
605        }
606
607        Ok(LeafIndex { index: NodeIndex::new(DEPTH, value)? })
608    }
609
610    /// Returns the position of this leaf index within its depth layer.
611    pub fn position(&self) -> u64 {
612        self.index.position()
613    }
614}
615
616impl LeafIndex<SMT_MAX_DEPTH> {
617    /// Creates a new `LeafIndex` at the maximum supported depth without validation.
618    pub const fn new_max_depth(value: u64) -> Self {
619        LeafIndex {
620            index: NodeIndex::new_unchecked(SMT_MAX_DEPTH, value),
621        }
622    }
623}
624
625impl<const DEPTH: u8> From<LeafIndex<DEPTH>> for NodeIndex {
626    fn from(value: LeafIndex<DEPTH>) -> Self {
627        value.index
628    }
629}
630
631impl<const DEPTH: u8> TryFrom<NodeIndex> for LeafIndex<DEPTH> {
632    type Error = MerkleError;
633
634    fn try_from(node_index: NodeIndex) -> Result<Self, Self::Error> {
635        if node_index.depth() != DEPTH {
636            return Err(MerkleError::InvalidNodeIndexDepth {
637                expected: DEPTH,
638                provided: node_index.depth(),
639            });
640        }
641
642        Self::new(node_index.position())
643    }
644}
645
646impl<const DEPTH: u8> Serializable for LeafIndex<DEPTH> {
647    fn write_into<W: ByteWriter>(&self, target: &mut W) {
648        self.index.write_into(target);
649    }
650}
651
652impl<const DEPTH: u8> Deserializable for LeafIndex<DEPTH> {
653    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
654        // A `NodeIndex` is valid on its own terms without knowing `DEPTH`, so route through
655        // `TryFrom` to enforce that its depth matches this type's `DEPTH`.
656        let index: NodeIndex = source.read()?;
657
658        Self::try_from(index).map_err(|err| DeserializationError::InvalidValue(err.to_string()))
659    }
660}
661
662impl<const DEPTH: u8> Display for LeafIndex<DEPTH> {
663    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
664        write!(f, "DEPTH={}, position={}", DEPTH, self.position())
665    }
666}
667
668// MUTATIONS
669// ================================================================================================
670
671/// A change to an inner node of a sparse Merkle tree that hasn't yet been applied.
672/// [`MutationSet`] stores this type in relation to a [`NodeIndex`] to keep track of what changes
673/// need to occur at which node indices.
674#[derive(Debug, Clone, PartialEq, Eq)]
675pub enum NodeMutation {
676    /// Node needs to be removed.
677    Removal,
678    /// Node needs to be inserted.
679    Addition(InnerNode),
680}
681
682/// Represents a group of prospective mutations to a `SparseMerkleTree`, created by
683/// `SparseMerkleTree::compute_mutations()`, and that can be applied with
684/// `SparseMerkleTree::apply_mutations()`.
685#[derive(Debug, Clone, Default, PartialEq, Eq)]
686pub struct MutationSet<const DEPTH: u8, K: Eq + Hash, V> {
687    /// The root of the Merkle tree this MutationSet is for, recorded at the time
688    /// [`SparseMerkleTree::compute_mutations()`] was called. Exists to guard against applying
689    /// mutations to the wrong tree or applying stale mutations to a tree that has since changed.
690    old_root: Word,
691    /// The set of nodes that need to be removed or added. The "effective" node at an index is the
692    /// Merkle tree's existing node at that index, with the [`NodeMutation`] in this map at that
693    /// index overlaid, if any. Each [`NodeMutation::Addition`] corresponds to a
694    /// [`SparseMerkleTree::insert_inner_node()`] call, and each [`NodeMutation::Removal`]
695    /// corresponds to a [`SparseMerkleTree::remove_inner_node()`] call.
696    node_mutations: NodeMutations,
697    /// The set of top-level key-value pairs we're prospectively adding to the tree, including
698    /// adding empty values. The "effective" value for a key is the value in this Map, falling
699    /// back to the existing value in the Merkle tree. Each entry corresponds to a
700    /// [`SparseMerkleTree::insert_value()`] call.
701    new_pairs: Map<K, V>,
702    /// The calculated root for the Merkle tree, given these mutations. Publicly retrievable with
703    /// [`MutationSet::root()`]. Corresponds to a [`SparseMerkleTree::set_root()`]. call.
704    new_root: Word,
705}
706
707impl<const DEPTH: u8, K: Eq + Hash, V> MutationSet<DEPTH, K, V> {
708    /// Returns the SMT root that was calculated during `SparseMerkleTree::compute_mutations()`. See
709    /// that method for more information.
710    pub fn root(&self) -> Word {
711        self.new_root
712    }
713
714    /// Returns the SMT root before the mutations were applied.
715    pub fn old_root(&self) -> Word {
716        self.old_root
717    }
718
719    /// Returns the set of inner nodes that need to be removed or added.
720    pub fn node_mutations(&self) -> &NodeMutations {
721        &self.node_mutations
722    }
723
724    /// Returns the set of top-level key-value pairs that need to be added, updated or deleted
725    /// (i.e. set to `EMPTY_WORD`).
726    pub fn new_pairs(&self) -> &Map<K, V> {
727        &self.new_pairs
728    }
729
730    /// Returns `true` if the mutation set represents no changes to the tree, and `false` otherwise.
731    pub fn is_empty(&self) -> bool {
732        self.node_mutations.is_empty()
733            && self.new_pairs.is_empty()
734            && self.old_root == self.new_root
735    }
736
737    /// Creates a new mutation set from pre-computed components.
738    ///
739    /// This constructor performs no validation. The caller must ensure the components are
740    /// internally consistent, meaning that applying `node_mutations` and `new_pairs` to a tree
741    /// whose root is `old_root` yields a tree whose root is `new_root`. Intended for storage
742    /// backends that compute mutations from persisted tree data instead of an in-memory tree.
743    pub fn from_parts(
744        old_root: Word,
745        node_mutations: impl IntoIterator<Item = (NodeIndex, NodeMutation)>,
746        new_pairs: impl IntoIterator<Item = (K, V)>,
747        new_root: Word,
748    ) -> Self
749    where
750        K: Ord,
751    {
752        Self {
753            old_root,
754            node_mutations: node_mutations.into_iter().collect(),
755            new_pairs: new_pairs.into_iter().collect(),
756            new_root,
757        }
758    }
759}
760
761// SERIALIZATION
762// ================================================================================================
763
764impl Serializable for InnerNode {
765    fn write_into<W: ByteWriter>(&self, target: &mut W) {
766        target.write(self.left);
767        target.write(self.right);
768    }
769}
770
771impl Deserializable for InnerNode {
772    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
773        let left = source.read()?;
774        let right = source.read()?;
775
776        Ok(Self { left, right })
777    }
778}
779
780impl Serializable for NodeMutation {
781    fn write_into<W: ByteWriter>(&self, target: &mut W) {
782        match self {
783            NodeMutation::Removal => target.write_bool(false),
784            NodeMutation::Addition(inner_node) => {
785                target.write_bool(true);
786                inner_node.write_into(target);
787            },
788        }
789    }
790}
791
792impl Deserializable for NodeMutation {
793    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
794        if source.read_bool()? {
795            let inner_node = source.read()?;
796            return Ok(NodeMutation::Addition(inner_node));
797        }
798
799        Ok(NodeMutation::Removal)
800    }
801}
802
803impl<const DEPTH: u8, K: Serializable + Eq + Hash, V: Serializable> Serializable
804    for MutationSet<DEPTH, K, V>
805{
806    fn write_into<W: ByteWriter>(&self, target: &mut W) {
807        target.write(self.old_root);
808        target.write(self.new_root);
809
810        let inner_removals: Vec<_> = self
811            .node_mutations
812            .iter()
813            .filter(|(_, value)| matches!(value, NodeMutation::Removal))
814            .map(|(key, _)| key)
815            .collect();
816        let inner_additions: Vec<_> = self
817            .node_mutations
818            .iter()
819            .filter_map(|(key, value)| match value {
820                NodeMutation::Addition(node) => Some((key, node)),
821                _ => None,
822            })
823            .collect();
824
825        target.write(inner_removals);
826        target.write(inner_additions);
827
828        target.write_usize(self.new_pairs.len());
829        target.write_many(&self.new_pairs);
830    }
831}
832
833impl<const DEPTH: u8, K: Deserializable + Ord + Eq + Hash, V: Deserializable> Deserializable
834    for MutationSet<DEPTH, K, V>
835{
836    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
837        let old_root = source.read()?;
838        let new_root = source.read()?;
839
840        let inner_removals: Vec<NodeIndex> = source.read()?;
841        let inner_additions: Vec<(NodeIndex, InnerNode)> = source.read()?;
842
843        let node_mutations = NodeMutations::from_iter(
844            inner_removals.into_iter().map(|index| (index, NodeMutation::Removal)).chain(
845                inner_additions
846                    .into_iter()
847                    .map(|(index, node)| (index, NodeMutation::Addition(node))),
848            ),
849        );
850
851        let num_new_pairs = source.read_usize()?;
852        let new_pairs: Map<_, _> =
853            source.read_many_iter(num_new_pairs)?.collect::<Result<_, _>>()?;
854
855        Ok(Self {
856            old_root,
857            node_mutations,
858            new_pairs,
859            new_root,
860        })
861    }
862}
863
864// TESTS
865// ================================================================================================
866
867#[cfg(test)]
868mod tests {
869    use super::{LeafIndex, NodeIndex, SMT_MAX_DEPTH};
870    use crate::utils::{Deserializable, Serializable};
871
872    #[test]
873    fn leaf_index_read_from_rejects_depth_mismatch() {
874        // A depth-3 index is valid on its own terms, but wrong for a `LeafIndex<SMT_MAX_DEPTH>`.
875        let mismatched = NodeIndex::new(3, 5).unwrap();
876        assert!(LeafIndex::<SMT_MAX_DEPTH>::try_from(mismatched).is_err());
877
878        assert!(LeafIndex::<SMT_MAX_DEPTH>::read_from_bytes(&mismatched.to_bytes()).is_err());
879    }
880
881    #[test]
882    fn leaf_index_read_from_rejects_depth_below_minimum() {
883        assert!(LeafIndex::<0>::new(0).is_err());
884
885        let root = NodeIndex::new(0, 0).unwrap();
886        assert!(LeafIndex::<0>::read_from_bytes(&root.to_bytes()).is_err());
887    }
888
889    #[test]
890    fn leaf_index_round_trips_at_matching_depth() {
891        let leaf = LeafIndex::<SMT_MAX_DEPTH>::new(5).unwrap();
892
893        let decoded = LeafIndex::<SMT_MAX_DEPTH>::read_from_bytes(&leaf.to_bytes()).unwrap();
894
895        assert_eq!(leaf, decoded);
896    }
897}