miden-crypto/src/merkle/mmr/tests.rs
src/merkle/mmr/tests.rsRaw
1use alloc::vec::Vec;
2
3use super::{
4 super::{InnerNodeInfo, Rpo256, RpoDigest},
5 bit::TrueBitPositionIterator,
6 full::high_bitmask,
7 leaf_to_corresponding_tree, nodes_in_forest, Mmr, MmrPeaks, PartialMmr,
8};
9use crate::{
10 merkle::{int_to_node, InOrderIndex, MerklePath, MerkleTree, MmrProof, NodeIndex},
11 Felt, Word,
12};
13
14#[test]
15fn test_position_equal_or_higher_than_leafs_is_never_contained() {
16 let empty_forest = 0;
17 for pos in 1..1024 {
18 // pos is index, 0 based
19 // tree is a length counter, 1 based
20 // so a valid pos is always smaller, not equal, to tree
21 assert_eq!(leaf_to_corresponding_tree(pos, pos), None);
22 assert_eq!(leaf_to_corresponding_tree(pos, pos - 1), None);
23 // and empty forest has no trees, so no position is valid
24 assert_eq!(leaf_to_corresponding_tree(pos, empty_forest), None);
25 }
26}
27
28#[test]
29fn test_position_zero_is_always_contained_by_the_highest_tree() {
30 for leaves in 1..1024usize {
31 let tree = leaves.ilog2();
32 assert_eq!(leaf_to_corresponding_tree(0, leaves), Some(tree));
33 }
34}
35
36#[test]
37fn test_leaf_to_corresponding_tree() {
38 assert_eq!(leaf_to_corresponding_tree(0, 0b0001), Some(0));
39 assert_eq!(leaf_to_corresponding_tree(0, 0b0010), Some(1));
40 assert_eq!(leaf_to_corresponding_tree(0, 0b0011), Some(1));
41 assert_eq!(leaf_to_corresponding_tree(0, 0b1011), Some(3));
42
43 // position one is always owned by the left-most tree
44 assert_eq!(leaf_to_corresponding_tree(1, 0b0010), Some(1));
45 assert_eq!(leaf_to_corresponding_tree(1, 0b0011), Some(1));
46 assert_eq!(leaf_to_corresponding_tree(1, 0b1011), Some(3));
47
48 // position two starts as its own root, and then it is merged with the left-most tree
49 assert_eq!(leaf_to_corresponding_tree(2, 0b0011), Some(0));
50 assert_eq!(leaf_to_corresponding_tree(2, 0b0100), Some(2));
51 assert_eq!(leaf_to_corresponding_tree(2, 0b1011), Some(3));
52
53 // position tree is merged on the left-most tree
54 assert_eq!(leaf_to_corresponding_tree(3, 0b0011), None);
55 assert_eq!(leaf_to_corresponding_tree(3, 0b0100), Some(2));
56 assert_eq!(leaf_to_corresponding_tree(3, 0b1011), Some(3));
57
58 assert_eq!(leaf_to_corresponding_tree(4, 0b0101), Some(0));
59 assert_eq!(leaf_to_corresponding_tree(4, 0b0110), Some(1));
60 assert_eq!(leaf_to_corresponding_tree(4, 0b0111), Some(1));
61 assert_eq!(leaf_to_corresponding_tree(4, 0b1000), Some(3));
62
63 assert_eq!(leaf_to_corresponding_tree(12, 0b01101), Some(0));
64 assert_eq!(leaf_to_corresponding_tree(12, 0b01110), Some(1));
65 assert_eq!(leaf_to_corresponding_tree(12, 0b01111), Some(1));
66 assert_eq!(leaf_to_corresponding_tree(12, 0b10000), Some(4));
67}
68
69#[test]
70fn test_high_bitmask() {
71 assert_eq!(high_bitmask(0), usize::MAX);
72 assert_eq!(high_bitmask(1), usize::MAX << 1);
73 assert_eq!(high_bitmask(usize::BITS - 2), 0b11usize.rotate_right(2));
74 assert_eq!(high_bitmask(usize::BITS - 1), 0b1usize.rotate_right(1));
75 assert_eq!(high_bitmask(usize::BITS), 0, "overflow should be handled");
76}
77
78#[test]
79fn test_nodes_in_forest() {
80 assert_eq!(nodes_in_forest(0b0000), 0);
81 assert_eq!(nodes_in_forest(0b0001), 1);
82 assert_eq!(nodes_in_forest(0b0010), 3);
83 assert_eq!(nodes_in_forest(0b0011), 4);
84 assert_eq!(nodes_in_forest(0b0100), 7);
85 assert_eq!(nodes_in_forest(0b0101), 8);
86 assert_eq!(nodes_in_forest(0b0110), 10);
87 assert_eq!(nodes_in_forest(0b0111), 11);
88 assert_eq!(nodes_in_forest(0b1000), 15);
89 assert_eq!(nodes_in_forest(0b1001), 16);
90 assert_eq!(nodes_in_forest(0b1010), 18);
91 assert_eq!(nodes_in_forest(0b1011), 19);
92}
93
94#[test]
95fn test_nodes_in_forest_single_bit() {
96 assert_eq!(nodes_in_forest(2usize.pow(0)), 2usize.pow(1) - 1);
97 assert_eq!(nodes_in_forest(2usize.pow(1)), 2usize.pow(2) - 1);
98 assert_eq!(nodes_in_forest(2usize.pow(2)), 2usize.pow(3) - 1);
99 assert_eq!(nodes_in_forest(2usize.pow(3)), 2usize.pow(4) - 1);
100
101 for bit in 0..(usize::BITS - 1) {
102 let size = 2usize.pow(bit + 1) - 1;
103 assert_eq!(nodes_in_forest(1usize << bit), size);
104 }
105}
106
107const LEAVES: [RpoDigest; 7] = [
108 int_to_node(0),
109 int_to_node(1),
110 int_to_node(2),
111 int_to_node(3),
112 int_to_node(4),
113 int_to_node(5),
114 int_to_node(6),
115];
116
117#[test]
118fn test_mmr_simple() {
119 let mut postorder = vec![
120 LEAVES[0],
121 LEAVES[1],
122 merge(LEAVES[0], LEAVES[1]),
123 LEAVES[2],
124 LEAVES[3],
125 merge(LEAVES[2], LEAVES[3]),
126 ];
127 postorder.push(merge(postorder[2], postorder[5]));
128 postorder.push(LEAVES[4]);
129 postorder.push(LEAVES[5]);
130 postorder.push(merge(LEAVES[4], LEAVES[5]));
131 postorder.push(LEAVES[6]);
132
133 let mut mmr = Mmr::new();
134 assert_eq!(mmr.forest(), 0);
135 assert_eq!(mmr.nodes.len(), 0);
136
137 mmr.add(LEAVES[0]);
138 assert_eq!(mmr.forest(), 1);
139 assert_eq!(mmr.nodes.len(), 1);
140 assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
141
142 let acc = mmr.peaks(mmr.forest()).unwrap();
143 assert_eq!(acc.num_leaves(), 1);
144 assert_eq!(acc.peaks(), &[postorder[0]]);
145
146 mmr.add(LEAVES[1]);
147 assert_eq!(mmr.forest(), 2);
148 assert_eq!(mmr.nodes.len(), 3);
149 assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
150
151 let acc = mmr.peaks(mmr.forest()).unwrap();
152 assert_eq!(acc.num_leaves(), 2);
153 assert_eq!(acc.peaks(), &[postorder[2]]);
154
155 mmr.add(LEAVES[2]);
156 assert_eq!(mmr.forest(), 3);
157 assert_eq!(mmr.nodes.len(), 4);
158 assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
159
160 let acc = mmr.peaks(mmr.forest()).unwrap();
161 assert_eq!(acc.num_leaves(), 3);
162 assert_eq!(acc.peaks(), &[postorder[2], postorder[3]]);
163
164 mmr.add(LEAVES[3]);
165 assert_eq!(mmr.forest(), 4);
166 assert_eq!(mmr.nodes.len(), 7);
167 assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
168
169 let acc = mmr.peaks(mmr.forest()).unwrap();
170 assert_eq!(acc.num_leaves(), 4);
171 assert_eq!(acc.peaks(), &[postorder[6]]);
172
173 mmr.add(LEAVES[4]);
174 assert_eq!(mmr.forest(), 5);
175 assert_eq!(mmr.nodes.len(), 8);
176 assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
177
178 let acc = mmr.peaks(mmr.forest()).unwrap();
179 assert_eq!(acc.num_leaves(), 5);
180 assert_eq!(acc.peaks(), &[postorder[6], postorder[7]]);
181
182 mmr.add(LEAVES[5]);
183 assert_eq!(mmr.forest(), 6);
184 assert_eq!(mmr.nodes.len(), 10);
185 assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
186
187 let acc = mmr.peaks(mmr.forest()).unwrap();
188 assert_eq!(acc.num_leaves(), 6);
189 assert_eq!(acc.peaks(), &[postorder[6], postorder[9]]);
190
191 mmr.add(LEAVES[6]);
192 assert_eq!(mmr.forest(), 7);
193 assert_eq!(mmr.nodes.len(), 11);
194 assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
195
196 let acc = mmr.peaks(mmr.forest()).unwrap();
197 assert_eq!(acc.num_leaves(), 7);
198 assert_eq!(acc.peaks(), &[postorder[6], postorder[9], postorder[10]]);
199}
200
201#[test]
202fn test_mmr_open() {
203 let mmr: Mmr = LEAVES.into();
204 let h01 = merge(LEAVES[0], LEAVES[1]);
205 let h23 = merge(LEAVES[2], LEAVES[3]);
206
207 // node at pos 7 is the root
208 assert!(
209 mmr.open(7, mmr.forest()).is_err(),
210 "Element 7 is not in the tree, result should be None"
211 );
212
213 // node at pos 6 is the root
214 let empty: MerklePath = MerklePath::new(vec![]);
215 let opening = mmr
216 .open(6, mmr.forest())
217 .expect("Element 6 is contained in the tree, expected an opening result.");
218 assert_eq!(opening.merkle_path, empty);
219 assert_eq!(opening.forest, mmr.forest);
220 assert_eq!(opening.position, 6);
221 assert!(
222 mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[6], opening),
223 "MmrProof should be valid for the current accumulator."
224 );
225
226 // nodes 4,5 are depth 1
227 let root_to_path = MerklePath::new(vec![LEAVES[4]]);
228 let opening = mmr
229 .open(5, mmr.forest())
230 .expect("Element 5 is contained in the tree, expected an opening result.");
231 assert_eq!(opening.merkle_path, root_to_path);
232 assert_eq!(opening.forest, mmr.forest);
233 assert_eq!(opening.position, 5);
234 assert!(
235 mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[5], opening),
236 "MmrProof should be valid for the current accumulator."
237 );
238
239 let root_to_path = MerklePath::new(vec![LEAVES[5]]);
240 let opening = mmr
241 .open(4, mmr.forest())
242 .expect("Element 4 is contained in the tree, expected an opening result.");
243 assert_eq!(opening.merkle_path, root_to_path);
244 assert_eq!(opening.forest, mmr.forest);
245 assert_eq!(opening.position, 4);
246 assert!(
247 mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[4], opening),
248 "MmrProof should be valid for the current accumulator."
249 );
250
251 // nodes 0,1,2,3 are detph 2
252 let root_to_path = MerklePath::new(vec![LEAVES[2], h01]);
253 let opening = mmr
254 .open(3, mmr.forest())
255 .expect("Element 3 is contained in the tree, expected an opening result.");
256 assert_eq!(opening.merkle_path, root_to_path);
257 assert_eq!(opening.forest, mmr.forest);
258 assert_eq!(opening.position, 3);
259 assert!(
260 mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[3], opening),
261 "MmrProof should be valid for the current accumulator."
262 );
263
264 let root_to_path = MerklePath::new(vec![LEAVES[3], h01]);
265 let opening = mmr
266 .open(2, mmr.forest())
267 .expect("Element 2 is contained in the tree, expected an opening result.");
268 assert_eq!(opening.merkle_path, root_to_path);
269 assert_eq!(opening.forest, mmr.forest);
270 assert_eq!(opening.position, 2);
271 assert!(
272 mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[2], opening),
273 "MmrProof should be valid for the current accumulator."
274 );
275
276 let root_to_path = MerklePath::new(vec![LEAVES[0], h23]);
277 let opening = mmr
278 .open(1, mmr.forest())
279 .expect("Element 1 is contained in the tree, expected an opening result.");
280 assert_eq!(opening.merkle_path, root_to_path);
281 assert_eq!(opening.forest, mmr.forest);
282 assert_eq!(opening.position, 1);
283 assert!(
284 mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[1], opening),
285 "MmrProof should be valid for the current accumulator."
286 );
287
288 let root_to_path = MerklePath::new(vec![LEAVES[1], h23]);
289 let opening = mmr
290 .open(0, mmr.forest())
291 .expect("Element 0 is contained in the tree, expected an opening result.");
292 assert_eq!(opening.merkle_path, root_to_path);
293 assert_eq!(opening.forest, mmr.forest);
294 assert_eq!(opening.position, 0);
295 assert!(
296 mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[0], opening),
297 "MmrProof should be valid for the current accumulator."
298 );
299}
300
301#[test]
302fn test_mmr_open_older_version() {
303 let mmr: Mmr = LEAVES.into();
304
305 fn is_even(v: &usize) -> bool {
306 v & 1 == 0
307 }
308
309 // merkle path of a node is empty if there are no elements to pair with it
310 for pos in (0..mmr.forest()).filter(is_even) {
311 let forest = pos + 1;
312 let proof = mmr.open(pos, forest).unwrap();
313 assert_eq!(proof.forest, forest);
314 assert_eq!(proof.merkle_path.nodes(), []);
315 assert_eq!(proof.position, pos);
316 }
317
318 // openings match that of a merkle tree
319 let mtree: MerkleTree = LEAVES[..4].try_into().unwrap();
320 for forest in 4..=LEAVES.len() {
321 for pos in 0..4 {
322 let idx = NodeIndex::new(2, pos).unwrap();
323 let path = mtree.get_path(idx).unwrap();
324 let proof = mmr.open(pos as usize, forest).unwrap();
325 assert_eq!(path, proof.merkle_path);
326 }
327 }
328 let mtree: MerkleTree = LEAVES[4..6].try_into().unwrap();
329 for forest in 6..=LEAVES.len() {
330 for pos in 0..2 {
331 let idx = NodeIndex::new(1, pos).unwrap();
332 let path = mtree.get_path(idx).unwrap();
333 // account for the bigger tree with 4 elements
334 let mmr_pos = (pos + 4) as usize;
335 let proof = mmr.open(mmr_pos, forest).unwrap();
336 assert_eq!(path, proof.merkle_path);
337 }
338 }
339}
340
341/// Tests the openings of a simple Mmr with a single tree of depth 8.
342#[test]
343fn test_mmr_open_eight() {
344 let leaves = [
345 int_to_node(0),
346 int_to_node(1),
347 int_to_node(2),
348 int_to_node(3),
349 int_to_node(4),
350 int_to_node(5),
351 int_to_node(6),
352 int_to_node(7),
353 ];
354
355 let mtree: MerkleTree = leaves.as_slice().try_into().unwrap();
356 let forest = leaves.len();
357 let mmr: Mmr = leaves.into();
358 let root = mtree.root();
359
360 let position = 0;
361 let proof = mmr.open(position, mmr.forest()).unwrap();
362 let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
363 assert_eq!(proof, MmrProof { forest, position, merkle_path });
364 assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
365
366 let position = 1;
367 let proof = mmr.open(position, mmr.forest()).unwrap();
368 let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
369 assert_eq!(proof, MmrProof { forest, position, merkle_path });
370 assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
371
372 let position = 2;
373 let proof = mmr.open(position, mmr.forest()).unwrap();
374 let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
375 assert_eq!(proof, MmrProof { forest, position, merkle_path });
376 assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
377
378 let position = 3;
379 let proof = mmr.open(position, mmr.forest()).unwrap();
380 let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
381 assert_eq!(proof, MmrProof { forest, position, merkle_path });
382 assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
383
384 let position = 4;
385 let proof = mmr.open(position, mmr.forest()).unwrap();
386 let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
387 assert_eq!(proof, MmrProof { forest, position, merkle_path });
388 assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
389
390 let position = 5;
391 let proof = mmr.open(position, mmr.forest()).unwrap();
392 let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
393 assert_eq!(proof, MmrProof { forest, position, merkle_path });
394 assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
395
396 let position = 6;
397 let proof = mmr.open(position, mmr.forest()).unwrap();
398 let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
399 assert_eq!(proof, MmrProof { forest, position, merkle_path });
400 assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
401
402 let position = 7;
403 let proof = mmr.open(position, mmr.forest()).unwrap();
404 let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
405 assert_eq!(proof, MmrProof { forest, position, merkle_path });
406 assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
407}
408
409/// Tests the openings of Mmr with a 3 trees of depths 4, 2, and 1.
410#[test]
411fn test_mmr_open_seven() {
412 let mtree1: MerkleTree = LEAVES[..4].try_into().unwrap();
413 let mtree2: MerkleTree = LEAVES[4..6].try_into().unwrap();
414
415 let forest = LEAVES.len();
416 let mmr: Mmr = LEAVES.into();
417
418 let position = 0;
419 let proof = mmr.open(position, mmr.forest()).unwrap();
420 let merkle_path: MerklePath =
421 mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap();
422 assert_eq!(proof, MmrProof { forest, position, merkle_path });
423 assert_eq!(proof.merkle_path.compute_root(0, LEAVES[0]).unwrap(), mtree1.root());
424
425 let position = 1;
426 let proof = mmr.open(position, mmr.forest()).unwrap();
427 let merkle_path: MerklePath =
428 mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap();
429 assert_eq!(proof, MmrProof { forest, position, merkle_path });
430 assert_eq!(proof.merkle_path.compute_root(1, LEAVES[1]).unwrap(), mtree1.root());
431
432 let position = 2;
433 let proof = mmr.open(position, mmr.forest()).unwrap();
434 let merkle_path: MerklePath =
435 mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap();
436 assert_eq!(proof, MmrProof { forest, position, merkle_path });
437 assert_eq!(proof.merkle_path.compute_root(2, LEAVES[2]).unwrap(), mtree1.root());
438
439 let position = 3;
440 let proof = mmr.open(position, mmr.forest()).unwrap();
441 let merkle_path: MerklePath =
442 mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap();
443 assert_eq!(proof, MmrProof { forest, position, merkle_path });
444 assert_eq!(proof.merkle_path.compute_root(3, LEAVES[3]).unwrap(), mtree1.root());
445
446 let position = 4;
447 let proof = mmr.open(position, mmr.forest()).unwrap();
448 let merkle_path: MerklePath = mtree2.get_path(NodeIndex::new(1, 0u64).unwrap()).unwrap();
449 assert_eq!(proof, MmrProof { forest, position, merkle_path });
450 assert_eq!(proof.merkle_path.compute_root(0, LEAVES[4]).unwrap(), mtree2.root());
451
452 let position = 5;
453 let proof = mmr.open(position, mmr.forest()).unwrap();
454 let merkle_path: MerklePath = mtree2.get_path(NodeIndex::new(1, 1u64).unwrap()).unwrap();
455 assert_eq!(proof, MmrProof { forest, position, merkle_path });
456 assert_eq!(proof.merkle_path.compute_root(1, LEAVES[5]).unwrap(), mtree2.root());
457
458 let position = 6;
459 let proof = mmr.open(position, mmr.forest()).unwrap();
460 let merkle_path: MerklePath = [].as_ref().into();
461 assert_eq!(proof, MmrProof { forest, position, merkle_path });
462 assert_eq!(proof.merkle_path.compute_root(0, LEAVES[6]).unwrap(), LEAVES[6]);
463}
464
465#[test]
466fn test_mmr_get() {
467 let mmr: Mmr = LEAVES.into();
468 assert_eq!(mmr.get(0).unwrap(), LEAVES[0], "value at pos 0 must correspond");
469 assert_eq!(mmr.get(1).unwrap(), LEAVES[1], "value at pos 1 must correspond");
470 assert_eq!(mmr.get(2).unwrap(), LEAVES[2], "value at pos 2 must correspond");
471 assert_eq!(mmr.get(3).unwrap(), LEAVES[3], "value at pos 3 must correspond");
472 assert_eq!(mmr.get(4).unwrap(), LEAVES[4], "value at pos 4 must correspond");
473 assert_eq!(mmr.get(5).unwrap(), LEAVES[5], "value at pos 5 must correspond");
474 assert_eq!(mmr.get(6).unwrap(), LEAVES[6], "value at pos 6 must correspond");
475 assert!(mmr.get(7).is_err());
476}
477
478#[test]
479fn test_mmr_invariants() {
480 let mut mmr = Mmr::new();
481 for v in 1..=1028 {
482 mmr.add(int_to_node(v));
483 let accumulator = mmr.peaks(mmr.forest()).unwrap();
484 assert_eq!(v as usize, mmr.forest(), "MMR leaf count must increase by one on every add");
485 assert_eq!(
486 v as usize,
487 accumulator.num_leaves(),
488 "MMR and its accumulator must match leaves count"
489 );
490 assert_eq!(
491 accumulator.num_leaves().count_ones() as usize,
492 accumulator.peaks().len(),
493 "bits on leaves must match the number of peaks"
494 );
495
496 let expected_nodes: usize = TrueBitPositionIterator::new(mmr.forest())
497 .map(|bit_pos| nodes_in_forest(1 << bit_pos))
498 .sum();
499
500 assert_eq!(
501 expected_nodes,
502 mmr.nodes.len(),
503 "the sum of every tree size must be equal to the number of nodes in the MMR (forest: {:b})",
504 mmr.forest(),
505 );
506 }
507}
508
509#[test]
510fn test_bit_position_iterator() {
511 assert_eq!(TrueBitPositionIterator::new(0).count(), 0);
512 assert_eq!(TrueBitPositionIterator::new(0).rev().count(), 0);
513
514 assert_eq!(TrueBitPositionIterator::new(1).collect::<Vec<u32>>(), vec![0]);
515 assert_eq!(TrueBitPositionIterator::new(1).rev().collect::<Vec<u32>>(), vec![0],);
516
517 assert_eq!(TrueBitPositionIterator::new(2).collect::<Vec<u32>>(), vec![1]);
518 assert_eq!(TrueBitPositionIterator::new(2).rev().collect::<Vec<u32>>(), vec![1],);
519
520 assert_eq!(TrueBitPositionIterator::new(3).collect::<Vec<u32>>(), vec![0, 1],);
521 assert_eq!(TrueBitPositionIterator::new(3).rev().collect::<Vec<u32>>(), vec![1, 0],);
522
523 assert_eq!(
524 TrueBitPositionIterator::new(0b11010101).collect::<Vec<u32>>(),
525 vec![0, 2, 4, 6, 7],
526 );
527 assert_eq!(
528 TrueBitPositionIterator::new(0b11010101).rev().collect::<Vec<u32>>(),
529 vec![7, 6, 4, 2, 0],
530 );
531}
532
533#[test]
534fn test_mmr_inner_nodes() {
535 let mmr: Mmr = LEAVES.into();
536 let nodes: Vec<InnerNodeInfo> = mmr.inner_nodes().collect();
537
538 let h01 = Rpo256::merge(&[LEAVES[0], LEAVES[1]]);
539 let h23 = Rpo256::merge(&[LEAVES[2], LEAVES[3]]);
540 let h0123 = Rpo256::merge(&[h01, h23]);
541 let h45 = Rpo256::merge(&[LEAVES[4], LEAVES[5]]);
542 let postorder = vec![
543 InnerNodeInfo {
544 value: h01,
545 left: LEAVES[0],
546 right: LEAVES[1],
547 },
548 InnerNodeInfo {
549 value: h23,
550 left: LEAVES[2],
551 right: LEAVES[3],
552 },
553 InnerNodeInfo { value: h0123, left: h01, right: h23 },
554 InnerNodeInfo {
555 value: h45,
556 left: LEAVES[4],
557 right: LEAVES[5],
558 },
559 ];
560
561 assert_eq!(postorder, nodes);
562}
563
564#[test]
565fn test_mmr_peaks() {
566 let mmr: Mmr = LEAVES.into();
567
568 let forest = 0b0001;
569 let acc = mmr.peaks(forest).unwrap();
570 assert_eq!(acc.num_leaves(), forest);
571 assert_eq!(acc.peaks(), &[mmr.nodes[0]]);
572
573 let forest = 0b0010;
574 let acc = mmr.peaks(forest).unwrap();
575 assert_eq!(acc.num_leaves(), forest);
576 assert_eq!(acc.peaks(), &[mmr.nodes[2]]);
577
578 let forest = 0b0011;
579 let acc = mmr.peaks(forest).unwrap();
580 assert_eq!(acc.num_leaves(), forest);
581 assert_eq!(acc.peaks(), &[mmr.nodes[2], mmr.nodes[3]]);
582
583 let forest = 0b0100;
584 let acc = mmr.peaks(forest).unwrap();
585 assert_eq!(acc.num_leaves(), forest);
586 assert_eq!(acc.peaks(), &[mmr.nodes[6]]);
587
588 let forest = 0b0101;
589 let acc = mmr.peaks(forest).unwrap();
590 assert_eq!(acc.num_leaves(), forest);
591 assert_eq!(acc.peaks(), &[mmr.nodes[6], mmr.nodes[7]]);
592
593 let forest = 0b0110;
594 let acc = mmr.peaks(forest).unwrap();
595 assert_eq!(acc.num_leaves(), forest);
596 assert_eq!(acc.peaks(), &[mmr.nodes[6], mmr.nodes[9]]);
597
598 let forest = 0b0111;
599 let acc = mmr.peaks(forest).unwrap();
600 assert_eq!(acc.num_leaves(), forest);
601 assert_eq!(acc.peaks(), &[mmr.nodes[6], mmr.nodes[9], mmr.nodes[10]]);
602}
603
604#[test]
605fn test_mmr_hash_peaks() {
606 let mmr: Mmr = LEAVES.into();
607 let peaks = mmr.peaks(mmr.forest()).unwrap();
608
609 let first_peak = Rpo256::merge(&[
610 Rpo256::merge(&[LEAVES[0], LEAVES[1]]),
611 Rpo256::merge(&[LEAVES[2], LEAVES[3]]),
612 ]);
613 let second_peak = Rpo256::merge(&[LEAVES[4], LEAVES[5]]);
614 let third_peak = LEAVES[6];
615
616 // minimum length is 16
617 let mut expected_peaks = [first_peak, second_peak, third_peak].to_vec();
618 expected_peaks.resize(16, RpoDigest::default());
619 assert_eq!(peaks.hash_peaks(), Rpo256::hash_elements(&digests_to_elements(&expected_peaks)));
620}
621
622#[test]
623fn test_mmr_peaks_hash_less_than_16() {
624 let mut peaks = Vec::new();
625
626 for i in 0..16 {
627 peaks.push(int_to_node(i));
628
629 let num_leaves = (1 << peaks.len()) - 1;
630 let accumulator = MmrPeaks::new(num_leaves, peaks.clone()).unwrap();
631
632 // minimum length is 16
633 let mut expected_peaks = peaks.clone();
634 expected_peaks.resize(16, RpoDigest::default());
635 assert_eq!(
636 accumulator.hash_peaks(),
637 Rpo256::hash_elements(&digests_to_elements(&expected_peaks))
638 );
639 }
640}
641
642#[test]
643fn test_mmr_peaks_hash_odd() {
644 let peaks: Vec<_> = (0..=17).map(int_to_node).collect();
645
646 let num_leaves = (1 << peaks.len()) - 1;
647 let accumulator = MmrPeaks::new(num_leaves, peaks.clone()).unwrap();
648
649 // odd length bigger than 16 is padded to the next even number
650 let mut expected_peaks = peaks;
651 expected_peaks.resize(18, RpoDigest::default());
652 assert_eq!(
653 accumulator.hash_peaks(),
654 Rpo256::hash_elements(&digests_to_elements(&expected_peaks))
655 );
656}
657
658#[test]
659fn test_mmr_delta() {
660 let mmr: Mmr = LEAVES.into();
661 let acc = mmr.peaks(mmr.forest()).unwrap();
662
663 // original_forest can't have more elements
664 assert!(
665 mmr.get_delta(LEAVES.len() + 1, mmr.forest()).is_err(),
666 "Can not provide updates for a newer Mmr"
667 );
668
669 // if the number of elements is the same there is no change
670 assert!(
671 mmr.get_delta(LEAVES.len(), mmr.forest()).unwrap().data.is_empty(),
672 "There are no updates for the same Mmr version"
673 );
674
675 // missing the last element added, which is itself a tree peak
676 assert_eq!(mmr.get_delta(6, mmr.forest()).unwrap().data, vec![acc.peaks()[2]], "one peak");
677
678 // missing the sibling to complete the tree of depth 2, and the last element
679 assert_eq!(
680 mmr.get_delta(5, mmr.forest()).unwrap().data,
681 vec![LEAVES[5], acc.peaks()[2]],
682 "one sibling, one peak"
683 );
684
685 // missing the whole last two trees, only send the peaks
686 assert_eq!(
687 mmr.get_delta(4, mmr.forest()).unwrap().data,
688 vec![acc.peaks()[1], acc.peaks()[2]],
689 "two peaks"
690 );
691
692 // missing the sibling to complete the first tree, and the two last trees
693 assert_eq!(
694 mmr.get_delta(3, mmr.forest()).unwrap().data,
695 vec![LEAVES[3], acc.peaks()[1], acc.peaks()[2]],
696 "one sibling, two peaks"
697 );
698
699 // missing half of the first tree, only send the computed element (not the leaves), and the new
700 // peaks
701 assert_eq!(
702 mmr.get_delta(2, mmr.forest()).unwrap().data,
703 vec![mmr.nodes[5], acc.peaks()[1], acc.peaks()[2]],
704 "one sibling, two peaks"
705 );
706
707 assert_eq!(
708 mmr.get_delta(1, mmr.forest()).unwrap().data,
709 vec![LEAVES[1], mmr.nodes[5], acc.peaks()[1], acc.peaks()[2]],
710 "one sibling, two peaks"
711 );
712
713 assert_eq!(&mmr.get_delta(0, mmr.forest()).unwrap().data, acc.peaks(), "all peaks");
714}
715
716#[test]
717fn test_mmr_delta_old_forest() {
718 let mmr: Mmr = LEAVES.into();
719
720 // from_forest must be smaller-or-equal to to_forest
721 for version in 1..=mmr.forest() {
722 assert!(mmr.get_delta(version + 1, version).is_err());
723 }
724
725 // when from_forest and to_forest are equal, there are no updates
726 for version in 1..=mmr.forest() {
727 let delta = mmr.get_delta(version, version).unwrap();
728 assert!(delta.data.is_empty());
729 assert_eq!(delta.forest, version);
730 }
731
732 // test update which merges the odd peak to the right
733 for count in 0..(mmr.forest() / 2) {
734 // *2 because every iteration tests a pair
735 // +1 because the Mmr is 1-indexed
736 let from_forest = (count * 2) + 1;
737 let to_forest = (count * 2) + 2;
738 let delta = mmr.get_delta(from_forest, to_forest).unwrap();
739
740 // *2 because every iteration tests a pair
741 // +1 because sibling is the odd element
742 let sibling = (count * 2) + 1;
743 assert_eq!(delta.data, [LEAVES[sibling]]);
744 assert_eq!(delta.forest, to_forest);
745 }
746
747 let version = 4;
748 let delta = mmr.get_delta(1, version).unwrap();
749 assert_eq!(delta.data, [mmr.nodes[1], mmr.nodes[5]]);
750 assert_eq!(delta.forest, version);
751
752 let version = 5;
753 let delta = mmr.get_delta(1, version).unwrap();
754 assert_eq!(delta.data, [mmr.nodes[1], mmr.nodes[5], mmr.nodes[7]]);
755 assert_eq!(delta.forest, version);
756}
757
758#[test]
759fn test_partial_mmr_simple() {
760 let mmr: Mmr = LEAVES.into();
761 let peaks = mmr.peaks(mmr.forest()).unwrap();
762 let mut partial: PartialMmr = peaks.clone().into();
763
764 // check initial state of the partial mmr
765 assert_eq!(partial.peaks(), peaks);
766 assert_eq!(partial.forest(), peaks.num_leaves());
767 assert_eq!(partial.forest(), LEAVES.len());
768 assert_eq!(partial.peaks().num_peaks(), 3);
769 assert_eq!(partial.nodes.len(), 0);
770
771 // check state after adding tracking one element
772 let proof1 = mmr.open(0, mmr.forest()).unwrap();
773 let el1 = mmr.get(proof1.position).unwrap();
774 partial.track(proof1.position, el1, &proof1.merkle_path).unwrap();
775
776 // check the number of nodes increased by the number of nodes in the proof
777 assert_eq!(partial.nodes.len(), proof1.merkle_path.len());
778 // check the values match
779 let idx = InOrderIndex::from_leaf_pos(proof1.position);
780 assert_eq!(partial.nodes[&idx.sibling()], proof1.merkle_path[0]);
781 let idx = idx.parent();
782 assert_eq!(partial.nodes[&idx.sibling()], proof1.merkle_path[1]);
783
784 let proof2 = mmr.open(1, mmr.forest()).unwrap();
785 let el2 = mmr.get(proof2.position).unwrap();
786 partial.track(proof2.position, el2, &proof2.merkle_path).unwrap();
787
788 // check the number of nodes increased by a single element (the one that is not shared)
789 assert_eq!(partial.nodes.len(), 3);
790 // check the values match
791 let idx = InOrderIndex::from_leaf_pos(proof2.position);
792 assert_eq!(partial.nodes[&idx.sibling()], proof2.merkle_path[0]);
793 let idx = idx.parent();
794 assert_eq!(partial.nodes[&idx.sibling()], proof2.merkle_path[1]);
795}
796
797#[test]
798fn test_partial_mmr_update_single() {
799 let mut full = Mmr::new();
800 let zero = int_to_node(0);
801 full.add(zero);
802 let mut partial: PartialMmr = full.peaks(full.forest()).unwrap().into();
803
804 let proof = full.open(0, full.forest()).unwrap();
805 partial.track(proof.position, zero, &proof.merkle_path).unwrap();
806
807 for i in 1..100 {
808 let node = int_to_node(i);
809 full.add(node);
810 let delta = full.get_delta(partial.forest(), full.forest()).unwrap();
811 partial.apply(delta).unwrap();
812
813 assert_eq!(partial.forest(), full.forest());
814 assert_eq!(partial.peaks(), full.peaks(full.forest()).unwrap());
815
816 let proof1 = full.open(i as usize, full.forest()).unwrap();
817 partial.track(proof1.position, node, &proof1.merkle_path).unwrap();
818 let proof2 = partial.open(proof1.position).unwrap().unwrap();
819 assert_eq!(proof1.merkle_path, proof2.merkle_path);
820 }
821}
822
823#[test]
824fn test_mmr_add_invalid_odd_leaf() {
825 let mmr: Mmr = LEAVES.into();
826 let acc = mmr.peaks(mmr.forest()).unwrap();
827 let mut partial: PartialMmr = acc.clone().into();
828
829 let empty = MerklePath::new(Vec::new());
830
831 // None of the other leaves should work
832 for node in LEAVES.iter().cloned().rev().skip(1) {
833 let result = partial.track(LEAVES.len() - 1, node, &empty);
834 assert!(result.is_err());
835 }
836
837 let result = partial.track(LEAVES.len() - 1, LEAVES[6], &empty);
838 assert!(result.is_ok());
839}
840
841mod property_tests {
842 use proptest::prelude::*;
843
844 use super::leaf_to_corresponding_tree;
845
846 proptest! {
847 #[test]
848 fn test_last_position_is_always_contained_in_the_last_tree(leaves in any::<usize>().prop_filter("cant have an empty tree", |v| *v != 0)) {
849 let last_pos = leaves - 1;
850 let lowest_bit = leaves.trailing_zeros();
851
852 assert_eq!(
853 leaf_to_corresponding_tree(last_pos, leaves),
854 Some(lowest_bit),
855 );
856 }
857 }
858
859 proptest! {
860 #[test]
861 fn test_contained_tree_is_always_power_of_two((leaves, pos) in any::<usize>().prop_flat_map(|v| (Just(v), 0..v))) {
862 let tree_bit = leaf_to_corresponding_tree(pos, leaves).expect("pos is smaller than leaves, there should always be a corresponding tree");
863 let mask = 1usize << tree_bit;
864
865 assert!(tree_bit < usize::BITS, "the result must be a bit in usize");
866 assert!(mask & leaves != 0, "the result should be a tree in leaves");
867 }
868 }
869}
870
871// HELPER FUNCTIONS
872// ================================================================================================
873
874fn digests_to_elements(digests: &[RpoDigest]) -> Vec<Felt> {
875 digests.iter().flat_map(Word::from).collect()
876}
877
878// short hand for the rpo hash, used to make test code more concise and easy to read
879fn merge(l: RpoDigest, r: RpoDigest) -> RpoDigest {
880 Rpo256::merge(&[l, r])
881}