Browse Source

feat: improve MMR api (#324)

al-update-winterfell
Bobbin Threadbare 8 months ago
committed by GitHub
parent
commit
a12e62ff22
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
4 changed files with 117 additions and 92 deletions
  1. +5
    -0
      CHANGELOG.md
  2. +33
    -8
      src/merkle/mmr/full.rs
  3. +21
    -23
      src/merkle/mmr/partial.rs
  4. +58
    -61
      src/merkle/mmr/tests.rs

+ 5
- 0
CHANGELOG.md

@ -1,3 +1,8 @@
## 0.11.0 (TBD)
- [BREAKING]: renamed `Mmr::open()` into `Mmr::open_at()` and `Mmr::peaks()` into `Mmr::peaks_at()` (#234).
- Added `Mmr::open()` and `Mmr::peaks()` which rely on `Mmr::open_at()` and `Mmr::peaks()` respectively (#234).
## 0.10.0 (2024-08-06) ## 0.10.0 (2024-08-06)
* Added more `RpoDigest` and `RpxDigest` conversions (#311). * Added more `RpoDigest` and `RpxDigest` conversions (#311).

+ 33
- 8
src/merkle/mmr/full.rs

@ -72,19 +72,36 @@ impl Mmr {
// FUNCTIONALITY // FUNCTIONALITY
// ============================================================================================ // ============================================================================================
/// Given a leaf position, returns the Merkle path to its corresponding peak. If the position
/// is greater-or-equal than the tree size an error is returned.
/// Returns an [MmrProof] for the leaf at the specified position.
/// ///
/// Note: The leaf position is the 0-indexed number corresponding to the order the leaves were /// Note: The leaf position is the 0-indexed number corresponding to the order the leaves were
/// added, this corresponds to the MMR size _prior_ to adding the element. So the 1st element /// added, this corresponds to the MMR size _prior_ to adding the element. So the 1st element
/// has position 0, the second position 1, and so on. /// has position 0, the second position 1, and so on.
pub fn open(&self, pos: usize, target_forest: usize) -> Result<MmrProof, MmrError> {
///
/// # Errors
/// Returns an error if the specified leaf position is out of bounds for this MMR.
pub fn open(&self, pos: usize) -> Result<MmrProof, MmrError> {
self.open_at(pos, self.forest)
}
/// Returns an [MmrProof] for the leaf at the specified position using the state of the MMR
/// at the specified `forest`.
///
/// Note: The leaf position is the 0-indexed number corresponding to the order the leaves were
/// added, this corresponds to the MMR size _prior_ to adding the element. So the 1st element
/// has position 0, the second position 1, and so on.
///
/// # Errors
/// Returns an error if:
/// - The specified leaf position is out of bounds for this MMR.
/// - The specified `forest` value is not valid for this MMR.
pub fn open_at(&self, pos: usize, forest: usize) -> Result<MmrProof, MmrError> {
// find the target tree responsible for the MMR position // find the target tree responsible for the MMR position
let tree_bit = let tree_bit =
leaf_to_corresponding_tree(pos, target_forest).ok_or(MmrError::InvalidPosition(pos))?;
leaf_to_corresponding_tree(pos, forest).ok_or(MmrError::InvalidPosition(pos))?;
// isolate the trees before the target // isolate the trees before the target
let forest_before = target_forest & high_bitmask(tree_bit + 1);
let forest_before = forest & high_bitmask(tree_bit + 1);
let index_offset = nodes_in_forest(forest_before); let index_offset = nodes_in_forest(forest_before);
// update the value position from global to the target tree // update the value position from global to the target tree
@ -94,7 +111,7 @@ impl Mmr {
let (_, path) = self.collect_merkle_path_and_value(tree_bit, relative_pos, index_offset); let (_, path) = self.collect_merkle_path_and_value(tree_bit, relative_pos, index_offset);
Ok(MmrProof { Ok(MmrProof {
forest: target_forest,
forest,
position: pos, position: pos,
merkle_path: MerklePath::new(path), merkle_path: MerklePath::new(path),
}) })
@ -145,8 +162,16 @@ impl Mmr {
self.forest += 1; self.forest += 1;
} }
/// Returns an peaks of the MMR for the version specified by `forest`.
pub fn peaks(&self, forest: usize) -> Result<MmrPeaks, MmrError> {
/// Returns the current peaks of the MMR.
pub fn peaks(&self) -> MmrPeaks {
self.peaks_at(self.forest).expect("failed to get peaks at current forest")
}
/// Returns the peaks of the MMR at the state specified by `forest`.
///
/// # Errors
/// Returns an error if the specified `forest` value is not valid for this MMR.
pub fn peaks_at(&self, forest: usize) -> Result<MmrPeaks, MmrError> {
if forest > self.forest { if forest > self.forest {
return Err(MmrError::InvalidPeaks); return Err(MmrError::InvalidPeaks);
} }

+ 21
- 23
src/merkle/mmr/partial.rs

@ -688,18 +688,18 @@ mod tests {
// build an MMR with 10 nodes (2 peaks) and a partial MMR based on it // build an MMR with 10 nodes (2 peaks) and a partial MMR based on it
let mut mmr = Mmr::default(); let mut mmr = Mmr::default();
(0..10).for_each(|i| mmr.add(int_to_node(i))); (0..10).for_each(|i| mmr.add(int_to_node(i)));
let mut partial_mmr: PartialMmr = mmr.peaks(mmr.forest()).unwrap().into();
let mut partial_mmr: PartialMmr = mmr.peaks().into();
// add authentication path for position 1 and 8 // add authentication path for position 1 and 8
{ {
let node = mmr.get(1).unwrap(); let node = mmr.get(1).unwrap();
let proof = mmr.open(1, mmr.forest()).unwrap();
let proof = mmr.open(1).unwrap();
partial_mmr.track(1, node, &proof.merkle_path).unwrap(); partial_mmr.track(1, node, &proof.merkle_path).unwrap();
} }
{ {
let node = mmr.get(8).unwrap(); let node = mmr.get(8).unwrap();
let proof = mmr.open(8, mmr.forest()).unwrap();
let proof = mmr.open(8).unwrap();
partial_mmr.track(8, node, &proof.merkle_path).unwrap(); partial_mmr.track(8, node, &proof.merkle_path).unwrap();
} }
@ -712,7 +712,7 @@ mod tests {
validate_apply_delta(&mmr, &mut partial_mmr); validate_apply_delta(&mmr, &mut partial_mmr);
{ {
let node = mmr.get(12).unwrap(); let node = mmr.get(12).unwrap();
let proof = mmr.open(12, mmr.forest()).unwrap();
let proof = mmr.open(12).unwrap();
partial_mmr.track(12, node, &proof.merkle_path).unwrap(); partial_mmr.track(12, node, &proof.merkle_path).unwrap();
assert!(partial_mmr.track_latest); assert!(partial_mmr.track_latest);
} }
@ -737,7 +737,7 @@ mod tests {
let nodes_delta = partial.apply(delta).unwrap(); let nodes_delta = partial.apply(delta).unwrap();
// new peaks were computed correctly // new peaks were computed correctly
assert_eq!(mmr.peaks(mmr.forest()).unwrap(), partial.peaks());
assert_eq!(mmr.peaks(), partial.peaks());
let mut expected_nodes = nodes_before; let mut expected_nodes = nodes_before;
for (key, value) in nodes_delta { for (key, value) in nodes_delta {
@ -753,7 +753,7 @@ mod tests {
let index_value: u64 = index.into(); let index_value: u64 = index.into();
let pos = index_value / 2; let pos = index_value / 2;
let proof1 = partial.open(pos as usize).unwrap().unwrap(); let proof1 = partial.open(pos as usize).unwrap().unwrap();
let proof2 = mmr.open(pos as usize, mmr.forest()).unwrap();
let proof2 = mmr.open(pos as usize).unwrap();
assert_eq!(proof1, proof2); assert_eq!(proof1, proof2);
} }
} }
@ -762,16 +762,16 @@ mod tests {
fn test_partial_mmr_inner_nodes_iterator() { fn test_partial_mmr_inner_nodes_iterator() {
// build the MMR // build the MMR
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
let first_peak = mmr.peaks(mmr.forest).unwrap().peaks()[0];
let first_peak = mmr.peaks().peaks()[0];
// -- test single tree ---------------------------- // -- test single tree ----------------------------
// get path and node for position 1 // get path and node for position 1
let node1 = mmr.get(1).unwrap(); let node1 = mmr.get(1).unwrap();
let proof1 = mmr.open(1, mmr.forest()).unwrap();
let proof1 = mmr.open(1).unwrap();
// create partial MMR and add authentication path to node at position 1 // create partial MMR and add authentication path to node at position 1
let mut partial_mmr: PartialMmr = mmr.peaks(mmr.forest()).unwrap().into();
let mut partial_mmr: PartialMmr = mmr.peaks().into();
partial_mmr.track(1, node1, &proof1.merkle_path).unwrap(); partial_mmr.track(1, node1, &proof1.merkle_path).unwrap();
// empty iterator should have no nodes // empty iterator should have no nodes
@ -789,13 +789,13 @@ mod tests {
// -- test no duplicates -------------------------- // -- test no duplicates --------------------------
// build the partial MMR // build the partial MMR
let mut partial_mmr: PartialMmr = mmr.peaks(mmr.forest()).unwrap().into();
let mut partial_mmr: PartialMmr = mmr.peaks().into();
let node0 = mmr.get(0).unwrap(); let node0 = mmr.get(0).unwrap();
let proof0 = mmr.open(0, mmr.forest()).unwrap();
let proof0 = mmr.open(0).unwrap();
let node2 = mmr.get(2).unwrap(); let node2 = mmr.get(2).unwrap();
let proof2 = mmr.open(2, mmr.forest()).unwrap();
let proof2 = mmr.open(2).unwrap();
partial_mmr.track(0, node0, &proof0.merkle_path).unwrap(); partial_mmr.track(0, node0, &proof0.merkle_path).unwrap();
partial_mmr.track(1, node1, &proof1.merkle_path).unwrap(); partial_mmr.track(1, node1, &proof1.merkle_path).unwrap();
@ -826,10 +826,10 @@ mod tests {
// -- test multiple trees ------------------------- // -- test multiple trees -------------------------
// build the partial MMR // build the partial MMR
let mut partial_mmr: PartialMmr = mmr.peaks(mmr.forest()).unwrap().into();
let mut partial_mmr: PartialMmr = mmr.peaks().into();
let node5 = mmr.get(5).unwrap(); let node5 = mmr.get(5).unwrap();
let proof5 = mmr.open(5, mmr.forest()).unwrap();
let proof5 = mmr.open(5).unwrap();
partial_mmr.track(1, node1, &proof1.merkle_path).unwrap(); partial_mmr.track(1, node1, &proof1.merkle_path).unwrap();
partial_mmr.track(5, node5, &proof5.merkle_path).unwrap(); partial_mmr.track(5, node5, &proof5.merkle_path).unwrap();
@ -841,7 +841,7 @@ mod tests {
let index1 = NodeIndex::new(2, 1).unwrap(); let index1 = NodeIndex::new(2, 1).unwrap();
let index5 = NodeIndex::new(1, 1).unwrap(); let index5 = NodeIndex::new(1, 1).unwrap();
let second_peak = mmr.peaks(mmr.forest).unwrap().peaks()[1];
let second_peak = mmr.peaks().peaks()[1];
let path1 = store.get_path(first_peak, index1).unwrap().path; let path1 = store.get_path(first_peak, index1).unwrap().path;
let path5 = store.get_path(second_peak, index5).unwrap().path; let path5 = store.get_path(second_peak, index5).unwrap().path;
@ -860,8 +860,7 @@ mod tests {
mmr.add(el); mmr.add(el);
partial_mmr.add(el, false); partial_mmr.add(el, false);
let mmr_peaks = mmr.peaks(mmr.forest()).unwrap();
assert_eq!(mmr_peaks, partial_mmr.peaks());
assert_eq!(mmr.peaks(), partial_mmr.peaks());
assert_eq!(mmr.forest(), partial_mmr.forest()); assert_eq!(mmr.forest(), partial_mmr.forest());
} }
} }
@ -877,12 +876,11 @@ mod tests {
mmr.add(el); mmr.add(el);
partial_mmr.add(el, true); partial_mmr.add(el, true);
let mmr_peaks = mmr.peaks(mmr.forest()).unwrap();
assert_eq!(mmr_peaks, partial_mmr.peaks());
assert_eq!(mmr.peaks(), partial_mmr.peaks());
assert_eq!(mmr.forest(), partial_mmr.forest()); assert_eq!(mmr.forest(), partial_mmr.forest());
for pos in 0..i { for pos in 0..i {
let mmr_proof = mmr.open(pos as usize, mmr.forest()).unwrap();
let mmr_proof = mmr.open(pos as usize).unwrap();
let partialmmr_proof = partial_mmr.open(pos as usize).unwrap().unwrap(); let partialmmr_proof = partial_mmr.open(pos as usize).unwrap().unwrap();
assert_eq!(mmr_proof, partialmmr_proof); assert_eq!(mmr_proof, partialmmr_proof);
} }
@ -894,8 +892,8 @@ mod tests {
let mut mmr = Mmr::from((0..7).map(int_to_node)); let mut mmr = Mmr::from((0..7).map(int_to_node));
// derive a partial Mmr from it which tracks authentication path to leaf 5 // derive a partial Mmr from it which tracks authentication path to leaf 5
let mut partial_mmr = PartialMmr::from_peaks(mmr.peaks(mmr.forest()).unwrap());
let path_to_5 = mmr.open(5, mmr.forest()).unwrap().merkle_path;
let mut partial_mmr = PartialMmr::from_peaks(mmr.peaks());
let path_to_5 = mmr.open(5).unwrap().merkle_path;
let leaf_at_5 = mmr.get(5).unwrap(); let leaf_at_5 = mmr.get(5).unwrap();
partial_mmr.track(5, leaf_at_5, &path_to_5).unwrap(); partial_mmr.track(5, leaf_at_5, &path_to_5).unwrap();
@ -905,6 +903,6 @@ mod tests {
partial_mmr.add(leaf_at_7, false); partial_mmr.add(leaf_at_7, false);
// the openings should be the same // the openings should be the same
assert_eq!(mmr.open(5, mmr.forest()).unwrap(), partial_mmr.open(5).unwrap().unwrap());
assert_eq!(mmr.open(5).unwrap(), partial_mmr.open(5).unwrap().unwrap());
} }
} }

+ 58
- 61
src/merkle/mmr/tests.rs

@ -138,7 +138,7 @@ fn test_mmr_simple() {
assert_eq!(mmr.nodes.len(), 1); assert_eq!(mmr.nodes.len(), 1);
assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]); assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
let acc = mmr.peaks(mmr.forest()).unwrap();
let acc = mmr.peaks();
assert_eq!(acc.num_leaves(), 1); assert_eq!(acc.num_leaves(), 1);
assert_eq!(acc.peaks(), &[postorder[0]]); assert_eq!(acc.peaks(), &[postorder[0]]);
@ -147,7 +147,7 @@ fn test_mmr_simple() {
assert_eq!(mmr.nodes.len(), 3); assert_eq!(mmr.nodes.len(), 3);
assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]); assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
let acc = mmr.peaks(mmr.forest()).unwrap();
let acc = mmr.peaks();
assert_eq!(acc.num_leaves(), 2); assert_eq!(acc.num_leaves(), 2);
assert_eq!(acc.peaks(), &[postorder[2]]); assert_eq!(acc.peaks(), &[postorder[2]]);
@ -156,7 +156,7 @@ fn test_mmr_simple() {
assert_eq!(mmr.nodes.len(), 4); assert_eq!(mmr.nodes.len(), 4);
assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]); assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
let acc = mmr.peaks(mmr.forest()).unwrap();
let acc = mmr.peaks();
assert_eq!(acc.num_leaves(), 3); assert_eq!(acc.num_leaves(), 3);
assert_eq!(acc.peaks(), &[postorder[2], postorder[3]]); assert_eq!(acc.peaks(), &[postorder[2], postorder[3]]);
@ -165,7 +165,7 @@ fn test_mmr_simple() {
assert_eq!(mmr.nodes.len(), 7); assert_eq!(mmr.nodes.len(), 7);
assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]); assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
let acc = mmr.peaks(mmr.forest()).unwrap();
let acc = mmr.peaks();
assert_eq!(acc.num_leaves(), 4); assert_eq!(acc.num_leaves(), 4);
assert_eq!(acc.peaks(), &[postorder[6]]); assert_eq!(acc.peaks(), &[postorder[6]]);
@ -174,7 +174,7 @@ fn test_mmr_simple() {
assert_eq!(mmr.nodes.len(), 8); assert_eq!(mmr.nodes.len(), 8);
assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]); assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
let acc = mmr.peaks(mmr.forest()).unwrap();
let acc = mmr.peaks();
assert_eq!(acc.num_leaves(), 5); assert_eq!(acc.num_leaves(), 5);
assert_eq!(acc.peaks(), &[postorder[6], postorder[7]]); assert_eq!(acc.peaks(), &[postorder[6], postorder[7]]);
@ -183,7 +183,7 @@ fn test_mmr_simple() {
assert_eq!(mmr.nodes.len(), 10); assert_eq!(mmr.nodes.len(), 10);
assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]); assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
let acc = mmr.peaks(mmr.forest()).unwrap();
let acc = mmr.peaks();
assert_eq!(acc.num_leaves(), 6); assert_eq!(acc.num_leaves(), 6);
assert_eq!(acc.peaks(), &[postorder[6], postorder[9]]); assert_eq!(acc.peaks(), &[postorder[6], postorder[9]]);
@ -192,7 +192,7 @@ fn test_mmr_simple() {
assert_eq!(mmr.nodes.len(), 11); assert_eq!(mmr.nodes.len(), 11);
assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]); assert_eq!(mmr.nodes.as_slice(), &postorder[0..mmr.nodes.len()]);
let acc = mmr.peaks(mmr.forest()).unwrap();
let acc = mmr.peaks();
assert_eq!(acc.num_leaves(), 7); assert_eq!(acc.num_leaves(), 7);
assert_eq!(acc.peaks(), &[postorder[6], postorder[9], postorder[10]]); assert_eq!(acc.peaks(), &[postorder[6], postorder[9], postorder[10]]);
} }
@ -204,95 +204,92 @@ fn test_mmr_open() {
let h23 = merge(LEAVES[2], LEAVES[3]); let h23 = merge(LEAVES[2], LEAVES[3]);
// node at pos 7 is the root // node at pos 7 is the root
assert!(
mmr.open(7, mmr.forest()).is_err(),
"Element 7 is not in the tree, result should be None"
);
assert!(mmr.open(7).is_err(), "Element 7 is not in the tree, result should be None");
// node at pos 6 is the root // node at pos 6 is the root
let empty: MerklePath = MerklePath::new(vec![]); let empty: MerklePath = MerklePath::new(vec![]);
let opening = mmr let opening = mmr
.open(6, mmr.forest())
.open(6)
.expect("Element 6 is contained in the tree, expected an opening result."); .expect("Element 6 is contained in the tree, expected an opening result.");
assert_eq!(opening.merkle_path, empty); assert_eq!(opening.merkle_path, empty);
assert_eq!(opening.forest, mmr.forest); assert_eq!(opening.forest, mmr.forest);
assert_eq!(opening.position, 6); assert_eq!(opening.position, 6);
assert!( assert!(
mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[6], opening),
mmr.peaks().verify(LEAVES[6], opening),
"MmrProof should be valid for the current accumulator." "MmrProof should be valid for the current accumulator."
); );
// nodes 4,5 are depth 1 // nodes 4,5 are depth 1
let root_to_path = MerklePath::new(vec![LEAVES[4]]); let root_to_path = MerklePath::new(vec![LEAVES[4]]);
let opening = mmr let opening = mmr
.open(5, mmr.forest())
.open(5)
.expect("Element 5 is contained in the tree, expected an opening result."); .expect("Element 5 is contained in the tree, expected an opening result.");
assert_eq!(opening.merkle_path, root_to_path); assert_eq!(opening.merkle_path, root_to_path);
assert_eq!(opening.forest, mmr.forest); assert_eq!(opening.forest, mmr.forest);
assert_eq!(opening.position, 5); assert_eq!(opening.position, 5);
assert!( assert!(
mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[5], opening),
mmr.peaks().verify(LEAVES[5], opening),
"MmrProof should be valid for the current accumulator." "MmrProof should be valid for the current accumulator."
); );
let root_to_path = MerklePath::new(vec![LEAVES[5]]); let root_to_path = MerklePath::new(vec![LEAVES[5]]);
let opening = mmr let opening = mmr
.open(4, mmr.forest())
.open(4)
.expect("Element 4 is contained in the tree, expected an opening result."); .expect("Element 4 is contained in the tree, expected an opening result.");
assert_eq!(opening.merkle_path, root_to_path); assert_eq!(opening.merkle_path, root_to_path);
assert_eq!(opening.forest, mmr.forest); assert_eq!(opening.forest, mmr.forest);
assert_eq!(opening.position, 4); assert_eq!(opening.position, 4);
assert!( assert!(
mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[4], opening),
mmr.peaks().verify(LEAVES[4], opening),
"MmrProof should be valid for the current accumulator." "MmrProof should be valid for the current accumulator."
); );
// nodes 0,1,2,3 are detph 2 // nodes 0,1,2,3 are detph 2
let root_to_path = MerklePath::new(vec![LEAVES[2], h01]); let root_to_path = MerklePath::new(vec![LEAVES[2], h01]);
let opening = mmr let opening = mmr
.open(3, mmr.forest())
.open(3)
.expect("Element 3 is contained in the tree, expected an opening result."); .expect("Element 3 is contained in the tree, expected an opening result.");
assert_eq!(opening.merkle_path, root_to_path); assert_eq!(opening.merkle_path, root_to_path);
assert_eq!(opening.forest, mmr.forest); assert_eq!(opening.forest, mmr.forest);
assert_eq!(opening.position, 3); assert_eq!(opening.position, 3);
assert!( assert!(
mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[3], opening),
mmr.peaks().verify(LEAVES[3], opening),
"MmrProof should be valid for the current accumulator." "MmrProof should be valid for the current accumulator."
); );
let root_to_path = MerklePath::new(vec![LEAVES[3], h01]); let root_to_path = MerklePath::new(vec![LEAVES[3], h01]);
let opening = mmr let opening = mmr
.open(2, mmr.forest())
.open(2)
.expect("Element 2 is contained in the tree, expected an opening result."); .expect("Element 2 is contained in the tree, expected an opening result.");
assert_eq!(opening.merkle_path, root_to_path); assert_eq!(opening.merkle_path, root_to_path);
assert_eq!(opening.forest, mmr.forest); assert_eq!(opening.forest, mmr.forest);
assert_eq!(opening.position, 2); assert_eq!(opening.position, 2);
assert!( assert!(
mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[2], opening),
mmr.peaks().verify(LEAVES[2], opening),
"MmrProof should be valid for the current accumulator." "MmrProof should be valid for the current accumulator."
); );
let root_to_path = MerklePath::new(vec![LEAVES[0], h23]); let root_to_path = MerklePath::new(vec![LEAVES[0], h23]);
let opening = mmr let opening = mmr
.open(1, mmr.forest())
.open(1)
.expect("Element 1 is contained in the tree, expected an opening result."); .expect("Element 1 is contained in the tree, expected an opening result.");
assert_eq!(opening.merkle_path, root_to_path); assert_eq!(opening.merkle_path, root_to_path);
assert_eq!(opening.forest, mmr.forest); assert_eq!(opening.forest, mmr.forest);
assert_eq!(opening.position, 1); assert_eq!(opening.position, 1);
assert!( assert!(
mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[1], opening),
mmr.peaks().verify(LEAVES[1], opening),
"MmrProof should be valid for the current accumulator." "MmrProof should be valid for the current accumulator."
); );
let root_to_path = MerklePath::new(vec![LEAVES[1], h23]); let root_to_path = MerklePath::new(vec![LEAVES[1], h23]);
let opening = mmr let opening = mmr
.open(0, mmr.forest())
.open(0)
.expect("Element 0 is contained in the tree, expected an opening result."); .expect("Element 0 is contained in the tree, expected an opening result.");
assert_eq!(opening.merkle_path, root_to_path); assert_eq!(opening.merkle_path, root_to_path);
assert_eq!(opening.forest, mmr.forest); assert_eq!(opening.forest, mmr.forest);
assert_eq!(opening.position, 0); assert_eq!(opening.position, 0);
assert!( assert!(
mmr.peaks(mmr.forest()).unwrap().verify(LEAVES[0], opening),
mmr.peaks().verify(LEAVES[0], opening),
"MmrProof should be valid for the current accumulator." "MmrProof should be valid for the current accumulator."
); );
} }
@ -308,7 +305,7 @@ fn test_mmr_open_older_version() {
// merkle path of a node is empty if there are no elements to pair with it // merkle path of a node is empty if there are no elements to pair with it
for pos in (0..mmr.forest()).filter(is_even) { for pos in (0..mmr.forest()).filter(is_even) {
let forest = pos + 1; let forest = pos + 1;
let proof = mmr.open(pos, forest).unwrap();
let proof = mmr.open_at(pos, forest).unwrap();
assert_eq!(proof.forest, forest); assert_eq!(proof.forest, forest);
assert_eq!(proof.merkle_path.nodes(), []); assert_eq!(proof.merkle_path.nodes(), []);
assert_eq!(proof.position, pos); assert_eq!(proof.position, pos);
@ -320,7 +317,7 @@ fn test_mmr_open_older_version() {
for pos in 0..4 { for pos in 0..4 {
let idx = NodeIndex::new(2, pos).unwrap(); let idx = NodeIndex::new(2, pos).unwrap();
let path = mtree.get_path(idx).unwrap(); let path = mtree.get_path(idx).unwrap();
let proof = mmr.open(pos as usize, forest).unwrap();
let proof = mmr.open_at(pos as usize, forest).unwrap();
assert_eq!(path, proof.merkle_path); assert_eq!(path, proof.merkle_path);
} }
} }
@ -331,7 +328,7 @@ fn test_mmr_open_older_version() {
let path = mtree.get_path(idx).unwrap(); let path = mtree.get_path(idx).unwrap();
// account for the bigger tree with 4 elements // account for the bigger tree with 4 elements
let mmr_pos = (pos + 4) as usize; let mmr_pos = (pos + 4) as usize;
let proof = mmr.open(mmr_pos, forest).unwrap();
let proof = mmr.open_at(mmr_pos, forest).unwrap();
assert_eq!(path, proof.merkle_path); assert_eq!(path, proof.merkle_path);
} }
} }
@ -357,49 +354,49 @@ fn test_mmr_open_eight() {
let root = mtree.root(); let root = mtree.root();
let position = 0; let position = 0;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap(); let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root); assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
let position = 1; let position = 1;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap(); let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root); assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
let position = 2; let position = 2;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap(); let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root); assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
let position = 3; let position = 3;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap(); let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root); assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
let position = 4; let position = 4;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap(); let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root); assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
let position = 5; let position = 5;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap(); let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root); assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
let position = 6; let position = 6;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap(); let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root); assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
let position = 7; let position = 7;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap(); let merkle_path = mtree.get_path(NodeIndex::new(3, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root); assert_eq!(proof.merkle_path.compute_root(position as u64, leaves[position]).unwrap(), root);
@ -415,47 +412,47 @@ fn test_mmr_open_seven() {
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
let position = 0; let position = 0;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path: MerklePath = let merkle_path: MerklePath =
mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap(); mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(0, LEAVES[0]).unwrap(), mtree1.root()); assert_eq!(proof.merkle_path.compute_root(0, LEAVES[0]).unwrap(), mtree1.root());
let position = 1; let position = 1;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path: MerklePath = let merkle_path: MerklePath =
mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap(); mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(1, LEAVES[1]).unwrap(), mtree1.root()); assert_eq!(proof.merkle_path.compute_root(1, LEAVES[1]).unwrap(), mtree1.root());
let position = 2; let position = 2;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path: MerklePath = let merkle_path: MerklePath =
mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap(); mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(2, LEAVES[2]).unwrap(), mtree1.root()); assert_eq!(proof.merkle_path.compute_root(2, LEAVES[2]).unwrap(), mtree1.root());
let position = 3; let position = 3;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path: MerklePath = let merkle_path: MerklePath =
mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap(); mtree1.get_path(NodeIndex::new(2, position as u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(3, LEAVES[3]).unwrap(), mtree1.root()); assert_eq!(proof.merkle_path.compute_root(3, LEAVES[3]).unwrap(), mtree1.root());
let position = 4; let position = 4;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path: MerklePath = mtree2.get_path(NodeIndex::new(1, 0u64).unwrap()).unwrap(); let merkle_path: MerklePath = mtree2.get_path(NodeIndex::new(1, 0u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(0, LEAVES[4]).unwrap(), mtree2.root()); assert_eq!(proof.merkle_path.compute_root(0, LEAVES[4]).unwrap(), mtree2.root());
let position = 5; let position = 5;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path: MerklePath = mtree2.get_path(NodeIndex::new(1, 1u64).unwrap()).unwrap(); let merkle_path: MerklePath = mtree2.get_path(NodeIndex::new(1, 1u64).unwrap()).unwrap();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(1, LEAVES[5]).unwrap(), mtree2.root()); assert_eq!(proof.merkle_path.compute_root(1, LEAVES[5]).unwrap(), mtree2.root());
let position = 6; let position = 6;
let proof = mmr.open(position, mmr.forest()).unwrap();
let proof = mmr.open(position).unwrap();
let merkle_path: MerklePath = [].as_ref().into(); let merkle_path: MerklePath = [].as_ref().into();
assert_eq!(proof, MmrProof { forest, position, merkle_path }); assert_eq!(proof, MmrProof { forest, position, merkle_path });
assert_eq!(proof.merkle_path.compute_root(0, LEAVES[6]).unwrap(), LEAVES[6]); assert_eq!(proof.merkle_path.compute_root(0, LEAVES[6]).unwrap(), LEAVES[6]);
@ -479,7 +476,7 @@ fn test_mmr_invariants() {
let mut mmr = Mmr::new(); let mut mmr = Mmr::new();
for v in 1..=1028 { for v in 1..=1028 {
mmr.add(int_to_node(v)); mmr.add(int_to_node(v));
let accumulator = mmr.peaks(mmr.forest()).unwrap();
let accumulator = mmr.peaks();
assert_eq!(v as usize, mmr.forest(), "MMR leaf count must increase by one on every add"); assert_eq!(v as usize, mmr.forest(), "MMR leaf count must increase by one on every add");
assert_eq!( assert_eq!(
v as usize, v as usize,
@ -565,37 +562,37 @@ fn test_mmr_peaks() {
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
let forest = 0b0001; let forest = 0b0001;
let acc = mmr.peaks(forest).unwrap();
let acc = mmr.peaks_at(forest).unwrap();
assert_eq!(acc.num_leaves(), forest); assert_eq!(acc.num_leaves(), forest);
assert_eq!(acc.peaks(), &[mmr.nodes[0]]); assert_eq!(acc.peaks(), &[mmr.nodes[0]]);
let forest = 0b0010; let forest = 0b0010;
let acc = mmr.peaks(forest).unwrap();
let acc = mmr.peaks_at(forest).unwrap();
assert_eq!(acc.num_leaves(), forest); assert_eq!(acc.num_leaves(), forest);
assert_eq!(acc.peaks(), &[mmr.nodes[2]]); assert_eq!(acc.peaks(), &[mmr.nodes[2]]);
let forest = 0b0011; let forest = 0b0011;
let acc = mmr.peaks(forest).unwrap();
let acc = mmr.peaks_at(forest).unwrap();
assert_eq!(acc.num_leaves(), forest); assert_eq!(acc.num_leaves(), forest);
assert_eq!(acc.peaks(), &[mmr.nodes[2], mmr.nodes[3]]); assert_eq!(acc.peaks(), &[mmr.nodes[2], mmr.nodes[3]]);
let forest = 0b0100; let forest = 0b0100;
let acc = mmr.peaks(forest).unwrap();
let acc = mmr.peaks_at(forest).unwrap();
assert_eq!(acc.num_leaves(), forest); assert_eq!(acc.num_leaves(), forest);
assert_eq!(acc.peaks(), &[mmr.nodes[6]]); assert_eq!(acc.peaks(), &[mmr.nodes[6]]);
let forest = 0b0101; let forest = 0b0101;
let acc = mmr.peaks(forest).unwrap();
let acc = mmr.peaks_at(forest).unwrap();
assert_eq!(acc.num_leaves(), forest); assert_eq!(acc.num_leaves(), forest);
assert_eq!(acc.peaks(), &[mmr.nodes[6], mmr.nodes[7]]); assert_eq!(acc.peaks(), &[mmr.nodes[6], mmr.nodes[7]]);
let forest = 0b0110; let forest = 0b0110;
let acc = mmr.peaks(forest).unwrap();
let acc = mmr.peaks_at(forest).unwrap();
assert_eq!(acc.num_leaves(), forest); assert_eq!(acc.num_leaves(), forest);
assert_eq!(acc.peaks(), &[mmr.nodes[6], mmr.nodes[9]]); assert_eq!(acc.peaks(), &[mmr.nodes[6], mmr.nodes[9]]);
let forest = 0b0111; let forest = 0b0111;
let acc = mmr.peaks(forest).unwrap();
let acc = mmr.peaks_at(forest).unwrap();
assert_eq!(acc.num_leaves(), forest); assert_eq!(acc.num_leaves(), forest);
assert_eq!(acc.peaks(), &[mmr.nodes[6], mmr.nodes[9], mmr.nodes[10]]); assert_eq!(acc.peaks(), &[mmr.nodes[6], mmr.nodes[9], mmr.nodes[10]]);
} }
@ -603,7 +600,7 @@ fn test_mmr_peaks() {
#[test] #[test]
fn test_mmr_hash_peaks() { fn test_mmr_hash_peaks() {
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
let peaks = mmr.peaks(mmr.forest()).unwrap();
let peaks = mmr.peaks();
let first_peak = Rpo256::merge(&[ let first_peak = Rpo256::merge(&[
Rpo256::merge(&[LEAVES[0], LEAVES[1]]), Rpo256::merge(&[LEAVES[0], LEAVES[1]]),
@ -657,7 +654,7 @@ fn test_mmr_peaks_hash_odd() {
#[test] #[test]
fn test_mmr_delta() { fn test_mmr_delta() {
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
let acc = mmr.peaks(mmr.forest()).unwrap();
let acc = mmr.peaks();
// original_forest can't have more elements // original_forest can't have more elements
assert!( assert!(
@ -757,7 +754,7 @@ fn test_mmr_delta_old_forest() {
#[test] #[test]
fn test_partial_mmr_simple() { fn test_partial_mmr_simple() {
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
let peaks = mmr.peaks(mmr.forest()).unwrap();
let peaks = mmr.peaks();
let mut partial: PartialMmr = peaks.clone().into(); let mut partial: PartialMmr = peaks.clone().into();
// check initial state of the partial mmr // check initial state of the partial mmr
@ -768,7 +765,7 @@ fn test_partial_mmr_simple() {
assert_eq!(partial.nodes.len(), 0); assert_eq!(partial.nodes.len(), 0);
// check state after adding tracking one element // check state after adding tracking one element
let proof1 = mmr.open(0, mmr.forest()).unwrap();
let proof1 = mmr.open(0).unwrap();
let el1 = mmr.get(proof1.position).unwrap(); let el1 = mmr.get(proof1.position).unwrap();
partial.track(proof1.position, el1, &proof1.merkle_path).unwrap(); partial.track(proof1.position, el1, &proof1.merkle_path).unwrap();
@ -780,7 +777,7 @@ fn test_partial_mmr_simple() {
let idx = idx.parent(); let idx = idx.parent();
assert_eq!(partial.nodes[&idx.sibling()], proof1.merkle_path[1]); assert_eq!(partial.nodes[&idx.sibling()], proof1.merkle_path[1]);
let proof2 = mmr.open(1, mmr.forest()).unwrap();
let proof2 = mmr.open(1).unwrap();
let el2 = mmr.get(proof2.position).unwrap(); let el2 = mmr.get(proof2.position).unwrap();
partial.track(proof2.position, el2, &proof2.merkle_path).unwrap(); partial.track(proof2.position, el2, &proof2.merkle_path).unwrap();
@ -798,9 +795,9 @@ fn test_partial_mmr_update_single() {
let mut full = Mmr::new(); let mut full = Mmr::new();
let zero = int_to_node(0); let zero = int_to_node(0);
full.add(zero); full.add(zero);
let mut partial: PartialMmr = full.peaks(full.forest()).unwrap().into();
let mut partial: PartialMmr = full.peaks().into();
let proof = full.open(0, full.forest()).unwrap();
let proof = full.open(0).unwrap();
partial.track(proof.position, zero, &proof.merkle_path).unwrap(); partial.track(proof.position, zero, &proof.merkle_path).unwrap();
for i in 1..100 { for i in 1..100 {
@ -810,9 +807,9 @@ fn test_partial_mmr_update_single() {
partial.apply(delta).unwrap(); partial.apply(delta).unwrap();
assert_eq!(partial.forest(), full.forest()); assert_eq!(partial.forest(), full.forest());
assert_eq!(partial.peaks(), full.peaks(full.forest()).unwrap());
assert_eq!(partial.peaks(), full.peaks());
let proof1 = full.open(i as usize, full.forest()).unwrap();
let proof1 = full.open(i as usize).unwrap();
partial.track(proof1.position, node, &proof1.merkle_path).unwrap(); partial.track(proof1.position, node, &proof1.merkle_path).unwrap();
let proof2 = partial.open(proof1.position).unwrap().unwrap(); let proof2 = partial.open(proof1.position).unwrap().unwrap();
assert_eq!(proof1.merkle_path, proof2.merkle_path); assert_eq!(proof1.merkle_path, proof2.merkle_path);
@ -822,7 +819,7 @@ fn test_partial_mmr_update_single() {
#[test] #[test]
fn test_mmr_add_invalid_odd_leaf() { fn test_mmr_add_invalid_odd_leaf() {
let mmr: Mmr = LEAVES.into(); let mmr: Mmr = LEAVES.into();
let acc = mmr.peaks(mmr.forest()).unwrap();
let acc = mmr.peaks();
let mut partial: PartialMmr = acc.clone().into(); let mut partial: PartialMmr = acc.clone().into();
let empty = MerklePath::new(Vec::new()); let empty = MerklePath::new(Vec::new());

Loading…
Cancel
Save