mirror of
https://github.com/mii443/merkle.rs.git
synced 2025-08-22 16:05:30 +00:00
Traverse tree only once for proof generation.
This commit is contained in:
committed by
Romain Ruetschi
parent
205853656b
commit
4f60edafcd
@ -166,14 +166,8 @@ impl<T> MerkleTree<T> {
|
|||||||
T: Hashable + Clone,
|
T: Hashable + Clone,
|
||||||
{
|
{
|
||||||
let root_hash = self.root_hash().clone();
|
let root_hash = self.root_hash().clone();
|
||||||
let value = if let Some(value) = self.root.nth_leaf(n, self.count) {
|
|
||||||
value
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
|
|
||||||
Lemma::new_by_index(&self.root, n, self.count)
|
Lemma::new_by_index(&self.root, n, self.count)
|
||||||
.map(|lemma| Proof::new(self.algorithm, root_hash, lemma, value.clone()))
|
.map(|(lemma, value)| Proof::new(self.algorithm, root_hash, lemma, value.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an `Iterator` over the values contained in this Merkle tree.
|
/// Creates an `Iterator` over the values contained in this Merkle tree.
|
||||||
|
65
src/proof.rs
65
src/proof.rs
@ -194,30 +194,54 @@ impl Lemma {
|
|||||||
|
|
||||||
/// Attempts to generate a proof that the `idx`-th leaf is a member of
|
/// Attempts to generate a proof that the `idx`-th leaf is a member of
|
||||||
/// the given tree. The `count` must equal the number of leaves in the
|
/// the given tree. The `count` must equal the number of leaves in the
|
||||||
/// `tree`. If `idx >= count`, `None` is returned.
|
/// `tree`. If `idx >= count`, `None` is returned. Otherwise it returns
|
||||||
pub fn new_by_index<T>(tree: &Tree<T>, idx: usize, count: usize) -> Option<Lemma> {
|
/// the new `Lemma` and the `idx`-th value.
|
||||||
|
pub fn new_by_index<T>(tree: &Tree<T>, idx: usize, count: usize) -> Option<(Lemma, &T)> {
|
||||||
if idx >= count {
|
if idx >= count {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
match *tree {
|
match *tree {
|
||||||
Tree::Empty { .. } => None,
|
Tree::Empty { .. } => None,
|
||||||
|
|
||||||
Tree::Leaf { ref hash, .. } => {
|
Tree::Leaf {
|
||||||
|
ref hash,
|
||||||
|
ref value,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
if count != 1 {
|
if count != 1 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(Lemma {
|
let lemma = Lemma {
|
||||||
node_hash: hash.clone(),
|
node_hash: hash.clone(),
|
||||||
sibling_hash: None,
|
sibling_hash: None,
|
||||||
sub_lemma: None,
|
sub_lemma: None,
|
||||||
})
|
};
|
||||||
|
Some((lemma, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
Tree::Node {
|
Tree::Node {
|
||||||
ref hash,
|
ref hash,
|
||||||
ref left,
|
ref left,
|
||||||
ref right,
|
ref right,
|
||||||
} => Lemma::new_tree_proof_by_index(hash, idx, count, left, right),
|
} => {
|
||||||
|
let left_count = count.next_power_of_two() / 2;
|
||||||
|
let (sub_lem_val, sibling_hash);
|
||||||
|
if idx < left_count {
|
||||||
|
sub_lem_val = Lemma::new_by_index(left, idx, left_count);
|
||||||
|
sibling_hash = Positioned::Right(right.hash().clone());
|
||||||
|
} else {
|
||||||
|
sub_lem_val = Lemma::new_by_index(right, idx - left_count, count - left_count);
|
||||||
|
sibling_hash = Positioned::Left(left.hash().clone());
|
||||||
|
}
|
||||||
|
sub_lem_val.map(|(sub_lemma, value)| {
|
||||||
|
let lemma = Lemma {
|
||||||
|
node_hash: hash.clone(),
|
||||||
|
sibling_hash: Some(sibling_hash),
|
||||||
|
sub_lemma: Some(Box::new(sub_lemma)),
|
||||||
|
};
|
||||||
|
(lemma, value)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,35 +317,6 @@ impl Lemma {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_tree_proof_by_index<T>(
|
|
||||||
hash: &[u8],
|
|
||||||
idx: usize,
|
|
||||||
count: usize,
|
|
||||||
left: &Tree<T>,
|
|
||||||
right: &Tree<T>,
|
|
||||||
) -> Option<Lemma> {
|
|
||||||
let left_count = count.next_power_of_two() / 2;
|
|
||||||
Lemma::new_by_index(left, idx, left_count)
|
|
||||||
.map(|lemma| {
|
|
||||||
let right_hash = right.hash().clone();
|
|
||||||
let sub_lemma = Some(Positioned::Right(right_hash));
|
|
||||||
(lemma, sub_lemma)
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
|
||||||
let sub_lemma = Lemma::new_by_index(right, idx - left_count, count - left_count);
|
|
||||||
sub_lemma.map(|lemma| {
|
|
||||||
let left_hash = left.hash().clone();
|
|
||||||
let sub_lemma = Some(Positioned::Left(left_hash));
|
|
||||||
(lemma, sub_lemma)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.map(|(sub_lemma, sibling_hash)| Lemma {
|
|
||||||
node_hash: hash.into(),
|
|
||||||
sibling_hash,
|
|
||||||
sub_lemma: Some(Box::new(sub_lemma)),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tags a value so that we know from which branch of a `Tree` (if any) it was found.
|
/// Tags a value so that we know from which branch of a `Tree` (if any) it was found.
|
||||||
|
@ -164,6 +164,9 @@ fn test_nth_proof() {
|
|||||||
assert!(proof.validate(&root_hash));
|
assert!(proof.validate(&root_hash));
|
||||||
assert_eq!(i, proof.index(tree.count()));
|
assert_eq!(i, proof.index(tree.count()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert!(tree.gen_nth_proof(count).is_none());
|
||||||
|
assert!(tree.gen_nth_proof(count + 1000).is_none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
src/tree.rs
29
src/tree.rs
@ -61,35 +61,6 @@ impl<T> Tree<T> {
|
|||||||
pub fn iter(&self) -> LeavesIterator<T> {
|
pub fn iter(&self) -> LeavesIterator<T> {
|
||||||
LeavesIterator::new(self)
|
LeavesIterator::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `n`-th leaf value, given the total `count`.
|
|
||||||
pub fn nth_leaf(&self, n: usize, count: usize) -> Option<&T> {
|
|
||||||
if n >= count {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let left_count = count.next_power_of_two() >> 1;
|
|
||||||
match *self {
|
|
||||||
Tree::Empty { .. } => None,
|
|
||||||
Tree::Leaf { ref value, .. } => {
|
|
||||||
if n == 0 {
|
|
||||||
Some(value)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tree::Node {
|
|
||||||
ref left,
|
|
||||||
ref right,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
if n < left_count {
|
|
||||||
left.nth_leaf(n, left_count)
|
|
||||||
} else {
|
|
||||||
right.nth_leaf(n - left_count, count - left_count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An borrowing iterator over the leaves of a `Tree`.
|
/// An borrowing iterator over the leaves of a `Tree`.
|
||||||
|
Reference in New Issue
Block a user