Refactor zcash_primitives::merkle_tree::CommitmentTreeWitness

- The internal Option wrapper was an unnecessary leftover from when this
  code was directly inside the prover, where Some(x) represents an
  assigned variable.
- CommitmentTreeWitness::from_slice_with_depth is more idiomatic Rust.
This commit is contained in:
Jack Grigg
2020-02-07 00:06:57 +00:00
parent ee32f7facb
commit 2064d1c801
2 changed files with 33 additions and 40 deletions

View File

@@ -385,9 +385,9 @@ impl<Node: Hashable> IncrementalWitness<Node> {
if let Some(node) = self.tree.left { if let Some(node) = self.tree.left {
if self.tree.right.is_some() { if self.tree.right.is_some() {
auth_path.push(Some((node, true))); auth_path.push((node, true));
} else { } else {
auth_path.push(Some((filler.next(0), false))); auth_path.push((filler.next(0), false));
} }
} else { } else {
// Can't create an authentication path for the beginning of the tree // Can't create an authentication path for the beginning of the tree
@@ -396,13 +396,13 @@ impl<Node: Hashable> IncrementalWitness<Node> {
for (i, p) in self.tree.parents.iter().enumerate() { for (i, p) in self.tree.parents.iter().enumerate() {
auth_path.push(match p { auth_path.push(match p {
Some(node) => Some((*node, true)), Some(node) => (*node, true),
None => Some((filler.next(i + 1), false)), None => (filler.next(i + 1), false),
}); });
} }
for i in self.tree.parents.len()..(depth - 1) { for i in self.tree.parents.len()..(depth - 1) {
auth_path.push(Some((filler.next(i + 1), false))); auth_path.push((filler.next(i + 1), false));
} }
assert_eq!(auth_path.len(), depth); assert_eq!(auth_path.len(), depth);
@@ -417,13 +417,13 @@ impl<Node: Hashable> IncrementalWitness<Node> {
/// that tree. /// that tree.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct CommitmentTreeWitness<Node: Hashable> { pub struct CommitmentTreeWitness<Node: Hashable> {
pub auth_path: Vec<Option<(Node, bool)>>, pub auth_path: Vec<(Node, bool)>,
pub position: u64, pub position: u64,
} }
impl<Node: Hashable> CommitmentTreeWitness<Node> { impl<Node: Hashable> CommitmentTreeWitness<Node> {
/// Constructs a witness directly from its path and position. /// Constructs a witness directly from its path and position.
pub fn from_path(auth_path: Vec<Option<(Node, bool)>>, position: u64) -> Self { pub fn from_path(auth_path: Vec<(Node, bool)>, position: u64) -> Self {
CommitmentTreeWitness { CommitmentTreeWitness {
auth_path, auth_path,
position, position,
@@ -444,48 +444,41 @@ impl<Node: Hashable> CommitmentTreeWitness<Node> {
witness = &witness[1..]; witness = &witness[1..];
// Begin to construct the authentication path // Begin to construct the authentication path
let mut auth_path = vec![None; depth]; let iter = witness.chunks_exact(33);
witness = iter.remainder();
// The vector works in reverse // The vector works in reverse
for i in (0..depth).rev() { let mut auth_path = iter
// skip length of inner vector .rev()
if witness[0] != 32 { .map(|bytes| {
// the length of a pedersen hash // Length of inner vector should be the length of a Pedersen hash
return Err(()); if bytes[0] == 32 {
} // Sibling node should be an element of Fr
witness = &witness[1..]; Node::read(&bytes[1..])
.map(|sibling| {
// Grab the sibling node at this depth in the tree // Set the value in the auth path; we put false here
let mut sibling = [0u8; 32]; // for now (signifying the position bit) which we'll
sibling.copy_from_slice(&witness[0..32]); // fill in later.
witness = &witness[32..]; (sibling, false)
})
// Sibling node should be an element of Fr .map_err(|_| ())
let sibling = match Node::read(&sibling[..]) { } else {
Ok(p) => p, Err(())
Err(_) => return Err(()), }
}; })
.collect::<Result<Vec<_>, _>>()?;
// Set the value in the auth path; we put false here if auth_path.len() != depth {
// for now (signifying the position bit) which we'll return Err(());
// fill in later.
auth_path[i] = Some((sibling, false));
} }
// Read the position from the witness // Read the position from the witness
let position = match witness.read_u64::<LittleEndian>() { let position = witness.read_u64::<LittleEndian>().map_err(|_| ())?;
Ok(pos) => pos,
Err(_) => return Err(()),
};
// Given the position, let's finish constructing the authentication // Given the position, let's finish constructing the authentication
// path // path
let mut tmp = position; let mut tmp = position;
for entry in auth_path.iter_mut() { for entry in auth_path.iter_mut() {
if let Some(p) = entry { entry.1 = (tmp & 1) == 1;
p.1 = (tmp & 1) == 1;
}
tmp >>= 1; tmp >>= 1;
} }

View File

@@ -117,7 +117,7 @@ impl SaplingProvingContext {
auth_path: witness auth_path: witness
.auth_path .auth_path
.iter() .iter()
.map(|n| n.map(|(node, b)| (node.into(), b))) .map(|(node, b)| Some(((*node).into(), *b)))
.collect(), .collect(),
anchor: Some(anchor), anchor: Some(anchor),
}; };