arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
miden-crypto/src/merkle/smt/simple/mod.rs
src/merkle/smt/simple/mod.rsRaw
  1use alloc::collections::{BTreeMap, BTreeSet};
  2
  3use super::{
  4    super::ValuePath, EmptySubtreeRoots, InnerNode, InnerNodeInfo, LeafIndex, MerkleError,
  5    MerklePath, NodeIndex, RpoDigest, SparseMerkleTree, Word, EMPTY_WORD, SMT_MAX_DEPTH,
  6    SMT_MIN_DEPTH,
  7};
  8
  9#[cfg(test)]
 10mod tests;
 11
 12// SPARSE MERKLE TREE
 13// ================================================================================================
 14
 15/// A sparse Merkle tree with 64-bit keys and 4-element leaf values, without compaction.
 16///
 17/// The root of the tree is recomputed on each new leaf update.
 18#[derive(Debug, Clone, PartialEq, Eq)]
 19#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
 20pub struct SimpleSmt<const DEPTH: u8> {
 21    root: RpoDigest,
 22    leaves: BTreeMap<u64, Word>,
 23    inner_nodes: BTreeMap<NodeIndex, InnerNode>,
 24}
 25
 26impl<const DEPTH: u8> SimpleSmt<DEPTH> {
 27    // CONSTANTS
 28    // --------------------------------------------------------------------------------------------
 29
 30    /// The default value used to compute the hash of empty leaves
 31    pub const EMPTY_VALUE: Word = <Self as SparseMerkleTree<DEPTH>>::EMPTY_VALUE;
 32
 33    // CONSTRUCTORS
 34    // --------------------------------------------------------------------------------------------
 35
 36    /// Returns a new [SimpleSmt].
 37    ///
 38    /// All leaves in the returned tree are set to [ZERO; 4].
 39    ///
 40    /// # Errors
 41    /// Returns an error if DEPTH is 0 or is greater than 64.
 42    pub fn new() -> Result<Self, MerkleError> {
 43        // validate the range of the depth.
 44        if DEPTH < SMT_MIN_DEPTH {
 45            return Err(MerkleError::DepthTooSmall(DEPTH));
 46        } else if SMT_MAX_DEPTH < DEPTH {
 47            return Err(MerkleError::DepthTooBig(DEPTH as u64));
 48        }
 49
 50        let root = *EmptySubtreeRoots::entry(DEPTH, 0);
 51
 52        Ok(Self {
 53            root,
 54            leaves: BTreeMap::new(),
 55            inner_nodes: BTreeMap::new(),
 56        })
 57    }
 58
 59    /// Returns a new [SimpleSmt] instantiated with leaves set as specified by the provided entries.
 60    ///
 61    /// All leaves omitted from the entries list are set to [ZERO; 4].
 62    ///
 63    /// # Errors
 64    /// Returns an error if:
 65    /// - If the depth is 0 or is greater than 64.
 66    /// - The number of entries exceeds the maximum tree capacity, that is 2^{depth}.
 67    /// - The provided entries contain multiple values for the same key.
 68    pub fn with_leaves(
 69        entries: impl IntoIterator<Item = (u64, Word)>,
 70    ) -> Result<Self, MerkleError> {
 71        // create an empty tree
 72        let mut tree = Self::new()?;
 73
 74        // compute the max number of entries. We use an upper bound of depth 63 because we consider
 75        // passing in a vector of size 2^64 infeasible.
 76        let max_num_entries = 2_usize.pow(DEPTH.min(63).into());
 77
 78        // This being a sparse data structure, the EMPTY_WORD is not assigned to the `BTreeMap`, so
 79        // entries with the empty value need additional tracking.
 80        let mut key_set_to_zero = BTreeSet::new();
 81
 82        for (idx, (key, value)) in entries.into_iter().enumerate() {
 83            if idx >= max_num_entries {
 84                return Err(MerkleError::InvalidNumEntries(max_num_entries));
 85            }
 86
 87            let old_value = tree.insert(LeafIndex::<DEPTH>::new(key)?, value);
 88
 89            if old_value != Self::EMPTY_VALUE || key_set_to_zero.contains(&key) {
 90                return Err(MerkleError::DuplicateValuesForIndex(key));
 91            }
 92
 93            if value == Self::EMPTY_VALUE {
 94                key_set_to_zero.insert(key);
 95            };
 96        }
 97        Ok(tree)
 98    }
 99
100    /// Wrapper around [`SimpleSmt::with_leaves`] which inserts leaves at contiguous indices
101    /// starting at index 0.
102    pub fn with_contiguous_leaves(
103        entries: impl IntoIterator<Item = Word>,
104    ) -> Result<Self, MerkleError> {
105        Self::with_leaves(
106            entries
107                .into_iter()
108                .enumerate()
109                .map(|(idx, word)| (idx.try_into().expect("tree max depth is 2^8"), word)),
110        )
111    }
112
113    // PUBLIC ACCESSORS
114    // --------------------------------------------------------------------------------------------
115
116    /// Returns the depth of the tree
117    pub const fn depth(&self) -> u8 {
118        DEPTH
119    }
120
121    /// Returns the root of the tree
122    pub fn root(&self) -> RpoDigest {
123        <Self as SparseMerkleTree<DEPTH>>::root(self)
124    }
125
126    /// Returns the number of non-empty leaves in this tree.
127    pub fn num_leaves(&self) -> usize {
128        self.leaves.len()
129    }
130
131    /// Returns the leaf at the specified index.
132    pub fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word {
133        <Self as SparseMerkleTree<DEPTH>>::get_leaf(self, key)
134    }
135
136    /// Returns a node at the specified index.
137    ///
138    /// # Errors
139    /// Returns an error if the specified index has depth set to 0 or the depth is greater than
140    /// the depth of this Merkle tree.
141    pub fn get_node(&self, index: NodeIndex) -> Result<RpoDigest, MerkleError> {
142        if index.is_root() {
143            Err(MerkleError::DepthTooSmall(index.depth()))
144        } else if index.depth() > DEPTH {
145            Err(MerkleError::DepthTooBig(index.depth() as u64))
146        } else if index.depth() == DEPTH {
147            let leaf = self.get_leaf(&LeafIndex::<DEPTH>::try_from(index)?);
148
149            Ok(leaf.into())
150        } else {
151            Ok(self.get_inner_node(index).hash())
152        }
153    }
154
155    /// Returns an opening of the leaf associated with `key`. Conceptually, an opening is a Merkle
156    /// path to the leaf, as well as the leaf itself.
157    pub fn open(&self, key: &LeafIndex<DEPTH>) -> ValuePath {
158        <Self as SparseMerkleTree<DEPTH>>::open(self, key)
159    }
160
161    // ITERATORS
162    // --------------------------------------------------------------------------------------------
163
164    /// Returns an iterator over the leaves of this [SimpleSmt].
165    pub fn leaves(&self) -> impl Iterator<Item = (u64, &Word)> {
166        self.leaves.iter().map(|(i, w)| (*i, w))
167    }
168
169    /// Returns an iterator over the inner nodes of this [SimpleSmt].
170    pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
171        self.inner_nodes.values().map(|e| InnerNodeInfo {
172            value: e.hash(),
173            left: e.left,
174            right: e.right,
175        })
176    }
177
178    // STATE MUTATORS
179    // --------------------------------------------------------------------------------------------
180
181    /// Inserts a value at the specified key, returning the previous value associated with that key.
182    /// Recall that by definition, any key that hasn't been updated is associated with
183    /// [`EMPTY_WORD`].
184    ///
185    /// This also recomputes all hashes between the leaf (associated with the key) and the root,
186    /// updating the root itself.
187    pub fn insert(&mut self, key: LeafIndex<DEPTH>, value: Word) -> Word {
188        <Self as SparseMerkleTree<DEPTH>>::insert(self, key, value)
189    }
190
191    /// Inserts a subtree at the specified index. The depth at which the subtree is inserted is
192    /// computed as `DEPTH - SUBTREE_DEPTH`.
193    ///
194    /// Returns the new root.
195    pub fn set_subtree<const SUBTREE_DEPTH: u8>(
196        &mut self,
197        subtree_insertion_index: u64,
198        subtree: SimpleSmt<SUBTREE_DEPTH>,
199    ) -> Result<RpoDigest, MerkleError> {
200        if SUBTREE_DEPTH > DEPTH {
201            return Err(MerkleError::InvalidSubtreeDepth {
202                subtree_depth: SUBTREE_DEPTH,
203                tree_depth: DEPTH,
204            });
205        }
206
207        // Verify that `subtree_insertion_index` is valid.
208        let subtree_root_insertion_depth = DEPTH - SUBTREE_DEPTH;
209        let subtree_root_index =
210            NodeIndex::new(subtree_root_insertion_depth, subtree_insertion_index)?;
211
212        // add leaves
213        // --------------
214
215        // The subtree's leaf indices live in their own context - i.e. a subtree of depth `d`. If we
216        // insert the subtree at `subtree_insertion_index = 0`, then the subtree leaf indices are
217        // valid as they are. However, consider what happens when we insert at
218        // `subtree_insertion_index = 1`. The first leaf of our subtree now will have index `2^d`;
219        // you can see it as there's a full subtree sitting on its left. In general, for
220        // `subtree_insertion_index = i`, there are `i` subtrees sitting before the subtree we want
221        // to insert, so we need to adjust all its leaves by `i * 2^d`.
222        let leaf_index_shift: u64 = subtree_insertion_index * 2_u64.pow(SUBTREE_DEPTH.into());
223        for (subtree_leaf_idx, leaf_value) in subtree.leaves() {
224            let new_leaf_idx = leaf_index_shift + subtree_leaf_idx;
225            debug_assert!(new_leaf_idx < 2_u64.pow(DEPTH.into()));
226
227            self.leaves.insert(new_leaf_idx, *leaf_value);
228        }
229
230        // add subtree's branch nodes (which includes the root)
231        // --------------
232        for (branch_idx, branch_node) in subtree.inner_nodes {
233            let new_branch_idx = {
234                let new_depth = subtree_root_insertion_depth + branch_idx.depth();
235                let new_value = subtree_insertion_index * 2_u64.pow(branch_idx.depth().into())
236                    + branch_idx.value();
237
238                NodeIndex::new(new_depth, new_value).expect("index guaranteed to be valid")
239            };
240
241            self.inner_nodes.insert(new_branch_idx, branch_node);
242        }
243
244        // recompute nodes starting from subtree root
245        // --------------
246        self.recompute_nodes_from_index_to_root(subtree_root_index, subtree.root);
247
248        Ok(self.root)
249    }
250}
251
252impl<const DEPTH: u8> SparseMerkleTree<DEPTH> for SimpleSmt<DEPTH> {
253    type Key = LeafIndex<DEPTH>;
254    type Value = Word;
255    type Leaf = Word;
256    type Opening = ValuePath;
257
258    const EMPTY_VALUE: Self::Value = EMPTY_WORD;
259
260    fn root(&self) -> RpoDigest {
261        self.root
262    }
263
264    fn set_root(&mut self, root: RpoDigest) {
265        self.root = root;
266    }
267
268    fn get_inner_node(&self, index: NodeIndex) -> InnerNode {
269        self.inner_nodes.get(&index).cloned().unwrap_or_else(|| {
270            let node = EmptySubtreeRoots::entry(DEPTH, index.depth() + 1);
271
272            InnerNode { left: *node, right: *node }
273        })
274    }
275
276    fn insert_inner_node(&mut self, index: NodeIndex, inner_node: InnerNode) {
277        self.inner_nodes.insert(index, inner_node);
278    }
279
280    fn remove_inner_node(&mut self, index: NodeIndex) {
281        let _ = self.inner_nodes.remove(&index);
282    }
283
284    fn insert_value(&mut self, key: LeafIndex<DEPTH>, value: Word) -> Option<Word> {
285        if value == Self::EMPTY_VALUE {
286            self.leaves.remove(&key.value())
287        } else {
288            self.leaves.insert(key.value(), value)
289        }
290    }
291
292    fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word {
293        let leaf_pos = key.value();
294        match self.leaves.get(&leaf_pos) {
295            Some(word) => *word,
296            None => Self::EMPTY_VALUE,
297        }
298    }
299
300    fn hash_leaf(leaf: &Word) -> RpoDigest {
301        // `SimpleSmt` takes the leaf value itself as the hash
302        leaf.into()
303    }
304
305    fn key_to_leaf_index(key: &LeafIndex<DEPTH>) -> LeafIndex<DEPTH> {
306        *key
307    }
308
309    fn path_and_leaf_to_opening(path: MerklePath, leaf: Word) -> ValuePath {
310        (path, leaf).into()
311    }
312}