diff --git a/crypto-primitives/src/mht/constraints-old.rs b/crypto-primitives/src/mht/constraints-old.rs deleted file mode 100644 index 038c3e7..0000000 --- a/crypto-primitives/src/mht/constraints-old.rs +++ /dev/null @@ -1,512 +0,0 @@ -use algebra::Field; -use r1cs_core::{ConstraintSystem, SynthesisError}; -use r1cs_std::prelude::*; -use r1cs_std::boolean::AllocatedBit; - -use crate::{mht::HashMembershipProof, CommitmentScheme, FixedLengthCRH}; - -use crate::{commitment::CommitmentGadget, crh::FixedLengthCRHGadget}; - -use crate::ledger::{CommPath, Digest, LedgerDigest, LedgerWitness}; - -use std::{borrow::Borrow, marker::PhantomData}; - -pub trait LCWGadget, ConstraintF: Field> { - type ParametersGadget: AllocGadget; - type CommitmentGadget: AllocGadget; - type DigestGadget: AllocGadget; - type WitnessGadget: AllocGadget; - - fn check_witness_gadget>( - cs: CS, - parameters: &Self::ParametersGadget, - ledger_state_digest: &Self::DigestGadget, - commitment: &Self::CommitmentGadget, - witness: &Self::WitnessGadget, - ) -> Result<(), SynthesisError> { - Self::conditionally_check_witness_gadget( - cs, - parameters, - ledger_state_digest, - commitment, - witness, - &Boolean::Constant(true), - ) - } - - fn conditionally_check_witness_gadget>( - cs: CS, - parameters: &Self::ParametersGadget, - ledger_state_digest: &Self::DigestGadget, - commitment: &Self::CommitmentGadget, - witness: &Self::WitnessGadget, - should_enforce: &Boolean, - ) -> Result<(), SynthesisError>; -} - -pub struct IdealLedgerGadget { - #[doc(hidden)] - _comm_scheme: PhantomData, - #[doc(hidden)] - _hash: PhantomData, - #[doc(hidden)] - _comm_gadget: PhantomData, - #[doc(hidden)] - _hash_gadget: PhantomData, -} - -pub struct CommitmentWitness< - H: FixedLengthCRH, - C: CommitmentScheme, - HGadget: FixedLengthCRHGadget, - ConstraintF: Field, -> { - path: Vec<(HGadget::OutputGadget, HGadget::OutputGadget)>, - _crh: PhantomData, - _comm: PhantomData, - _engine: PhantomData, -} - -pub struct DigestGadget, ConstraintF: Field> { - digest: HGadget::OutputGadget, - #[doc(hidden)] - _crh: PhantomData, - #[doc(hidden)] - _engine: PhantomData, -} - -impl LCWGadget, CommPath, ConstraintF> - for IdealLedgerGadget -where - C: CommitmentScheme, - C::Output: Eq, - ConstraintF: Field, - H: FixedLengthCRH, - CGadget: CommitmentGadget, - HGadget: FixedLengthCRHGadget, -{ - type ParametersGadget = >::ParametersGadget; - type DigestGadget = DigestGadget; - - type CommitmentGadget = >::OutputGadget; - type WitnessGadget = CommitmentWitness; - - /// Given a `leaf` and `path`, check that the `path` is a valid - /// authentication path for the `leaf` in a Merkle tree. - /// Note: It is assumed that the root is contained in the `path`. - fn conditionally_check_witness_gadget>( - mut cs: CS, - parameters: &Self::ParametersGadget, - root_hash: &Self::DigestGadget, - commitment: &Self::CommitmentGadget, - witness: &Self::WitnessGadget, - should_enforce: &Boolean, - ) -> Result<(), SynthesisError> { - assert_eq!( - witness.path.len(), - (HashMembershipProof::::MAX_HEIGHT - 1) as usize - ); - // Check that the hash of the given leaf matches the leaf hash in the membership - // proof. - let commitment_bits = commitment.to_bytes(&mut cs.ns(|| "commitment_to_bytes"))?; - let commitment_hash = HGadget::check_evaluation_gadget( - cs.ns(|| "check_evaluation_gadget"), - parameters, - &commitment_bits, - )?; - - // Check if leaf is one of the bottom-most siblings. - let leaf_is_left = AllocatedBit::alloc(&mut cs.ns(|| "leaf_is_left"), || { - Ok(commitment_hash == witness.path[0].0) - })? - .into(); - ::conditional_enforce_equal_or( - &mut cs.ns(|| "check_leaf_is_left"), - &leaf_is_left, - &commitment_hash, - &witness.path[0].0, - &witness.path[0].1, - should_enforce, - )?; - - // Check levels between leaf level and root. - let mut previous_hash = commitment_hash; - for (i, &(ref left_hash, ref right_hash)) in witness.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)), || { - Ok(&previous_hash == left_hash) - })? - .into(); - - ::conditional_enforce_equal_or( - &mut cs.ns(|| format!("check_equals_which_{}", i)), - &previous_is_left, - &previous_hash, - left_hash, - right_hash, - should_enforce, - )?; - - previous_hash = hash_inner_node_gadget::( - &mut cs.ns(|| format!("hash_inner_node_{}", i)), - parameters, - left_hash, - right_hash, - )?; - } - - root_hash.digest.conditional_enforce_equal( - &mut cs.ns(|| "root_is_last"), - &previous_hash, - should_enforce, - ) - } -} - -pub(crate) fn hash_inner_node_gadget( - mut cs: CS, - parameters: &HG::ParametersGadget, - left_child: &HG::OutputGadget, - right_child: &HG::OutputGadget, -) -> Result -where - ConstraintF: Field, - CS: ConstraintSystem, - H: FixedLengthCRH, - HG: FixedLengthCRHGadget, -{ - let left_bytes = left_child.to_bytes(&mut cs.ns(|| "left_to_bytes"))?; - let right_bytes = right_child.to_bytes(&mut cs.ns(|| "right_to_bytes"))?; - let mut bytes = left_bytes; - bytes.extend_from_slice(&right_bytes); - - HG::check_evaluation_gadget(cs, parameters, &bytes) -} - -impl AllocGadget, ConstraintF> for DigestGadget -where - H: FixedLengthCRH, - HGadget: FixedLengthCRHGadget, - ConstraintF: Field, -{ - fn alloc>( - mut cs: CS, - value_gen: F, - ) -> Result - where - F: FnOnce() -> Result, - T: Borrow>, - { - let digest = HGadget::OutputGadget::alloc(&mut cs.ns(|| "digest"), || { - Ok(value_gen()?.borrow().0.clone()) - })?; - - Ok(DigestGadget { - digest, - _crh: PhantomData, - _engine: PhantomData, - }) - } - - fn alloc_input>( - mut cs: CS, - value_gen: F, - ) -> Result - where - F: FnOnce() -> Result, - T: Borrow>, - { - let digest = HGadget::OutputGadget::alloc_input(&mut cs.ns(|| "input_digest"), || { - Ok(value_gen()?.borrow().0.clone()) - })?; - Ok(DigestGadget { - digest, - _crh: PhantomData, - _engine: PhantomData, - }) - } -} - -impl AllocGadget, ConstraintF> - for CommitmentWitness -where - H: FixedLengthCRH, - C: CommitmentScheme, - HGadget: FixedLengthCRHGadget, - ConstraintF: Field, -{ - fn alloc>( - mut cs: CS, - value_gen: F, - ) -> Result - where - F: FnOnce() -> Result, - T: Borrow>, - { - let mut path = Vec::new(); - for (i, &(ref l, ref r)) in value_gen()?.borrow().0.path.iter().enumerate() { - let l_hash = - HGadget::OutputGadget::alloc(&mut cs.ns(|| format!("l_child_{}", i)), || { - Ok(l.clone()) - })?; - let r_hash = - HGadget::OutputGadget::alloc(&mut cs.ns(|| format!("r_child_{}", i)), || { - Ok(r.clone()) - })?; - path.push((l_hash, r_hash)); - } - Ok(CommitmentWitness { - path, - _crh: PhantomData, - _comm: PhantomData, - _engine: PhantomData, - }) - } - - fn alloc_input>( - mut cs: CS, - value_gen: F, - ) -> Result - where - F: FnOnce() -> Result, - T: Borrow>, - { - let mut path = Vec::new(); - for (i, &(ref l, ref r)) in value_gen()?.borrow().0.path.iter().enumerate() { - let l_hash = HGadget::OutputGadget::alloc_input( - &mut cs.ns(|| format!("l_child_{}", i)), - || Ok(l.clone()), - )?; - let r_hash = HGadget::OutputGadget::alloc_input( - &mut cs.ns(|| format!("r_child_{}", i)), - || Ok(r.clone()), - )?; - path.push((l_hash, r_hash)); - } - - Ok(CommitmentWitness { - path, - _crh: PhantomData, - _comm: PhantomData, - _engine: PhantomData, - }) - } -} - -#[cfg(test)] -mod test { - use std::rc::Rc; - - use crate::crypto_primitives::{ - commitment::{ - pedersen::{PedersenCommitment, PedersenRandomness}, - CommitmentScheme, - }, - crh::{ - pedersen::{PedersenCRH, PedersenWindow}, - FixedLengthCRH, - }, - mht::*, - }; - use algebra::{ - curves::jubjub::JubJubAffine as JubJub, - fields::jubjub::fr::Fr, - fields::jubjub::fq::Fq, - Group - }; - use rand::SeedableRng; - use algebra::UniformRand; - use rand_xorshift::XorShiftRng; - use r1cs_core::ConstraintSystem; - - use super::*; - use crate::gadgets::{ - commitment::pedersen::PedersenCommitmentGadget, - crh::{pedersen::PedersenCRHGadget, FixedLengthCRHGadget}, - }; - use r1cs_std::{ - groups::curves::twisted_edwards::jubjub::JubJubGadget, - test_constraint_system::TestConstraintSystem, - }; - - use crate::ledger::{CommPath, Digest}; - - #[derive(Clone)] - pub(super) struct Window4x256; - impl PedersenWindow for Window4x256 { - const WINDOW_SIZE: usize = 4; - const NUM_WINDOWS: usize = 256; - } - - type H = PedersenCRH; - type HG = PedersenCRHGadget; - type C = PedersenCommitment; - type CG = PedersenCommitmentGadget; - type JubJubMHT = MerkleHashTree::Output>; - type LG = IdealLedgerGadget; - type DG = DigestGadget; - type LCWG = CommitmentWitness; - - fn generate_merkle_tree(leaves: &[::Output]) -> () { - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - - let crh_parameters = Rc::new(H::setup(&mut rng).unwrap()); - let tree = JubJubMHT::new(crh_parameters.clone(), &leaves).unwrap(); - let root = tree.root(); - let mut satisfied = true; - for (i, leaf) in leaves.iter().enumerate() { - let mut cs = TestConstraintSystem::::new(); - let proof = tree.generate_proof(i, &leaf).unwrap(); - assert!(proof.verify(&crh_parameters, &root, &leaf).unwrap()); - - let digest = DG::alloc(&mut cs.ns(|| format!("new_digest_{}", i)), || { - Ok(Digest(root)) - }) - .unwrap(); - let constraints_from_digest = cs.num_constraints(); - println!("constraints from digest: {}", constraints_from_digest); - - let crh_parameters = - >::ParametersGadget::alloc( - &mut cs.ns(|| format!("new_parameters_{}", i)), - || Ok(crh_parameters.clone()), - ) - .unwrap(); - let constraints_from_parameters = cs.num_constraints() - constraints_from_digest; - println!( - "constraints from parameters: {}", - constraints_from_parameters - ); - - let comm = >::OutputGadget::alloc( - &mut cs.ns(|| format!("new_comm_{}", i)), - || { - let leaf: JubJub = *leaf; - Ok(leaf) - }, - ) - .unwrap(); - let constraints_from_comm = - cs.num_constraints() - constraints_from_parameters - constraints_from_digest; - println!("constraints from comm: {}", constraints_from_comm); - - let cw = LCWG::alloc(&mut cs.ns(|| format!("new_witness_{}", i)), || { - Ok(CommPath(proof)) - }) - .unwrap(); - let constraints_from_path = cs.num_constraints() - - constraints_from_parameters - - constraints_from_digest - - constraints_from_comm; - println!("constraints from path: {}", constraints_from_path); - LG::check_witness_gadget( - &mut cs.ns(|| format!("new_witness_check_{}", i)), - &crh_parameters, - &digest, - &comm, - &cw, - ) - .unwrap(); - if !cs.is_satisfied() { - satisfied = false; - println!( - "Unsatisfied constraint: {}", - cs.which_is_unsatisfied().unwrap() - ); - } - let setup_constraints = constraints_from_comm - + constraints_from_digest - + constraints_from_parameters - + constraints_from_path; - println!( - "number of constraints: {}", - cs.num_constraints() - setup_constraints - ); - } - assert!(satisfied); - } - - #[test] - fn mht_gadget_test() { - let mut leaves = Vec::new(); - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - let comm_parameters = C::setup(&mut rng).unwrap(); - for i in 0..4u8 { - let r = PedersenRandomness(Fr::rand(&mut rng)); - let input = [i, i, i, i, i, i, i, i]; - leaves.push(C::commit(&comm_parameters, &input, &r).unwrap()); - } - generate_merkle_tree(&leaves); - // let mut leaves = Vec::new(); - // for i in 0..100u8 { - // leaves.push([i, i, i, i, i, i, i, i]); - // } - // generate_merkle_tree(&leaves); - } - - fn bad_merkle_tree_verify(leaves: &[::Output]) -> () { - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - - let crh_parameters = Rc::new(H::setup(&mut rng).unwrap()); - let tree = JubJubMHT::new(crh_parameters.clone(), &leaves).unwrap(); - let root = tree.root(); - for (i, leaf) in leaves.iter().enumerate() { - let mut cs = TestConstraintSystem::::new(); - let proof = tree.generate_proof(i, &leaf).unwrap(); - assert!(proof.verify(&crh_parameters, &root, &leaf).unwrap()); - - let digest = DG::alloc(&mut cs.ns(|| format!("new_digest_{}", i)), || { - Ok(Digest(JubJub::zero())) - }) - .unwrap(); - let crh_parameters = - >::ParametersGadget::alloc( - &mut cs.ns(|| format!("new_parameters_{}", i)), - || Ok(crh_parameters.clone()), - ) - .unwrap(); - let comm = >::OutputGadget::alloc( - &mut cs.ns(|| format!("new_comm_{}", i)), - || { - let leaf = *leaf; - Ok(leaf) - }, - ) - .unwrap(); - let cw = LCWG::alloc(&mut cs.ns(|| format!("new_witness_{}", i)), || { - Ok(CommPath(proof)) - }) - .unwrap(); - LG::check_witness_gadget( - &mut cs.ns(|| format!("new_witness_check_{}", i)), - &crh_parameters, - &digest, - &comm, - &cw, - ) - .unwrap(); - if !cs.is_satisfied() { - println!( - "Unsatisfied constraints: {}", - cs.which_is_unsatisfied().unwrap() - ); - } - assert!(cs.is_satisfied()); - } - } - - #[should_panic] - #[test] - fn bad_root_test() { - let mut leaves = Vec::new(); - let mut rng = XorShiftRng::seed_from_u64(1231275789u64); - let comm_parameters = C::setup(&mut rng).unwrap(); - for i in 0..4u8 { - let r = PedersenRandomness(Fr::rand(&mut rng)); - let input = [i, i, i, i, i, i, i, i]; - leaves.push(C::commit(&comm_parameters, &input, &r).unwrap()); - } - bad_merkle_tree_verify(&leaves); - } -}