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, MutationSet, NodeIndex, RpoDigest, SparseMerkleTree, Word, EMPTY_WORD,
6 SMT_MAX_DEPTH, 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 /// Computes what changes are necessary to insert the specified key-value pairs into this
192 /// Merkle tree, allowing for validation before applying those changes.
193 ///
194 /// This method returns a [`MutationSet`], which contains all the information for inserting
195 /// `kv_pairs` into this Merkle tree already calculated, including the new root hash, which can
196 /// be queried with [`MutationSet::root()`]. Once a mutation set is returned,
197 /// [`SimpleSmt::apply_mutations()`] can be called in order to commit these changes to the
198 /// Merkle tree, or [`drop()`] to discard them.
199
200 /// # Example
201 /// ```
202 /// # use miden_crypto::{hash::rpo::RpoDigest, Felt, Word};
203 /// # use miden_crypto::merkle::{LeafIndex, SimpleSmt, EmptySubtreeRoots, SMT_DEPTH};
204 /// let mut smt: SimpleSmt<3> = SimpleSmt::new().unwrap();
205 /// let pair = (LeafIndex::default(), Word::default());
206 /// let mutations = smt.compute_mutations(vec![pair]);
207 /// assert_eq!(mutations.root(), *EmptySubtreeRoots::entry(3, 0));
208 /// smt.apply_mutations(mutations);
209 /// assert_eq!(smt.root(), *EmptySubtreeRoots::entry(3, 0));
210 /// ```
211 pub fn compute_mutations(
212 &self,
213 kv_pairs: impl IntoIterator<Item = (LeafIndex<DEPTH>, Word)>,
214 ) -> MutationSet<DEPTH, LeafIndex<DEPTH>, Word> {
215 <Self as SparseMerkleTree<DEPTH>>::compute_mutations(self, kv_pairs)
216 }
217
218 /// Apply the prospective mutations computed with [`SimpleSmt::compute_mutations()`] to this
219 /// tree.
220 ///
221 /// # Errors
222 /// If `mutations` was computed on a tree with a different root than this one, returns
223 /// [`MerkleError::ConflictingRoots`] with a two-item [`alloc::vec::Vec`]. The first item is the
224 /// root hash the `mutations` were computed against, and the second item is the actual
225 /// current root of this tree.
226 pub fn apply_mutations(
227 &mut self,
228 mutations: MutationSet<DEPTH, LeafIndex<DEPTH>, Word>,
229 ) -> Result<(), MerkleError> {
230 <Self as SparseMerkleTree<DEPTH>>::apply_mutations(self, mutations)
231 }
232
233 /// Inserts a subtree at the specified index. The depth at which the subtree is inserted is
234 /// computed as `DEPTH - SUBTREE_DEPTH`.
235 ///
236 /// Returns the new root.
237 pub fn set_subtree<const SUBTREE_DEPTH: u8>(
238 &mut self,
239 subtree_insertion_index: u64,
240 subtree: SimpleSmt<SUBTREE_DEPTH>,
241 ) -> Result<RpoDigest, MerkleError> {
242 if SUBTREE_DEPTH > DEPTH {
243 return Err(MerkleError::InvalidSubtreeDepth {
244 subtree_depth: SUBTREE_DEPTH,
245 tree_depth: DEPTH,
246 });
247 }
248
249 // Verify that `subtree_insertion_index` is valid.
250 let subtree_root_insertion_depth = DEPTH - SUBTREE_DEPTH;
251 let subtree_root_index =
252 NodeIndex::new(subtree_root_insertion_depth, subtree_insertion_index)?;
253
254 // add leaves
255 // --------------
256
257 // The subtree's leaf indices live in their own context - i.e. a subtree of depth `d`. If we
258 // insert the subtree at `subtree_insertion_index = 0`, then the subtree leaf indices are
259 // valid as they are. However, consider what happens when we insert at
260 // `subtree_insertion_index = 1`. The first leaf of our subtree now will have index `2^d`;
261 // you can see it as there's a full subtree sitting on its left. In general, for
262 // `subtree_insertion_index = i`, there are `i` subtrees sitting before the subtree we want
263 // to insert, so we need to adjust all its leaves by `i * 2^d`.
264 let leaf_index_shift: u64 = subtree_insertion_index * 2_u64.pow(SUBTREE_DEPTH.into());
265 for (subtree_leaf_idx, leaf_value) in subtree.leaves() {
266 let new_leaf_idx = leaf_index_shift + subtree_leaf_idx;
267 debug_assert!(new_leaf_idx < 2_u64.pow(DEPTH.into()));
268
269 self.leaves.insert(new_leaf_idx, *leaf_value);
270 }
271
272 // add subtree's branch nodes (which includes the root)
273 // --------------
274 for (branch_idx, branch_node) in subtree.inner_nodes {
275 let new_branch_idx = {
276 let new_depth = subtree_root_insertion_depth + branch_idx.depth();
277 let new_value = subtree_insertion_index * 2_u64.pow(branch_idx.depth().into())
278 + branch_idx.value();
279
280 NodeIndex::new(new_depth, new_value).expect("index guaranteed to be valid")
281 };
282
283 self.inner_nodes.insert(new_branch_idx, branch_node);
284 }
285
286 // recompute nodes starting from subtree root
287 // --------------
288 self.recompute_nodes_from_index_to_root(subtree_root_index, subtree.root);
289
290 Ok(self.root)
291 }
292}
293
294impl<const DEPTH: u8> SparseMerkleTree<DEPTH> for SimpleSmt<DEPTH> {
295 type Key = LeafIndex<DEPTH>;
296 type Value = Word;
297 type Leaf = Word;
298 type Opening = ValuePath;
299
300 const EMPTY_VALUE: Self::Value = EMPTY_WORD;
301
302 fn root(&self) -> RpoDigest {
303 self.root
304 }
305
306 fn set_root(&mut self, root: RpoDigest) {
307 self.root = root;
308 }
309
310 fn get_inner_node(&self, index: NodeIndex) -> InnerNode {
311 self.inner_nodes
312 .get(&index)
313 .cloned()
314 .unwrap_or_else(|| EmptySubtreeRoots::get_inner_node(DEPTH, index.depth()))
315 }
316
317 fn insert_inner_node(&mut self, index: NodeIndex, inner_node: InnerNode) {
318 self.inner_nodes.insert(index, inner_node);
319 }
320
321 fn remove_inner_node(&mut self, index: NodeIndex) {
322 let _ = self.inner_nodes.remove(&index);
323 }
324
325 fn insert_value(&mut self, key: LeafIndex<DEPTH>, value: Word) -> Option<Word> {
326 if value == Self::EMPTY_VALUE {
327 self.leaves.remove(&key.value())
328 } else {
329 self.leaves.insert(key.value(), value)
330 }
331 }
332
333 fn get_value(&self, key: &LeafIndex<DEPTH>) -> Word {
334 self.get_leaf(key)
335 }
336
337 fn get_leaf(&self, key: &LeafIndex<DEPTH>) -> Word {
338 let leaf_pos = key.value();
339 match self.leaves.get(&leaf_pos) {
340 Some(word) => *word,
341 None => Self::EMPTY_VALUE,
342 }
343 }
344
345 fn hash_leaf(leaf: &Word) -> RpoDigest {
346 // `SimpleSmt` takes the leaf value itself as the hash
347 leaf.into()
348 }
349
350 fn construct_prospective_leaf(
351 &self,
352 _existing_leaf: Word,
353 _key: &LeafIndex<DEPTH>,
354 value: &Word,
355 ) -> Word {
356 *value
357 }
358
359 fn key_to_leaf_index(key: &LeafIndex<DEPTH>) -> LeafIndex<DEPTH> {
360 *key
361 }
362
363 fn path_and_leaf_to_opening(path: MerklePath, leaf: Word) -> ValuePath {
364 (path, leaf).into()
365 }
366}