Skip to main content

miden_crypto/merkle/smt/simple/
mod.rs

1use alloc::collections::BTreeSet;
2
3use super::{
4    EMPTY_WORD, EmptySubtreeRoots, InnerNode, InnerNodeInfo, InnerNodes, LeafIndex, MerkleError,
5    MutationSet, NodeIndex, SMT_MAX_DEPTH, SMT_MIN_DEPTH, SparseMerkleTree, SparseMerkleTreeReader,
6    Word,
7};
8use crate::merkle::{SparseMerklePath, smt::SmtLeafError};
9
10mod proof;
11pub use proof::SimpleSmtProof;
12
13#[cfg(test)]
14mod tests;
15
16// SPARSE MERKLE TREE
17// ================================================================================================
18
19type Leaves = super::Leaves<Word>;
20
21/// A sparse Merkle tree with 64-bit keys and 4-element leaf values, without compaction.
22///
23/// The root of the tree is recomputed on each new leaf update.
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct SimpleSmt<const DEPTH: u8> {
26    root: Word,
27    inner_nodes: InnerNodes,
28    leaves: Leaves,
29}
30
31impl<const DEPTH: u8> SimpleSmt<DEPTH> {
32    // CONSTANTS
33    // --------------------------------------------------------------------------------------------
34
35    /// The default value used to compute the hash of empty leaves
36    pub const EMPTY_VALUE: Word = <Self as SparseMerkleTreeReader<DEPTH>>::EMPTY_VALUE;
37
38    // CONSTRUCTORS
39    // --------------------------------------------------------------------------------------------
40
41    /// Returns a new [SimpleSmt].
42    ///
43    /// All leaves in the returned tree are set to [ZERO; 4].
44    ///
45    /// # Errors
46    /// Returns an error if DEPTH is 0 or is greater than 64.
47    pub fn new() -> Result<Self, MerkleError> {
48        // validate the range of the depth.
49        if DEPTH < SMT_MIN_DEPTH {
50            return Err(MerkleError::DepthTooSmall(DEPTH));
51        } else if SMT_MAX_DEPTH < DEPTH {
52            return Err(MerkleError::DepthTooBig(DEPTH as u64));
53        }
54
55        let root = *EmptySubtreeRoots::entry(DEPTH, 0);
56
57        Ok(Self {
58            root,
59            inner_nodes: Default::default(),
60            leaves: Default::default(),
61        })
62    }
63
64    /// Returns a new [SimpleSmt] instantiated with leaves set as specified by the provided entries.
65    ///
66    /// All leaves omitted from the entries list are set to [ZERO; 4].
67    ///
68    /// # Errors
69    /// Returns an error if:
70    /// - If the depth is 0 or is greater than 64.
71    /// - The number of entries exceeds the maximum tree capacity, that is 2^{depth}.
72    /// - The provided entries contain multiple values for the same key.
73    pub fn with_leaves(
74        entries: impl IntoIterator<Item = (u64, Word)>,
75    ) -> Result<Self, MerkleError> {
76        // create an empty tree
77        let mut tree = Self::new()?;
78
79        // compute the max number of entries. We use an upper bound of depth 63 because we consider
80        // passing in a vector of size 2^64 infeasible.
81        let max_num_entries = 2_u64.pow(DEPTH.min(63).into());
82
83        // This being a sparse data structure, the EMPTY_WORD is not assigned to the `BTreeMap`, so
84        // entries with the empty value need additional tracking.
85        let mut key_set_to_zero = BTreeSet::new();
86
87        for (idx, (key, value)) in entries.into_iter().enumerate() {
88            if idx as u64 >= max_num_entries {
89                return Err(MerkleError::TooManyEntries(DEPTH));
90            }
91
92            let old_value = tree.insert(LeafIndex::<DEPTH>::new(key)?, value);
93
94            if old_value != Self::EMPTY_VALUE || key_set_to_zero.contains(&key) {
95                return Err(MerkleError::DuplicateValuesForIndex(key));
96            }
97
98            if value == Self::EMPTY_VALUE {
99                key_set_to_zero.insert(key);
100            };
101        }
102        Ok(tree)
103    }
104
105    /// Returns a new [`SimpleSmt`] instantiated from already computed leaves and nodes.
106    ///
107    /// This function performs minimal consistency checking. It is the caller's responsibility to
108    /// ensure the passed arguments are correct and consistent with each other.
109    ///
110    /// # Panics
111    /// With debug assertions on, this function panics if `root` does not match the root node in
112    /// `inner_nodes`.
113    pub fn from_raw_parts(inner_nodes: InnerNodes, leaves: Leaves, root: Word) -> Self {
114        if cfg!(debug_assertions) {
115            let root_node_hash = inner_nodes
116                .get(&NodeIndex::root())
117                .map(InnerNode::hash)
118                .unwrap_or(Self::EMPTY_ROOT);
119
120            assert_eq!(root_node_hash, root);
121        }
122
123        Self { root, inner_nodes, leaves }
124    }
125
126    /// Wrapper around [`SimpleSmt::with_leaves`] which inserts leaves at contiguous indices
127    /// starting at index 0.
128    pub fn with_contiguous_leaves(
129        entries: impl IntoIterator<Item = Word>,
130    ) -> Result<Self, MerkleError> {
131        Self::with_leaves(
132            entries
133                .into_iter()
134                .enumerate()
135                .map(|(idx, word)| (idx.try_into().expect("tree max depth is 2^8"), word)),
136        )
137    }
138
139    // PUBLIC ACCESSORS
140    // --------------------------------------------------------------------------------------------
141
142    /// Returns the depth of the tree
143    pub const fn depth(&self) -> u8 {
144        DEPTH
145    }
146
147    /// Returns the root of the tree
148    pub fn root(&self) -> Word {
149        <Self as SparseMerkleTreeReader<DEPTH>>::root(self)
150    }
151
152    /// Returns the number of non-empty leaves in this tree.
153    pub fn num_leaves(&self) -> usize {
154        self.leaves.len()
155    }
156
157    /// Returns the leaf at the specified index.
158    pub fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word {
159        <Self as SparseMerkleTreeReader<DEPTH>>::get_leaf(self, key)
160    }
161
162    /// Returns a node at the specified index.
163    ///
164    /// # Errors
165    /// Returns an error if the specified index has depth set to 0 or the depth is greater than
166    /// the depth of this Merkle tree.
167    pub fn get_node(&self, index: NodeIndex) -> Result<Word, MerkleError> {
168        if index.is_root() {
169            Err(MerkleError::DepthTooSmall(index.depth()))
170        } else if index.depth() > DEPTH {
171            Err(MerkleError::DepthTooBig(index.depth() as u64))
172        } else if index.depth() == DEPTH {
173            let leaf = self.get_leaf(&LeafIndex::<DEPTH>::try_from(index)?);
174
175            Ok(leaf)
176        } else {
177            Ok(self.get_inner_node(index).hash())
178        }
179    }
180
181    /// Returns an opening of the leaf associated with `key`. Conceptually, an opening is a Merkle
182    /// path to the leaf, as well as the leaf itself.
183    pub fn open(&self, key: &LeafIndex<DEPTH>) -> SimpleSmtProof {
184        let value = self.get_value(key);
185        let nodes = key.index.proof_indices().map(|index| self.get_node_hash(index));
186        // `from_sized_iter()` returns an error if there are more nodes than `SMT_MAX_DEPTH`, but
187        // this could only happen if we have more levels than `SMT_MAX_DEPTH` ourselves, which is
188        // guarded against in `SimpleSmt::new()`.
189        let path = SparseMerklePath::from_sized_iter(nodes).unwrap();
190
191        SimpleSmtProof { value, path }
192    }
193
194    /// Returns a boolean value indicating whether the SMT is empty.
195    pub fn is_empty(&self) -> bool {
196        debug_assert_eq!(self.leaves.is_empty(), self.root == Self::EMPTY_ROOT);
197        self.root == Self::EMPTY_ROOT
198    }
199
200    // ITERATORS
201    // --------------------------------------------------------------------------------------------
202
203    /// Returns an iterator over the leaves of this [SimpleSmt].
204    pub fn leaves(&self) -> impl Iterator<Item = (u64, &Word)> {
205        self.leaves.iter().map(|(i, w)| (*i, w))
206    }
207
208    /// Returns an iterator over the inner nodes of this [SimpleSmt].
209    pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
210        self.inner_nodes.values().map(|e| InnerNodeInfo {
211            value: e.hash(),
212            left: e.left,
213            right: e.right,
214        })
215    }
216
217    // STATE MUTATORS
218    // --------------------------------------------------------------------------------------------
219
220    /// Inserts a value at the specified key, returning the previous value associated with that key.
221    /// Recall that by definition, any key that hasn't been updated is associated with
222    /// [`EMPTY_WORD`].
223    ///
224    /// This also recomputes all hashes between the leaf (associated with the key) and the root,
225    /// updating the root itself.
226    pub fn insert(&mut self, key: LeafIndex<DEPTH>, value: Word) -> Word {
227        // SAFETY: a SimpleSmt does not contain multi-value leaves. The underlying
228        // SimpleSmt::insert_value does not return any errors so it's safe to unwrap here.
229        <Self as SparseMerkleTree<DEPTH>>::insert(self, key, value)
230            .expect("inserting a value into a simple smt never returns an error")
231    }
232
233    /// Computes what changes are necessary to insert the specified key-value pairs into this
234    /// Merkle tree, allowing for validation before applying those changes.
235    ///
236    /// This method returns a [`MutationSet`], which contains all the information for inserting
237    /// `kv_pairs` into this Merkle tree already calculated, including the new root hash, which can
238    /// be queried with [`MutationSet::root()`]. Once a mutation set is returned,
239    /// [`SimpleSmt::apply_mutations()`] can be called in order to commit these changes to the
240    /// Merkle tree, or [`drop()`] to discard them.
241    ///
242    /// # Errors
243    ///
244    /// - [`MerkleError::DuplicateValuesForIndex`] if the provided `kv_pairs` contain duplicate
245    ///   keys.
246    ///
247    /// # Example
248    /// ```
249    /// # use miden_crypto::{Felt, Word};
250    /// # use miden_crypto::merkle::{smt::{LeafIndex, SimpleSmt, SMT_DEPTH}, EmptySubtreeRoots};
251    /// let mut smt: SimpleSmt<3> = SimpleSmt::new().unwrap();
252    /// let pair = (LeafIndex::default(), Word::default());
253    /// let mutations = smt.compute_mutations(vec![pair]).unwrap();
254    /// assert_eq!(mutations.root(), *EmptySubtreeRoots::entry(3, 0));
255    /// smt.apply_mutations(mutations).unwrap();
256    /// assert_eq!(smt.root(), *EmptySubtreeRoots::entry(3, 0));
257    /// ```
258    pub fn compute_mutations(
259        &self,
260        kv_pairs: impl IntoIterator<Item = (LeafIndex<DEPTH>, Word)>,
261    ) -> Result<MutationSet<DEPTH, LeafIndex<DEPTH>, Word>, MerkleError> {
262        <Self as SparseMerkleTreeReader<DEPTH>>::compute_mutations(self, kv_pairs)
263    }
264
265    /// Applies the prospective mutations computed with [`SimpleSmt::compute_mutations()`] to this
266    /// tree.
267    ///
268    /// # Errors
269    /// If `mutations` was computed on a tree with a different root than this one, returns
270    /// [`MerkleError::ConflictingRoots`] with a two-item [`alloc::vec::Vec`]. The first item is the
271    /// root hash the `mutations` were computed against, and the second item is the actual
272    /// current root of this tree.
273    pub fn apply_mutations(
274        &mut self,
275        mutations: MutationSet<DEPTH, LeafIndex<DEPTH>, Word>,
276    ) -> Result<(), MerkleError> {
277        <Self as SparseMerkleTree<DEPTH>>::apply_mutations(self, mutations)
278    }
279
280    /// Applies the prospective mutations computed with [`SimpleSmt::compute_mutations()`] to
281    /// this tree and returns the reverse mutation set.
282    ///
283    /// Applying the reverse mutation sets to the updated tree will revert the changes.
284    ///
285    /// # Errors
286    /// If `mutations` was computed on a tree with a different root than this one, returns
287    /// [`MerkleError::ConflictingRoots`] with a two-item [`alloc::vec::Vec`]. The first item is the
288    /// root hash the `mutations` were computed against, and the second item is the actual
289    /// current root of this tree.
290    pub fn apply_mutations_with_reversion(
291        &mut self,
292        mutations: MutationSet<DEPTH, LeafIndex<DEPTH>, Word>,
293    ) -> Result<MutationSet<DEPTH, LeafIndex<DEPTH>, Word>, MerkleError> {
294        <Self as SparseMerkleTree<DEPTH>>::apply_mutations_with_reversion(self, mutations)
295    }
296
297    /// Inserts a subtree at the specified index. The depth at which the subtree is inserted is
298    /// computed as `DEPTH - SUBTREE_DEPTH`.
299    ///
300    /// Returns the new root.
301    pub fn set_subtree<const SUBTREE_DEPTH: u8>(
302        &mut self,
303        subtree_insertion_index: u64,
304        subtree: SimpleSmt<SUBTREE_DEPTH>,
305    ) -> Result<Word, MerkleError> {
306        if SUBTREE_DEPTH > DEPTH {
307            return Err(MerkleError::SubtreeDepthExceedsDepth {
308                subtree_depth: SUBTREE_DEPTH,
309                tree_depth: DEPTH,
310            });
311        }
312
313        // Verify that `subtree_insertion_index` is valid.
314        let subtree_root_insertion_depth = DEPTH - SUBTREE_DEPTH;
315        let subtree_root_index =
316            NodeIndex::new(subtree_root_insertion_depth, subtree_insertion_index)?;
317
318        // remove leaves and inner nodes under the insertion root
319        // --------------
320
321        // The subtree's leaf indices live in their own context - i.e. a subtree of depth `d`. If we
322        // insert the subtree at `subtree_insertion_index = 0`, then the subtree leaf indices are
323        // valid as they are. However, consider what happens when we insert at
324        // `subtree_insertion_index = 1`. The first leaf of our subtree now will have index `2^d`;
325        // you can see it as there's a full subtree sitting on its left. In general, for
326        // `subtree_insertion_index = i`, there are `i` subtrees sitting before the subtree we want
327        // to insert, so we need to adjust all its leaves by `i * 2^d`.
328        let leaf_index_shift: u64 = if SUBTREE_DEPTH == SMT_MAX_DEPTH {
329            0
330        } else {
331            subtree_insertion_index << u32::from(SUBTREE_DEPTH)
332        };
333
334        self.leaves.retain(|leaf_idx, _| {
335            !Self::leaf_is_in_subtree::<SUBTREE_DEPTH>(*leaf_idx, subtree_insertion_index)
336        });
337        self.inner_nodes.retain(|node_idx, _| {
338            !Self::node_is_in_subtree(
339                *node_idx,
340                subtree_root_insertion_depth,
341                subtree_insertion_index,
342            )
343        });
344
345        // add leaves
346        // --------------
347        for (subtree_leaf_idx, leaf_value) in subtree.leaves() {
348            let new_leaf_idx = leaf_index_shift + subtree_leaf_idx;
349            debug_assert!(DEPTH == SMT_MAX_DEPTH || new_leaf_idx < 2_u64.pow(DEPTH.into()));
350
351            self.leaves.insert(new_leaf_idx, *leaf_value);
352        }
353
354        // add subtree's branch nodes (which includes the root)
355        // --------------
356        for (branch_idx, branch_node) in subtree.inner_nodes {
357            let new_branch_idx = {
358                let new_depth = subtree_root_insertion_depth + branch_idx.depth();
359                let new_value = subtree_insertion_index * 2_u64.pow(branch_idx.depth().into())
360                    + branch_idx.position();
361
362                NodeIndex::new(new_depth, new_value).expect("index guaranteed to be valid")
363            };
364
365            self.inner_nodes.insert(new_branch_idx, branch_node);
366        }
367
368        // recompute nodes starting from subtree root
369        // --------------
370        self.recompute_nodes_from_index_to_root(subtree_root_index, subtree.root);
371
372        Ok(self.root)
373    }
374
375    fn leaf_is_in_subtree<const SUBTREE_DEPTH: u8>(
376        leaf_idx: u64,
377        subtree_insertion_index: u64,
378    ) -> bool {
379        if SUBTREE_DEPTH == SMT_MAX_DEPTH {
380            true
381        } else {
382            (leaf_idx >> u32::from(SUBTREE_DEPTH)) == subtree_insertion_index
383        }
384    }
385
386    fn node_is_in_subtree(
387        node_idx: NodeIndex,
388        subtree_root_depth: u8,
389        subtree_insertion_index: u64,
390    ) -> bool {
391        if node_idx.depth() < subtree_root_depth {
392            return false;
393        }
394
395        let depth_offset = node_idx.depth() - subtree_root_depth;
396        if depth_offset == SMT_MAX_DEPTH {
397            subtree_insertion_index == 0
398        } else {
399            (node_idx.position() >> u32::from(depth_offset)) == subtree_insertion_index
400        }
401    }
402}
403
404impl<const DEPTH: u8> SparseMerkleTreeReader<DEPTH> for SimpleSmt<DEPTH> {
405    type Key = LeafIndex<DEPTH>;
406    type Value = Word;
407    type Leaf = Word;
408    type Opening = SimpleSmtProof;
409
410    const EMPTY_VALUE: Self::Value = EMPTY_WORD;
411    const EMPTY_ROOT: Word = *EmptySubtreeRoots::entry(DEPTH, 0);
412
413    fn root(&self) -> Word {
414        self.root
415    }
416
417    fn get_inner_node(&self, index: NodeIndex) -> InnerNode {
418        self.inner_nodes
419            .get(&index)
420            .cloned()
421            .unwrap_or_else(|| EmptySubtreeRoots::get_inner_node(DEPTH, index.depth()))
422    }
423
424    fn get_value(&self, key: &LeafIndex<DEPTH>) -> Word {
425        self.get_leaf(key)
426    }
427
428    fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word {
429        let leaf_pos = key.position();
430        match self.leaves.get(&leaf_pos) {
431            Some(word) => *word,
432            None => Self::EMPTY_VALUE,
433        }
434    }
435
436    fn hash_leaf(leaf: &Word) -> Word {
437        // `SimpleSmt` takes the leaf value itself as the hash
438        *leaf
439    }
440
441    fn construct_prospective_leaf(
442        &self,
443        _existing_leaf: Word,
444        _key: &LeafIndex<DEPTH>,
445        value: &Word,
446    ) -> Result<Word, SmtLeafError> {
447        Ok(*value)
448    }
449
450    fn key_to_leaf_index(key: &LeafIndex<DEPTH>) -> LeafIndex<DEPTH> {
451        *key
452    }
453
454    fn path_and_leaf_to_opening(path: SparseMerklePath, leaf: Word) -> SimpleSmtProof {
455        (path, leaf).into()
456    }
457}
458
459impl<const DEPTH: u8> SparseMerkleTree<DEPTH> for SimpleSmt<DEPTH> {
460    fn set_root(&mut self, root: Word) {
461        self.root = root;
462    }
463
464    fn insert_inner_node(&mut self, index: NodeIndex, inner_node: InnerNode) -> Option<InnerNode> {
465        self.inner_nodes.insert(index, inner_node)
466    }
467
468    fn remove_inner_node(&mut self, index: NodeIndex) -> Option<InnerNode> {
469        self.inner_nodes.remove(&index)
470    }
471
472    fn insert_value(
473        &mut self,
474        key: LeafIndex<DEPTH>,
475        value: Word,
476    ) -> Result<Option<Word>, MerkleError> {
477        let result = if value == Self::EMPTY_VALUE {
478            self.leaves.remove(&key.position())
479        } else {
480            self.leaves.insert(key.position(), value)
481        };
482        Ok(result)
483    }
484}