Browse Source

Merkle Tree name refactors

master
Pratyush Mishra 5 years ago
parent
commit
2a86b59138
3 changed files with 63 additions and 72 deletions
  1. +3
    -3
      crypto-primitives/src/lib.rs
  2. +29
    -42
      crypto-primitives/src/merkle_tree/constraints.rs
  3. +31
    -27
      crypto-primitives/src/merkle_tree/mod.rs

+ 3
- 3
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,

crypto-primitives/src/mht/constraints.rs → 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<P, HGadget, ConstraintF>
pub struct MerkleTreePathGadget<P, HGadget, ConstraintF>
where
P: MHTParameters,
P: MerkleTreeConfig,
HGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
ConstraintF: Field,
{
path: Vec<(HGadget::OutputGadget, HGadget::OutputGadget)>,
}
pub struct MerklePathVerifierGadget<P, CRHGadget, ConstraintF>
impl<P, CRHGadget, ConstraintF> MerkleTreePathGadget<P, CRHGadget, ConstraintF>
where
P: MHTParameters,
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,
P: MerkleTreeConfig,
ConstraintF: Field,
CRHGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
{
pub fn check_membership<CS: ConstraintSystem<ConstraintF>>(
&self,
cs: CS,
parameters: &CRHGadget::ParametersGadget,
root: &CRHGadget::OutputGadget,
leaf: impl ToBytesGadget<ConstraintF>,
witness: &MerklePath<P, CRHGadget, ConstraintF>,
) -> Result<(), SynthesisError> {
Self::conditionally_check_membership(
self.conditionally_check_membership(
cs,
parameters,
root,
leaf,
witness,
&Boolean::Constant(true),
)
}
pub fn conditionally_check_membership<CS: ConstraintSystem<ConstraintF>>(
&self,
mut cs: CS,
parameters: &CRHGadget::ParametersGadget,
root: &CRHGadget::OutputGadget,
leaf: impl ToBytesGadget<ConstraintF>,
witness: &MerklePath<P, CRHGadget, ConstraintF>,
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<P, HGadget, ConstraintF> AllocGadget<HashMembershipProof<P>, ConstraintF>
for MerklePath<P, HGadget, ConstraintF>
impl<P, HGadget, ConstraintF> AllocGadget<MerkleTreePath<P>, ConstraintF>
for MerkleTreePathGadget<P, HGadget, ConstraintF>
where
P: MHTParameters,
P: MerkleTreeConfig,
HGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
ConstraintF: Field,
{
@ -151,7 +139,7 @@ where
) -> Result<Self, SynthesisError>
where
F: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<HashMembershipProof<P>>,
T: Borrow<MerkleTreePath<P>>,
{
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<Self, SynthesisError>
where
F: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<HashMembershipProof<P>>,
T: Borrow<MerkleTreePath<P>>,
{
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<JubJub, Window4x256>;
type HG = PedersenCRHGadget<JubJub, Fq, JubJubGadget>;
struct JubJubMHTParams;
struct JubJubMerkleTreeParams;
impl MHTParameters for JubJubMHTParams {
impl MerkleTreeConfig for JubJubMerkleTreeParams {
const HEIGHT: usize = 32;
type H = H;
}
type JubJubMHT = MerkleHashTree<JubJubMHTParams>;
type JubJubMerkleTree = MerkleHashTree<JubJubMerkleTreeParams>;
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];

crypto-primitives/src/mht/mod.rs → 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, <P::H as FixedLengthCRH>::Output: fmt::Debug")
Clone(bound = "P: MerkleTreeConfig"),
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)>,
}
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 {
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<P: MHTParameters> HashMembershipProof<P> {
impl<P: MerkleTreeConfig> MerkleTreePath<P> {
pub fn verify<L: ToBytes>(
&self,
parameters: &<P::H as FixedLengthCRH>::Parameters,
@ -76,14 +80,14 @@ impl HashMembershipProof

{

}
}
pub struct MerkleHashTree<P: MHTParameters> {
pub struct MerkleHashTree<P: MerkleTreeConfig> {
tree: Vec<<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>,
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 fn blank(parameters: Rc<<P::H as FixedLengthCRH>::Parameters>) -> Self {
@ -96,7 +100,7 @@ impl MerkleHashTree

{

}
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 tree_size = 2 * last_level_size - 1;
@ -177,8 +181,8 @@ impl MerkleHashTree

{

&self,
index: usize,
leaf: &L,
) -> Result<HashMembershipProof<P>, Error> {
let prove_time = start_timer!(|| "MHT::GenProof");
) -> Result<MerkleTreePath<P>, 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<JubJub, Window4x256>;
struct JubJubMHTParams;
struct JubJubMerkleTreeParams;
impl MHTParameters for JubJubMHTParams {
impl MerkleTreeConfig for JubJubMerkleTreeParams {
const HEIGHT: usize = 32;
type H = H;
}
type JubJubMHT = MerkleHashTree<JubJubMHTParams>;
type JubJubMerkleTree = MerkleHashTree<JubJubMerkleTreeParams>;
fn generate_merkle_tree<L: ToBytes + Clone + Eq>(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]);

Loading…
Cancel
Save