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}