miden_crypto/merkle/partial_mt/
mod.rs1use alloc::{
2 collections::{BTreeMap, BTreeSet},
3 string::String,
4 vec::Vec,
5};
6use core::fmt;
7
8use super::{
9 EMPTY_WORD, Eidos, InnerNodeInfo, MerkleError, MerklePath, MerkleProof, NodeIndex, Word,
10};
11use crate::utils::{
12 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, word_to_hex,
13};
14
15#[cfg(test)]
16mod tests;
17
18#[cfg(any(test, feature = "arbitrary"))]
22mod arbitrary {
23 extern crate alloc;
24
25 use alloc::vec::Vec;
26
27 use proptest::prelude::*;
28
29 use super::PartialMerkleTree;
30 use crate::{
31 Word,
32 merkle::{MerklePath, MerkleTree, NodeIndex},
33 };
34
35 impl Arbitrary for PartialMerkleTree {
36 type Parameters = ();
37 type Strategy = BoxedStrategy<Self>;
38
39 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
40 prop_oneof![paths_from_real_tree().boxed(), single_deep_path().boxed()].boxed()
48 }
49 }
50
51 fn paths_from_real_tree() -> impl Strategy<Value = PartialMerkleTree> {
52 (1u8..=6)
53 .prop_flat_map(|depth| {
54 let count = 1usize << depth;
55 (
56 Just(depth),
57 proptest::collection::vec(any::<Word>(), count),
58 proptest::collection::vec(any::<bool>(), count),
59 )
60 })
61 .prop_map(|(depth, leaves, track_mask)| {
62 let tree = MerkleTree::new(&leaves).expect("leaf count is a power of two >= 2");
63 let paths: Vec<(u64, Word, MerklePath)> = track_mask
64 .iter()
65 .enumerate()
66 .filter(|(_, tracked)| **tracked)
67 .map(|(pos, _)| {
68 let node_index =
69 NodeIndex::new(depth, pos as u64).expect("position fits the depth");
70 let path = tree.get_path(node_index).expect("position within the tree");
71 (pos as u64, leaves[pos], path)
72 })
73 .collect();
74 PartialMerkleTree::with_paths(paths)
75 .expect("paths from one tree share a depth and no ancestor relation")
76 })
77 }
78
79 fn single_deep_path() -> impl Strategy<Value = PartialMerkleTree> {
80 (7u8..=64, any::<u64>(), any::<Word>())
81 .prop_flat_map(|(depth, index, value)| {
82 let mask = if depth == 64 { u64::MAX } else { (1u64 << depth) - 1 };
83 (
84 Just(depth),
85 Just(value),
86 Just(index & mask),
87 proptest::collection::vec(any::<Word>(), depth as usize),
88 )
89 })
90 .prop_map(|(_depth, value, index, path_nodes)| {
91 let path = MerklePath::new(path_nodes);
92 PartialMerkleTree::with_paths([(index, value, path)])
93 .expect("a single path is always a valid partial tree")
94 })
95 }
96}
97
98const ROOT_INDEX: NodeIndex = NodeIndex::root();
103
104const EMPTY_DIGEST: Word = EMPTY_WORD;
106
107#[derive(Debug, Clone, PartialEq, Eq)]
115#[cfg_attr(
116 all(feature = "arbitrary", test),
117 miden_test_serialization_macros::serialization_test
118)]
119pub struct PartialMerkleTree {
120 max_depth: u8,
121 nodes: BTreeMap<NodeIndex, Word>,
122 leaves: BTreeSet<NodeIndex>,
123}
124
125impl Default for PartialMerkleTree {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
131impl PartialMerkleTree {
132 pub const MIN_DEPTH: u8 = 1;
137
138 pub const MAX_DEPTH: u8 = 64;
140
141 pub fn new() -> Self {
146 PartialMerkleTree {
147 max_depth: 0,
148 nodes: BTreeMap::new(),
149 leaves: BTreeSet::new(),
150 }
151 }
152
153 pub fn with_paths<I>(paths: I) -> Result<Self, MerkleError>
157 where
158 I: IntoIterator<Item = (u64, Word, MerklePath)>,
159 {
160 let tree = PartialMerkleTree::new();
162
163 paths.into_iter().try_fold(tree, |mut tree, (index, value, path)| {
164 tree.add_path(index, value, path)?;
165 Ok(tree)
166 })
167 }
168
169 pub fn with_leaves<R, I>(entries: R) -> Result<Self, MerkleError>
181 where
182 R: IntoIterator<IntoIter = I>,
183 I: Iterator<Item = (NodeIndex, Word)> + ExactSizeIterator,
184 {
185 let entries = entries.into_iter();
186 if entries.len() == 0 {
187 return Ok(PartialMerkleTree::new());
188 }
189
190 let mut layers: BTreeMap<u8, Vec<u64>> = BTreeMap::new();
191 let mut leaves = BTreeSet::new();
192 let mut nodes = BTreeMap::new();
193
194 for (node_index, hash) in entries {
197 Self::check_depth(node_index.depth())?;
198 leaves.insert(node_index);
199 nodes.insert(node_index, hash);
200 layers
201 .entry(node_index.depth())
202 .and_modify(|layer_vec| layer_vec.push(node_index.position()))
203 .or_insert(vec![node_index.position()]);
204 }
205
206 let max_depth = *layers.keys().next_back().unwrap_or(&0);
208
209 for depth in 0..max_depth {
211 layers.entry(depth).or_default();
212 }
213
214 let mut layer_iter = layers.into_values().rev();
215 let mut parent_layer = layer_iter.next().unwrap();
216 let mut current_layer;
217
218 for depth in (1..max_depth + 1).rev() {
219 current_layer = layer_iter.next().unwrap();
221 core::mem::swap(&mut current_layer, &mut parent_layer);
222
223 current_layer.sort_unstable();
226 current_layer.dedup_by_key(|position| *position / 2);
227
228 for index_value in current_layer {
229 let parent_node = NodeIndex::new(depth - 1, index_value / 2)?;
231
232 if leaves.contains(&parent_node) {
234 return Err(MerkleError::EntryIsNotLeaf { node: parent_node });
235 }
236
237 let index = NodeIndex::new(depth, index_value)?;
239
240 let node = nodes.get(&index).ok_or(MerkleError::NodeIndexNotFoundInTree(index))?;
242 let sibling = nodes
244 .get(&index.sibling())
245 .ok_or(MerkleError::NodeIndexNotFoundInTree(index.sibling()))?;
246 let parent = Eidos::merge(&index.build_node(*node, *sibling));
248
249 parent_layer.push(parent_node.position());
251 nodes.insert(parent_node, parent);
253 }
254 }
255
256 Ok(PartialMerkleTree { max_depth, nodes, leaves })
257 }
258
259 pub fn root(&self) -> Word {
264 self.nodes.get(&ROOT_INDEX).cloned().unwrap_or(EMPTY_DIGEST)
265 }
266
267 pub fn max_depth(&self) -> u8 {
269 self.max_depth
270 }
271
272 pub fn get_node(&self, index: NodeIndex) -> Result<Word, MerkleError> {
277 self.nodes
278 .get(&index)
279 .ok_or(MerkleError::NodeIndexNotFoundInTree(index))
280 .copied()
281 }
282
283 pub fn is_leaf(&self, index: NodeIndex) -> bool {
285 self.leaves.contains(&index)
286 }
287
288 pub fn to_paths(&self) -> Vec<(NodeIndex, MerkleProof)> {
290 let mut paths = Vec::new();
291 self.leaves.iter().for_each(|&leaf| {
292 paths.push((
293 leaf,
294 MerkleProof {
295 value: self.get_node(leaf).expect("Failed to get leaf node"),
296 path: self.get_path(leaf).expect("Failed to get path"),
297 },
298 ));
299 });
300 paths
301 }
302
303 pub fn get_path(&self, mut index: NodeIndex) -> Result<MerklePath, MerkleError> {
313 if index.is_root() {
314 return Err(MerkleError::DepthTooSmall(index.depth()));
315 } else if index.depth() > self.max_depth() {
316 return Err(MerkleError::DepthTooBig(index.depth() as u64));
317 }
318
319 if !self.nodes.contains_key(&index) {
320 return Err(MerkleError::NodeIndexNotFoundInTree(index));
321 }
322
323 let mut path = Vec::new();
324 for _ in 0..index.depth() {
325 let sibling_index = index.sibling();
326 index.move_up();
327 let sibling =
328 self.nodes.get(&sibling_index).cloned().expect("Sibling node not in the map");
329 path.push(sibling);
330 }
331 Ok(MerklePath::new(path))
332 }
333
334 pub fn leaves(&self) -> impl Iterator<Item = (NodeIndex, Word)> + '_ {
339 self.leaves.iter().map(|&leaf| {
340 (
341 leaf,
342 self.get_node(leaf)
343 .unwrap_or_else(|_| panic!("Leaf with {leaf} is not in the nodes map")),
344 )
345 })
346 }
347
348 pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
350 let inner_nodes = self.nodes.iter().filter(|(index, _)| !self.leaves.contains(index));
351 inner_nodes.map(|(index, digest)| {
352 let left_hash =
353 self.nodes.get(&index.left_child()).expect("Failed to get left child hash");
354 let right_hash =
355 self.nodes.get(&index.right_child()).expect("Failed to get right child hash");
356 InnerNodeInfo {
357 value: *digest,
358 left: *left_hash,
359 right: *right_hash,
360 }
361 })
362 }
363
364 pub fn add_path(
376 &mut self,
377 index_value: u64,
378 value: Word,
379 path: MerklePath,
380 ) -> Result<(), MerkleError> {
381 let index_value = NodeIndex::new(path.len() as u8, index_value)?;
382
383 Self::check_depth(index_value.depth())?;
384 self.update_depth(index_value.depth());
385
386 self.leaves.insert(index_value);
388 let sibling_node_index = index_value.sibling();
389 self.leaves.insert(sibling_node_index);
390
391 self.nodes.insert(index_value, value);
393 self.nodes.insert(sibling_node_index, path[0]);
394
395 let mut index_value = index_value;
397 let node = Eidos::merge(&index_value.build_node(value, path[0]));
398 let root = path.iter().skip(1).copied().fold(node, |node, hash| {
399 index_value.move_up();
400 self.nodes.insert(index_value, node);
402
403 self.leaves.remove(&index_value);
405
406 let sibling_node = index_value.sibling();
407
408 if self.nodes.insert(sibling_node, hash).is_none() {
420 self.leaves.insert(sibling_node);
421 }
422
423 Eidos::merge(&index_value.build_node(node, hash))
424 });
425
426 if self.root() == EMPTY_DIGEST {
429 self.nodes.insert(ROOT_INDEX, root);
430 } else if self.root() != root {
431 return Err(MerkleError::ConflictingRoots {
432 expected_root: self.root(),
433 actual_root: root,
434 });
435 }
436
437 Ok(())
438 }
439
440 pub fn update_leaf(&mut self, index: u64, value: Word) -> Result<Word, MerkleError> {
452 let mut node_index = NodeIndex::new(self.max_depth(), index)?;
453
454 for _ in 0..node_index.depth() {
456 if !self.leaves.contains(&node_index) {
457 node_index.move_up();
458 }
459 }
460
461 let old_value = self
463 .nodes
464 .insert(node_index, value)
465 .ok_or(MerkleError::NodeIndexNotFoundInTree(node_index))?;
466
467 if value == old_value {
469 return Ok(old_value);
470 }
471
472 let mut value = value;
473 for _ in 0..node_index.depth() {
474 let sibling = self.nodes.get(&node_index.sibling()).expect("sibling should exist");
475 value = Eidos::merge(&node_index.build_node(value, *sibling));
476 node_index.move_up();
477 self.nodes.insert(node_index, value);
478 }
479
480 Ok(old_value)
481 }
482
483 pub fn print(&self) -> Result<String, fmt::Error> {
488 let indent = " ";
489 let mut s = String::new();
490 s.push_str("root: ");
491 s.push_str(&word_to_hex(&self.root())?);
492 s.push('\n');
493 for d in 1..=self.max_depth() {
494 let entries = 2u64.pow(d.into());
495 for i in 0..entries {
496 let index = NodeIndex::new(d, i).expect("The index must always be valid");
497 let node = self.get_node(index);
498 let node = match node {
499 Err(_) => continue,
500 Ok(node) => node,
501 };
502
503 for _ in 0..d {
504 s.push_str(indent);
505 }
506 s.push_str(&format!("({}, {}): ", index.depth(), index.position()));
507 s.push_str(&word_to_hex(&node)?);
508 s.push('\n');
509 }
510 }
511
512 Ok(s)
513 }
514
515 fn update_depth(&mut self, new_depth: u8) {
520 self.max_depth = new_depth.max(self.max_depth);
521 }
522
523 fn check_depth(depth: u8) -> Result<(), MerkleError> {
525 if depth < Self::MIN_DEPTH {
527 return Err(MerkleError::DepthTooSmall(depth));
528 } else if Self::MAX_DEPTH < depth {
529 return Err(MerkleError::DepthTooBig(depth as u64));
530 }
531 Ok(())
532 }
533}
534
535impl Serializable for PartialMerkleTree {
539 fn write_into<W: ByteWriter>(&self, target: &mut W) {
540 target.write_u64(self.leaves.len() as u64);
542 for leaf_index in self.leaves.iter() {
543 leaf_index.write_into(target);
544 self.get_node(*leaf_index).expect("Leaf hash not found").write_into(target);
545 }
546 }
547}
548
549impl Deserializable for PartialMerkleTree {
550 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
551 let leaves_len_u64 = source.read_u64()?;
552 let leaves_len = usize::try_from(leaves_len_u64).map_err(|_| {
553 DeserializationError::InvalidValue("PartialMerkleTree leaf count too large".into())
554 })?;
555
556 let leaf_nodes: Vec<(NodeIndex, Word)> =
558 source.read_many_iter(leaves_len)?.collect::<Result<_, _>>()?;
559
560 let pmt = PartialMerkleTree::with_leaves(leaf_nodes).map_err(|_| {
561 DeserializationError::InvalidValue("Invalid data for PartialMerkleTree creation".into())
562 })?;
563
564 Ok(pmt)
565 }
566
567 fn min_serialized_size() -> usize {
569 8
570 }
571}