Rename authentication_path -> witness
This commit is contained in:
parent
ee93cb8598
commit
6b6548f02e
|
@ -153,9 +153,9 @@ impl<H: Hashable + Clone> NonEmptyFrontier<H> {
|
||||||
.0
|
.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs an authentication path for the leaf at the tip of this
|
/// Constructs a witness for the leaf at the tip of this
|
||||||
/// frontier, given a source of node values that complement this frontier.
|
/// frontier, given a source of node values that complement this frontier.
|
||||||
pub fn authentication_path<F>(&self, depth: u8, bridge_value_at: F) -> Result<Vec<H>, PathError>
|
pub fn witness<F>(&self, depth: u8, bridge_value_at: F) -> Result<Vec<H>, PathError>
|
||||||
where
|
where
|
||||||
F: Fn(Address) -> Option<H>,
|
F: Fn(Address) -> Option<H>,
|
||||||
{
|
{
|
||||||
|
@ -349,7 +349,7 @@ impl<H> MerkleBridge<H> {
|
||||||
|
|
||||||
impl<'a, H: Hashable + Ord + Clone + 'a> MerkleBridge<H> {
|
impl<'a, H: Hashable + Ord + Clone + 'a> MerkleBridge<H> {
|
||||||
/// Constructs a new bridge to follow this one. If mark_current_leaf is true, the successor
|
/// Constructs a new bridge to follow this one. If mark_current_leaf is true, the successor
|
||||||
/// will track the information necessary to create an authentication path for the leaf most
|
/// will track the information necessary to create a witness for the leaf most
|
||||||
/// recently appended to this bridge's frontier.
|
/// recently appended to this bridge's frontier.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn successor(&self, mark_current_leaf: bool) -> Self {
|
pub fn successor(&self, mark_current_leaf: bool) -> Self {
|
||||||
|
@ -443,14 +443,14 @@ impl<'a, H: Hashable + Ord + Clone + 'a> MerkleBridge<H> {
|
||||||
/// path for the specified position by interleaving with values from the prior frontier. This
|
/// path for the specified position by interleaving with values from the prior frontier. This
|
||||||
/// method will panic if the position of the prior frontier does not match this bridge's prior
|
/// method will panic if the position of the prior frontier does not match this bridge's prior
|
||||||
/// position.
|
/// position.
|
||||||
fn authentication_path(
|
fn witness(
|
||||||
&self,
|
&self,
|
||||||
depth: u8,
|
depth: u8,
|
||||||
prior_frontier: &NonEmptyFrontier<H>,
|
prior_frontier: &NonEmptyFrontier<H>,
|
||||||
) -> Result<Vec<H>, PathError> {
|
) -> Result<Vec<H>, PathError> {
|
||||||
assert!(Some(prior_frontier.position()) == self.prior_position);
|
assert!(Some(prior_frontier.position()) == self.prior_position);
|
||||||
|
|
||||||
prior_frontier.authentication_path(depth, |addr| {
|
prior_frontier.witness(depth, |addr| {
|
||||||
let r = addr.position_range();
|
let r = addr.position_range();
|
||||||
if self.frontier.position() < r.start {
|
if self.frontier.position() < r.start {
|
||||||
Some(H::empty_root(addr.level))
|
Some(H::empty_root(addr.level))
|
||||||
|
@ -589,8 +589,8 @@ pub struct BridgeTree<H, const DEPTH: u8> {
|
||||||
prior_bridges: Vec<MerkleBridge<H>>,
|
prior_bridges: Vec<MerkleBridge<H>>,
|
||||||
/// The current (mutable) bridge at the tip of the tree.
|
/// The current (mutable) bridge at the tip of the tree.
|
||||||
current_bridge: Option<MerkleBridge<H>>,
|
current_bridge: Option<MerkleBridge<H>>,
|
||||||
/// A map from positions for which we wish to be able to compute an
|
/// A map from positions for which we wish to be able to compute a
|
||||||
/// authentication path to index in the bridges vector.
|
/// witness to index in the bridges vector.
|
||||||
saved: BTreeMap<Position, usize>,
|
saved: BTreeMap<Position, usize>,
|
||||||
/// A stack of bridge indices to which it's possible to rewind directly.
|
/// A stack of bridge indices to which it's possible to rewind directly.
|
||||||
checkpoints: Vec<Checkpoint>,
|
checkpoints: Vec<Checkpoint>,
|
||||||
|
@ -774,11 +774,7 @@ impl<H: Hashable + Ord + Clone, const DEPTH: u8> BridgeTree<H, DEPTH> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn authentication_path_inner(
|
fn witness_inner(&self, position: Position, as_of_root: &H) -> Result<Vec<H>, PathError> {
|
||||||
&self,
|
|
||||||
position: Position,
|
|
||||||
as_of_root: &H,
|
|
||||||
) -> Result<Vec<H>, PathError> {
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum AuthBase<'a> {
|
enum AuthBase<'a> {
|
||||||
Current,
|
Current,
|
||||||
|
@ -861,7 +857,7 @@ impl<H: Hashable + Ord + Clone, const DEPTH: u8> BridgeTree<H, DEPTH> {
|
||||||
}
|
}
|
||||||
.ok_or(PathError::BridgeFusionError)?;
|
.ok_or(PathError::BridgeFusionError)?;
|
||||||
|
|
||||||
successor.authentication_path(DEPTH, prior_frontier)
|
successor.witness(DEPTH, prior_frontier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,8 +1017,8 @@ impl<H: Hashable + Ord + Clone, const DEPTH: u8> Tree<H> for BridgeTree<H, DEPTH
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn authentication_path(&self, position: Position, as_of_root: &H) -> Option<Vec<H>> {
|
fn witness(&self, position: Position, as_of_root: &H) -> Option<Vec<H>> {
|
||||||
self.authentication_path_inner(position, as_of_root).ok()
|
self.witness_inner(position, as_of_root).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn garbage_collect(&mut self) {
|
fn garbage_collect(&mut self) {
|
||||||
|
@ -1149,7 +1145,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn frontier_auth_path() {
|
fn frontier_witness() {
|
||||||
let mut frontier = NonEmptyFrontier::<String>::new("a".to_string());
|
let mut frontier = NonEmptyFrontier::<String>::new("a".to_string());
|
||||||
for c in 'b'..'h' {
|
for c in 'b'..'h' {
|
||||||
frontier.append(c.to_string());
|
frontier.append(c.to_string());
|
||||||
|
@ -1164,7 +1160,7 @@ mod tests {
|
||||||
Ok(["h", "ef", "abcd", "xxxxxxxx"]
|
Ok(["h", "ef", "abcd", "xxxxxxxx"]
|
||||||
.map(|v| v.to_string())
|
.map(|v| v.to_string())
|
||||||
.to_vec()),
|
.to_vec()),
|
||||||
frontier.authentication_path(4, bridge_value_at)
|
frontier.witness(4, bridge_value_at)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1228,8 +1224,8 @@ mod tests {
|
||||||
|
|
||||||
for pos in tree.saved.keys() {
|
for pos in tree.saved.keys() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(*pos, &tree.root(0).unwrap()),
|
tree.witness(*pos, &tree.root(0).unwrap()),
|
||||||
tree_mut.authentication_path(*pos, &tree.root(0).unwrap())
|
tree_mut.witness(*pos, &tree.root(0).unwrap())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1256,8 +1252,8 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn auth_paths() {
|
fn witnesss() {
|
||||||
crate::tests::check_auth_paths(BridgeTree::<String, 4>::new);
|
crate::tests::check_witnesss(BridgeTree::<String, 4>::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1274,7 +1270,7 @@ mod tests {
|
||||||
fn garbage_collect() {
|
fn garbage_collect() {
|
||||||
let mut t = BridgeTree::<String, 7>::new(10);
|
let mut t = BridgeTree::<String, 7>::new(10);
|
||||||
let mut to_unmark = vec![];
|
let mut to_unmark = vec![];
|
||||||
let mut has_auth_path = vec![];
|
let mut has_witness = vec![];
|
||||||
for i in 0usize..100 {
|
for i in 0usize..100 {
|
||||||
let elem: String = format!("{},", i);
|
let elem: String = format!("{},", i);
|
||||||
assert!(t.append(&elem), "Append should succeed.");
|
assert!(t.append(&elem), "Append should succeed.");
|
||||||
|
@ -1286,7 +1282,7 @@ mod tests {
|
||||||
if i > 0 && i % 2 == 0 {
|
if i > 0 && i % 2 == 0 {
|
||||||
to_unmark.push(Position::from(i));
|
to_unmark.push(Position::from(i));
|
||||||
} else {
|
} else {
|
||||||
has_auth_path.push(Position::from(i));
|
has_witness.push(Position::from(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i % 11 == 0 && !to_unmark.is_empty() {
|
if i % 11 == 0 && !to_unmark.is_empty() {
|
||||||
|
@ -1296,26 +1292,24 @@ mod tests {
|
||||||
}
|
}
|
||||||
// 32 = 20 (checkpointed) + 14 (marked) - 2 (marked & checkpointed)
|
// 32 = 20 (checkpointed) + 14 (marked) - 2 (marked & checkpointed)
|
||||||
assert_eq!(t.prior_bridges().len(), 20 + 14 - 2);
|
assert_eq!(t.prior_bridges().len(), 20 + 14 - 2);
|
||||||
let auth_paths = has_auth_path
|
let witnesss = has_witness
|
||||||
.iter()
|
.iter()
|
||||||
.map(
|
.map(|pos| match t.witness_inner(*pos, &t.root(0).unwrap()) {
|
||||||
|pos| match t.authentication_path_inner(*pos, &t.root(0).unwrap()) {
|
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(e) => panic!("Failed to get auth path: {:?}", e),
|
Err(e) => panic!("Failed to get auth path: {:?}", e),
|
||||||
},
|
})
|
||||||
)
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
t.garbage_collect();
|
t.garbage_collect();
|
||||||
// 20 = 32 - 10 (removed checkpoints) + 1 (not removed due to mark) - 3 (removed marks)
|
// 20 = 32 - 10 (removed checkpoints) + 1 (not removed due to mark) - 3 (removed marks)
|
||||||
assert_eq!(t.prior_bridges().len(), 32 - 10 + 1 - 3);
|
assert_eq!(t.prior_bridges().len(), 32 - 10 + 1 - 3);
|
||||||
let retained_auth_paths = has_auth_path
|
let retained_witnesss = has_witness
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pos| {
|
.map(|pos| {
|
||||||
t.authentication_path(*pos, &t.root(0).unwrap())
|
t.witness(*pos, &t.root(0).unwrap())
|
||||||
.expect("Must be able to get auth path")
|
.expect("Must be able to get auth path")
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert_eq!(auth_paths, retained_auth_paths);
|
assert_eq!(witnesss, retained_witnesss);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
109
src/lib.rs
109
src/lib.rs
|
@ -10,8 +10,8 @@
|
||||||
//! ## Marking
|
//! ## Marking
|
||||||
//!
|
//!
|
||||||
//! Merkle trees are typically used to show that a value exists in the tree via
|
//! Merkle trees are typically used to show that a value exists in the tree via
|
||||||
//! an authentication path. We need an API that allows us to identify the
|
//! a witness. We need an API that allows us to identify the
|
||||||
//! current leaf as a value we wish to compute authentication paths for even as
|
//! current leaf as a value we wish to compute witnesss for even as
|
||||||
//! the tree continues to be appended to in the future; this is called
|
//! the tree continues to be appended to in the future; this is called
|
||||||
//! maintaining a witness. When we're later uninterested in such a leaf, we can
|
//! maintaining a witness. When we're later uninterested in such a leaf, we can
|
||||||
//! prune a witness and remove all unnecessary information from the structure as
|
//! prune a witness and remove all unnecessary information from the structure as
|
||||||
|
@ -362,11 +362,11 @@ pub trait Tree<H> {
|
||||||
fn current_leaf(&self) -> Option<&H>;
|
fn current_leaf(&self) -> Option<&H>;
|
||||||
|
|
||||||
/// Returns the leaf at the specified position if the tree can produce
|
/// Returns the leaf at the specified position if the tree can produce
|
||||||
/// an authentication path for it.
|
/// a witness for it.
|
||||||
fn get_marked_leaf(&self, position: Position) -> Option<&H>;
|
fn get_marked_leaf(&self, position: Position) -> Option<&H>;
|
||||||
|
|
||||||
/// Marks the current leaf as one for which we're interested in producing
|
/// Marks the current leaf as one for which we're interested in producing
|
||||||
/// an authentication path. Returns an optional value containing the
|
/// a witness. Returns an optional value containing the
|
||||||
/// current position if successful or if the current value was already
|
/// current position if successful or if the current value was already
|
||||||
/// marked, or None if the tree is empty.
|
/// marked, or None if the tree is empty.
|
||||||
fn mark(&mut self) -> Option<Position>;
|
fn mark(&mut self) -> Option<Position>;
|
||||||
|
@ -380,12 +380,12 @@ pub trait Tree<H> {
|
||||||
/// requested checkpoint depth.
|
/// requested checkpoint depth.
|
||||||
fn root(&self, checkpoint_depth: usize) -> Option<H>;
|
fn root(&self, checkpoint_depth: usize) -> Option<H>;
|
||||||
|
|
||||||
/// Obtains an authentication path to the value at the specified position,
|
/// Obtains a witness to the value at the specified position,
|
||||||
/// as of the tree state corresponding to the given root.
|
/// as of the tree state corresponding to the given root.
|
||||||
/// Returns `None` if there is no available authentication path to that
|
/// Returns `None` if there is no available witness to that
|
||||||
/// position or if the root does not correspond to a checkpointed
|
/// position or if the root does not correspond to a checkpointed
|
||||||
/// root of the tree.
|
/// root of the tree.
|
||||||
fn authentication_path(&self, position: Position, as_of_root: &H) -> Option<Vec<H>>;
|
fn witness(&self, position: Position, as_of_root: &H) -> Option<Vec<H>>;
|
||||||
|
|
||||||
/// Marks the value at the specified position as a value we're no longer
|
/// Marks the value at the specified position as a value we're no longer
|
||||||
/// interested in maintaining a mark for. Returns true if successful and
|
/// interested in maintaining a mark for. Returns true if successful and
|
||||||
|
@ -577,14 +577,14 @@ pub(crate) mod tests {
|
||||||
assert_eq!(t.root(0).unwrap(), "aaaa____________");
|
assert_eq!(t.root(0).unwrap(), "aaaa____________");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_auth_paths<T: Tree<String> + std::fmt::Debug, F: Fn(usize) -> T>(
|
pub(crate) fn check_witnesss<T: Tree<String> + std::fmt::Debug, F: Fn(usize) -> T>(
|
||||||
new_tree: F,
|
new_tree: F,
|
||||||
) {
|
) {
|
||||||
let mut tree = new_tree(100);
|
let mut tree = new_tree(100);
|
||||||
tree.append(&"a".to_string());
|
tree.append(&"a".to_string());
|
||||||
tree.mark();
|
tree.mark();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(Position(0), &tree.root(0).unwrap()),
|
tree.witness(Position(0), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"_".to_string(),
|
"_".to_string(),
|
||||||
"__".to_string(),
|
"__".to_string(),
|
||||||
|
@ -595,7 +595,7 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
tree.append(&"b".to_string());
|
tree.append(&"b".to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(0.into(), &tree.root(0).unwrap()),
|
tree.witness(0.into(), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"b".to_string(),
|
"b".to_string(),
|
||||||
"__".to_string(),
|
"__".to_string(),
|
||||||
|
@ -607,7 +607,7 @@ pub(crate) mod tests {
|
||||||
tree.append(&"c".to_string());
|
tree.append(&"c".to_string());
|
||||||
tree.mark();
|
tree.mark();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(Position(2), &tree.root(0).unwrap()),
|
tree.witness(Position(2), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"_".to_string(),
|
"_".to_string(),
|
||||||
"ab".to_string(),
|
"ab".to_string(),
|
||||||
|
@ -618,7 +618,7 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
tree.append(&"d".to_string());
|
tree.append(&"d".to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(Position(2), &tree.root(0).unwrap()),
|
tree.witness(Position(2), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"d".to_string(),
|
"d".to_string(),
|
||||||
"ab".to_string(),
|
"ab".to_string(),
|
||||||
|
@ -629,7 +629,7 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
tree.append(&"e".to_string());
|
tree.append(&"e".to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(Position(2), &tree.root(0).unwrap()),
|
tree.witness(Position(2), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"d".to_string(),
|
"d".to_string(),
|
||||||
"ab".to_string(),
|
"ab".to_string(),
|
||||||
|
@ -648,7 +648,7 @@ pub(crate) mod tests {
|
||||||
tree.append(&"h".to_string());
|
tree.append(&"h".to_string());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(0.into(), &tree.root(0).unwrap()),
|
tree.witness(0.into(), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"b".to_string(),
|
"b".to_string(),
|
||||||
"cd".to_string(),
|
"cd".to_string(),
|
||||||
|
@ -671,7 +671,7 @@ pub(crate) mod tests {
|
||||||
tree.append(&"g".to_string());
|
tree.append(&"g".to_string());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(Position(5), &tree.root(0).unwrap()),
|
tree.witness(Position(5), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"e".to_string(),
|
"e".to_string(),
|
||||||
"g_".to_string(),
|
"g_".to_string(),
|
||||||
|
@ -688,7 +688,7 @@ pub(crate) mod tests {
|
||||||
tree.append(&'l'.to_string());
|
tree.append(&'l'.to_string());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(Position(10), &tree.root(0).unwrap()),
|
tree.witness(Position(10), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"l".to_string(),
|
"l".to_string(),
|
||||||
"ij".to_string(),
|
"ij".to_string(),
|
||||||
|
@ -711,7 +711,7 @@ pub(crate) mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(0.into(), &tree.root(0).unwrap()),
|
tree.witness(0.into(), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"b".to_string(),
|
"b".to_string(),
|
||||||
"cd".to_string(),
|
"cd".to_string(),
|
||||||
|
@ -735,7 +735,7 @@ pub(crate) mod tests {
|
||||||
assert!(tree.rewind());
|
assert!(tree.rewind());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(Position(2), &tree.root(0).unwrap()),
|
tree.witness(Position(2), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"d".to_string(),
|
"d".to_string(),
|
||||||
"ab".to_string(),
|
"ab".to_string(),
|
||||||
|
@ -748,10 +748,7 @@ pub(crate) mod tests {
|
||||||
tree.append(&'a'.to_string());
|
tree.append(&'a'.to_string());
|
||||||
tree.append(&'b'.to_string());
|
tree.append(&'b'.to_string());
|
||||||
tree.mark();
|
tree.mark();
|
||||||
assert_eq!(
|
assert_eq!(tree.witness(Position(0), &tree.root(0).unwrap()), None);
|
||||||
tree.authentication_path(Position(0), &tree.root(0).unwrap()),
|
|
||||||
None
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut tree = new_tree(100);
|
let mut tree = new_tree(100);
|
||||||
for c in 'a'..'n' {
|
for c in 'a'..'n' {
|
||||||
|
@ -764,7 +761,7 @@ pub(crate) mod tests {
|
||||||
tree.append(&'p'.to_string());
|
tree.append(&'p'.to_string());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tree.authentication_path(Position(12), &tree.root(0).unwrap()),
|
tree.witness(Position(12), &tree.root(0).unwrap()),
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"n".to_string(),
|
"n".to_string(),
|
||||||
"op".to_string(),
|
"op".to_string(),
|
||||||
|
@ -890,14 +887,7 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
let samples = vec![
|
let samples = vec![
|
||||||
vec![append("x"), Checkpoint, Mark, Rewind, unmark(0)],
|
vec![append("x"), Checkpoint, Mark, Rewind, unmark(0)],
|
||||||
vec![
|
vec![append("d"), Checkpoint, Mark, unmark(0), Rewind, unmark(0)],
|
||||||
append("d"),
|
|
||||||
Checkpoint,
|
|
||||||
Mark,
|
|
||||||
unmark(0),
|
|
||||||
Rewind,
|
|
||||||
unmark(0),
|
|
||||||
],
|
|
||||||
vec![
|
vec![
|
||||||
append("o"),
|
append("o"),
|
||||||
Checkpoint,
|
Checkpoint,
|
||||||
|
@ -1002,9 +992,9 @@ pub(crate) mod tests {
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
fn authentication_path(&self, position: Position, as_of_root: &H) -> Option<Vec<H>> {
|
fn witness(&self, position: Position, as_of_root: &H) -> Option<Vec<H>> {
|
||||||
let a = self.inefficient.authentication_path(position, as_of_root);
|
let a = self.inefficient.witness(position, as_of_root);
|
||||||
let b = self.efficient.authentication_path(position, as_of_root);
|
let b = self.efficient.witness(position, as_of_root);
|
||||||
assert_eq!(a, b);
|
assert_eq!(a, b);
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
@ -1096,7 +1086,7 @@ pub(crate) mod tests {
|
||||||
}
|
}
|
||||||
Authpath(p, d) => tree
|
Authpath(p, d) => tree
|
||||||
.root(*d)
|
.root(*d)
|
||||||
.and_then(|root| tree.authentication_path(*p, &root))
|
.and_then(|root| tree.witness(*p, &root))
|
||||||
.map(|xs| (*p, xs)),
|
.map(|xs| (*p, xs)),
|
||||||
GarbageCollect => None,
|
GarbageCollect => None,
|
||||||
}
|
}
|
||||||
|
@ -1114,7 +1104,7 @@ pub(crate) mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compute_root_from_auth_path<H: Hashable>(
|
pub(crate) fn compute_root_from_witness<H: Hashable>(
|
||||||
value: H,
|
value: H,
|
||||||
position: Position,
|
position: Position,
|
||||||
path: &[H],
|
path: &[H],
|
||||||
|
@ -1137,7 +1127,7 @@ pub(crate) mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_compute_root_from_auth_path() {
|
fn test_compute_root_from_witness() {
|
||||||
let expected = SipHashable::combine(
|
let expected = SipHashable::combine(
|
||||||
<Level>::from(2),
|
<Level>::from(2),
|
||||||
&SipHashable::combine(
|
&SipHashable::combine(
|
||||||
|
@ -1153,7 +1143,7 @@ pub(crate) mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compute_root_from_auth_path::<SipHashable>(
|
compute_root_from_witness::<SipHashable>(
|
||||||
SipHashable(0),
|
SipHashable(0),
|
||||||
0.into(),
|
0.into(),
|
||||||
&[
|
&[
|
||||||
|
@ -1170,7 +1160,7 @@ pub(crate) mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compute_root_from_auth_path(
|
compute_root_from_witness(
|
||||||
SipHashable(4),
|
SipHashable(4),
|
||||||
<Position>::from(4),
|
<Position>::from(4),
|
||||||
&[
|
&[
|
||||||
|
@ -1188,30 +1178,12 @@ pub(crate) mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_auth_path_consistency() {
|
fn test_witness_consistency() {
|
||||||
let samples = vec![
|
let samples = vec![
|
||||||
// Reduced examples
|
// Reduced examples
|
||||||
vec![
|
vec![append("a"), append("b"), Checkpoint, Mark, authpath(0, 1)],
|
||||||
append("a"),
|
vec![append("c"), append("d"), Mark, Checkpoint, authpath(1, 1)],
|
||||||
append("b"),
|
vec![append("e"), Checkpoint, Mark, append("f"), authpath(0, 1)],
|
||||||
Checkpoint,
|
|
||||||
Mark,
|
|
||||||
authpath(0, 1),
|
|
||||||
],
|
|
||||||
vec![
|
|
||||||
append("c"),
|
|
||||||
append("d"),
|
|
||||||
Mark,
|
|
||||||
Checkpoint,
|
|
||||||
authpath(1, 1),
|
|
||||||
],
|
|
||||||
vec![
|
|
||||||
append("e"),
|
|
||||||
Checkpoint,
|
|
||||||
Mark,
|
|
||||||
append("f"),
|
|
||||||
authpath(0, 1),
|
|
||||||
],
|
|
||||||
vec![
|
vec![
|
||||||
append("g"),
|
append("g"),
|
||||||
Mark,
|
Mark,
|
||||||
|
@ -1334,14 +1306,7 @@ pub(crate) mod tests {
|
||||||
fn test_rewind_remove_mark_consistency() {
|
fn test_rewind_remove_mark_consistency() {
|
||||||
let samples = vec![
|
let samples = vec![
|
||||||
vec![append("x"), Checkpoint, Mark, Rewind, unmark(0)],
|
vec![append("x"), Checkpoint, Mark, Rewind, unmark(0)],
|
||||||
vec![
|
vec![append("d"), Checkpoint, Mark, unmark(0), Rewind, unmark(0)],
|
||||||
append("d"),
|
|
||||||
Checkpoint,
|
|
||||||
Mark,
|
|
||||||
unmark(0),
|
|
||||||
Rewind,
|
|
||||||
unmark(0),
|
|
||||||
],
|
|
||||||
vec![
|
vec![
|
||||||
append("o"),
|
append("o"),
|
||||||
Checkpoint,
|
Checkpoint,
|
||||||
|
@ -1490,9 +1455,7 @@ pub(crate) mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Authpath(position, depth) => {
|
Authpath(position, depth) => {
|
||||||
if let Some(path) = tree
|
if let Some(path) = tree.root(*depth).and_then(|r| tree.witness(*position, &r))
|
||||||
.root(*depth)
|
|
||||||
.and_then(|r| tree.authentication_path(*position, &r))
|
|
||||||
{
|
{
|
||||||
let value: H = tree_values[<usize>::from(*position)].clone();
|
let value: H = tree_values[<usize>::from(*position)].clone();
|
||||||
let tree_root = tree.root(*depth);
|
let tree_root = tree.root(*depth);
|
||||||
|
@ -1515,7 +1478,7 @@ pub(crate) mod tests {
|
||||||
prop_assert_eq!(&tree_root.unwrap(), &expected_root);
|
prop_assert_eq!(&tree_root.unwrap(), &expected_root);
|
||||||
|
|
||||||
prop_assert_eq!(
|
prop_assert_eq!(
|
||||||
&compute_root_from_auth_path(value, *position, &path),
|
&compute_root_from_witness(value, *position, &path),
|
||||||
&expected_root
|
&expected_root
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl<H: Hashable + PartialEq + Clone> TreeState<H> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the leaf at the specified position if the tree can produce
|
/// Returns the leaf at the specified position if the tree can produce
|
||||||
/// an authentication path for it.
|
/// a witness for it.
|
||||||
fn get_marked_leaf(&self, position: Position) -> Option<&H> {
|
fn get_marked_leaf(&self, position: Position) -> Option<&H> {
|
||||||
if self.marks.contains(&position) {
|
if self.marks.contains(&position) {
|
||||||
self.leaves.get(<usize>::from(position))
|
self.leaves.get(<usize>::from(position))
|
||||||
|
@ -74,10 +74,10 @@ impl<H: Hashable + PartialEq + Clone> TreeState<H> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtains an authentication path to the value at the specified position.
|
/// Obtains a witness to the value at the specified position.
|
||||||
/// Returns `None` if there is no available authentication path to that
|
/// Returns `None` if there is no available witness to that
|
||||||
/// value.
|
/// value.
|
||||||
fn authentication_path(&self, position: Position) -> Option<Vec<H>> {
|
fn witness(&self, position: Position) -> Option<Vec<H>> {
|
||||||
if Some(position) <= self.current_position() {
|
if Some(position) <= self.current_position() {
|
||||||
let mut path = vec![];
|
let mut path = vec![];
|
||||||
|
|
||||||
|
@ -183,9 +183,9 @@ impl<H: Hashable + PartialEq + Clone + std::fmt::Debug> Tree<H> for CompleteTree
|
||||||
.map(|s| s.root())
|
.map(|s| s.root())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn authentication_path(&self, position: Position, root: &H) -> Option<Vec<H>> {
|
fn witness(&self, position: Position, root: &H) -> Option<Vec<H>> {
|
||||||
// Search for the checkpointed state corresponding to the provided root, and if one is
|
// Search for the checkpointed state corresponding to the provided root, and if one is
|
||||||
// found, compute the authentication path as of that root.
|
// found, compute the witness as of that root.
|
||||||
self.checkpoints
|
self.checkpoints
|
||||||
.iter()
|
.iter()
|
||||||
.chain(Some(&self.tree_state))
|
.chain(Some(&self.tree_state))
|
||||||
|
@ -193,7 +193,7 @@ impl<H: Hashable + PartialEq + Clone + std::fmt::Debug> Tree<H> for CompleteTree
|
||||||
.skip_while(|c| !c.marks.contains(&position))
|
.skip_while(|c| !c.marks.contains(&position))
|
||||||
.find_map(|c| {
|
.find_map(|c| {
|
||||||
if &c.root() == root {
|
if &c.root() == root {
|
||||||
c.authentication_path(position)
|
c.witness(position)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,7 @@ pub(crate) fn lazy_root<H: Hashable + Clone>(mut leaves: Vec<H>) -> H {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests::{compute_root_from_auth_path, SipHashable};
|
use crate::tests::{compute_root_from_witness, SipHashable};
|
||||||
use crate::{Hashable, Level, Position, Tree};
|
use crate::{Hashable, Level, Position, Tree};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
@ -303,12 +303,12 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn auth_paths() {
|
fn witnesss() {
|
||||||
crate::tests::check_auth_paths(|max_c| CompleteTree::<String>::new(4, max_c));
|
crate::tests::check_witnesss(|max_c| CompleteTree::<String>::new(4, max_c));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn correct_auth_path() {
|
fn correct_witness() {
|
||||||
const DEPTH: usize = 3;
|
const DEPTH: usize = 3;
|
||||||
let values = (0..(1 << DEPTH)).into_iter().map(SipHashable);
|
let values = (0..(1 << DEPTH)).into_iter().map(SipHashable);
|
||||||
|
|
||||||
|
@ -337,11 +337,9 @@ mod tests {
|
||||||
|
|
||||||
for i in 0u64..(1 << DEPTH) {
|
for i in 0u64..(1 << DEPTH) {
|
||||||
let position = Position::try_from(i).unwrap();
|
let position = Position::try_from(i).unwrap();
|
||||||
let path = tree
|
let path = tree.witness(position, &tree.root(0).unwrap()).unwrap();
|
||||||
.authentication_path(position, &tree.root(0).unwrap())
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compute_root_from_auth_path(SipHashable(i), position, &path),
|
compute_root_from_witness(SipHashable(i), position, &path),
|
||||||
expected
|
expected
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue