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, Word,
6};
7use crate::merkle::{SmtLeafError, SparseMerklePath};
8
9mod proof;
10pub use proof::SimpleSmtProof;
11
12#[cfg(test)]
13mod tests;
14
15// SPARSE MERKLE TREE
16// ================================================================================================
17
18type Leaves = super::Leaves<Word>;
19
20/// A sparse Merkle tree with 64-bit keys and 4-element leaf values, without compaction.
21///
22/// The root of the tree is recomputed on each new leaf update.
23#[derive(Debug, Clone, PartialEq, Eq)]
24#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
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 SparseMerkleTree<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_usize.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 >= max_num_entries {
89 return Err(MerkleError::TooManyEntries(max_num_entries));
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 // Our particular implementation of `from_raw_parts()` never returns `Err`.
115 <Self as SparseMerkleTree<DEPTH>>::from_raw_parts(inner_nodes, leaves, root).unwrap()
116 }
117
118 /// Wrapper around [`SimpleSmt::with_leaves`] which inserts leaves at contiguous indices
119 /// starting at index 0.
120 pub fn with_contiguous_leaves(
121 entries: impl IntoIterator<Item = Word>,
122 ) -> Result<Self, MerkleError> {
123 Self::with_leaves(
124 entries
125 .into_iter()
126 .enumerate()
127 .map(|(idx, word)| (idx.try_into().expect("tree max depth is 2^8"), word)),
128 )
129 }
130
131 // PUBLIC ACCESSORS
132 // --------------------------------------------------------------------------------------------
133
134 /// Returns the depth of the tree
135 pub const fn depth(&self) -> u8 {
136 DEPTH
137 }
138
139 /// Returns the root of the tree
140 pub fn root(&self) -> Word {
141 <Self as SparseMerkleTree<DEPTH>>::root(self)
142 }
143
144 /// Returns the number of non-empty leaves in this tree.
145 pub fn num_leaves(&self) -> usize {
146 self.leaves.len()
147 }
148
149 /// Returns the leaf at the specified index.
150 pub fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word {
151 <Self as SparseMerkleTree<DEPTH>>::get_leaf(self, key)
152 }
153
154 /// Returns a node at the specified index.
155 ///
156 /// # Errors
157 /// Returns an error if the specified index has depth set to 0 or the depth is greater than
158 /// the depth of this Merkle tree.
159 pub fn get_node(&self, index: NodeIndex) -> Result<Word, MerkleError> {
160 if index.is_root() {
161 Err(MerkleError::DepthTooSmall(index.depth()))
162 } else if index.depth() > DEPTH {
163 Err(MerkleError::DepthTooBig(index.depth() as u64))
164 } else if index.depth() == DEPTH {
165 let leaf = self.get_leaf(&LeafIndex::<DEPTH>::try_from(index)?);
166
167 Ok(leaf)
168 } else {
169 Ok(self.get_inner_node(index).hash())
170 }
171 }
172
173 /// Returns an opening of the leaf associated with `key`. Conceptually, an opening is a Merkle
174 /// path to the leaf, as well as the leaf itself.
175 pub fn open(&self, key: &LeafIndex<DEPTH>) -> SimpleSmtProof {
176 let value = self.get_value(key);
177 let nodes = key.index.proof_indices().map(|index| self.get_node_hash(index));
178 // `from_sized_iter()` returns an error if there are more nodes than `SMT_MAX_DEPTH`, but
179 // this could only happen if we have more levels than `SMT_MAX_DEPTH` ourselves, which is
180 // guarded against in `SimpleSmt::new()`.
181 let path = SparseMerklePath::from_sized_iter(nodes).unwrap();
182
183 SimpleSmtProof { value, path }
184 }
185
186 /// Returns a boolean value indicating whether the SMT is empty.
187 pub fn is_empty(&self) -> bool {
188 debug_assert_eq!(self.leaves.is_empty(), self.root == Self::EMPTY_ROOT);
189 self.root == Self::EMPTY_ROOT
190 }
191
192 // ITERATORS
193 // --------------------------------------------------------------------------------------------
194
195 /// Returns an iterator over the leaves of this [SimpleSmt].
196 pub fn leaves(&self) -> impl Iterator<Item = (u64, &Word)> {
197 self.leaves.iter().map(|(i, w)| (*i, w))
198 }
199
200 /// Returns an iterator over the inner nodes of this [SimpleSmt].
201 pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
202 self.inner_nodes.values().map(|e| InnerNodeInfo {
203 value: e.hash(),
204 left: e.left,
205 right: e.right,
206 })
207 }
208
209 // STATE MUTATORS
210 // --------------------------------------------------------------------------------------------
211
212 /// Inserts a value at the specified key, returning the previous value associated with that key.
213 /// Recall that by definition, any key that hasn't been updated is associated with
214 /// [`EMPTY_WORD`].
215 ///
216 /// This also recomputes all hashes between the leaf (associated with the key) and the root,
217 /// updating the root itself.
218 pub fn insert(&mut self, key: LeafIndex<DEPTH>, value: Word) -> Word {
219 // SAFETY: a SimpleSmt does not contain multi-value leaves. The underlying
220 // SimpleSmt::insert_value does not return any errors so it's safe to unwrap here.
221 <Self as SparseMerkleTree<DEPTH>>::insert(self, key, value)
222 .expect("inserting a value into a simple smt never returns an error")
223 }
224
225 /// Computes what changes are necessary to insert the specified key-value pairs into this
226 /// Merkle tree, allowing for validation before applying those changes.
227 ///
228 /// This method returns a [`MutationSet`], which contains all the information for inserting
229 /// `kv_pairs` into this Merkle tree already calculated, including the new root hash, which can
230 /// be queried with [`MutationSet::root()`]. Once a mutation set is returned,
231 /// [`SimpleSmt::apply_mutations()`] can be called in order to commit these changes to the
232 /// Merkle tree, or [`drop()`] to discard them.
233 ///
234 /// # Example
235 /// ```
236 /// # use miden_crypto::{Felt, Word};
237 /// # use miden_crypto::merkle::{LeafIndex, SimpleSmt, EmptySubtreeRoots, SMT_DEPTH};
238 /// let mut smt: SimpleSmt<3> = SimpleSmt::new().unwrap();
239 /// let pair = (LeafIndex::default(), Word::default());
240 /// let mutations = smt.compute_mutations(vec![pair]);
241 /// assert_eq!(mutations.root(), *EmptySubtreeRoots::entry(3, 0));
242 /// smt.apply_mutations(mutations).unwrap();
243 /// assert_eq!(smt.root(), *EmptySubtreeRoots::entry(3, 0));
244 /// ```
245 pub fn compute_mutations(
246 &self,
247 kv_pairs: impl IntoIterator<Item = (LeafIndex<DEPTH>, Word)>,
248 ) -> MutationSet<DEPTH, LeafIndex<DEPTH>, Word> {
249 // SAFETY: a SimpleSmt does not contain multi-value leaves. The underlying
250 // SimpleSmt::construct_prospective_leaf does not return any errors so it's safe to unwrap
251 // here.
252 <Self as SparseMerkleTree<DEPTH>>::compute_mutations(self, kv_pairs)
253 .expect("computing mutations on a simple smt never returns an error")
254 }
255
256 /// Applies the prospective mutations computed with [`SimpleSmt::compute_mutations()`] to this
257 /// tree.
258 ///
259 /// # Errors
260 /// If `mutations` was computed on a tree with a different root than this one, returns
261 /// [`MerkleError::ConflictingRoots`] with a two-item [`alloc::vec::Vec`]. The first item is the
262 /// root hash the `mutations` were computed against, and the second item is the actual
263 /// current root of this tree.
264 pub fn apply_mutations(
265 &mut self,
266 mutations: MutationSet<DEPTH, LeafIndex<DEPTH>, Word>,
267 ) -> Result<(), MerkleError> {
268 <Self as SparseMerkleTree<DEPTH>>::apply_mutations(self, mutations)
269 }
270
271 /// Applies the prospective mutations computed with [`SimpleSmt::compute_mutations()`] to
272 /// this tree and returns the reverse mutation set.
273 ///
274 /// Applying the reverse mutation sets to the updated tree will revert the changes.
275 ///
276 /// # Errors
277 /// If `mutations` was computed on a tree with a different root than this one, returns
278 /// [`MerkleError::ConflictingRoots`] with a two-item [`alloc::vec::Vec`]. The first item is the
279 /// root hash the `mutations` were computed against, and the second item is the actual
280 /// current root of this tree.
281 pub fn apply_mutations_with_reversion(
282 &mut self,
283 mutations: MutationSet<DEPTH, LeafIndex<DEPTH>, Word>,
284 ) -> Result<MutationSet<DEPTH, LeafIndex<DEPTH>, Word>, MerkleError> {
285 <Self as SparseMerkleTree<DEPTH>>::apply_mutations_with_reversion(self, mutations)
286 }
287
288 /// Inserts a subtree at the specified index. The depth at which the subtree is inserted is
289 /// computed as `DEPTH - SUBTREE_DEPTH`.
290 ///
291 /// Returns the new root.
292 pub fn set_subtree<const SUBTREE_DEPTH: u8>(
293 &mut self,
294 subtree_insertion_index: u64,
295 subtree: SimpleSmt<SUBTREE_DEPTH>,
296 ) -> Result<Word, MerkleError> {
297 if SUBTREE_DEPTH > DEPTH {
298 return Err(MerkleError::SubtreeDepthExceedsDepth {
299 subtree_depth: SUBTREE_DEPTH,
300 tree_depth: DEPTH,
301 });
302 }
303
304 // Verify that `subtree_insertion_index` is valid.
305 let subtree_root_insertion_depth = DEPTH - SUBTREE_DEPTH;
306 let subtree_root_index =
307 NodeIndex::new(subtree_root_insertion_depth, subtree_insertion_index)?;
308
309 // add leaves
310 // --------------
311
312 // The subtree's leaf indices live in their own context - i.e. a subtree of depth `d`. If we
313 // insert the subtree at `subtree_insertion_index = 0`, then the subtree leaf indices are
314 // valid as they are. However, consider what happens when we insert at
315 // `subtree_insertion_index = 1`. The first leaf of our subtree now will have index `2^d`;
316 // you can see it as there's a full subtree sitting on its left. In general, for
317 // `subtree_insertion_index = i`, there are `i` subtrees sitting before the subtree we want
318 // to insert, so we need to adjust all its leaves by `i * 2^d`.
319 let leaf_index_shift: u64 = subtree_insertion_index * 2_u64.pow(SUBTREE_DEPTH.into());
320 for (subtree_leaf_idx, leaf_value) in subtree.leaves() {
321 let new_leaf_idx = leaf_index_shift + subtree_leaf_idx;
322 debug_assert!(new_leaf_idx < 2_u64.pow(DEPTH.into()));
323
324 self.leaves.insert(new_leaf_idx, *leaf_value);
325 }
326
327 // add subtree's branch nodes (which includes the root)
328 // --------------
329 for (branch_idx, branch_node) in subtree.inner_nodes {
330 let new_branch_idx = {
331 let new_depth = subtree_root_insertion_depth + branch_idx.depth();
332 let new_value = subtree_insertion_index * 2_u64.pow(branch_idx.depth().into())
333 + branch_idx.value();
334
335 NodeIndex::new(new_depth, new_value).expect("index guaranteed to be valid")
336 };
337
338 self.inner_nodes.insert(new_branch_idx, branch_node);
339 }
340
341 // recompute nodes starting from subtree root
342 // --------------
343 self.recompute_nodes_from_index_to_root(subtree_root_index, subtree.root);
344
345 Ok(self.root)
346 }
347}
348
349impl<const DEPTH: u8> SparseMerkleTree<DEPTH> for SimpleSmt<DEPTH> {
350 type Key = LeafIndex<DEPTH>;
351 type Value = Word;
352 type Leaf = Word;
353 type Opening = SimpleSmtProof;
354
355 const EMPTY_VALUE: Self::Value = EMPTY_WORD;
356 const EMPTY_ROOT: Word = *EmptySubtreeRoots::entry(DEPTH, 0);
357
358 fn from_raw_parts(
359 inner_nodes: InnerNodes,
360 leaves: Leaves,
361 root: Word,
362 ) -> Result<Self, MerkleError> {
363 if cfg!(debug_assertions) {
364 let root_node_hash = inner_nodes
365 .get(&NodeIndex::root())
366 .map(InnerNode::hash)
367 .unwrap_or(Self::EMPTY_ROOT);
368
369 assert_eq!(root_node_hash, root);
370 }
371
372 Ok(Self { root, inner_nodes, leaves })
373 }
374
375 fn root(&self) -> Word {
376 self.root
377 }
378
379 fn set_root(&mut self, root: Word) {
380 self.root = root;
381 }
382
383 fn get_inner_node(&self, index: NodeIndex) -> InnerNode {
384 self.inner_nodes
385 .get(&index)
386 .cloned()
387 .unwrap_or_else(|| EmptySubtreeRoots::get_inner_node(DEPTH, index.depth()))
388 }
389
390 fn insert_inner_node(&mut self, index: NodeIndex, inner_node: InnerNode) -> Option<InnerNode> {
391 self.inner_nodes.insert(index, inner_node)
392 }
393
394 fn remove_inner_node(&mut self, index: NodeIndex) -> Option<InnerNode> {
395 self.inner_nodes.remove(&index)
396 }
397
398 fn insert_value(
399 &mut self,
400 key: LeafIndex<DEPTH>,
401 value: Word,
402 ) -> Result<Option<Word>, MerkleError> {
403 let result = if value == Self::EMPTY_VALUE {
404 self.leaves.remove(&key.value())
405 } else {
406 self.leaves.insert(key.value(), value)
407 };
408 Ok(result)
409 }
410
411 fn get_value(&self, key: &LeafIndex<DEPTH>) -> Word {
412 self.get_leaf(key)
413 }
414
415 fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word {
416 let leaf_pos = key.value();
417 match self.leaves.get(&leaf_pos) {
418 Some(word) => *word,
419 None => Self::EMPTY_VALUE,
420 }
421 }
422
423 fn hash_leaf(leaf: &Word) -> Word {
424 // `SimpleSmt` takes the leaf value itself as the hash
425 *leaf
426 }
427
428 fn construct_prospective_leaf(
429 &self,
430 _existing_leaf: Word,
431 _key: &LeafIndex<DEPTH>,
432 value: &Word,
433 ) -> Result<Word, SmtLeafError> {
434 Ok(*value)
435 }
436
437 fn key_to_leaf_index(key: &LeafIndex<DEPTH>) -> LeafIndex<DEPTH> {
438 *key
439 }
440
441 fn path_and_leaf_to_opening(path: SparseMerklePath, leaf: Word) -> SimpleSmtProof {
442 (path, leaf).into()
443 }
444}