miden_crypto/merkle/partial_mt/mod.rs
1use alloc::{
2 collections::{BTreeMap, BTreeSet},
3 string::String,
4 vec::Vec,
5};
6use core::fmt;
7
8use super::{
9 EMPTY_WORD, InnerNodeInfo, MerkleError, MerklePath, MerkleProof, NodeIndex, Poseidon2, Word,
10};
11use crate::utils::{
12 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, word_to_hex,
13};
14
15#[cfg(test)]
16mod tests;
17
18// CONSTANTS
19// ================================================================================================
20
21/// Index of the root node.
22const ROOT_INDEX: NodeIndex = NodeIndex::root();
23
24/// An Word consisting of 4 ZERO elements.
25const EMPTY_DIGEST: Word = EMPTY_WORD;
26
27// PARTIAL MERKLE TREE
28// ================================================================================================
29
30/// A partial Merkle tree with NodeIndex keys and 4-element [Word] leaf values. Partial Merkle
31/// Tree allows to create Merkle Tree by providing Merkle paths of different lengths.
32///
33/// The root of the tree is recomputed on each new leaf update.
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct PartialMerkleTree {
36 max_depth: u8,
37 nodes: BTreeMap<NodeIndex, Word>,
38 leaves: BTreeSet<NodeIndex>,
39}
40
41impl Default for PartialMerkleTree {
42 fn default() -> Self {
43 Self::new()
44 }
45}
46
47impl PartialMerkleTree {
48 // CONSTANTS
49 // --------------------------------------------------------------------------------------------
50
51 /// Minimum supported depth.
52 pub const MIN_DEPTH: u8 = 1;
53
54 /// Maximum supported depth.
55 pub const MAX_DEPTH: u8 = 64;
56
57 // CONSTRUCTORS
58 // --------------------------------------------------------------------------------------------
59
60 /// Returns a new empty [PartialMerkleTree].
61 pub fn new() -> Self {
62 PartialMerkleTree {
63 max_depth: 0,
64 nodes: BTreeMap::new(),
65 leaves: BTreeSet::new(),
66 }
67 }
68
69 /// Appends the provided paths iterator into the set.
70 ///
71 /// Analogous to [Self::add_path].
72 pub fn with_paths<I>(paths: I) -> Result<Self, MerkleError>
73 where
74 I: IntoIterator<Item = (u64, Word, MerklePath)>,
75 {
76 // create an empty tree
77 let tree = PartialMerkleTree::new();
78
79 paths.into_iter().try_fold(tree, |mut tree, (index, value, path)| {
80 tree.add_path(index, value, path)?;
81 Ok(tree)
82 })
83 }
84
85 /// Returns a new [PartialMerkleTree] instantiated with leaves map as specified by the provided
86 /// entries.
87 ///
88 /// # Errors
89 /// Returns an error if:
90 /// - Any entry has depth 0 or is greater than 64.
91 /// - The number of entries exceeds the maximum tree capacity, that is 2^{depth}.
92 /// - The provided entries contain an insufficient set of nodes.
93 /// - Any entry is an ancestor of another entry (creates hash ambiguity).
94 ///
95 /// An empty input returns an empty tree.
96 pub fn with_leaves<R, I>(entries: R) -> Result<Self, MerkleError>
97 where
98 R: IntoIterator<IntoIter = I>,
99 I: Iterator<Item = (NodeIndex, Word)> + ExactSizeIterator,
100 {
101 let entries = entries.into_iter();
102 if entries.len() == 0 {
103 return Ok(PartialMerkleTree::new());
104 }
105
106 let mut layers: BTreeMap<u8, Vec<u64>> = BTreeMap::new();
107 let mut leaves = BTreeSet::new();
108 let mut nodes = BTreeMap::new();
109
110 // add data to the leaves and nodes maps and also fill layers map, where the key is the
111 // depth of the node and value is its index.
112 for (node_index, hash) in entries {
113 Self::check_depth(node_index.depth())?;
114 leaves.insert(node_index);
115 nodes.insert(node_index, hash);
116 layers
117 .entry(node_index.depth())
118 .and_modify(|layer_vec| layer_vec.push(node_index.position()))
119 .or_insert(vec![node_index.position()]);
120 }
121
122 // Get maximum depth
123 let max_depth = *layers.keys().next_back().unwrap_or(&0);
124
125 // fill layers without nodes with empty vector
126 for depth in 0..max_depth {
127 layers.entry(depth).or_default();
128 }
129
130 let mut layer_iter = layers.into_values().rev();
131 let mut parent_layer = layer_iter.next().unwrap();
132 let mut current_layer;
133
134 for depth in (1..max_depth + 1).rev() {
135 // set current_layer = parent_layer and parent_layer = layer_iter.next()
136 current_layer = layer_iter.next().unwrap();
137 core::mem::swap(&mut current_layer, &mut parent_layer);
138
139 for index_value in current_layer {
140 // get the parent node index
141 let parent_node = NodeIndex::new(depth - 1, index_value / 2)?;
142
143 // If parent already exists, check if it's user-provided (invalid) or computed
144 // (skip)
145 if parent_layer.contains(&parent_node.position()) {
146 // If the parent was provided as a leaf, that's invalid - we can't have both
147 // a node and its descendant in the input set.
148 if leaves.contains(&parent_node) {
149 return Err(MerkleError::EntryIsNotLeaf { node: parent_node });
150 }
151 continue;
152 }
153
154 // create current node index
155 let index = NodeIndex::new(depth, index_value)?;
156
157 // get hash of the current node
158 let node = nodes.get(&index).ok_or(MerkleError::NodeIndexNotFoundInTree(index))?;
159 // get hash of the sibling node
160 let sibling = nodes
161 .get(&index.sibling())
162 .ok_or(MerkleError::NodeIndexNotFoundInTree(index.sibling()))?;
163 // get parent hash
164 let parent = Poseidon2::merge(&index.build_node(*node, *sibling));
165
166 // add index value of the calculated node to the parents layer
167 parent_layer.push(parent_node.position());
168 // add index and hash to the nodes map
169 nodes.insert(parent_node, parent);
170 }
171 }
172
173 Ok(PartialMerkleTree { max_depth, nodes, leaves })
174 }
175
176 // PUBLIC ACCESSORS
177 // --------------------------------------------------------------------------------------------
178
179 /// Returns the root of this Merkle tree.
180 pub fn root(&self) -> Word {
181 self.nodes.get(&ROOT_INDEX).cloned().unwrap_or(EMPTY_DIGEST)
182 }
183
184 /// Returns the depth of this Merkle tree.
185 pub fn max_depth(&self) -> u8 {
186 self.max_depth
187 }
188
189 /// Returns a node at the specified NodeIndex.
190 ///
191 /// # Errors
192 /// Returns an error if the specified NodeIndex is not contained in the nodes map.
193 pub fn get_node(&self, index: NodeIndex) -> Result<Word, MerkleError> {
194 self.nodes
195 .get(&index)
196 .ok_or(MerkleError::NodeIndexNotFoundInTree(index))
197 .copied()
198 }
199
200 /// Returns true if provided index contains in the leaves set, false otherwise.
201 pub fn is_leaf(&self, index: NodeIndex) -> bool {
202 self.leaves.contains(&index)
203 }
204
205 /// Returns a vector of paths from every leaf to the root.
206 pub fn to_paths(&self) -> Vec<(NodeIndex, MerkleProof)> {
207 let mut paths = Vec::new();
208 self.leaves.iter().for_each(|&leaf| {
209 paths.push((
210 leaf,
211 MerkleProof {
212 value: self.get_node(leaf).expect("Failed to get leaf node"),
213 path: self.get_path(leaf).expect("Failed to get path"),
214 },
215 ));
216 });
217 paths
218 }
219
220 /// Returns a Merkle path from the node at the specified index to the root.
221 ///
222 /// The node itself is not included in the path.
223 ///
224 /// # Errors
225 /// Returns an error if:
226 /// - the specified index has depth set to 0 or the depth is greater than the depth of this
227 /// Merkle tree.
228 /// - the specified index is not contained in the nodes map.
229 pub fn get_path(&self, mut index: NodeIndex) -> Result<MerklePath, MerkleError> {
230 if index.is_root() {
231 return Err(MerkleError::DepthTooSmall(index.depth()));
232 } else if index.depth() > self.max_depth() {
233 return Err(MerkleError::DepthTooBig(index.depth() as u64));
234 }
235
236 if !self.nodes.contains_key(&index) {
237 return Err(MerkleError::NodeIndexNotFoundInTree(index));
238 }
239
240 let mut path = Vec::new();
241 for _ in 0..index.depth() {
242 let sibling_index = index.sibling();
243 index.move_up();
244 let sibling =
245 self.nodes.get(&sibling_index).cloned().expect("Sibling node not in the map");
246 path.push(sibling);
247 }
248 Ok(MerklePath::new(path))
249 }
250
251 // ITERATORS
252 // --------------------------------------------------------------------------------------------
253
254 /// Returns an iterator over the leaves of this [PartialMerkleTree].
255 pub fn leaves(&self) -> impl Iterator<Item = (NodeIndex, Word)> + '_ {
256 self.leaves.iter().map(|&leaf| {
257 (
258 leaf,
259 self.get_node(leaf)
260 .unwrap_or_else(|_| panic!("Leaf with {leaf} is not in the nodes map")),
261 )
262 })
263 }
264
265 /// Returns an iterator over the inner nodes of this Merkle tree.
266 pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
267 let inner_nodes = self.nodes.iter().filter(|(index, _)| !self.leaves.contains(index));
268 inner_nodes.map(|(index, digest)| {
269 let left_hash =
270 self.nodes.get(&index.left_child()).expect("Failed to get left child hash");
271 let right_hash =
272 self.nodes.get(&index.right_child()).expect("Failed to get right child hash");
273 InnerNodeInfo {
274 value: *digest,
275 left: *left_hash,
276 right: *right_hash,
277 }
278 })
279 }
280
281 // STATE MUTATORS
282 // --------------------------------------------------------------------------------------------
283
284 /// Adds the nodes of the specified Merkle path to this [PartialMerkleTree]. The `index_value`
285 /// and `value` parameters specify the leaf node at which the path starts.
286 ///
287 /// # Errors
288 /// Returns an error if:
289 /// - The depth of the specified node_index is greater than 64 or smaller than 1.
290 /// - The specified path is not consistent with other paths in the set (i.e., resolves to a
291 /// different root).
292 pub fn add_path(
293 &mut self,
294 index_value: u64,
295 value: Word,
296 path: MerklePath,
297 ) -> Result<(), MerkleError> {
298 let index_value = NodeIndex::new(path.len() as u8, index_value)?;
299
300 Self::check_depth(index_value.depth())?;
301 self.update_depth(index_value.depth());
302
303 // add provided node and its sibling to the leaves set
304 self.leaves.insert(index_value);
305 let sibling_node_index = index_value.sibling();
306 self.leaves.insert(sibling_node_index);
307
308 // add provided node and its sibling to the nodes map
309 self.nodes.insert(index_value, value);
310 self.nodes.insert(sibling_node_index, path[0]);
311
312 // traverse to the root, updating the nodes
313 let mut index_value = index_value;
314 let node = Poseidon2::merge(&index_value.build_node(value, path[0]));
315 let root = path.iter().skip(1).copied().fold(node, |node, hash| {
316 index_value.move_up();
317 // insert calculated node to the nodes map
318 self.nodes.insert(index_value, node);
319
320 // if the calculated node was a leaf, remove it from leaves set.
321 self.leaves.remove(&index_value);
322
323 let sibling_node = index_value.sibling();
324
325 // Insert node from Merkle path to the nodes map. This sibling node becomes a leaf only
326 // if it is a new node (it wasn't in nodes map).
327 // Node can be in 3 states: internal node, leaf of the tree and not a tree node at all.
328 // - Internal node can only stay in this state -- addition of a new path can't make it
329 // a leaf or remove it from the tree.
330 // - Leaf node can stay in the same state (remain a leaf) or can become an internal
331 // node. In the first case we don't need to do anything, and the second case is handled
332 // by the call of `self.leaves.remove(&index_value);`
333 // - New node can be a calculated node or a "sibling" node from a Merkle Path:
334 // --- Calculated node, obviously, never can be a leaf.
335 // --- Sibling node can be only a leaf, because otherwise it is not a new node.
336 if self.nodes.insert(sibling_node, hash).is_none() {
337 self.leaves.insert(sibling_node);
338 }
339
340 Poseidon2::merge(&index_value.build_node(node, hash))
341 });
342
343 // if the path set is empty (the root is all ZEROs), set the root to the root of the added
344 // path; otherwise, the root of the added path must be identical to the current root
345 if self.root() == EMPTY_DIGEST {
346 self.nodes.insert(ROOT_INDEX, root);
347 } else if self.root() != root {
348 return Err(MerkleError::ConflictingRoots {
349 expected_root: self.root(),
350 actual_root: root,
351 });
352 }
353
354 Ok(())
355 }
356
357 /// Updates value of the leaf at the specified index returning the old leaf value.
358 ///
359 /// By default the specified index is assumed to belong to the deepest layer. If the considered
360 /// node does not belong to the tree, the first node on the way to the root will be changed.
361 ///
362 /// This also recomputes all hashes between the leaf and the root, updating the root itself.
363 ///
364 /// # Errors
365 /// Returns an error if:
366 /// - No entry exists at the specified index.
367 /// - The specified index is greater than the maximum number of nodes on the deepest layer.
368 pub fn update_leaf(&mut self, index: u64, value: Word) -> Result<Word, MerkleError> {
369 let mut node_index = NodeIndex::new(self.max_depth(), index)?;
370
371 // proceed to the leaf
372 for _ in 0..node_index.depth() {
373 if !self.leaves.contains(&node_index) {
374 node_index.move_up();
375 }
376 }
377
378 // add node value to the nodes Map
379 let old_value = self
380 .nodes
381 .insert(node_index, value)
382 .ok_or(MerkleError::NodeIndexNotFoundInTree(node_index))?;
383
384 // if the old value and new value are the same, there is nothing to update
385 if value == old_value {
386 return Ok(old_value);
387 }
388
389 let mut value = value;
390 for _ in 0..node_index.depth() {
391 let sibling = self.nodes.get(&node_index.sibling()).expect("sibling should exist");
392 value = Poseidon2::merge(&node_index.build_node(value, *sibling));
393 node_index.move_up();
394 self.nodes.insert(node_index, value);
395 }
396
397 Ok(old_value)
398 }
399
400 // UTILITY FUNCTIONS
401 // --------------------------------------------------------------------------------------------
402
403 /// Utility to visualize a [PartialMerkleTree] in text.
404 pub fn print(&self) -> Result<String, fmt::Error> {
405 let indent = " ";
406 let mut s = String::new();
407 s.push_str("root: ");
408 s.push_str(&word_to_hex(&self.root())?);
409 s.push('\n');
410 for d in 1..=self.max_depth() {
411 let entries = 2u64.pow(d.into());
412 for i in 0..entries {
413 let index = NodeIndex::new(d, i).expect("The index must always be valid");
414 let node = self.get_node(index);
415 let node = match node {
416 Err(_) => continue,
417 Ok(node) => node,
418 };
419
420 for _ in 0..d {
421 s.push_str(indent);
422 }
423 s.push_str(&format!("({}, {}): ", index.depth(), index.position()));
424 s.push_str(&word_to_hex(&node)?);
425 s.push('\n');
426 }
427 }
428
429 Ok(s)
430 }
431
432 // HELPER METHODS
433 // --------------------------------------------------------------------------------------------
434
435 /// Updates depth value with the maximum of current and provided depth.
436 fn update_depth(&mut self, new_depth: u8) {
437 self.max_depth = new_depth.max(self.max_depth);
438 }
439
440 /// Returns an error if the depth is 0 or is greater than 64.
441 fn check_depth(depth: u8) -> Result<(), MerkleError> {
442 // validate the range of the depth.
443 if depth < Self::MIN_DEPTH {
444 return Err(MerkleError::DepthTooSmall(depth));
445 } else if Self::MAX_DEPTH < depth {
446 return Err(MerkleError::DepthTooBig(depth as u64));
447 }
448 Ok(())
449 }
450}
451
452// SERIALIZATION
453// ================================================================================================
454
455impl Serializable for PartialMerkleTree {
456 fn write_into<W: ByteWriter>(&self, target: &mut W) {
457 // write leaf nodes
458 target.write_u64(self.leaves.len() as u64);
459 for leaf_index in self.leaves.iter() {
460 leaf_index.write_into(target);
461 self.get_node(*leaf_index).expect("Leaf hash not found").write_into(target);
462 }
463 }
464}
465
466impl Deserializable for PartialMerkleTree {
467 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
468 let leaves_len_u64 = source.read_u64()?;
469 let leaves_len = usize::try_from(leaves_len_u64).map_err(|_| {
470 DeserializationError::InvalidValue("PartialMerkleTree leaf count too large".into())
471 })?;
472
473 // Use read_many_iter to avoid eager allocation and respect BudgetedReader limits
474 let leaf_nodes: Vec<(NodeIndex, Word)> =
475 source.read_many_iter(leaves_len)?.collect::<Result<_, _>>()?;
476
477 let pmt = PartialMerkleTree::with_leaves(leaf_nodes).map_err(|_| {
478 DeserializationError::InvalidValue("Invalid data for PartialMerkleTree creation".into())
479 })?;
480
481 Ok(pmt)
482 }
483
484 /// Minimum serialized size: u64 length prefix (0 entries).
485 fn min_serialized_size() -> usize {
486 8
487 }
488}