miden_crypto/merkle/smt/mod.rs
1//! Sparse Merkle Tree (SMT) data structures.
2
3use alloc::{string::ToString, vec::Vec};
4use core::{
5 fmt::{self, Display},
6 hash::Hash,
7};
8
9use super::{EmptySubtreeRoots, InnerNodeInfo, MerkleError, NodeIndex, SparseMerklePath};
10use crate::{
11 EMPTY_WORD, Map, Set, Word,
12 hash::poseidon2::Poseidon2,
13 utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
14};
15
16mod full;
17pub use full::{MAX_LEAF_ENTRIES, SMT_DEPTH, Smt, SmtLeaf, SmtLeafError, SmtProof, SmtProofError};
18
19#[cfg(feature = "concurrent")]
20mod large;
21#[cfg(feature = "internal")]
22pub use full::concurrent::{SubtreeLeaf, build_subtree_for_bench};
23#[cfg(feature = "concurrent")]
24pub use large::{
25 LargeSmt, LargeSmtError, LargeSmtResult, MemoryStorage, MemoryStorageSnapshot, SmtStorage,
26 SmtStorageReader, StorageError, StorageResult, StorageUpdateParts, StorageUpdates, Subtree,
27 SubtreeError, SubtreeUpdate,
28};
29#[cfg(feature = "rocksdb")]
30pub use large::{
31 RocksDbBloomFilterBitsPerKey, RocksDbConfig, RocksDbDurabilityMode, RocksDbMemoryBudget,
32 RocksDbSnapshotStorage, RocksDbStorage, RocksDbTuningOptions, RocksDbWriteBufferManagerBudget,
33};
34
35mod large_forest;
36pub use large_forest::{
37 AppliedLineageMutation, Backend, BackendError, BackendReader, Config as ForestConfig,
38 DEFAULT_MAX_HISTORY_VERSIONS as FOREST_DEFAULT_MAX_HISTORY_VERSIONS,
39 InMemoryBackend as ForestInMemoryBackend,
40 InMemoryBackendSnapshot as ForestInMemoryBackendReader, LargeSmtForest, LargeSmtForestError,
41 LineageId, LineageMutation, LineageMutationKind,
42 MIN_HISTORY_VERSIONS as FOREST_MIN_HISTORY_VERSIONS, RootInfo, SmtForestMutationSet,
43 SmtForestOperation, SmtForestUpdateBatch, SmtUpdateBatch, TreeEntry, TreeId, TreeWithRoot,
44 VersionId,
45};
46#[cfg(feature = "persistent-forest")]
47pub use large_forest::{
48 PersistentBackend as ForestPersistentBackend, PersistentBackendConfig,
49 PersistentBackendReader as ForestPersistentBackendReader,
50};
51
52mod simple;
53pub use simple::{SimpleSmt, SimpleSmtProof};
54
55mod partial;
56use miden_field::Felt;
57pub use partial::{PartialSmt, UniqueNodes};
58// CONSTANTS
59// ================================================================================================
60
61/// Minimum supported depth.
62pub const SMT_MIN_DEPTH: u8 = 1;
63
64/// Maximum supported depth.
65pub const SMT_MAX_DEPTH: u8 = 64;
66
67/// The felt used as a domain separator when hashing leaves in merkle trees.
68pub const LEAF_DOMAIN: Felt = Felt::new_unchecked(0x13af);
69
70// SPARSE MERKLE TREE
71// ================================================================================================
72
73type InnerNodes = Map<NodeIndex, InnerNode>;
74type Leaves<T> = Map<u64, T>;
75type NodeMutations = Map<NodeIndex, NodeMutation>;
76
77/// The read-only view of a sparse Merkle tree.
78///
79/// This trait contains all methods that require only read access to the tree, including querying
80/// values, generating proofs/openings, and computing prospective mutations. Splitting this from
81/// [`SparseMerkleTree`] allows types like `LargeSmt` to implement read-only operations with
82/// weaker generic bounds (e.g., `SmtStorageReader` instead of `SmtStorage`).
83pub(crate) trait SparseMerkleTreeReader<const DEPTH: u8> {
84 /// The type for a key
85 type Key: Clone + Ord + Eq + Hash;
86 /// The type for a value
87 type Value: Clone + PartialEq;
88 /// The type for a leaf
89 type Leaf: Clone;
90 /// The type for an opening (i.e. a "proof") of a leaf
91 type Opening;
92
93 /// The default value used to compute the hash of empty leaves
94 const EMPTY_VALUE: Self::Value;
95
96 /// The root of the empty tree with provided DEPTH
97 const EMPTY_ROOT: Word;
98
99 // PROVIDED METHODS
100 // ---------------------------------------------------------------------------------------------
101
102 /// Returns a [SparseMerklePath] to the specified key.
103 ///
104 /// Mostly this is an implementation detail of [`Self::open()`].
105 fn get_path(&self, key: &Self::Key) -> SparseMerklePath {
106 let index = NodeIndex::from(Self::key_to_leaf_index(key));
107
108 // SAFETY: this is guaranteed to have depth <= SMT_MAX_DEPTH
109 SparseMerklePath::from_sized_iter(
110 index.proof_indices().map(|index| self.get_node_hash(index)),
111 )
112 .expect("failed to convert to SparseMerklePath")
113 }
114
115 /// Get the hash of a node at an arbitrary index, including the root or leaf hashes.
116 ///
117 /// The root index simply returns [`Self::root()`]. Other hashes are retrieved by calling
118 /// [`Self::get_inner_node()`] on the parent, and returning the respective child hash.
119 fn get_node_hash(&self, index: NodeIndex) -> Word {
120 if index.is_root() {
121 return self.root();
122 }
123
124 let InnerNode { left, right } = self.get_inner_node(index.parent());
125
126 let index_is_right = index.is_position_odd();
127 if index_is_right { right } else { left }
128 }
129
130 /// Returns an opening of the leaf associated with `key`. Conceptually, an opening is a sparse
131 /// Merkle path to the leaf, as well as the leaf itself.
132 fn open(&self, key: &Self::Key) -> Self::Opening {
133 let leaf = self.get_leaf(key);
134 let merkle_path = self.get_path(key);
135
136 Self::path_and_leaf_to_opening(merkle_path, leaf)
137 }
138
139 /// Computes what changes are necessary to insert the specified key-value pairs into this Merkle
140 /// tree, allowing for validation before applying those changes.
141 ///
142 /// This method returns a [`MutationSet`], which contains all the information for inserting
143 /// `kv_pairs` into this Merkle tree already calculated, including the new root hash, which can
144 /// be queried with [`MutationSet::root()`]. Once a mutation set is returned,
145 /// [`SparseMerkleTree::apply_mutations()`] can be called in order to commit these changes to
146 /// the Merkle tree, or [`drop()`] to discard them.
147 ///
148 /// # Errors
149 /// - Returns [`MerkleError::DuplicateValuesForIndex`] if `kv_pairs` contains duplicate keys.
150 /// - If mutations would exceed [`crate::merkle::smt::MAX_LEAF_ENTRIES`] (1024 entries) in a
151 /// leaf, returns [`MerkleError::TooManyLeafEntries`].
152 fn compute_mutations(
153 &self,
154 kv_pairs: impl IntoIterator<Item = (Self::Key, Self::Value)>,
155 ) -> Result<MutationSet<DEPTH, Self::Key, Self::Value>, MerkleError> {
156 self.compute_mutations_sequential(kv_pairs)
157 }
158
159 /// Sequential version of [`SparseMerkleTreeReader::compute_mutations()`].
160 /// This is the default implementation.
161 ///
162 /// # Errors
163 ///
164 /// - [`MerkleError::DuplicateValuesForIndex`] if `kv_pairs` contains multiple pairs with the
165 /// same key.
166 /// - [`MerkleError::TooManyLeafEntries`] if the mutations would cause the tree to exceed
167 /// [`crate::merkle::smt::MAX_LEAF_ENTRIES`] in a single leaf.
168 fn compute_mutations_sequential(
169 &self,
170 kv_pairs: impl IntoIterator<Item = (Self::Key, Self::Value)>,
171 ) -> Result<MutationSet<DEPTH, Self::Key, Self::Value>, MerkleError> {
172 use NodeMutation::*;
173
174 let mut new_root = self.root();
175 let mut new_pairs: Map<Self::Key, Self::Value> = Default::default();
176 let mut node_mutations: NodeMutations = NodeMutations::new();
177 let mut seen_keys: Set<Self::Key> = Set::new();
178
179 for (key, value) in kv_pairs {
180 // Reject duplicate keys.
181 if !seen_keys.insert(key.clone()) {
182 return Err(MerkleError::DuplicateValuesForIndex(
183 Self::key_to_leaf_index(&key).position(),
184 ));
185 }
186
187 // If the old value and the new value are the same, there is nothing to update.
188 let old_value = new_pairs.get(&key).cloned().unwrap_or_else(|| self.get_value(&key));
189 if value == old_value {
190 continue;
191 }
192
193 let leaf_index = Self::key_to_leaf_index(&key);
194 let mut node_index = NodeIndex::from(leaf_index);
195
196 // We need the current leaf's hash to calculate the new leaf, but in the rare case that
197 // `kv_pairs` has multiple pairs that go into the same leaf, then those pairs are also
198 // part of the "current leaf".
199 let old_leaf = {
200 let pairs_at_index = new_pairs
201 .iter()
202 .filter(|&(new_key, _)| Self::key_to_leaf_index(new_key) == leaf_index);
203
204 pairs_at_index.fold(self.get_leaf(&key), |acc, (k, v)| {
205 // Most of the time `pairs_at_index` should only contain a single entry (or
206 // none at all), as multi-leaves should be really rare.
207 let existing_leaf = acc;
208 self.construct_prospective_leaf(existing_leaf, k, v)
209 .expect("current leaf should be valid")
210 })
211 };
212
213 let new_leaf =
214 self.construct_prospective_leaf(old_leaf, &key, &value).map_err(|e| match e {
215 SmtLeafError::TooManyLeafEntries { actual } => {
216 MerkleError::TooManyLeafEntries { actual }
217 },
218 other => panic!("unexpected SmtLeaf::insert error: {other:?}"),
219 })?;
220
221 let mut new_child_hash = Self::hash_leaf(&new_leaf);
222
223 for node_depth in (0..node_index.depth()).rev() {
224 // Whether the node we're replacing is the right child or the left child.
225 let is_right = node_index.is_position_odd();
226 node_index.move_up();
227
228 let old_node = node_mutations
229 .get(&node_index)
230 .map(|mutation| match mutation {
231 Addition(node) => node.clone(),
232 Removal => EmptySubtreeRoots::get_inner_node(DEPTH, node_depth),
233 })
234 .unwrap_or_else(|| self.get_inner_node(node_index));
235
236 let new_node = if is_right {
237 InnerNode {
238 left: old_node.left,
239 right: new_child_hash,
240 }
241 } else {
242 InnerNode {
243 left: new_child_hash,
244 right: old_node.right,
245 }
246 };
247
248 // The next iteration will operate on this new node's hash.
249 new_child_hash = new_node.hash();
250
251 let &equivalent_empty_hash = EmptySubtreeRoots::entry(DEPTH, node_depth);
252 let is_removal = new_child_hash == equivalent_empty_hash;
253 let new_entry = if is_removal { Removal } else { Addition(new_node) };
254 node_mutations.insert(node_index, new_entry);
255 }
256
257 // Once we're at depth 0, the last node we made is the new root.
258 new_root = new_child_hash;
259 // And then we're done with this pair; on to the next one.
260 new_pairs.insert(key, value);
261 }
262
263 Ok(MutationSet {
264 old_root: self.root(),
265 new_root,
266 node_mutations,
267 new_pairs,
268 })
269 }
270
271 // REQUIRED METHODS
272 // ---------------------------------------------------------------------------------------------
273
274 /// The root of the tree
275 fn root(&self) -> Word;
276
277 /// Retrieves an inner node at the given index
278 fn get_inner_node(&self, index: NodeIndex) -> InnerNode;
279
280 /// Returns the value at the specified key. Recall that by definition, any key that hasn't been
281 /// updated is associated with [`Self::EMPTY_VALUE`].
282 fn get_value(&self, key: &Self::Key) -> Self::Value;
283
284 /// Returns the leaf at the specified index.
285 fn get_leaf(&self, key: &Self::Key) -> Self::Leaf;
286
287 /// Returns the hash of a leaf
288 fn hash_leaf(leaf: &Self::Leaf) -> Word;
289
290 /// Returns what a leaf would look like if a key-value pair were inserted into the tree, without
291 /// mutating the tree itself. The existing leaf can be empty.
292 ///
293 /// To get a prospective leaf based on the current state of the tree, use `self.get_leaf(key)`
294 /// as the argument for `existing_leaf`. The return value from this function can be chained back
295 /// into this function as the first argument to continue making prospective changes.
296 ///
297 /// # Invariants
298 /// Because this method is for a prospective key-value insertion into a specific leaf,
299 /// `existing_leaf` must have the same leaf index as `key` (as determined by
300 /// [`SparseMerkleTreeReader::key_to_leaf_index()`]), or the result will be meaningless.
301 ///
302 /// # Errors
303 /// If inserting the key-value pair would exceed
304 /// [`crate::merkle::smt::MAX_LEAF_ENTRIES`] (1024 entries) in a leaf,
305 /// returns [`SmtLeafError::TooManyLeafEntries`].
306 fn construct_prospective_leaf(
307 &self,
308 existing_leaf: Self::Leaf,
309 key: &Self::Key,
310 value: &Self::Value,
311 ) -> Result<Self::Leaf, SmtLeafError>;
312
313 /// Checks a slice of key-value pairs (assumed sorted by key) for duplicate keys.
314 ///
315 /// The input `sorted_kv_pairs` must be sorted for this function to return correct results, as
316 /// it only performs checks of adjacent elements.
317 ///
318 /// # Errors
319 ///
320 /// - [`MerkleError::DuplicateValuesForIndex`] at the first duplicate key found in
321 /// `sorted_kv_pairs`.
322 #[cfg(feature = "concurrent")] // Currently only used in concurrent contexts
323 fn check_for_duplicate_keys(
324 sorted_kv_pairs: &[(Self::Key, Self::Value)],
325 ) -> Result<(), MerkleError> {
326 if let Some(window) = sorted_kv_pairs.windows(2).find(|w| w[0].0 == w[1].0) {
327 return Err(MerkleError::DuplicateValuesForIndex(
328 Self::key_to_leaf_index(&window[0].0).position(),
329 ));
330 }
331 Ok(())
332 }
333
334 /// Maps a key to a leaf index
335 fn key_to_leaf_index(key: &Self::Key) -> LeafIndex<DEPTH>;
336
337 /// Maps a (SparseMerklePath, Self::Leaf) to an opening.
338 ///
339 /// The length `path` is guaranteed to be equal to `DEPTH`
340 fn path_and_leaf_to_opening(path: SparseMerklePath, leaf: Self::Leaf) -> Self::Opening;
341}
342
343/// An abstract description of a sparse Merkle tree with write capabilities.
344///
345/// A sparse Merkle tree is a key-value map which also supports proving that a given value is indeed
346/// stored at a given key in the tree. It is viewed as always being fully populated. If a leaf's
347/// value was not explicitly set, then its value is the default value. Typically, the vast majority
348/// of leaves will store the default value (hence it is "sparse"), and therefore the internal
349/// representation of the tree will only keep track of the leaves that have a different value from
350/// the default.
351///
352/// All leaves sit at the same depth. The deeper the tree, the more leaves it has; but also the
353/// longer its proofs are - of exactly `log(depth)` size. A tree cannot have depth 0, since such a
354/// tree is just a single value, and is probably a programming mistake.
355///
356/// Every key maps to one leaf. If there are as many keys as there are leaves, then
357/// [Self::Leaf] should be the same type as [Self::Value], as is the case with
358/// [`SimpleSmt`]. However, if there are more keys than leaves, then [`Self::Leaf`]
359/// must accommodate all keys that map to the same leaf.
360///
361/// [SparseMerkleTree] currently doesn't support optimizations that compress Merkle proofs.
362pub(crate) trait SparseMerkleTree<const DEPTH: u8>: SparseMerkleTreeReader<DEPTH> {
363 // PROVIDED METHODS
364 // ---------------------------------------------------------------------------------------------
365
366 /// Inserts a value at the specified key, returning the previous value associated with that key.
367 /// Recall that by definition, any key that hasn't been updated is associated with
368 /// [`Self::EMPTY_VALUE`].
369 ///
370 /// This also recomputes all hashes between the leaf (associated with the key) and the root,
371 /// updating the root itself.
372 fn insert(&mut self, key: Self::Key, value: Self::Value) -> Result<Self::Value, MerkleError> {
373 let old_value = self.insert_value(key.clone(), value.clone())?.unwrap_or(Self::EMPTY_VALUE);
374
375 // if the old value and new value are the same, there is nothing to update
376 if value == old_value {
377 return Ok(value);
378 }
379
380 let leaf = self.get_leaf(&key);
381 let node_index = {
382 let leaf_index: LeafIndex<DEPTH> = Self::key_to_leaf_index(&key);
383 leaf_index.into()
384 };
385
386 self.recompute_nodes_from_index_to_root(node_index, Self::hash_leaf(&leaf));
387
388 Ok(old_value)
389 }
390
391 /// Recomputes the branch nodes (including the root) from `index` all the way to the root.
392 /// `node_hash_at_index` is the hash of the node stored at index.
393 fn recompute_nodes_from_index_to_root(
394 &mut self,
395 mut index: NodeIndex,
396 node_hash_at_index: Word,
397 ) {
398 let mut node_hash = node_hash_at_index;
399 for node_depth in (0..index.depth()).rev() {
400 let is_right = index.is_position_odd();
401 index.move_up();
402 let InnerNode { left, right } = self.get_inner_node(index);
403 let (left, right) = if is_right {
404 (left, node_hash)
405 } else {
406 (node_hash, right)
407 };
408 node_hash = Poseidon2::merge(&[left, right]);
409
410 if node_hash == *EmptySubtreeRoots::entry(DEPTH, node_depth) {
411 // If a subtree is empty, then can remove the inner node, since it's equal to the
412 // default value
413 self.remove_inner_node(index);
414 } else {
415 self.insert_inner_node(index, InnerNode { left, right });
416 }
417 }
418 self.set_root(node_hash);
419 }
420
421 /// Applies the prospective mutations computed with [`SparseMerkleTree::compute_mutations()`] to
422 /// this tree.
423 ///
424 /// # Errors
425 /// If `mutations` was computed on a tree with a different root than this one, returns
426 /// [`MerkleError::ConflictingRoots`] with a two-item [`Vec`]. The first item is the root hash
427 /// the `mutations` were computed against, and the second item is the actual current root of
428 /// this tree.
429 /// If mutations would exceed [`crate::merkle::smt::MAX_LEAF_ENTRIES`] (1024 entries) in a leaf,
430 /// returns
431 /// [`MerkleError::TooManyLeafEntries`].
432 fn apply_mutations(
433 &mut self,
434 mutations: MutationSet<DEPTH, Self::Key, Self::Value>,
435 ) -> Result<(), MerkleError>
436 where
437 Self: Sized,
438 {
439 use NodeMutation::*;
440 let MutationSet {
441 old_root,
442 node_mutations,
443 new_pairs,
444 new_root,
445 } = mutations;
446
447 // Guard against accidentally trying to apply mutations that were computed against a
448 // different tree, including a stale version of this tree.
449 if old_root != self.root() {
450 return Err(MerkleError::ConflictingRoots {
451 expected_root: self.root(),
452 actual_root: old_root,
453 });
454 }
455
456 for (index, mutation) in node_mutations {
457 match mutation {
458 Removal => {
459 self.remove_inner_node(index);
460 },
461 Addition(node) => {
462 self.insert_inner_node(index, node);
463 },
464 }
465 }
466
467 for (key, value) in new_pairs {
468 self.insert_value(key, value)?;
469 }
470
471 self.set_root(new_root);
472
473 Ok(())
474 }
475
476 /// Applies the prospective mutations computed with [`SparseMerkleTree::compute_mutations()`] to
477 /// this tree and returns the reverse mutation set. Applying the reverse mutation sets to the
478 /// updated tree will revert the changes.
479 ///
480 /// # Errors
481 /// If `mutations` was computed on a tree with a different root than this one, returns
482 /// [`MerkleError::ConflictingRoots`] with a two-item [`Vec`]. The first item is the root hash
483 /// the `mutations` were computed against, and the second item is the actual current root of
484 /// this tree.
485 fn apply_mutations_with_reversion(
486 &mut self,
487 mutations: MutationSet<DEPTH, Self::Key, Self::Value>,
488 ) -> Result<MutationSet<DEPTH, Self::Key, Self::Value>, MerkleError>
489 where
490 Self: Sized,
491 {
492 use NodeMutation::*;
493 let MutationSet {
494 old_root,
495 node_mutations,
496 new_pairs,
497 new_root,
498 } = mutations;
499
500 // Guard against accidentally trying to apply mutations that were computed against a
501 // different tree, including a stale version of this tree.
502 if old_root != self.root() {
503 return Err(MerkleError::ConflictingRoots {
504 expected_root: self.root(),
505 actual_root: old_root,
506 });
507 }
508
509 let mut reverse_mutations = NodeMutations::new();
510 for (index, mutation) in node_mutations {
511 match mutation {
512 Removal => {
513 if let Some(node) = self.remove_inner_node(index) {
514 reverse_mutations.insert(index, Addition(node));
515 }
516 },
517 Addition(node) => {
518 if let Some(old_node) = self.insert_inner_node(index, node) {
519 reverse_mutations.insert(index, Addition(old_node));
520 } else {
521 reverse_mutations.insert(index, Removal);
522 }
523 },
524 }
525 }
526
527 let mut reverse_pairs = Map::new();
528 for (key, value) in new_pairs {
529 match self.insert_value(key.clone(), value)? {
530 Some(old_value) => {
531 reverse_pairs.insert(key, old_value);
532 },
533 None => {
534 reverse_pairs.insert(key, Self::EMPTY_VALUE);
535 },
536 }
537 }
538
539 self.set_root(new_root);
540
541 Ok(MutationSet {
542 old_root: new_root,
543 node_mutations: reverse_mutations,
544 new_pairs: reverse_pairs,
545 new_root: old_root,
546 })
547 }
548
549 // REQUIRED METHODS
550 // ---------------------------------------------------------------------------------------------
551
552 /// Sets the root of the tree
553 fn set_root(&mut self, root: Word);
554
555 /// Inserts an inner node at the given index
556 fn insert_inner_node(&mut self, index: NodeIndex, inner_node: InnerNode) -> Option<InnerNode>;
557
558 /// Removes an inner node at the given index
559 fn remove_inner_node(&mut self, index: NodeIndex) -> Option<InnerNode>;
560
561 /// Inserts a leaf node, and returns the value at the key if already exists
562 fn insert_value(
563 &mut self,
564 key: Self::Key,
565 value: Self::Value,
566 ) -> Result<Option<Self::Value>, MerkleError>;
567}
568
569// INNER NODE
570// ================================================================================================
571
572/// This struct is public so functions returning it can be used in `benches/`, but is otherwise not
573/// part of the public API.
574#[doc(hidden)]
575#[derive(Debug, Default, Clone, PartialEq, Eq)]
576pub struct InnerNode {
577 pub left: Word,
578 pub right: Word,
579}
580
581impl InnerNode {
582 pub fn hash(&self) -> Word {
583 Poseidon2::merge(&[self.left, self.right])
584 }
585}
586
587// LEAF INDEX
588// ================================================================================================
589
590/// The index of a leaf, at a depth known at compile-time.
591#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
592pub struct LeafIndex<const DEPTH: u8> {
593 index: NodeIndex,
594}
595
596impl<const DEPTH: u8> LeafIndex<DEPTH> {
597 /// Creates a new `LeafIndex` with the specified value.
598 ///
599 /// # Errors
600 ///
601 /// Returns an error if the provided depth is less than the minimum supported depth.
602 pub fn new(value: u64) -> Result<Self, MerkleError> {
603 if DEPTH < SMT_MIN_DEPTH {
604 return Err(MerkleError::DepthTooSmall(DEPTH));
605 }
606
607 Ok(LeafIndex { index: NodeIndex::new(DEPTH, value)? })
608 }
609
610 /// Returns the position of this leaf index within its depth layer.
611 pub fn position(&self) -> u64 {
612 self.index.position()
613 }
614}
615
616impl LeafIndex<SMT_MAX_DEPTH> {
617 /// Creates a new `LeafIndex` at the maximum supported depth without validation.
618 pub const fn new_max_depth(value: u64) -> Self {
619 LeafIndex {
620 index: NodeIndex::new_unchecked(SMT_MAX_DEPTH, value),
621 }
622 }
623}
624
625impl<const DEPTH: u8> From<LeafIndex<DEPTH>> for NodeIndex {
626 fn from(value: LeafIndex<DEPTH>) -> Self {
627 value.index
628 }
629}
630
631impl<const DEPTH: u8> TryFrom<NodeIndex> for LeafIndex<DEPTH> {
632 type Error = MerkleError;
633
634 fn try_from(node_index: NodeIndex) -> Result<Self, Self::Error> {
635 if node_index.depth() != DEPTH {
636 return Err(MerkleError::InvalidNodeIndexDepth {
637 expected: DEPTH,
638 provided: node_index.depth(),
639 });
640 }
641
642 Self::new(node_index.position())
643 }
644}
645
646impl<const DEPTH: u8> Serializable for LeafIndex<DEPTH> {
647 fn write_into<W: ByteWriter>(&self, target: &mut W) {
648 self.index.write_into(target);
649 }
650}
651
652impl<const DEPTH: u8> Deserializable for LeafIndex<DEPTH> {
653 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
654 // A `NodeIndex` is valid on its own terms without knowing `DEPTH`, so route through
655 // `TryFrom` to enforce that its depth matches this type's `DEPTH`.
656 let index: NodeIndex = source.read()?;
657
658 Self::try_from(index).map_err(|err| DeserializationError::InvalidValue(err.to_string()))
659 }
660}
661
662impl<const DEPTH: u8> Display for LeafIndex<DEPTH> {
663 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
664 write!(f, "DEPTH={}, position={}", DEPTH, self.position())
665 }
666}
667
668// MUTATIONS
669// ================================================================================================
670
671/// A change to an inner node of a sparse Merkle tree that hasn't yet been applied.
672/// [`MutationSet`] stores this type in relation to a [`NodeIndex`] to keep track of what changes
673/// need to occur at which node indices.
674#[derive(Debug, Clone, PartialEq, Eq)]
675pub enum NodeMutation {
676 /// Node needs to be removed.
677 Removal,
678 /// Node needs to be inserted.
679 Addition(InnerNode),
680}
681
682/// Represents a group of prospective mutations to a `SparseMerkleTree`, created by
683/// `SparseMerkleTree::compute_mutations()`, and that can be applied with
684/// `SparseMerkleTree::apply_mutations()`.
685#[derive(Debug, Clone, Default, PartialEq, Eq)]
686pub struct MutationSet<const DEPTH: u8, K: Eq + Hash, V> {
687 /// The root of the Merkle tree this MutationSet is for, recorded at the time
688 /// [`SparseMerkleTree::compute_mutations()`] was called. Exists to guard against applying
689 /// mutations to the wrong tree or applying stale mutations to a tree that has since changed.
690 old_root: Word,
691 /// The set of nodes that need to be removed or added. The "effective" node at an index is the
692 /// Merkle tree's existing node at that index, with the [`NodeMutation`] in this map at that
693 /// index overlaid, if any. Each [`NodeMutation::Addition`] corresponds to a
694 /// [`SparseMerkleTree::insert_inner_node()`] call, and each [`NodeMutation::Removal`]
695 /// corresponds to a [`SparseMerkleTree::remove_inner_node()`] call.
696 node_mutations: NodeMutations,
697 /// The set of top-level key-value pairs we're prospectively adding to the tree, including
698 /// adding empty values. The "effective" value for a key is the value in this Map, falling
699 /// back to the existing value in the Merkle tree. Each entry corresponds to a
700 /// [`SparseMerkleTree::insert_value()`] call.
701 new_pairs: Map<K, V>,
702 /// The calculated root for the Merkle tree, given these mutations. Publicly retrievable with
703 /// [`MutationSet::root()`]. Corresponds to a [`SparseMerkleTree::set_root()`]. call.
704 new_root: Word,
705}
706
707impl<const DEPTH: u8, K: Eq + Hash, V> MutationSet<DEPTH, K, V> {
708 /// Returns the SMT root that was calculated during `SparseMerkleTree::compute_mutations()`. See
709 /// that method for more information.
710 pub fn root(&self) -> Word {
711 self.new_root
712 }
713
714 /// Returns the SMT root before the mutations were applied.
715 pub fn old_root(&self) -> Word {
716 self.old_root
717 }
718
719 /// Returns the set of inner nodes that need to be removed or added.
720 pub fn node_mutations(&self) -> &NodeMutations {
721 &self.node_mutations
722 }
723
724 /// Returns the set of top-level key-value pairs that need to be added, updated or deleted
725 /// (i.e. set to `EMPTY_WORD`).
726 pub fn new_pairs(&self) -> &Map<K, V> {
727 &self.new_pairs
728 }
729
730 /// Returns `true` if the mutation set represents no changes to the tree, and `false` otherwise.
731 pub fn is_empty(&self) -> bool {
732 self.node_mutations.is_empty()
733 && self.new_pairs.is_empty()
734 && self.old_root == self.new_root
735 }
736
737 /// Creates a new mutation set from pre-computed components.
738 ///
739 /// This constructor performs no validation. The caller must ensure the components are
740 /// internally consistent, meaning that applying `node_mutations` and `new_pairs` to a tree
741 /// whose root is `old_root` yields a tree whose root is `new_root`. Intended for storage
742 /// backends that compute mutations from persisted tree data instead of an in-memory tree.
743 pub fn from_parts(
744 old_root: Word,
745 node_mutations: impl IntoIterator<Item = (NodeIndex, NodeMutation)>,
746 new_pairs: impl IntoIterator<Item = (K, V)>,
747 new_root: Word,
748 ) -> Self
749 where
750 K: Ord,
751 {
752 Self {
753 old_root,
754 node_mutations: node_mutations.into_iter().collect(),
755 new_pairs: new_pairs.into_iter().collect(),
756 new_root,
757 }
758 }
759}
760
761// SERIALIZATION
762// ================================================================================================
763
764impl Serializable for InnerNode {
765 fn write_into<W: ByteWriter>(&self, target: &mut W) {
766 target.write(self.left);
767 target.write(self.right);
768 }
769}
770
771impl Deserializable for InnerNode {
772 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
773 let left = source.read()?;
774 let right = source.read()?;
775
776 Ok(Self { left, right })
777 }
778}
779
780impl Serializable for NodeMutation {
781 fn write_into<W: ByteWriter>(&self, target: &mut W) {
782 match self {
783 NodeMutation::Removal => target.write_bool(false),
784 NodeMutation::Addition(inner_node) => {
785 target.write_bool(true);
786 inner_node.write_into(target);
787 },
788 }
789 }
790}
791
792impl Deserializable for NodeMutation {
793 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
794 if source.read_bool()? {
795 let inner_node = source.read()?;
796 return Ok(NodeMutation::Addition(inner_node));
797 }
798
799 Ok(NodeMutation::Removal)
800 }
801}
802
803impl<const DEPTH: u8, K: Serializable + Eq + Hash, V: Serializable> Serializable
804 for MutationSet<DEPTH, K, V>
805{
806 fn write_into<W: ByteWriter>(&self, target: &mut W) {
807 target.write(self.old_root);
808 target.write(self.new_root);
809
810 let inner_removals: Vec<_> = self
811 .node_mutations
812 .iter()
813 .filter(|(_, value)| matches!(value, NodeMutation::Removal))
814 .map(|(key, _)| key)
815 .collect();
816 let inner_additions: Vec<_> = self
817 .node_mutations
818 .iter()
819 .filter_map(|(key, value)| match value {
820 NodeMutation::Addition(node) => Some((key, node)),
821 _ => None,
822 })
823 .collect();
824
825 target.write(inner_removals);
826 target.write(inner_additions);
827
828 target.write_usize(self.new_pairs.len());
829 target.write_many(&self.new_pairs);
830 }
831}
832
833impl<const DEPTH: u8, K: Deserializable + Ord + Eq + Hash, V: Deserializable> Deserializable
834 for MutationSet<DEPTH, K, V>
835{
836 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
837 let old_root = source.read()?;
838 let new_root = source.read()?;
839
840 let inner_removals: Vec<NodeIndex> = source.read()?;
841 let inner_additions: Vec<(NodeIndex, InnerNode)> = source.read()?;
842
843 let node_mutations = NodeMutations::from_iter(
844 inner_removals.into_iter().map(|index| (index, NodeMutation::Removal)).chain(
845 inner_additions
846 .into_iter()
847 .map(|(index, node)| (index, NodeMutation::Addition(node))),
848 ),
849 );
850
851 let num_new_pairs = source.read_usize()?;
852 let new_pairs: Map<_, _> =
853 source.read_many_iter(num_new_pairs)?.collect::<Result<_, _>>()?;
854
855 Ok(Self {
856 old_root,
857 node_mutations,
858 new_pairs,
859 new_root,
860 })
861 }
862}
863
864// TESTS
865// ================================================================================================
866
867#[cfg(test)]
868mod tests {
869 use super::{LeafIndex, NodeIndex, SMT_MAX_DEPTH};
870 use crate::utils::{Deserializable, Serializable};
871
872 #[test]
873 fn leaf_index_read_from_rejects_depth_mismatch() {
874 // A depth-3 index is valid on its own terms, but wrong for a `LeafIndex<SMT_MAX_DEPTH>`.
875 let mismatched = NodeIndex::new(3, 5).unwrap();
876 assert!(LeafIndex::<SMT_MAX_DEPTH>::try_from(mismatched).is_err());
877
878 assert!(LeafIndex::<SMT_MAX_DEPTH>::read_from_bytes(&mismatched.to_bytes()).is_err());
879 }
880
881 #[test]
882 fn leaf_index_read_from_rejects_depth_below_minimum() {
883 assert!(LeafIndex::<0>::new(0).is_err());
884
885 let root = NodeIndex::new(0, 0).unwrap();
886 assert!(LeafIndex::<0>::read_from_bytes(&root.to_bytes()).is_err());
887 }
888
889 #[test]
890 fn leaf_index_round_trips_at_matching_depth() {
891 let leaf = LeafIndex::<SMT_MAX_DEPTH>::new(5).unwrap();
892
893 let decoded = LeafIndex::<SMT_MAX_DEPTH>::read_from_bytes(&leaf.to_bytes()).unwrap();
894
895 assert_eq!(leaf, decoded);
896 }
897}