Merkle Tree name refactors

This commit is contained in:
Pratyush Mishra
2019-10-11 19:24:21 -07:00
parent 25e35a25d0
commit 2a86b59138
3 changed files with 63 additions and 72 deletions

View File

@@ -6,7 +6,7 @@ extern crate derivative;
pub mod commitment; pub mod commitment;
pub mod crh; pub mod crh;
pub mod mht; pub mod merkle_tree;
pub mod nizk; pub mod nizk;
pub mod prf; pub mod prf;
pub mod signature; pub mod signature;
@@ -14,7 +14,7 @@ pub mod signature;
pub use self::{ pub use self::{
commitment::CommitmentScheme, commitment::CommitmentScheme,
crh::FixedLengthCRH, crh::FixedLengthCRH,
mht::{HashMembershipProof, MerkleHashTree}, merkle_tree::{MerkleTreePath, MerkleHashTree},
nizk::NIZK, nizk::NIZK,
prf::PRF, prf::PRF,
signature::SignatureScheme, signature::SignatureScheme,
@@ -24,7 +24,7 @@ pub use self::{
pub use self::{ pub use self::{
commitment::CommitmentGadget, commitment::CommitmentGadget,
crh::FixedLengthCRHGadget, crh::FixedLengthCRHGadget,
mht::constraints::{MerklePath, MerklePathVerifierGadget}, merkle_tree::constraints::MerkleTreePathGadget,
nizk::NIZKVerifierGadget, nizk::NIZKVerifierGadget,
prf::PRFGadget, prf::PRFGadget,
signature::SigRandomizePkGadget, signature::SigRandomizePkGadget,

View File

@@ -3,63 +3,51 @@ use r1cs_core::{ConstraintSystem, SynthesisError};
use r1cs_std::prelude::*; use r1cs_std::prelude::*;
use r1cs_std::boolean::AllocatedBit; use r1cs_std::boolean::AllocatedBit;
use crate::mht::*; use crate::merkle_tree::*;
use crate::crh::{FixedLengthCRH, FixedLengthCRHGadget}; use crate::crh::{FixedLengthCRH, FixedLengthCRHGadget};
use std::{borrow::Borrow, marker::PhantomData}; use std::borrow::Borrow;
pub struct MerklePath<P, HGadget, ConstraintF> pub struct MerkleTreePathGadget<P, HGadget, ConstraintF>
where where
P: MHTParameters, P: MerkleTreeConfig,
HGadget: FixedLengthCRHGadget<P::H, ConstraintF>, HGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
ConstraintF: Field, ConstraintF: Field,
{ {
path: Vec<(HGadget::OutputGadget, HGadget::OutputGadget)>, path: Vec<(HGadget::OutputGadget, HGadget::OutputGadget)>,
} }
pub struct MerklePathVerifierGadget<P, CRHGadget, ConstraintF> impl<P, CRHGadget, ConstraintF> MerkleTreePathGadget<P, CRHGadget, ConstraintF>
where where
P: MHTParameters, P: MerkleTreeConfig,
ConstraintF: Field,
CRHGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
{
_p: PhantomData<CRHGadget>,
_p2: PhantomData<P>,
_f: PhantomData<ConstraintF>,
}
impl<P, CRHGadget, ConstraintF> MerklePathVerifierGadget<P, CRHGadget, ConstraintF>
where
P: MHTParameters,
ConstraintF: Field, ConstraintF: Field,
CRHGadget: FixedLengthCRHGadget<P::H, ConstraintF>, CRHGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
{ {
pub fn check_membership<CS: ConstraintSystem<ConstraintF>>( pub fn check_membership<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS, cs: CS,
parameters: &CRHGadget::ParametersGadget, parameters: &CRHGadget::ParametersGadget,
root: &CRHGadget::OutputGadget, root: &CRHGadget::OutputGadget,
leaf: impl ToBytesGadget<ConstraintF>, leaf: impl ToBytesGadget<ConstraintF>,
witness: &MerklePath<P, CRHGadget, ConstraintF>,
) -> Result<(), SynthesisError> { ) -> Result<(), SynthesisError> {
Self::conditionally_check_membership( self.conditionally_check_membership(
cs, cs,
parameters, parameters,
root, root,
leaf, leaf,
witness,
&Boolean::Constant(true), &Boolean::Constant(true),
) )
} }
pub fn conditionally_check_membership<CS: ConstraintSystem<ConstraintF>>( pub fn conditionally_check_membership<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS, mut cs: CS,
parameters: &CRHGadget::ParametersGadget, parameters: &CRHGadget::ParametersGadget,
root: &CRHGadget::OutputGadget, root: &CRHGadget::OutputGadget,
leaf: impl ToBytesGadget<ConstraintF>, leaf: impl ToBytesGadget<ConstraintF>,
witness: &MerklePath<P, CRHGadget, ConstraintF>,
should_enforce: &Boolean, should_enforce: &Boolean,
) -> Result<(), SynthesisError> { ) -> Result<(), SynthesisError> {
assert_eq!(witness.path.len(), P::HEIGHT - 1); assert_eq!(self.path.len(), P::HEIGHT - 1);
// Check that the hash of the given leaf matches the leaf hash in the membership // Check that the hash of the given leaf matches the leaf hash in the membership
// proof. // proof.
let leaf_bits = leaf.to_bytes(&mut cs.ns(|| "leaf_to_bytes"))?; let leaf_bits = leaf.to_bytes(&mut cs.ns(|| "leaf_to_bytes"))?;
@@ -71,21 +59,21 @@ where
// Check if leaf is one of the bottom-most siblings. // Check if leaf is one of the bottom-most siblings.
let leaf_is_left = AllocatedBit::alloc(&mut cs.ns(|| "leaf_is_left"), || { let leaf_is_left = AllocatedBit::alloc(&mut cs.ns(|| "leaf_is_left"), || {
Ok(leaf_hash == witness.path[0].0) Ok(leaf_hash == self.path[0].0)
})? })?
.into(); .into();
CRHGadget::OutputGadget::conditional_enforce_equal_or( CRHGadget::OutputGadget::conditional_enforce_equal_or(
&mut cs.ns(|| "check_leaf_is_left"), &mut cs.ns(|| "check_leaf_is_left"),
&leaf_is_left, &leaf_is_left,
&leaf_hash, &leaf_hash,
&witness.path[0].0, &self.path[0].0,
&witness.path[0].1, &self.path[0].1,
should_enforce, should_enforce,
)?; )?;
// Check levels between leaf level and root. // Check levels between leaf level and root.
let mut previous_hash = leaf_hash; let mut previous_hash = leaf_hash;
for (i, &(ref left_hash, ref right_hash)) in witness.path.iter().enumerate() { for (i, &(ref left_hash, ref right_hash)) in self.path.iter().enumerate() {
// Check if the previous_hash matches the correct current hash. // Check if the previous_hash matches the correct current hash.
let previous_is_left = let previous_is_left =
AllocatedBit::alloc(&mut cs.ns(|| format!("previous_is_left_{}", i)), || { AllocatedBit::alloc(&mut cs.ns(|| format!("previous_is_left_{}", i)), || {
@@ -138,10 +126,10 @@ where
HG::check_evaluation_gadget(cs, parameters, &bytes) HG::check_evaluation_gadget(cs, parameters, &bytes)
} }
impl<P, HGadget, ConstraintF> AllocGadget<HashMembershipProof<P>, ConstraintF> impl<P, HGadget, ConstraintF> AllocGadget<MerkleTreePath<P>, ConstraintF>
for MerklePath<P, HGadget, ConstraintF> for MerkleTreePathGadget<P, HGadget, ConstraintF>
where where
P: MHTParameters, P: MerkleTreeConfig,
HGadget: FixedLengthCRHGadget<P::H, ConstraintF>, HGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
ConstraintF: Field, ConstraintF: Field,
{ {
@@ -151,7 +139,7 @@ where
) -> Result<Self, SynthesisError> ) -> Result<Self, SynthesisError>
where where
F: FnOnce() -> Result<T, SynthesisError>, F: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<HashMembershipProof<P>>, T: Borrow<MerkleTreePath<P>>,
{ {
let mut path = Vec::new(); let mut path = Vec::new();
for (i, &(ref l, ref r)) in value_gen()?.borrow().path.iter().enumerate() { for (i, &(ref l, ref r)) in value_gen()?.borrow().path.iter().enumerate() {
@@ -165,7 +153,7 @@ where
})?; })?;
path.push((l_hash, r_hash)); path.push((l_hash, r_hash));
} }
Ok(MerklePath { Ok(MerkleTreePathGadget {
path, path,
}) })
} }
@@ -176,7 +164,7 @@ where
) -> Result<Self, SynthesisError> ) -> Result<Self, SynthesisError>
where where
F: FnOnce() -> Result<T, SynthesisError>, F: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<HashMembershipProof<P>>, T: Borrow<MerkleTreePath<P>>,
{ {
let mut path = Vec::new(); let mut path = Vec::new();
for (i, &(ref l, ref r)) in value_gen()?.borrow().path.iter().enumerate() { for (i, &(ref l, ref r)) in value_gen()?.borrow().path.iter().enumerate() {
@@ -191,7 +179,7 @@ where
path.push((l_hash, r_hash)); path.push((l_hash, r_hash));
} }
Ok(MerklePath { Ok(MerkleTreePathGadget {
path, path,
}) })
} }
@@ -208,7 +196,7 @@ mod test {
FixedLengthCRH, FixedLengthCRH,
FixedLengthCRHGadget, FixedLengthCRHGadget,
}, },
mht::*, merkle_tree::*,
}; };
use algebra::{ use algebra::{
curves::jubjub::JubJubAffine as JubJub, curves::jubjub::JubJubAffine as JubJub,
@@ -234,20 +222,20 @@ mod test {
type H = PedersenCRH<JubJub, Window4x256>; type H = PedersenCRH<JubJub, Window4x256>;
type HG = PedersenCRHGadget<JubJub, Fq, JubJubGadget>; type HG = PedersenCRHGadget<JubJub, Fq, JubJubGadget>;
struct JubJubMHTParams; struct JubJubMerkleTreeParams;
impl MHTParameters for JubJubMHTParams { impl MerkleTreeConfig for JubJubMerkleTreeParams {
const HEIGHT: usize = 32; const HEIGHT: usize = 32;
type H = H; type H = H;
} }
type JubJubMHT = MerkleHashTree<JubJubMHTParams>; type JubJubMerkleTree = MerkleHashTree<JubJubMerkleTreeParams>;
fn generate_merkle_tree(leaves: &[[u8; 30]], use_bad_root: bool) -> () { fn generate_merkle_tree(leaves: &[[u8; 30]], use_bad_root: bool) -> () {
let mut rng = XorShiftRng::seed_from_u64(9174123u64); let mut rng = XorShiftRng::seed_from_u64(9174123u64);
let crh_parameters = Rc::new(H::setup(&mut rng).unwrap()); let crh_parameters = Rc::new(H::setup(&mut rng).unwrap());
let tree = JubJubMHT::new(crh_parameters.clone(), leaves).unwrap(); let tree = JubJubMerkleTree::new(crh_parameters.clone(), leaves).unwrap();
let root = tree.root(); let root = tree.root();
let mut satisfied = true; let mut satisfied = true;
for (i, leaf) in leaves.iter().enumerate() { for (i, leaf) in leaves.iter().enumerate() {
@@ -290,7 +278,7 @@ mod test {
println!("constraints from leaf: {}", constraints_from_leaf); println!("constraints from leaf: {}", constraints_from_leaf);
// Allocate Merkle Tree Path // Allocate Merkle Tree Path
let cw = MerklePath::<_, HG, _>::alloc(&mut cs.ns(|| format!("new_witness_{}", i)), || { let cw = MerkleTreePathGadget::<_, HG, _>::alloc(&mut cs.ns(|| format!("new_witness_{}", i)), || {
Ok(proof) Ok(proof)
}) })
.unwrap(); .unwrap();
@@ -301,12 +289,11 @@ mod test {
- constraints_from_leaf; - constraints_from_leaf;
println!("constraints from path: {}", constraints_from_path); println!("constraints from path: {}", constraints_from_path);
let leaf_g: &[UInt8] = leaf_g.as_slice(); let leaf_g: &[UInt8] = leaf_g.as_slice();
MerklePathVerifierGadget::<_, HG, _>::check_membership( cw.check_membership(
&mut cs.ns(|| format!("new_witness_check_{}", i)), &mut cs.ns(|| format!("new_witness_check_{}", i)),
&crh_parameters, &crh_parameters,
&root, &root,
&leaf_g, &leaf_g,
&cw,
) )
.unwrap(); .unwrap();
if !cs.is_satisfied() { if !cs.is_satisfied() {
@@ -330,7 +317,7 @@ mod test {
} }
#[test] #[test]
fn mht_gadget_test() { fn good_root_test() {
let mut leaves = Vec::new(); let mut leaves = Vec::new();
for i in 0..4u8 { for i in 0..4u8 {
let input = [i ; 30]; let input = [i ; 30];

View File

@@ -7,7 +7,7 @@ use std::{fmt, rc::Rc};
#[cfg(feature = "r1cs")] #[cfg(feature = "r1cs")]
pub mod constraints; pub mod constraints;
pub trait MHTParameters { pub trait MerkleTreeConfig {
const HEIGHT: usize; const HEIGHT: usize;
type H: FixedLengthCRH; type H: FixedLengthCRH;
} }
@@ -16,14 +16,18 @@ pub trait MHTParameters {
/// Our path `is_left_child()` if the boolean in `path` is true. /// Our path `is_left_child()` if the boolean in `path` is true.
#[derive(Derivative)] #[derive(Derivative)]
#[derivative( #[derivative(
Clone(bound = "P: MHTParameters"), Clone(bound = "P: MerkleTreeConfig"),
Debug(bound = "P: MHTParameters, <P::H as FixedLengthCRH>::Output: fmt::Debug") Debug(bound = "P: MerkleTreeConfig, <P::H as FixedLengthCRH>::Output: fmt::Debug")
)] )]
pub struct HashMembershipProof<P: MHTParameters> { pub struct MerkleTreePath<P: MerkleTreeConfig> {
pub(crate) path: Vec<(<P::H as FixedLengthCRH>::Output, <P::H as FixedLengthCRH>::Output)>, pub(crate) path: Vec<(<P::H as FixedLengthCRH>::Output, <P::H as FixedLengthCRH>::Output)>,
} }
impl<P: MHTParameters> Default for HashMembershipProof<P> { pub type MerkleTreeParams<P> = <<P as MerkleTreeConfig>::H as FixedLengthCRH>::Parameters;
pub type MerkleTreeDigest<P> = <<P as MerkleTreeConfig>::H as FixedLengthCRH>::Output;
impl<P: MerkleTreeConfig> Default for MerkleTreePath<P> {
fn default() -> Self { fn default() -> Self {
let mut path = Vec::with_capacity(P::HEIGHT as usize); let mut path = Vec::with_capacity(P::HEIGHT as usize);
for _i in 1..P::HEIGHT as usize { for _i in 1..P::HEIGHT as usize {
@@ -35,7 +39,7 @@ impl<P: MHTParameters> Default for HashMembershipProof<P> {
} }
} }
impl<P: MHTParameters> HashMembershipProof<P> { impl<P: MerkleTreeConfig> MerkleTreePath<P> {
pub fn verify<L: ToBytes>( pub fn verify<L: ToBytes>(
&self, &self,
parameters: &<P::H as FixedLengthCRH>::Parameters, parameters: &<P::H as FixedLengthCRH>::Parameters,
@@ -76,14 +80,14 @@ impl<P: MHTParameters> HashMembershipProof<P> {
} }
} }
pub struct MerkleHashTree<P: MHTParameters> { pub struct MerkleHashTree<P: MerkleTreeConfig> {
tree: Vec<<P::H as FixedLengthCRH>::Output>, tree: Vec<<P::H as FixedLengthCRH>::Output>,
padding_tree: Vec<(<P::H as FixedLengthCRH>::Output, <P::H as FixedLengthCRH>::Output)>, padding_tree: Vec<(<P::H as FixedLengthCRH>::Output, <P::H as FixedLengthCRH>::Output)>,
parameters: Rc<<P::H as FixedLengthCRH>::Parameters>, parameters: Rc<<P::H as FixedLengthCRH>::Parameters>,
root: Option<<P::H as FixedLengthCRH>::Output>, root: Option<<P::H as FixedLengthCRH>::Output>,
} }
impl<P: MHTParameters> MerkleHashTree<P> { impl<P: MerkleTreeConfig> MerkleHashTree<P> {
pub const HEIGHT: u8 = P::HEIGHT as u8; pub const HEIGHT: u8 = P::HEIGHT as u8;
pub fn blank(parameters: Rc<<P::H as FixedLengthCRH>::Parameters>) -> Self { pub fn blank(parameters: Rc<<P::H as FixedLengthCRH>::Parameters>) -> Self {
@@ -96,7 +100,7 @@ impl<P: MHTParameters> MerkleHashTree<P> {
} }
pub fn new<L: ToBytes>(parameters: Rc<<P::H as FixedLengthCRH>::Parameters>, leaves: &[L]) -> Result<Self, Error> { pub fn new<L: ToBytes>(parameters: Rc<<P::H as FixedLengthCRH>::Parameters>, leaves: &[L]) -> Result<Self, Error> {
let new_time = start_timer!(|| "MHT::New"); let new_time = start_timer!(|| "MerkleTree::New");
let last_level_size = leaves.len().next_power_of_two(); let last_level_size = leaves.len().next_power_of_two();
let tree_size = 2 * last_level_size - 1; let tree_size = 2 * last_level_size - 1;
@@ -177,8 +181,8 @@ impl<P: MHTParameters> MerkleHashTree<P> {
&self, &self,
index: usize, index: usize,
leaf: &L, leaf: &L,
) -> Result<HashMembershipProof<P>, Error> { ) -> Result<MerkleTreePath<P>, Error> {
let prove_time = start_timer!(|| "MHT::GenProof"); let prove_time = start_timer!(|| "MerkleTree::GenProof");
let mut path = Vec::new(); let mut path = Vec::new();
let mut buffer = [0u8; 128]; let mut buffer = [0u8; 128];
@@ -189,7 +193,7 @@ impl<P: MHTParameters> MerkleHashTree<P> {
// Check that the given index corresponds to the correct leaf. // Check that the given index corresponds to the correct leaf.
if leaf_hash != self.tree[tree_index] { if leaf_hash != self.tree[tree_index] {
Err(MHTError::IncorrectLeafIndex(tree_index))? Err(MerkleTreeError::IncorrectLeafIndex(tree_index))?
} }
// Iterate from the leaf up to the root, storing all intermediate hash values. // Iterate from the leaf up to the root, storing all intermediate hash values.
@@ -219,9 +223,9 @@ impl<P: MHTParameters> MerkleHashTree<P> {
} }
end_timer!(prove_time); end_timer!(prove_time);
if path.len() != (Self::HEIGHT - 1) as usize { if path.len() != (Self::HEIGHT - 1) as usize {
Err(MHTError::IncorrectPathLength(path.len()))? Err(MerkleTreeError::IncorrectPathLength(path.len()))?
} else { } else {
Ok(HashMembershipProof { Ok(MerkleTreePath {
path, path,
}) })
} }
@@ -229,22 +233,22 @@ impl<P: MHTParameters> MerkleHashTree<P> {
} }
#[derive(Debug)] #[derive(Debug)]
pub enum MHTError { pub enum MerkleTreeError {
IncorrectLeafIndex(usize), IncorrectLeafIndex(usize),
IncorrectPathLength(usize), IncorrectPathLength(usize),
} }
impl std::fmt::Display for MHTError { impl std::fmt::Display for MerkleTreeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let msg = match self { let msg = match self {
MHTError::IncorrectLeafIndex(index) => format!("incorrect leaf index: {}", index), MerkleTreeError::IncorrectLeafIndex(index) => format!("incorrect leaf index: {}", index),
MHTError::IncorrectPathLength(len) => format!("incorrect path length: {}", len), MerkleTreeError::IncorrectPathLength(len) => format!("incorrect path length: {}", len),
}; };
write!(f, "{}", msg) write!(f, "{}", msg)
} }
} }
impl std::error::Error for MHTError { impl std::error::Error for MerkleTreeError {
#[inline] #[inline]
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None None
@@ -357,7 +361,7 @@ pub(crate) fn hash_empty<H: FixedLengthCRH>(
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::{crh::{pedersen::*, *}, mht::*}; use crate::{crh::{pedersen::*, *}, merkle_tree::*};
use algebra::curves::jubjub::JubJubAffine as JubJub; use algebra::curves::jubjub::JubJubAffine as JubJub;
use rand::SeedableRng; use rand::SeedableRng;
use rand_xorshift::XorShiftRng; use rand_xorshift::XorShiftRng;
@@ -372,20 +376,20 @@ mod test {
type H = PedersenCRH<JubJub, Window4x256>; type H = PedersenCRH<JubJub, Window4x256>;
struct JubJubMHTParams; struct JubJubMerkleTreeParams;
impl MHTParameters for JubJubMHTParams { impl MerkleTreeConfig for JubJubMerkleTreeParams {
const HEIGHT: usize = 32; const HEIGHT: usize = 32;
type H = H; type H = H;
} }
type JubJubMHT = MerkleHashTree<JubJubMHTParams>; type JubJubMerkleTree = MerkleHashTree<JubJubMerkleTreeParams>;
fn generate_merkle_tree<L: ToBytes + Clone + Eq>(leaves: &[L]) -> () { fn generate_merkle_tree<L: ToBytes + Clone + Eq>(leaves: &[L]) -> () {
let mut rng = XorShiftRng::seed_from_u64(9174123u64); let mut rng = XorShiftRng::seed_from_u64(9174123u64);
let crh_parameters = Rc::new(H::setup(&mut rng).unwrap()); let crh_parameters = Rc::new(H::setup(&mut rng).unwrap());
let tree = JubJubMHT::new(crh_parameters.clone(), &leaves).unwrap(); let tree = JubJubMerkleTree::new(crh_parameters.clone(), &leaves).unwrap();
let root = tree.root(); let root = tree.root();
for (i, leaf) in leaves.iter().enumerate() { for (i, leaf) in leaves.iter().enumerate() {
let proof = tree.generate_proof(i, &leaf).unwrap(); let proof = tree.generate_proof(i, &leaf).unwrap();
@@ -394,7 +398,7 @@ mod test {
} }
#[test] #[test]
fn mht_test() { fn good_root_test() {
let mut leaves = Vec::new(); let mut leaves = Vec::new();
for i in 0..4u8 { for i in 0..4u8 {
leaves.push([i, i, i, i, i, i, i, i]); leaves.push([i, i, i, i, i, i, i, i]);
@@ -412,7 +416,7 @@ mod test {
let mut rng = XorShiftRng::seed_from_u64(13423423u64); let mut rng = XorShiftRng::seed_from_u64(13423423u64);
let crh_parameters = Rc::new(H::setup(&mut rng).unwrap()); let crh_parameters = Rc::new(H::setup(&mut rng).unwrap());
let tree = JubJubMHT::new(crh_parameters.clone(), &leaves).unwrap(); let tree = JubJubMerkleTree::new(crh_parameters.clone(), &leaves).unwrap();
let root = JubJub::zero(); let root = JubJub::zero();
for (i, leaf) in leaves.iter().enumerate() { for (i, leaf) in leaves.iter().enumerate() {
let proof = tree.generate_proof(i, &leaf).unwrap(); let proof = tree.generate_proof(i, &leaf).unwrap();
@@ -422,7 +426,7 @@ mod test {
#[should_panic] #[should_panic]
#[test] #[test]
fn bad_root_mht_test() { fn bad_root_test() {
let mut leaves = Vec::new(); let mut leaves = Vec::new();
for i in 0..4u8 { for i in 0..4u8 {
leaves.push([i, i, i, i, i, i, i, i]); leaves.push([i, i, i, i, i, i, i, i]);