Anchor computation is partial.

This commit is contained in:
Kris Nuttycombe 2021-06-24 09:43:10 -06:00
parent 52394b8e8d
commit 78adc9c810
2 changed files with 10 additions and 10 deletions

View File

@ -211,7 +211,8 @@ impl Builder {
// Consistency check: all anchors must be equal. // Consistency check: all anchors must be equal.
let cm = note.commitment(); let cm = note.commitment();
let path_root: Anchor = merkle_path.root(cm.into()); let path_root: Anchor =
<Option<_>>::from(merkle_path.root(cm.into())).ok_or("Derived the bottom anchor")?;
if path_root != self.anchor { if path_root != self.anchor {
return Err("All anchors must be equal."); return Err("All anchors must be equal.");
} }

View File

@ -89,16 +89,15 @@ impl MerklePath {
/// - when hashing two leaves, we produce a node on the layer above the leaves, i.e. /// - when hashing two leaves, we produce a node on the layer above the leaves, i.e.
/// layer = 31, l = 0 /// layer = 31, l = 0
/// - when hashing to the final root, we produce the anchor with layer = 0, l = 31. /// - when hashing to the final root, we produce the anchor with layer = 0, l = 31.
pub fn root(&self, cmx: ExtractedNoteCommitment) -> Anchor { pub fn root(&self, cmx: ExtractedNoteCommitment) -> CtOption<Anchor> {
let node = self self.auth_path
.auth_path
.iter() .iter()
.enumerate() .enumerate()
.fold(*cmx, |node, (l, sibling)| { .fold(CtOption::new(*cmx, 1.into()), |node, (l, sibling)| {
let swap = self.position & (1 << l) != 0; let swap = self.position & (1 << l) != 0;
hash_with_l(l, cond_swap(swap, node, *sibling)).unwrap() node.and_then(|n| hash_with_l(l, cond_swap(swap, n, *sibling)))
}); })
Anchor(node) .map(Anchor)
} }
/// Returns the position of the leaf using this Merkle path. /// Returns the position of the leaf using this Merkle path.
@ -365,7 +364,7 @@ pub mod testing {
}; };
// Compute anchor for this tree // Compute anchor for this tree
let anchor = auth_paths[0].root(notes[0].commitment().into()); let anchor = auth_paths[0].root(notes[0].commitment().into()).unwrap();
( (
notes.into_iter().zip(auth_paths.into_iter()).map(|(note, auth_path)| (note, auth_path)).collect(), notes.into_iter().zip(auth_paths.into_iter()).map(|(note, auth_path)| (note, auth_path)).collect(),
@ -382,7 +381,7 @@ pub mod testing {
(notes_and_auth_paths, anchor) in (1usize..4).prop_flat_map(|n_notes| arb_tree(n_notes)) (notes_and_auth_paths, anchor) in (1usize..4).prop_flat_map(|n_notes| arb_tree(n_notes))
) { ) {
for (note, auth_path) in notes_and_auth_paths.iter() { for (note, auth_path) in notes_and_auth_paths.iter() {
let computed_anchor = auth_path.root(note.commitment().into()); let computed_anchor = auth_path.root(note.commitment().into()).unwrap();
assert_eq!(anchor, computed_anchor); assert_eq!(anchor, computed_anchor);
} }
} }