Skip to content

Commit

Permalink
Merge pull request #73 from nuttycom/frontier_witness
Browse files Browse the repository at this point in the history
Add the ability to compute a `MerklePath` from a Frontier
  • Loading branch information
nuttycom authored May 24, 2023
2 parents beb6ead + b43902f commit 62f0c90
Showing 1 changed file with 43 additions and 3 deletions.
46 changes: 43 additions & 3 deletions incrementalmerkletree/src/frontier.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::convert::TryFrom;
use std::mem::size_of;

use crate::{Address, Hashable, Level, Position, Source};
use crate::{Address, Hashable, Level, MerklePath, Position, Source};

#[cfg(feature = "legacy-api")]
use {std::collections::VecDeque, std::iter::repeat};
Expand Down Expand Up @@ -248,6 +248,27 @@ impl<H: Hashable + Clone, const DEPTH: u8> Frontier<H, DEPTH> {
frontier.root(Some(DEPTH.into()))
})
}

/// Constructs a Merkle path that is suitable as a witness for the leaf at the tip of this
/// frontier by using empty roots for the right-hand ommers. This is generally only useful
/// for testing, so is not exposed in the public API.
///
/// Returns `Ok(Some(MerklePath))` if successful, `Ok(None)` if the frontier is empty,
/// or an error containing the address of the failure.
pub fn witness<F>(&self, complement_nodes: F) -> Result<Option<MerklePath<H, DEPTH>>, Address>
where
F: Fn(Address) -> Option<H>,
{
self.frontier
.as_ref()
.map(|f| {
f.witness(DEPTH, complement_nodes).map(|path_elems| {
MerklePath::from_parts(path_elems, f.position())
.expect("Path length should be equal to frontier depth.")
})
})
.transpose()
}
}

#[cfg(feature = "legacy-api")]
Expand Down Expand Up @@ -604,9 +625,9 @@ mod tests {
}

#[test]
fn frontier_witness() {
fn nonempty_frontier_witness() {
let mut frontier = NonEmptyFrontier::<String>::new("a".to_string());
for c in 'b'..'h' {
for c in 'b'..='g' {
frontier.append(c.to_string());
}
let bridge_value_at = |addr: Address| match <u8>::from(addr.level()) {
Expand All @@ -623,6 +644,25 @@ mod tests {
);
}

#[test]
fn frontier_witness() {
let mut frontier = Frontier::<String, 4>::empty();
for c in 'a'..='g' {
frontier.append(c.to_string());
}

assert_eq!(
frontier
.witness(|addr| Some(String::empty_root(addr.level())))
.map(|maybe_p| maybe_p.map(|p| p.path_elems().to_vec())),
Ok(Some(
["_", "ef", "abcd", "________"]
.map(|v| v.to_string())
.to_vec()
)),
);
}

#[test]
#[cfg(feature = "legacy-api")]
fn test_commitment_tree_complete() {
Expand Down

0 comments on commit 62f0c90

Please sign in to comment.