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