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