diff --git a/crypto-primitives/src/lib.rs b/crypto-primitives/src/lib.rs index b987ef9..b33aef6 100644 --- a/crypto-primitives/src/lib.rs +++ b/crypto-primitives/src/lib.rs @@ -6,7 +6,7 @@ extern crate derivative; pub mod commitment; pub mod crh; -pub mod mht; +pub mod merkle_tree; pub mod nizk; pub mod prf; pub mod signature; @@ -14,7 +14,7 @@ pub mod signature; pub use self::{ commitment::CommitmentScheme, crh::FixedLengthCRH, - mht::{HashMembershipProof, MerkleHashTree}, + merkle_tree::{MerkleTreePath, MerkleHashTree}, nizk::NIZK, prf::PRF, signature::SignatureScheme, @@ -24,7 +24,7 @@ pub use self::{ pub use self::{ commitment::CommitmentGadget, crh::FixedLengthCRHGadget, - mht::constraints::{MerklePath, MerklePathVerifierGadget}, + merkle_tree::constraints::MerkleTreePathGadget, nizk::NIZKVerifierGadget, prf::PRFGadget, signature::SigRandomizePkGadget, diff --git a/crypto-primitives/src/mht/constraints.rs b/crypto-primitives/src/merkle_tree/constraints.rs similarity index 85% rename from crypto-primitives/src/mht/constraints.rs rename to crypto-primitives/src/merkle_tree/constraints.rs index 3d6a4ed..16e40aa 100644 --- a/crypto-primitives/src/mht/constraints.rs +++ b/crypto-primitives/src/merkle_tree/constraints.rs @@ -3,63 +3,51 @@ use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_std::prelude::*; use r1cs_std::boolean::AllocatedBit; -use crate::mht::*; +use crate::merkle_tree::*; use crate::crh::{FixedLengthCRH, FixedLengthCRHGadget}; -use std::{borrow::Borrow, marker::PhantomData}; +use std::borrow::Borrow; -pub struct MerklePath +pub struct MerkleTreePathGadget where - P: MHTParameters, + P: MerkleTreeConfig, HGadget: FixedLengthCRHGadget, ConstraintF: Field, { path: Vec<(HGadget::OutputGadget, HGadget::OutputGadget)>, } -pub struct MerklePathVerifierGadget +impl MerkleTreePathGadget where - P: MHTParameters, - ConstraintF: Field, - CRHGadget: FixedLengthCRHGadget, -{ - _p: PhantomData, - _p2: PhantomData

, - _f: PhantomData, -} - -impl MerklePathVerifierGadget -where - P: MHTParameters, + P: MerkleTreeConfig, ConstraintF: Field, CRHGadget: FixedLengthCRHGadget, { pub fn check_membership>( + &self, cs: CS, parameters: &CRHGadget::ParametersGadget, root: &CRHGadget::OutputGadget, leaf: impl ToBytesGadget, - witness: &MerklePath, ) -> Result<(), SynthesisError> { - Self::conditionally_check_membership( + self.conditionally_check_membership( cs, parameters, root, leaf, - witness, &Boolean::Constant(true), ) } pub fn conditionally_check_membership>( + &self, mut cs: CS, parameters: &CRHGadget::ParametersGadget, root: &CRHGadget::OutputGadget, leaf: impl ToBytesGadget, - witness: &MerklePath, should_enforce: &Boolean, ) -> 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 // proof. 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. 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(); CRHGadget::OutputGadget::conditional_enforce_equal_or( &mut cs.ns(|| "check_leaf_is_left"), &leaf_is_left, &leaf_hash, - &witness.path[0].0, - &witness.path[0].1, + &self.path[0].0, + &self.path[0].1, should_enforce, )?; // Check levels between leaf level and root. 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. let previous_is_left = AllocatedBit::alloc(&mut cs.ns(|| format!("previous_is_left_{}", i)), || { @@ -138,10 +126,10 @@ where HG::check_evaluation_gadget(cs, parameters, &bytes) } -impl AllocGadget, ConstraintF> - for MerklePath +impl AllocGadget, ConstraintF> + for MerkleTreePathGadget where - P: MHTParameters, + P: MerkleTreeConfig, HGadget: FixedLengthCRHGadget, ConstraintF: Field, { @@ -151,7 +139,7 @@ where ) -> Result where F: FnOnce() -> Result, - T: Borrow>, + T: Borrow>, { let mut path = Vec::new(); for (i, &(ref l, ref r)) in value_gen()?.borrow().path.iter().enumerate() { @@ -165,7 +153,7 @@ where })?; path.push((l_hash, r_hash)); } - Ok(MerklePath { + Ok(MerkleTreePathGadget { path, }) } @@ -176,7 +164,7 @@ where ) -> Result where F: FnOnce() -> Result, - T: Borrow>, + T: Borrow>, { let mut path = Vec::new(); for (i, &(ref l, ref r)) in value_gen()?.borrow().path.iter().enumerate() { @@ -191,7 +179,7 @@ where path.push((l_hash, r_hash)); } - Ok(MerklePath { + Ok(MerkleTreePathGadget { path, }) } @@ -208,7 +196,7 @@ mod test { FixedLengthCRH, FixedLengthCRHGadget, }, - mht::*, + merkle_tree::*, }; use algebra::{ curves::jubjub::JubJubAffine as JubJub, @@ -234,20 +222,20 @@ mod test { type H = PedersenCRH; type HG = PedersenCRHGadget; - struct JubJubMHTParams; + struct JubJubMerkleTreeParams; - impl MHTParameters for JubJubMHTParams { + impl MerkleTreeConfig for JubJubMerkleTreeParams { const HEIGHT: usize = 32; type H = H; } - type JubJubMHT = MerkleHashTree; + type JubJubMerkleTree = MerkleHashTree; fn generate_merkle_tree(leaves: &[[u8; 30]], use_bad_root: bool) -> () { let mut rng = XorShiftRng::seed_from_u64(9174123u64); 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 mut satisfied = true; for (i, leaf) in leaves.iter().enumerate() { @@ -290,7 +278,7 @@ mod test { println!("constraints from leaf: {}", constraints_from_leaf); // 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) }) .unwrap(); @@ -301,12 +289,11 @@ mod test { - constraints_from_leaf; println!("constraints from path: {}", constraints_from_path); let leaf_g: &[UInt8] = leaf_g.as_slice(); - MerklePathVerifierGadget::<_, HG, _>::check_membership( + cw.check_membership( &mut cs.ns(|| format!("new_witness_check_{}", i)), &crh_parameters, &root, &leaf_g, - &cw, ) .unwrap(); if !cs.is_satisfied() { @@ -330,7 +317,7 @@ mod test { } #[test] - fn mht_gadget_test() { + fn good_root_test() { let mut leaves = Vec::new(); for i in 0..4u8 { let input = [i ; 30]; diff --git a/crypto-primitives/src/mht/mod.rs b/crypto-primitives/src/merkle_tree/mod.rs similarity index 88% rename from crypto-primitives/src/mht/mod.rs rename to crypto-primitives/src/merkle_tree/mod.rs index f462cf3..5cce751 100644 --- a/crypto-primitives/src/mht/mod.rs +++ b/crypto-primitives/src/merkle_tree/mod.rs @@ -7,7 +7,7 @@ use std::{fmt, rc::Rc}; #[cfg(feature = "r1cs")] pub mod constraints; -pub trait MHTParameters { +pub trait MerkleTreeConfig { const HEIGHT: usize; type H: FixedLengthCRH; } @@ -16,14 +16,18 @@ pub trait MHTParameters { /// Our path `is_left_child()` if the boolean in `path` is true. #[derive(Derivative)] #[derivative( - Clone(bound = "P: MHTParameters"), - Debug(bound = "P: MHTParameters, ::Output: fmt::Debug") + Clone(bound = "P: MerkleTreeConfig"), + Debug(bound = "P: MerkleTreeConfig, ::Output: fmt::Debug") )] -pub struct HashMembershipProof { +pub struct MerkleTreePath { pub(crate) path: Vec<(::Output, ::Output)>, } -impl Default for HashMembershipProof

{ +pub type MerkleTreeParams

= <

::H as FixedLengthCRH>::Parameters; +pub type MerkleTreeDigest

= <

::H as FixedLengthCRH>::Output; + + +impl Default for MerkleTreePath

{ fn default() -> Self { let mut path = Vec::with_capacity(P::HEIGHT as usize); for _i in 1..P::HEIGHT as usize { @@ -35,7 +39,7 @@ impl Default for HashMembershipProof

{ } } -impl HashMembershipProof

{ +impl MerkleTreePath

{ pub fn verify( &self, parameters: &::Parameters, @@ -76,14 +80,14 @@ impl HashMembershipProof

{ } } -pub struct MerkleHashTree { +pub struct MerkleHashTree { tree: Vec<::Output>, padding_tree: Vec<(::Output, ::Output)>, parameters: Rc<::Parameters>, root: Option<::Output>, } -impl MerkleHashTree

{ +impl MerkleHashTree

{ pub const HEIGHT: u8 = P::HEIGHT as u8; pub fn blank(parameters: Rc<::Parameters>) -> Self { @@ -96,7 +100,7 @@ impl MerkleHashTree

{ } pub fn new(parameters: Rc<::Parameters>, leaves: &[L]) -> Result { - 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 tree_size = 2 * last_level_size - 1; @@ -177,8 +181,8 @@ impl MerkleHashTree

{ &self, index: usize, leaf: &L, - ) -> Result, Error> { - let prove_time = start_timer!(|| "MHT::GenProof"); + ) -> Result, Error> { + let prove_time = start_timer!(|| "MerkleTree::GenProof"); let mut path = Vec::new(); let mut buffer = [0u8; 128]; @@ -189,7 +193,7 @@ impl MerkleHashTree

{ // Check that the given index corresponds to the correct leaf. 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. @@ -219,9 +223,9 @@ impl MerkleHashTree

{ } end_timer!(prove_time); if path.len() != (Self::HEIGHT - 1) as usize { - Err(MHTError::IncorrectPathLength(path.len()))? + Err(MerkleTreeError::IncorrectPathLength(path.len()))? } else { - Ok(HashMembershipProof { + Ok(MerkleTreePath { path, }) } @@ -229,22 +233,22 @@ impl MerkleHashTree

{ } #[derive(Debug)] -pub enum MHTError { +pub enum MerkleTreeError { IncorrectLeafIndex(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 { let msg = match self { - MHTError::IncorrectLeafIndex(index) => format!("incorrect leaf index: {}", index), - MHTError::IncorrectPathLength(len) => format!("incorrect path length: {}", len), + MerkleTreeError::IncorrectLeafIndex(index) => format!("incorrect leaf index: {}", index), + MerkleTreeError::IncorrectPathLength(len) => format!("incorrect path length: {}", len), }; write!(f, "{}", msg) } } -impl std::error::Error for MHTError { +impl std::error::Error for MerkleTreeError { #[inline] fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None @@ -357,7 +361,7 @@ pub(crate) fn hash_empty( #[cfg(test)] mod test { - use crate::{crh::{pedersen::*, *}, mht::*}; + use crate::{crh::{pedersen::*, *}, merkle_tree::*}; use algebra::curves::jubjub::JubJubAffine as JubJub; use rand::SeedableRng; use rand_xorshift::XorShiftRng; @@ -372,20 +376,20 @@ mod test { type H = PedersenCRH; - struct JubJubMHTParams; + struct JubJubMerkleTreeParams; - impl MHTParameters for JubJubMHTParams { + impl MerkleTreeConfig for JubJubMerkleTreeParams { const HEIGHT: usize = 32; type H = H; } - type JubJubMHT = MerkleHashTree; + type JubJubMerkleTree = MerkleHashTree; fn generate_merkle_tree(leaves: &[L]) -> () { let mut rng = XorShiftRng::seed_from_u64(9174123u64); 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(); for (i, leaf) in leaves.iter().enumerate() { let proof = tree.generate_proof(i, &leaf).unwrap(); @@ -394,7 +398,7 @@ mod test { } #[test] - fn mht_test() { + fn good_root_test() { let mut leaves = Vec::new(); for i in 0..4u8 { 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 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(); for (i, leaf) in leaves.iter().enumerate() { let proof = tree.generate_proof(i, &leaf).unwrap(); @@ -422,7 +426,7 @@ mod test { #[should_panic] #[test] - fn bad_root_mht_test() { + fn bad_root_test() { let mut leaves = Vec::new(); for i in 0..4u8 { leaves.push([i, i, i, i, i, i, i, i]);