From 3ba3090cd0e105749eeb59ca20844ed117fa33c0 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 16 Aug 2021 15:22:31 -0700 Subject: [PATCH 01/13] Reduce generics for common traits --- Cargo.toml | 8 +- src/commitment/blake2s/constraints.rs | 23 +-- src/commitment/constraints.rs | 8 +- src/commitment/injective_map/constraints.rs | 45 ++--- src/commitment/pedersen/constraints.rs | 79 +++------ src/crh/bowe_hopwood/constraints.rs | 83 ++++------ src/crh/constraints.rs | 12 +- src/crh/injective_map/constraints.rs | 128 ++++----------- src/crh/pedersen/constraints.rs | 71 +++----- src/crh/poseidon/constraints.rs | 30 +--- src/lib.rs | 12 +- src/merkle_tree/constraints.rs | 172 +++++++++----------- src/merkle_tree/mod.rs | 142 +++++++--------- 13 files changed, 301 insertions(+), 512 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 143ce7dd..6fa01f9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,8 +28,6 @@ digest = "0.9" ark-r1cs-std = { version = "^0.3.0", optional = true, default-features = false } ark-snark = { version = "^0.3.0", default-features = false } -ark-nonnative-field = { version = "^0.3.0", optional = true, default-features = false } - rayon = { version = "1.0", optional = true } derivative = { version = "2.0", features = ["use_core"] } tracing = { version = "0.1", default-features = false, features = [ "attributes" ], optional = true } @@ -39,10 +37,14 @@ default = ["std"] std = [ "ark-ff/std", "ark-ec/std", "ark-std/std", "ark-relations/std" ] print-trace = [ "ark-std/print-trace" ] parallel = [ "std", "rayon", "ark-ec/parallel", "ark-std/parallel", "ark-ff/parallel" ] -r1cs = [ "ark-r1cs-std", "tracing", "ark-nonnative-field", "ark-sponge/r1cs" ] +r1cs = [ "ark-r1cs-std", "tracing", "ark-sponge/r1cs" ] [dev-dependencies] ark-ed-on-bls12-381 = { version = "^0.3.0", default-features = false, features = [ "r1cs" ] } ark-bls12-377 = { version = "^0.3.0", default-features = false, features = [ "curve", "r1cs" ] } ark-mnt4-298 = { version = "^0.3.0", default-features = false, features = [ "curve", "r1cs" ] } ark-mnt6-298 = { version = "^0.3.0", default-features = false, features = [ "r1cs" ] } + +[patch.crates-io] +ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", branch = "reduce-generics", optional = true, default-features = false } +ark-sponge = { git = "https://github.com/arkworks-rs/sponge", branch = "reduce-generics", default-features = false } diff --git a/src/commitment/blake2s/constraints.rs b/src/commitment/blake2s/constraints.rs index 4659faae..c87da760 100644 --- a/src/commitment/blake2s/constraints.rs +++ b/src/commitment/blake2s/constraints.rs @@ -16,9 +16,7 @@ pub struct ParametersVar; #[derive(Clone)] pub struct RandomnessVar(pub Vec>); -pub struct CommGadget; - -impl CommitmentGadget for CommGadget { +impl CommitmentGadget for blake2s::Commitment { type OutputVar = OutputVar; type ParametersVar = ParametersVar; type RandomnessVar = RandomnessVar; @@ -72,10 +70,7 @@ impl AllocVar<[u8; 32], ConstraintF> for RandomnessVar< #[cfg(test)] mod test { use crate::commitment::{ - blake2s::{ - constraints::{CommGadget, RandomnessVar}, - Commitment, - }, + blake2s::{constraints::RandomnessVar, Commitment}, CommitmentGadget, CommitmentScheme, }; use ark_ed_on_bls12_381::Fq as Fr; @@ -92,7 +87,6 @@ mod test { let rng = &mut ark_std::test_rng(); type TestCOMM = Commitment; - type TestCOMMGadget = CommGadget; let mut randomness = [0u8; 32]; rng.fill(&mut randomness); @@ -111,13 +105,12 @@ mod test { } let randomness_var = RandomnessVar(randomness_var); - let parameters_var = - >::ParametersVar::new_witness( - ark_relations::ns!(cs, "gadget_parameters"), - || Ok(¶meters), - ) - .unwrap(); - let result_var = >::commit( + let parameters_var = >::ParametersVar::new_witness( + ark_relations::ns!(cs, "gadget_parameters"), + || Ok(¶meters), + ) + .unwrap(); + let result_var = >::commit( ¶meters_var, &input_var, &randomness_var, diff --git a/src/commitment/constraints.rs b/src/commitment/constraints.rs index 5124e5a5..1e27aa88 100644 --- a/src/commitment/constraints.rs +++ b/src/commitment/constraints.rs @@ -4,16 +4,16 @@ use ark_r1cs_std::prelude::*; use ark_relations::r1cs::SynthesisError; use core::fmt::Debug; -pub trait CommitmentGadget { +pub trait CommitmentGadget: CommitmentScheme { type OutputVar: EqGadget + ToBytesGadget - + AllocVar + + AllocVar + R1CSVar + Clone + Sized + Debug; - type ParametersVar: AllocVar + Clone; - type RandomnessVar: AllocVar + Clone; + type ParametersVar: AllocVar + Clone; + type RandomnessVar: AllocVar + Clone; fn commit( parameters: &Self::ParametersVar, diff --git a/src/commitment/injective_map/constraints.rs b/src/commitment/injective_map/constraints.rs index 7a1ce3cb..4baa4a0b 100644 --- a/src/commitment/injective_map/constraints.rs +++ b/src/commitment/injective_map/constraints.rs @@ -1,8 +1,8 @@ use crate::commitment::{ - injective_map::{InjectiveMap, PedersenCommCompressor}, + injective_map::PedersenCommCompressor, pedersen::{ - constraints::{CommGadget, ParametersVar, RandomnessVar}, - Window, + constraints::{ParametersVar, RandomnessVar}, + Commitment, Window, }, }; @@ -10,43 +10,24 @@ pub use crate::crh::injective_map::constraints::InjectiveMapGadget; use ark_ec::ProjectiveCurve; use ark_ff::{Field, PrimeField}; use ark_r1cs_std::{ - groups::{CurveVar, GroupOpsBounds}, + groups::{CurveWithVar, GroupOpsBounds}, uint8::UInt8, }; use ark_relations::r1cs::SynthesisError; -use ark_std::marker::PhantomData; - type ConstraintF = <::BaseField as Field>::BasePrimeField; -pub struct CommitmentCompressorGadget -where - C: ProjectiveCurve, - I: InjectiveMap, - W: Window, - GG: CurveVar>, - IG: InjectiveMapGadget, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - _compressor: PhantomData, - _compressor_gadget: PhantomData, - _comm: PhantomData>, -} - -impl - crate::commitment::CommitmentGadget, ConstraintF> - for CommitmentCompressorGadget +impl crate::commitment::CommitmentGadget> + for PedersenCommCompressor where - C: ProjectiveCurve, - I: InjectiveMap, - GG: CurveVar>, + C: CurveWithVar>, + I: InjectiveMapGadget, ConstraintF: PrimeField, - IG: InjectiveMapGadget, W: Window, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + for<'a> &'a C::Var: GroupOpsBounds<'a, C, C::Var>, { - type OutputVar = IG::OutputVar; - type ParametersVar = ParametersVar; + type OutputVar = I::OutputVar; + type ParametersVar = ParametersVar; type RandomnessVar = RandomnessVar>; fn commit( @@ -54,7 +35,7 @@ where input: &[UInt8>], r: &Self::RandomnessVar, ) -> Result { - let result = CommGadget::::commit(parameters, input, r)?; - IG::evaluate(&result) + let result = Commitment::::commit(parameters, input, r)?; + I::evaluate(&result) } } diff --git a/src/commitment/pedersen/constraints.rs b/src/commitment/pedersen/constraints.rs index 83ddcab1..3594a3f3 100644 --- a/src/commitment/pedersen/constraints.rs +++ b/src/commitment/pedersen/constraints.rs @@ -11,47 +11,28 @@ use ark_ff::{ use ark_relations::r1cs::{Namespace, SynthesisError}; use ark_r1cs_std::prelude::*; -use core::{borrow::Borrow, marker::PhantomData}; +use core::borrow::Borrow; type ConstraintF = <::BaseField as Field>::BasePrimeField; #[derive(Derivative)] -#[derivative(Clone(bound = "C: ProjectiveCurve, GG: CurveVar>"))] -pub struct ParametersVar>> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ +#[derivative(Clone(bound = "C: CurveWithVar>"))] +pub struct ParametersVar>> { params: Parameters, - #[doc(hidden)] - _group_var: PhantomData, } #[derive(Clone, Debug)] pub struct RandomnessVar(Vec>); -pub struct CommGadget>, W: Window> +impl crate::commitment::CommitmentGadget> for Commitment where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - #[doc(hidden)] - _curve: PhantomData<*const C>, - #[doc(hidden)] - _group_var: PhantomData<*const GG>, - #[doc(hidden)] - _window: PhantomData<*const W>, -} - -impl crate::commitment::CommitmentGadget, ConstraintF> - for CommGadget -where - C: ProjectiveCurve, - GG: CurveVar>, + C: CurveWithVar>, W: Window, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + for<'a> &'a C::Var: GroupOpsBounds<'a, C, C::Var>, ConstraintF: PrimeField, { - type OutputVar = GG; - type ParametersVar = ParametersVar; + type OutputVar = C::Var; + type ParametersVar = ParametersVar; type RandomnessVar = RandomnessVar>; #[tracing::instrument(target = "r1cs", skip(parameters, r))] @@ -80,8 +61,10 @@ where .flat_map(|byte| byte.to_bits_le().unwrap()) .collect(); let input_in_bits = input_in_bits.chunks(W::WINDOW_SIZE); - let mut result = - GG::precomputed_base_multiscalar_mul_le(¶meters.params.generators, input_in_bits)?; + let mut result = C::Var::precomputed_base_multiscalar_mul_le( + ¶meters.params.generators, + input_in_bits, + )?; // Compute h^r let rand_bits: Vec<_> = @@ -98,11 +81,10 @@ where } } -impl AllocVar, ConstraintF> for ParametersVar +impl AllocVar, ConstraintF> for ParametersVar where - C: ProjectiveCurve, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + C: CurveWithVar>, + for<'a> &'a C::Var: GroupOpsBounds<'a, C, C::Var>, { fn new_variable>>( _cs: impl Into>>, @@ -110,10 +92,7 @@ where _mode: AllocationMode, ) -> Result { let params = f()?.borrow().clone(); - Ok(ParametersVar { - params, - _group_var: PhantomData, - }) + Ok(ParametersVar { params }) } } @@ -168,7 +147,6 @@ mod test { let rng = &mut test_rng(); type TestCOMM = Commitment; - type TestCOMMGadget = CommGadget; let randomness = Randomness(Fr::rand(rng)); @@ -181,20 +159,17 @@ mod test { input_var.push(UInt8::new_witness(cs.clone(), || Ok(*input_byte)).unwrap()); } - let randomness_var = - >::RandomnessVar::new_witness( - ark_relations::ns!(cs, "gadget_randomness"), - || Ok(&randomness), - ) - .unwrap(); - let parameters_var = - >::ParametersVar::new_witness( - ark_relations::ns!(cs, "gadget_parameters"), - || Ok(¶meters), - ) - .unwrap(); - let result_var = - TestCOMMGadget::commit(¶meters_var, &input_var, &randomness_var).unwrap(); + let randomness_var = >::RandomnessVar::new_witness( + ark_relations::ns!(cs, "gadget_randomness"), + || Ok(&randomness), + ) + .unwrap(); + let parameters_var = >::ParametersVar::new_witness( + ark_relations::ns!(cs, "gadget_parameters"), + || Ok(¶meters), + ) + .unwrap(); + let result_var = TestCOMM::commit(¶meters_var, &input_var, &randomness_var).unwrap(); let primitive_result = primitive_result; assert_eq!(primitive_result, result_var.value().unwrap()); diff --git a/src/crh/bowe_hopwood/constraints.rs b/src/crh/bowe_hopwood/constraints.rs index bc0dfed4..cd5aa780 100644 --- a/src/crh/bowe_hopwood/constraints.rs +++ b/src/crh/bowe_hopwood/constraints.rs @@ -2,7 +2,7 @@ use core::{borrow::Borrow, iter, marker::PhantomData}; use crate::{ crh::{ - bowe_hopwood::{Parameters, CHUNK_SIZE}, + bowe_hopwood::{Parameters, TwoToOneCRH, CHUNK_SIZE, CRH}, pedersen::{self, Window}, CRHSchemeGadget, TwoToOneCRHSchemeGadget, }, @@ -17,7 +17,6 @@ use ark_r1cs_std::{ }; use ark_relations::r1cs::{Namespace, SynthesisError}; -use crate::crh::bowe_hopwood::{TwoToOneCRH, CRH}; use ark_r1cs_std::bits::boolean::Boolean; type ConstraintF

= <

::BaseField as Field>::BasePrimeField; @@ -30,28 +29,22 @@ pub struct ParametersVar { _window: PhantomData, } -pub struct CRHGadget>> -where - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, -{ - #[doc(hidden)] - _params: PhantomData

, - #[doc(hidden)] - _base_field: PhantomData, -} +type BF

=

::BaseField; +type BFVar

= as FieldWithVar>::Var; -impl CRHSchemeGadget, ConstraintF

> for CRHGadget +impl CRHSchemeGadget> for CRH where - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, - F: FieldVar>, - F: TwoBitLookupGadget, TableConstant = P::BaseField> - + ThreeBitCondNegLookupGadget, TableConstant = P::BaseField>, + BF

: FieldWithVar, + BFVar

: TwoBitLookupGadget, TableConstant = BF

> + + ThreeBitCondNegLookupGadget, TableConstant = BF

>, + + for<'a> &'a BFVar

: FieldOpsBounds<'a, BF

, BFVar

>, P: TEModelParameters, W: Window, { type InputVar = [UInt8>]; - type OutputVar = F; + type OutputVar = BFVar

; type ParametersVar = ParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters, input))] @@ -90,27 +83,18 @@ where } } -pub struct TwoToOneCRHGadget>> +impl TwoToOneCRHSchemeGadget> for TwoToOneCRH where - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, -{ - #[doc(hidden)] - _params: PhantomData

, - #[doc(hidden)] - _base_field: PhantomData, -} + BF

: FieldWithVar, + BFVar

: TwoBitLookupGadget, TableConstant = BF

> + + ThreeBitCondNegLookupGadget, TableConstant = BF

>, -impl TwoToOneCRHSchemeGadget, ConstraintF

> for TwoToOneCRHGadget -where - for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>, - F: FieldVar>, - F: TwoBitLookupGadget, TableConstant = P::BaseField> - + ThreeBitCondNegLookupGadget, TableConstant = P::BaseField>, + for<'a> &'a BFVar

: FieldOpsBounds<'a, BF

, BFVar

>, P: TEModelParameters, W: Window, { type InputVar = [UInt8>]; - type OutputVar = F; + type OutputVar = BFVar

; type ParametersVar = ParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters))] @@ -133,7 +117,7 @@ where .chain(right_input.to_vec().into_iter()) .chain(iter::repeat(UInt8::constant(0u8)).take(num_trailing_zeros)) .collect(); - CRHGadget::::evaluate(parameters, &chained_input) + CRH::::evaluate(parameters, &chained_input) } fn compress( @@ -179,11 +163,8 @@ mod test { use ark_std::test_rng; type TestCRH = bowe_hopwood::CRH; - type TestCRHGadget = bowe_hopwood::constraints::CRHGadget; type TestTwoToOneCRH = bowe_hopwood::TwoToOneCRH; - type TestTwoToOneCRHGadget = - bowe_hopwood::constraints::TwoToOneCRHGadget; #[derive(Clone, PartialEq, Eq, Hash)] pub(super) struct Window; @@ -219,18 +200,17 @@ mod test { let parameters = TestCRH::setup(rng).unwrap(); let primitive_result = TestCRH::evaluate(¶meters, input.as_slice()).unwrap(); - let parameters_var = - >::ParametersVar::new_witness( - ark_relations::ns!(cs, "parameters_var"), - || Ok(¶meters), - ) - .unwrap(); + let parameters_var = >::ParametersVar::new_witness( + ark_relations::ns!(cs, "parameters_var"), + || Ok(¶meters), + ) + .unwrap(); println!( "number of constraints for input + params: {}", cs.num_constraints() ); - let result_var = TestCRHGadget::evaluate(¶meters_var, &input_var).unwrap(); + let result_var = TestCRH::evaluate(¶meters_var, &input_var).unwrap(); println!("number of constraints total: {}", cs.num_constraints()); @@ -252,18 +232,15 @@ mod test { TestTwoToOneCRH::evaluate(¶meters, left_input.as_slice(), right_input.as_slice()) .unwrap(); - let parameters_var = >::ParametersVar::new_witness( - ark_relations::ns!(cs, "parameters_var"), - || Ok(¶meters), - ) - .unwrap(); + let parameters_var = + >::ParametersVar::new_witness( + ark_relations::ns!(cs, "parameters_var"), + || Ok(¶meters), + ) + .unwrap(); let result_var = - TestTwoToOneCRHGadget::evaluate(¶meters_var, &left_input_var, &right_input_var) - .unwrap(); + TestTwoToOneCRH::evaluate(¶meters_var, &left_input_var, &right_input_var).unwrap(); let primitive_result = primitive_result; assert_eq!(primitive_result, result_var.value().unwrap()); diff --git a/src/crh/constraints.rs b/src/crh/constraints.rs index 81c0aebd..d32290ca 100644 --- a/src/crh/constraints.rs +++ b/src/crh/constraints.rs @@ -6,17 +6,17 @@ use ark_relations::r1cs::SynthesisError; use ark_r1cs_std::prelude::*; -pub trait CRHSchemeGadget: Sized { +pub trait CRHSchemeGadget: CRHScheme { type InputVar: ?Sized; type OutputVar: EqGadget + ToBytesGadget + CondSelectGadget - + AllocVar + + AllocVar + R1CSVar + Debug + Clone + Sized; - type ParametersVar: AllocVar + Clone; + type ParametersVar: AllocVar + Clone; fn evaluate( parameters: &Self::ParametersVar, @@ -24,18 +24,18 @@ pub trait CRHSchemeGadget: Sized { ) -> Result; } -pub trait TwoToOneCRHSchemeGadget: Sized { +pub trait TwoToOneCRHSchemeGadget: TwoToOneCRHScheme { type InputVar: ?Sized; type OutputVar: EqGadget + ToBytesGadget + CondSelectGadget - + AllocVar + + AllocVar + R1CSVar + Debug + Clone + Sized; - type ParametersVar: AllocVar + Clone; + type ParametersVar: AllocVar + Clone; fn evaluate( parameters: &Self::ParametersVar, diff --git a/src/crh/injective_map/constraints.rs b/src/crh/injective_map/constraints.rs index ea67326c..06b74839 100644 --- a/src/crh/injective_map/constraints.rs +++ b/src/crh/injective_map/constraints.rs @@ -1,138 +1,86 @@ use crate::crh::{ constraints, injective_map::{InjectiveMap, PedersenCRHCompressor, TECompressor}, - pedersen::{constraints as ped_constraints, Window}, + pedersen::{self, constraints as ped_constraints, Window}, TwoToOneCRHSchemeGadget, }; -use core::{fmt::Debug, marker::PhantomData}; +use core::fmt::Debug; use crate::crh::injective_map::PedersenTwoToOneCRHCompressor; -use crate::CRHSchemeGadget; use ark_ec::{ - models::{ModelParameters, TEModelParameters}, - twisted_edwards_extended::GroupProjective as TEProjective, - ProjectiveCurve, + models::TEModelParameters, twisted_edwards_extended::GroupProjective as TEProjective, + ModelParameters, ProjectiveCurve, }; use ark_ff::fields::{Field, PrimeField, SquareRootField}; -use ark_r1cs_std::{ - fields::fp::FpVar, - groups::{curves::twisted_edwards::AffineVar as TEVar, CurveVar}, - prelude::*, -}; +use ark_r1cs_std::{groups::curves::twisted_edwards::AffineVar as TEVar, prelude::*}; use ark_relations::r1cs::SynthesisError; type ConstraintF = <::BaseField as Field>::BasePrimeField; -pub trait InjectiveMapGadget< - C: ProjectiveCurve, - I: InjectiveMap, - GG: CurveVar>, -> where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ +pub trait InjectiveMapGadget>>: InjectiveMap { type OutputVar: EqGadget> + ToBytesGadget> + CondSelectGadget> - + AllocVar> - + R1CSVar, Value = I::Output> + + AllocVar> + + R1CSVar, Value = Self::Output> + Debug + Clone + Sized; - fn evaluate(ge: &GG) -> Result; + fn evaluate(ge: &C::Var) -> Result; } -pub struct TECompressorGadget; +type BFVar

= <

::BaseField as FieldWithVar>::Var; -impl InjectiveMapGadget, TECompressor, TEVar>> - for TECompressorGadget +impl

InjectiveMapGadget> for TECompressor where - F: PrimeField + SquareRootField, - P: TEModelParameters + ModelParameters, + P: TEModelParameters, + BFVar

: + TwoBitLookupGadget<::BasePrimeField, TableConstant = P::BaseField>, + for<'a> &'a BFVar

: FieldOpsBounds<'a, P::BaseField, BFVar

>, + P::BaseField: FieldWithVar + PrimeField + SquareRootField, { - type OutputVar = FpVar; + type OutputVar = BFVar

; - fn evaluate(ge: &TEVar>) -> Result { + fn evaluate(ge: &TEVar

) -> Result { Ok(ge.x.clone()) } } -pub struct PedersenCRHCompressorGadget -where - C: ProjectiveCurve, - I: InjectiveMap, - W: Window, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, - IG: InjectiveMapGadget, -{ - #[doc(hidden)] - _compressor: PhantomData, - #[doc(hidden)] - _compressor_gadget: PhantomData, - #[doc(hidden)] - _crh: ped_constraints::CRHGadget, -} - -impl constraints::CRHSchemeGadget, ConstraintF> - for PedersenCRHCompressorGadget +impl constraints::CRHSchemeGadget> for PedersenCRHCompressor where - C: ProjectiveCurve, - I: InjectiveMap, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, - IG: InjectiveMapGadget, + C: CurveWithVar>, + for<'a> &'a C::Var: GroupOpsBounds<'a, C, C::Var>, + I: InjectiveMapGadget, W: Window, { type InputVar = [UInt8>]; - type OutputVar = IG::OutputVar; - type ParametersVar = ped_constraints::CRHParametersVar; + type OutputVar = I::OutputVar; + type ParametersVar = ped_constraints::CRHParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters, input))] fn evaluate( parameters: &Self::ParametersVar, input: &Self::InputVar, ) -> Result { - let result = as CRHSchemeGadget<_, _>>::evaluate( - parameters, input, - )?; - IG::evaluate(&result) + let result = pedersen::CRH::::evaluate(parameters, input)?; + I::evaluate(&result) } } -pub struct PedersenTwoToOneCRHCompressorGadget +impl constraints::TwoToOneCRHSchemeGadget> + for PedersenTwoToOneCRHCompressor where - C: ProjectiveCurve, - I: InjectiveMap, - W: Window, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, - IG: InjectiveMapGadget, -{ - #[doc(hidden)] - _compressor: PhantomData, - #[doc(hidden)] - _compressor_gadget: PhantomData, - #[doc(hidden)] - _crh: ped_constraints::CRHGadget, -} - -impl - constraints::TwoToOneCRHSchemeGadget, ConstraintF> - for PedersenTwoToOneCRHCompressorGadget -where - C: ProjectiveCurve, - I: InjectiveMap, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, - IG: InjectiveMapGadget, + C: CurveWithVar>, + I: InjectiveMapGadget, + for<'a> &'a C::Var: GroupOpsBounds<'a, C, C::Var>, W: Window, { type InputVar = [UInt8>]; - type OutputVar = IG::OutputVar; - type ParametersVar = ped_constraints::CRHParametersVar; + type OutputVar = I::OutputVar; + type ParametersVar = ped_constraints::CRHParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters))] fn evaluate( @@ -142,12 +90,8 @@ where ) -> Result { // assume equality of left and right length assert_eq!(left_input.len(), right_input.len()); - let result = ped_constraints::TwoToOneCRHGadget::::evaluate( - parameters, - left_input, - right_input, - )?; - IG::evaluate(&result) + let result = pedersen::TwoToOneCRH::::evaluate(parameters, left_input, right_input)?; + I::evaluate(&result) } fn compress( @@ -157,7 +101,7 @@ where ) -> Result { let left_input_bytes = left_input.to_non_unique_bytes()?; let right_input_bytes = right_input.to_non_unique_bytes()?; - >::evaluate( + >::evaluate( parameters, &left_input_bytes, &right_input_bytes, diff --git a/src/crh/pedersen/constraints.rs b/src/crh/pedersen/constraints.rs index 1ec6d6c5..7822e39a 100644 --- a/src/crh/pedersen/constraints.rs +++ b/src/crh/pedersen/constraints.rs @@ -1,7 +1,7 @@ use crate::{ crh::{ - pedersen::{Parameters, Window}, - CRHSchemeGadget as CRHGadgetTrait, + pedersen::{Parameters, TwoToOneCRH, Window, CRH}, + CRHSchemeGadget, TwoToOneCRHSchemeGadget, }, Vec, }; @@ -10,44 +10,24 @@ use ark_ff::Field; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::{Namespace, SynthesisError}; -use crate::crh::pedersen::{TwoToOneCRH, CRH}; -use crate::crh::{CRHSchemeGadget, TwoToOneCRHSchemeGadget}; use core::{borrow::Borrow, marker::PhantomData}; +type ConstraintF = <::BaseField as Field>::BasePrimeField; #[derive(Derivative)] -#[derivative(Clone(bound = "C: ProjectiveCurve, GG: CurveVar>"))] -pub struct CRHParametersVar>> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ +#[derivative(Clone(bound = "C: CurveWithVar>"))] +pub struct CRHParametersVar>> { params: Parameters, - #[doc(hidden)] - _group_g: PhantomData, -} - -type ConstraintF = <::BaseField as Field>::BasePrimeField; -pub struct CRHGadget>, W: Window> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - #[doc(hidden)] - _group: PhantomData<*const C>, - #[doc(hidden)] - _group_var: PhantomData<*const GG>, - #[doc(hidden)] - _window: PhantomData<*const W>, } -impl CRHSchemeGadget, ConstraintF> for CRHGadget +impl CRHSchemeGadget> for CRH where - C: ProjectiveCurve, - GG: CurveVar>, + C: CurveWithVar>, W: Window, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + for<'a> &'a C::Var: GroupOpsBounds<'a, C, C::Var>, { type InputVar = [UInt8>]; - type OutputVar = GG; - type ParametersVar = CRHParametersVar; + type OutputVar = C::Var; + type ParametersVar = CRHParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters, input))] fn evaluate( @@ -71,8 +51,10 @@ where .flat_map(|b| b.to_bits_le().unwrap()) .collect(); let input_in_bits = input_in_bits.chunks(W::WINDOW_SIZE); - let result = - GG::precomputed_base_multiscalar_mul_le(¶meters.params.generators, input_in_bits)?; + let result = C::Var::precomputed_base_multiscalar_mul_le( + ¶meters.params.generators, + input_in_bits, + )?; Ok(result) } } @@ -89,17 +71,15 @@ where _window: PhantomData<*const W>, } -impl TwoToOneCRHSchemeGadget, ConstraintF> - for TwoToOneCRHGadget +impl TwoToOneCRHSchemeGadget> for TwoToOneCRH where - C: ProjectiveCurve, - GG: CurveVar>, + C: CurveWithVar>, W: Window, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + for<'a> &'a C::Var: GroupOpsBounds<'a, C, C::Var>, { type InputVar = [UInt8>]; - type OutputVar = GG; - type ParametersVar = CRHParametersVar; + type OutputVar = C::Var; + type ParametersVar = CRHParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters))] fn evaluate( @@ -114,7 +94,7 @@ where .into_iter() .chain(right_input.to_vec().into_iter()) .collect(); - CRHGadget::::evaluate(parameters, &chained_input) + CRH::::evaluate(parameters, &chained_input) } #[tracing::instrument(target = "r1cs", skip(parameters))] @@ -130,11 +110,9 @@ where } } -impl AllocVar, ConstraintF> for CRHParametersVar +impl AllocVar, ConstraintF> for CRHParametersVar where - C: ProjectiveCurve, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + C: CurveWithVar>, { #[tracing::instrument(target = "r1cs", skip(_cs, f))] fn new_variable>>( @@ -143,10 +121,7 @@ where _mode: AllocationMode, ) -> Result { let params = f()?.borrow().clone(); - Ok(CRHParametersVar { - params, - _group_g: PhantomData, - }) + Ok(CRHParametersVar { params }) } } diff --git a/src/crh/poseidon/constraints.rs b/src/crh/poseidon/constraints.rs index 93ae7f1b..65d6df7b 100644 --- a/src/crh/poseidon/constraints.rs +++ b/src/crh/poseidon/constraints.rs @@ -13,18 +13,13 @@ use ark_sponge::poseidon::constraints::PoseidonSpongeVar; use ark_sponge::poseidon::PoseidonParameters; use ark_sponge::Absorb; use ark_std::borrow::Borrow; -use ark_std::marker::PhantomData; #[derive(Clone)] pub struct CRHParametersVar { pub parameters: PoseidonParameters, } -pub struct CRHGadget { - field_phantom: PhantomData, -} - -impl CRHGadgetTrait, F> for CRHGadget { +impl CRHGadgetTrait for CRH { type InputVar = [FpVar]; type OutputVar = FpVar; type ParametersVar = CRHParametersVar; @@ -36,12 +31,9 @@ impl CRHGadgetTrait, F> for CRHGadget { let cs = input.cs(); if cs.is_none() { - let mut constant_input = Vec::new(); - for var in input.iter() { - constant_input.push(var.value()?); - } + let input = input.iter().map(|f| f.value().unwrap()).collect::>(); Ok(FpVar::Constant( - CRH::::evaluate(¶meters.parameters, constant_input).unwrap(), + as CRHScheme>::evaluate(¶meters.parameters, input).unwrap(), )) } else { let mut sponge = PoseidonSpongeVar::new(cs, ¶meters.parameters); @@ -52,11 +44,7 @@ impl CRHGadgetTrait, F> for CRHGadget { } } -pub struct TwoToOneCRHGadget { - field_phantom: PhantomData, -} - -impl TwoToOneCRHGadgetTrait, F> for TwoToOneCRHGadget { +impl TwoToOneCRHGadgetTrait for TwoToOneCRH { type InputVar = FpVar; type OutputVar = FpVar; type ParametersVar = CRHParametersVar; @@ -78,7 +66,7 @@ impl TwoToOneCRHGadgetTrait, F> for TwoTo if cs.is_none() { Ok(FpVar::Constant( - CRH::::evaluate( + as CRHScheme>::evaluate( ¶meters.parameters, vec![left_input.value()?, right_input.value()?], ) @@ -110,7 +98,7 @@ impl AllocVar, F> for CRHParameter #[cfg(test)] mod test { - use crate::crh::poseidon::constraints::{CRHGadget, CRHParametersVar, TwoToOneCRHGadget}; + use crate::crh::poseidon::constraints::CRHParametersVar; use crate::crh::poseidon::{TwoToOneCRH, CRH}; use crate::crh::{TwoToOneCRHScheme, TwoToOneCRHSchemeGadget}; use crate::{CRHScheme, CRHSchemeGadget}; @@ -174,9 +162,9 @@ mod test { } let params_g = CRHParametersVar::::new_witness(cs, || Ok(params)).unwrap(); - let crh_a_g = CRHGadget::::evaluate(¶ms_g, &test_a_g).unwrap(); - let crh_b_g = CRHGadget::::evaluate(¶ms_g, &test_b_g).unwrap(); - let crh_g = TwoToOneCRHGadget::::compress(¶ms_g, &crh_a_g, &crh_b_g).unwrap(); + let crh_a_g = CRH::::evaluate(¶ms_g, &test_a_g).unwrap(); + let crh_b_g = CRH::::evaluate(¶ms_g, &test_b_g).unwrap(); + let crh_g = TwoToOneCRH::::compress(¶ms_g, &crh_a_g, &crh_b_g).unwrap(); assert_eq!(crh_a, crh_a_g.value().unwrap()); assert_eq!(crh_b, crh_b_g.value().unwrap()); diff --git a/src/lib.rs b/src/lib.rs index f1de5d1c..7b4424b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,21 +24,23 @@ pub mod merkle_tree; pub mod encryption; pub mod prf; pub mod signature; -pub mod snark; +// pub mod snark; pub use self::{ commitment::CommitmentScheme, crh::CRHScheme, - merkle_tree::{MerkleTree, Path}, + // merkle_tree::{MerkleTree, Path}, prf::PRF, signature::SignatureScheme, - snark::{CircuitSpecificSetupSNARK, UniversalSetupSNARK, SNARK}, + // snark::{CircuitSpecificSetupSNARK, UniversalSetupSNARK, SNARK}, }; #[cfg(feature = "r1cs")] pub use self::{ - commitment::CommitmentGadget, crh::CRHSchemeGadget, merkle_tree::constraints::PathVar, - prf::PRFGadget, signature::SigRandomizePkGadget, snark::SNARKGadget, + commitment::CommitmentGadget, + crh::CRHSchemeGadget, //merkle_tree::constraints::PathVar, + prf::PRFGadget, + signature::SigRandomizePkGadget, //snark::SNARKGadget, }; pub type Error = Box; diff --git a/src/merkle_tree/constraints.rs b/src/merkle_tree/constraints.rs index 74d9f68a..29caf236 100644 --- a/src/merkle_tree/constraints.rs +++ b/src/merkle_tree/constraints.rs @@ -1,6 +1,6 @@ use crate::crh::TwoToOneCRHSchemeGadget; -use crate::merkle_tree::{Config, IdentityDigestConverter}; -use crate::{CRHSchemeGadget, Path}; +use crate::merkle_tree::{Config, Path}; +use crate::CRHSchemeGadget; use ark_ff::Field; use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::boolean::Boolean; @@ -12,100 +12,71 @@ use ark_std::borrow::Borrow; use ark_std::fmt::Debug; use ark_std::vec::Vec; -pub trait DigestVarConverter { - type TargetType: Borrow; - fn convert(from: From) -> Result; -} - -impl DigestVarConverter for IdentityDigestConverter { - type TargetType = T; +use super::ByteDigestConverter; - fn convert(from: T) -> Result { - Ok(from) - } -} - -pub struct BytesVarDigestConverter, ConstraintF: Field> { - _prev_layer_digest: T, - _constraint_field: ConstraintF, +pub trait DigestVarConverter { + type Target: Borrow; + fn convert(from: &From) -> Result; } impl, ConstraintF: Field> DigestVarConverter]> - for BytesVarDigestConverter + for ByteDigestConverter { - type TargetType = Vec>; + type Target = Vec>; - fn convert(from: T) -> Result { + fn convert(from: &T) -> Result { from.to_non_unique_bytes() } } -pub trait ConfigGadget { - type Leaf: Debug + ?Sized; - type LeafDigest: AllocVar - + EqGadget - + ToBytesGadget - + CondSelectGadget - + R1CSVar - + Debug - + Clone - + Sized; - type LeafInnerConverter: DigestVarConverter< - Self::LeafDigest, - >::InputVar, - >; - type InnerDigest: AllocVar - + EqGadget - + ToBytesGadget - + CondSelectGadget - + R1CSVar - + Debug - + Clone - + Sized; - - type LeafHash: CRHSchemeGadget< - P::LeafHash, - ConstraintF, - InputVar = Self::Leaf, - OutputVar = Self::LeafDigest, - >; - type TwoToOneHash: TwoToOneCRHSchemeGadget< - P::TwoToOneHash, - ConstraintF, - OutputVar = Self::InnerDigest, +pub trait ConfigGadget: Config +where + Self::LeafHash: CRHSchemeGadget, + Self::TwoToOneHash: TwoToOneCRHSchemeGadget, +{ + type LeafVar: Debug + ?Sized; + + type LeafToInnerVarConverter: DigestVarConverter< + LeafDigestVar, + TwoToOneInputVar, >; } -type LeafParam = - <>::LeafHash as CRHSchemeGadget< -

::LeafHash, - ConstraintF, - >>::ParametersVar; -type TwoToOneParam = - <>::TwoToOneHash as TwoToOneCRHSchemeGadget< -

::TwoToOneHash, - ConstraintF, - >>::ParametersVar; +pub type TwoToOneInputVar = + <::TwoToOneHash as TwoToOneCRHSchemeGadget>::InputVar; +pub type LeafDigestVar = <::LeafHash as CRHSchemeGadget>::OutputVar; +pub type TwoToOneDigestVar = + <::TwoToOneHash as TwoToOneCRHSchemeGadget>::OutputVar; + +pub type LeafParamsVar = + <::LeafHash as CRHSchemeGadget>::ParametersVar; + +pub type TwoToOneParamsVar = + <::TwoToOneHash as TwoToOneCRHSchemeGadget>::ParametersVar; /// Represents a merkle tree path gadget. #[derive(Debug, Derivative)] -#[derivative(Clone(bound = "P: Config, ConstraintF: Field, PG: ConfigGadget"))] -pub struct PathVar> { +#[derivative(Clone(bound = "P: ConfigGadget, ConstraintF: Field"))] +pub struct PathVar, ConstraintF: Field> +where + P::LeafHash: CRHSchemeGadget, + P::TwoToOneHash: TwoToOneCRHSchemeGadget, +{ /// `path[i]` is 0 (false) iff ith non-leaf node from top to bottom is left. path: Vec>, /// `auth_path[i]` is the entry of sibling of ith non-leaf node from top to bottom. - auth_path: Vec, + auth_path: Vec>, /// The sibling of leaf. - leaf_sibling: PG::LeafDigest, + leaf_sibling: LeafDigestVar, /// Is this leaf the right child? leaf_is_right_child: Boolean, } -impl> AllocVar, ConstraintF> - for PathVar +impl, ConstraintF: Field> AllocVar, ConstraintF> + for PathVar where - P: Config, - ConstraintF: Field, + P::LeafHash: CRHSchemeGadget, + P::TwoToOneHash: TwoToOneCRHSchemeGadget, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( @@ -116,7 +87,7 @@ where let ns = cs.into(); let cs = ns.cs(); f().and_then(|val| { - let leaf_sibling = PG::LeafDigest::new_variable( + let leaf_sibling = LeafDigestVar::::new_variable( ark_relations::ns!(cs, "leaf_sibling"), || Ok(val.borrow().leaf_sibling_hash.clone()), mode, @@ -148,16 +119,20 @@ where } } -impl> PathVar { +impl, ConstraintF: Field> PathVar +where + P::LeafHash: CRHSchemeGadget, + P::TwoToOneHash: TwoToOneCRHSchemeGadget, +{ /// Calculate the root of the Merkle tree assuming that `leaf` is the leaf on the path defined by `self`. #[tracing::instrument(target = "r1cs", skip(self, leaf_params, two_to_one_params))] pub fn calculate_root( &self, - leaf_params: &LeafParam, - two_to_one_params: &TwoToOneParam, - leaf: &PG::Leaf, - ) -> Result { - let claimed_leaf_hash = PG::LeafHash::evaluate(leaf_params, leaf)?; + leaf_params: &LeafParamsVar, + two_to_one_params: &TwoToOneParamsVar, + leaf: &P::LeafVar, + ) -> Result, SynthesisError> { + let claimed_leaf_hash = P::LeafHash::evaluate(leaf_params, leaf)?; let leaf_sibling_hash = &self.leaf_sibling; // calculate hash for the bottom non_leaf_layer @@ -174,21 +149,22 @@ impl> PathVar> PathVar, - two_to_one_params: &TwoToOneParam, - root: &PG::InnerDigest, - leaf: &PG::Leaf, + leaf_params: &LeafParamsVar, + two_to_one_params: &TwoToOneParamsVar, + root: &TwoToOneDigestVar, + leaf: &P::LeafVar, ) -> Result, SynthesisError> { let expected_root = self.calculate_root(leaf_params, two_to_one_params, leaf)?; Ok(expected_root.is_eq(root)?) @@ -213,12 +189,12 @@ impl> PathVar, - two_to_one_params: &TwoToOneParam, - old_root: &PG::InnerDigest, - old_leaf: &PG::Leaf, - new_leaf: &PG::Leaf, - ) -> Result { + leaf_params: &LeafParamsVar, + two_to_one_params: &TwoToOneParamsVar, + old_root: &TwoToOneDigestVar, + old_leaf: &P::LeafVar, + new_leaf: &P::LeafVar, + ) -> Result, SynthesisError> { self.verify_membership(leaf_params, two_to_one_params, old_root, old_leaf)? .enforce_equal(&Boolean::TRUE)?; Ok(self.calculate_root(leaf_params, two_to_one_params, new_leaf)?) @@ -230,12 +206,12 @@ impl> PathVar, - two_to_one_params: &TwoToOneParam, - old_root: &PG::InnerDigest, - new_root: &PG::InnerDigest, - old_leaf: &PG::Leaf, - new_leaf: &PG::Leaf, + leaf_params: &LeafParamsVar, + two_to_one_params: &TwoToOneParamsVar, + old_root: &TwoToOneDigestVar, + new_root: &TwoToOneDigestVar, + old_leaf: &P::LeafVar, + new_leaf: &P::LeafVar, ) -> Result, SynthesisError> { let actual_new_root = self.update_leaf(leaf_params, two_to_one_params, old_root, old_leaf, new_leaf)?; diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index a51b5cd3..83d694e1 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -1,12 +1,11 @@ #![allow(clippy::needless_range_loop)] +use crate::CRHScheme; /// Defines a trait to chain two types of CRHs. -use crate::crh::TwoToOneCRHScheme; -use crate::{CRHScheme, Error}; +use crate::{crh::TwoToOneCRHScheme, Error}; use ark_ff::ToBytes; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write}; use ark_std::borrow::Borrow; -use ark_std::hash::Hash; use ark_std::vec::Vec; #[cfg(test)] @@ -18,32 +17,28 @@ pub mod constraints; /// Convert the hash digest in different layers by converting previous layer's output to /// `TargetType`, which is a `Borrow` to next layer's input. pub trait DigestConverter { - type TargetType: Borrow; - fn convert(item: From) -> Result; + type Target: Borrow; + fn convert(item: &From) -> Result; } /// A trivial converter where digest of previous layer's hash is the same as next layer's input. -pub struct IdentityDigestConverter { - _prev_layer_digest: T, -} +pub struct IdentityDigestConverter; -impl DigestConverter for IdentityDigestConverter { - type TargetType = T; - fn convert(item: T) -> Result { - Ok(item) +impl DigestConverter for IdentityDigestConverter { + type Target = T; + fn convert(item: &T) -> Result { + Ok(item.clone()) } } /// Convert previous layer's digest to bytes and use bytes as input for next layer's digest. /// TODO: `ToBytes` trait will be deprecated in future versions. -pub struct ByteDigestConverter { - _prev_layer_digest: T, -} +pub struct ByteDigestConverter; -impl DigestConverter for ByteDigestConverter { - type TargetType = Vec; +impl DigestConverter for ByteDigestConverter { + type Target = Vec; - fn convert(item: T) -> Result { + fn convert(item: &T) -> Result { // TODO: In some tests, `serialize` is not consistent with constraints. Try fix those. Ok(crate::to_unchecked_bytes!(item)?) } @@ -51,48 +46,29 @@ impl DigestConverter for ByteDigestCon /// Merkle tree have three types of hashes. /// * `LeafHash`: Convert leaf to leaf digest -/// * `TwoLeavesToOneHash`: Convert two leaf digests to one inner digest. This one can be a wrapped -/// version `TwoHashesToOneHash`, which first converts leaf digest to inner digest. -/// * `TwoHashesToOneHash`: Compress two inner digests to one inner digest +/// * `TwoLeavesToOneHash`: Convert two leaf digests to one inner digest. +/// This can be a wrapped version `TwoToOneHash`, which first converts a leaf digest to an inner digest. pub trait Config { type Leaf: ?Sized; // merkle tree does not store the leaf // leaf layer - type LeafDigest: ToBytes - + Clone - + Eq - + core::fmt::Debug - + Hash - + Default - + CanonicalSerialize - + CanonicalDeserialize; - // transition between leaf layer to inner layer - type LeafInnerDigestConverter: DigestConverter< - Self::LeafDigest, + // Tom's Note: in the future, if we want different hash function, we can simply add more + // types of digest here and specify a digest converter. Same for constraints. + + type LeafHash: CRHScheme; + /// 2 inner digest -> inner digest + type TwoToOneHash: TwoToOneCRHScheme; + + type LeafToInnerConverter: DigestConverter< + LeafDigest, ::Input, >; - // inner layer - type InnerDigest: ToBytes - + Clone - + Eq - + core::fmt::Debug - + Hash - + Default - + CanonicalSerialize - + CanonicalDeserialize; - - // Tom's Note: in the future, if we want different hash function, we can simply add more - // types of digest here and specify a digest converter. Same for constraints. - - /// leaf -> leaf digest - /// If leaf hash digest and inner hash digest are different, we can create a new - /// leaf hash which wraps the original leaf hash and convert its output to `Digest`. - type LeafHash: CRHScheme; - /// 2 inner digest -> inner digest - type TwoToOneHash: TwoToOneCRHScheme; } -pub type TwoToOneParam

= <

::TwoToOneHash as TwoToOneCRHScheme>::Parameters; -pub type LeafParam

= <

::LeafHash as CRHScheme>::Parameters; +pub type LeafDigest = <::LeafHash as CRHScheme>::Output; +pub type TwoToOneDigest = <::TwoToOneHash as TwoToOneCRHScheme>::Output; + +pub type TwoToOneParams

= <

::TwoToOneHash as TwoToOneCRHScheme>::Parameters; +pub type LeafParams

= <

::LeafHash as CRHScheme>::Parameters; /// Stores the hashes of a particular path (in order) from root to leaf. /// For example: @@ -109,9 +85,9 @@ pub type LeafParam

= <

::LeafHash as CRHScheme>::Parameters; #[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)] #[derivative(Clone(bound = "P: Config"))] pub struct Path { - pub leaf_sibling_hash: P::LeafDigest, + pub leaf_sibling_hash: LeafDigest

, /// The sibling of path node ordered from higher layer to lower layer (does not include root node). - pub auth_path: Vec, + pub auth_path: Vec>, /// stores the leaf index of the node pub leaf_index: usize, } @@ -136,9 +112,9 @@ impl Path

{ /// `verify` infers the tree height by setting `tree_height = self.auth_path.len() + 2` pub fn verify>( &self, - leaf_hash_params: &LeafParam

, - two_to_one_params: &TwoToOneParam

, - root_hash: &P::InnerDigest, + leaf_hash_params: &LeafParams

, + two_to_one_params: &TwoToOneParams

, + root_hash: &TwoToOneDigest

, leaf: L, ) -> Result { // calculate leaf hash @@ -148,8 +124,8 @@ impl Path

{ select_left_right_child(self.leaf_index, &claimed_leaf_hash, &self.leaf_sibling_hash)?; // leaf layer to inner layer conversion - let left_child = P::LeafInnerDigestConverter::convert(left_child)?; - let right_child = P::LeafInnerDigestConverter::convert(right_child)?; + let left_child = P::LeafToInnerConverter::convert(&left_child)?; + let right_child = P::LeafToInnerConverter::convert(&right_child)?; let mut curr_path_node = P::TwoToOneHash::evaluate(&two_to_one_params, left_child, right_child)?; @@ -210,13 +186,13 @@ fn select_left_right_child( pub struct MerkleTree { /// stores the non-leaf nodes in level order. The first element is the root node. /// The ith nodes (starting at 1st) children are at indices `2*i`, `2*i+1` - non_leaf_nodes: Vec, + non_leaf_nodes: Vec>, /// store the hash of leaf nodes from left to right - leaf_nodes: Vec, + leaf_nodes: Vec>, /// Store the inner hash parameters - two_to_one_hash_param: TwoToOneParam

, + two_to_one_hash_param: TwoToOneParams

, /// Store the leaf hash parameters - leaf_hash_param: LeafParam

, + leaf_hash_param: LeafParams

, /// Stores the height of the MerkleTree height: usize, } @@ -225,19 +201,19 @@ impl MerkleTree

{ /// Create an empty merkle tree such that all leaves are zero-filled. /// Consider using a sparse merkle tree if you need the tree to be low memory pub fn blank( - leaf_hash_param: &LeafParam

, - two_to_one_hash_param: &TwoToOneParam

, + leaf_hash_param: &LeafParams

, + two_to_one_hash_param: &TwoToOneParams

, height: usize, ) -> Result { // use empty leaf digest - let leaves_digest = vec![P::LeafDigest::default(); 1 << (height - 1)]; + let leaves_digest = vec![LeafDigest::

::default(); 1 << (height - 1)]; Self::new_with_leaf_digest(leaf_hash_param, two_to_one_hash_param, leaves_digest) } /// Returns a new merkle tree. `leaves.len()` should be power of two. pub fn new>( - leaf_hash_param: &LeafParam

, - two_to_one_hash_param: &TwoToOneParam

, + leaf_hash_param: &LeafParams

, + two_to_one_hash_param: &TwoToOneParams

, leaves: impl IntoIterator, ) -> Result { let mut leaves_digests = Vec::new(); @@ -251,9 +227,9 @@ impl MerkleTree

{ } pub fn new_with_leaf_digest( - leaf_hash_param: &LeafParam

, - two_to_one_hash_param: &TwoToOneParam

, - leaves_digest: Vec, + leaf_hash_param: &LeafParams

, + two_to_one_hash_param: &TwoToOneParams

, + leaves_digest: Vec>, ) -> Result { let leaf_nodes_size = leaves_digest.len(); assert!( @@ -264,10 +240,10 @@ impl MerkleTree

{ let tree_height = tree_height(leaf_nodes_size); - let hash_of_empty: P::InnerDigest = P::InnerDigest::default(); + let hash_of_empty = TwoToOneDigest::

::default(); // initialize the merkle tree as array of nodes in level order - let mut non_leaf_nodes: Vec = (0..non_leaf_nodes_size) + let mut non_leaf_nodes: Vec> = (0..non_leaf_nodes_size) .map(|_| hash_of_empty.clone()) .collect(); @@ -292,8 +268,8 @@ impl MerkleTree

{ // compute hash non_leaf_nodes[current_index] = P::TwoToOneHash::evaluate( &two_to_one_hash_param, - P::LeafInnerDigestConverter::convert(leaves_digest[left_leaf_index].clone())?, - P::LeafInnerDigestConverter::convert(leaves_digest[right_leaf_index].clone())?, + P::LeafToInnerConverter::convert(&leaves_digest[left_leaf_index].clone())?, + P::LeafToInnerConverter::convert(&leaves_digest[right_leaf_index].clone())?, )? } } @@ -324,7 +300,7 @@ impl MerkleTree

{ } /// Returns the root of the Merkle tree. - pub fn root(&self) -> P::InnerDigest { + pub fn root(&self) -> TwoToOneDigest

{ self.non_leaf_nodes[0].clone() } @@ -376,12 +352,12 @@ impl MerkleTree

{ &self, index: usize, new_leaf: T, - ) -> Result<(P::LeafDigest, Vec), crate::Error> { + ) -> Result<(LeafDigest

, Vec>), crate::Error> { // calculate the hash of leaf - let new_leaf_hash: P::LeafDigest = P::LeafHash::evaluate(&self.leaf_hash_param, new_leaf)?; + let new_leaf_hash: LeafDigest

= P::LeafHash::evaluate(&self.leaf_hash_param, new_leaf)?; // calculate leaf sibling hash and locate its position (left or right) - let (leaf_left, leaf_right) = if index & 1 == 0 { + let (left_leaf, right_leaf) = if index & 1 == 0 { // leaf on left (&new_leaf_hash, &self.leaf_nodes[index + 1]) } else { @@ -393,8 +369,8 @@ impl MerkleTree

{ { path_bottom_to_top.push(P::TwoToOneHash::evaluate( &self.two_to_one_hash_param, - P::LeafInnerDigestConverter::convert(leaf_left.clone())?, - P::LeafInnerDigestConverter::convert(leaf_right.clone())?, + P::LeafToInnerConverter::convert(&left_leaf)?, + P::LeafToInnerConverter::convert(&right_leaf)?, )?); } @@ -454,7 +430,7 @@ impl MerkleTree

{ &mut self, index: usize, new_leaf: &P::Leaf, - asserted_new_root: &P::InnerDigest, + asserted_new_root: &TwoToOneDigest

, ) -> Result { let new_leaf = new_leaf.borrow(); assert!(index < self.leaf_nodes.len(), "index out of range"); From 7bdad08224d79675749a9d8b38c2410f9e73c953 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 16 Aug 2021 15:38:10 -0700 Subject: [PATCH 02/13] Reduce generics for PRF and SNARK --- src/lib.rs | 10 +++++----- src/prf/blake2s/constraints.rs | 10 ++++------ src/prf/constraints.rs | 20 +++++++++++++------- src/snark/constraints.rs | 34 ++++++++++++++-------------------- 4 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7b4424b0..ab0f4669 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,23 +24,23 @@ pub mod merkle_tree; pub mod encryption; pub mod prf; pub mod signature; -// pub mod snark; +pub mod snark; pub use self::{ commitment::CommitmentScheme, crh::CRHScheme, - // merkle_tree::{MerkleTree, Path}, + merkle_tree::{MerkleTree, Path}, prf::PRF, signature::SignatureScheme, - // snark::{CircuitSpecificSetupSNARK, UniversalSetupSNARK, SNARK}, + snark::{CircuitSpecificSetupSNARK, UniversalSetupSNARK, SNARK}, }; #[cfg(feature = "r1cs")] pub use self::{ commitment::CommitmentGadget, - crh::CRHSchemeGadget, //merkle_tree::constraints::PathVar, + crh::CRHSchemeGadget, merkle_tree::constraints::PathVar, prf::PRFGadget, - signature::SigRandomizePkGadget, //snark::SNARKGadget, + signature::SigRandomizePkGadget, snark::SNARKGadget, }; pub type Error = Box; diff --git a/src/prf/blake2s/constraints.rs b/src/prf/blake2s/constraints.rs index a7bd093a..9a68cc45 100644 --- a/src/prf/blake2s/constraints.rs +++ b/src/prf/blake2s/constraints.rs @@ -289,7 +289,6 @@ pub fn evaluate_blake2s_with_parameters( use crate::prf::Blake2s; -pub struct Blake2sGadget; #[derive(Clone, Debug)] pub struct OutputVar(pub Vec>); @@ -363,7 +362,7 @@ impl R1CSVar for OutputVar { } } -impl PRFGadget for Blake2sGadget { +impl PRFGadget for Blake2s { type OutputVar = OutputVar; #[tracing::instrument(target = "r1cs", skip(cs))] @@ -398,7 +397,6 @@ mod test { use ark_relations::r1cs::ConstraintSystem; use blake2::VarBlake2s; - use super::Blake2sGadget; use ark_r1cs_std::prelude::*; #[test] @@ -427,11 +425,11 @@ mod test { let mut input = [0u8; 32]; rng.fill(&mut input); - let seed_var = Blake2sGadget::new_seed(cs.clone(), &seed); + let seed_var = Blake2s::new_seed(cs.clone(), &seed); let input_var = UInt8::new_witness_vec(ark_relations::ns!(cs, "declare_input"), &input).unwrap(); - let out = B2SPRF::evaluate(&seed, &input).unwrap(); - let actual_out_var = >::OutputVar::new_witness( + let out = Blake2s::evaluate(&seed, &input).unwrap(); + let actual_out_var = >::OutputVar::new_witness( ark_relations::ns!(cs, "declare_output"), || Ok(out), ) diff --git a/src/prf/constraints.rs b/src/prf/constraints.rs index bbca88c7..53b097f2 100644 --- a/src/prf/constraints.rs +++ b/src/prf/constraints.rs @@ -6,15 +6,21 @@ use ark_relations::r1cs::{Namespace, SynthesisError}; use ark_r1cs_std::prelude::*; -pub trait PRFGadget { - type OutputVar: EqGadget - + ToBytesGadget - + AllocVar - + R1CSVar +pub trait PRFGadget: PRF { + type OutputVar: EqGadget + + ToBytesGadget + + AllocVar + + R1CSVar + Clone + Debug; - fn new_seed(cs: impl Into>, seed: &P::Seed) -> Vec>; + fn new_seed( + cs: impl Into>, + seed: &Self::Seed, + ) -> Vec>; - fn evaluate(seed: &[UInt8], input: &[UInt8]) -> Result; + fn evaluate( + seed: &[UInt8], + input: &[UInt8], + ) -> Result; } diff --git a/src/snark/constraints.rs b/src/snark/constraints.rs index 05a76b2a..d0036e41 100644 --- a/src/snark/constraints.rs +++ b/src/snark/constraints.rs @@ -1,6 +1,6 @@ use ark_ff::{BigInteger, FpParameters, PrimeField}; -use ark_nonnative_field::params::{get_params, OptimizationType}; -use ark_nonnative_field::{AllocatedNonNativeFieldVar, NonNativeFieldVar}; +use ark_r1cs_std::fields::nonnative::params::{get_params, OptimizationType}; +use ark_r1cs_std::fields::nonnative::{AllocatedNonNativeFieldVar, NonNativeFieldVar}; use ark_r1cs_std::prelude::*; use ark_r1cs_std::{ bits::boolean::Boolean, @@ -23,13 +23,13 @@ use ark_std::{ }; /// This implements constraints for SNARK verifiers. -pub trait SNARKGadget> { - type ProcessedVerifyingKeyVar: AllocVar + Clone; - type VerifyingKeyVar: AllocVar +pub trait SNARKGadget: SNARK { + type ProcessedVerifyingKeyVar: AllocVar + Clone; + type VerifyingKeyVar: AllocVar + ToBytesGadget + Clone; type InputVar: AllocVar, ConstraintF> + FromFieldElementsGadget + Clone; - type ProofVar: AllocVar + Clone; + type ProofVar: AllocVar + Clone; /// Information about the R1CS constraints required to check proofs relative /// a given verification key. In the context of a LPCP-based pairing-based SNARK @@ -42,7 +42,7 @@ pub trait SNARKGadget> { /// Returns information about the R1CS constraints required to check proofs relative /// to the verification key `circuit_vk`. - fn verifier_size(circuit_vk: &S::VerifyingKey) -> Self::VerifierSize; + fn verifier_size(circuit_vk: &Self::VerifyingKey) -> Self::VerifierSize; /// Optionally allocates `S::Proof` in `cs` without performing /// additional checks, such as subgroup membership checks. Use this *only* @@ -54,7 +54,7 @@ pub trait SNARKGadget> { /// The default implementation does not omit such checks, and just invokes /// `Self::ProofVar::new_variable`. #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_proof_unchecked>( + fn new_proof_unchecked>( cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, @@ -72,7 +72,7 @@ pub trait SNARKGadget> { /// The default implementation does not omit such checks, and just invokes /// `Self::VerifyingKeyVar::new_variable`. #[tracing::instrument(target = "r1cs", skip(cs, f))] - fn new_verification_key_unchecked>( + fn new_verification_key_unchecked>( cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, @@ -93,21 +93,15 @@ pub trait SNARKGadget> { ) -> Result, SynthesisError>; } -pub trait CircuitSpecificSetupSNARKGadget< - F: PrimeField, - ConstraintF: PrimeField, - S: CircuitSpecificSetupSNARK, ->: SNARKGadget +pub trait CircuitSpecificSetupSNARKGadget: + SNARKGadget + CircuitSpecificSetupSNARK { } -pub trait UniversalSetupSNARKGadget< - F: PrimeField, - ConstraintF: PrimeField, - S: UniversalSetupSNARK, ->: SNARKGadget +pub trait UniversalSetupSNARKGadget: + SNARKGadget + UniversalSetupSNARK { - type BoundCircuit: From + ConstraintSynthesizer + Clone; + type BoundCircuit: From + ConstraintSynthesizer + Clone; } /// Gadgets to convert elements between different fields for recursive proofs From d47fe598dc17e3ab88f1e74af4441af55421bcad Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 10:46:59 -0400 Subject: [PATCH 03/13] Update CRH --- src/crh/bowe_hopwood/constraints.rs | 76 +++++++++----------- src/crh/bowe_hopwood/mod.rs | 35 +++++----- src/crh/constraints.rs | 101 ++++++++++++++++++++++++--- src/crh/injective_map/constraints.rs | 42 +++++------ src/crh/injective_map/mod.rs | 16 ++--- src/crh/mod.rs | 8 +-- src/crh/pedersen/constraints.rs | 78 +++++++++------------ src/crh/pedersen/mod.rs | 26 +++---- src/crh/poseidon/constraints.rs | 42 +++++------ src/crh/poseidon/mod.rs | 18 ++--- 10 files changed, 254 insertions(+), 188 deletions(-) diff --git a/src/crh/bowe_hopwood/constraints.rs b/src/crh/bowe_hopwood/constraints.rs index cd5aa780..bd13bb5d 100644 --- a/src/crh/bowe_hopwood/constraints.rs +++ b/src/crh/bowe_hopwood/constraints.rs @@ -1,16 +1,7 @@ use core::{borrow::Borrow, iter, marker::PhantomData}; -use crate::{ - crh::{ - bowe_hopwood::{Parameters, TwoToOneCRH, CHUNK_SIZE, CRH}, - pedersen::{self, Window}, - CRHSchemeGadget, TwoToOneCRHSchemeGadget, - }, - Vec, -}; -use ark_ec::{ - twisted_edwards_extended::GroupProjective as TEProjective, ModelParameters, TEModelParameters, -}; +use crate::{Vec, crh::{CRHWithGadget, TwoToOneCRHWithGadget, bowe_hopwood::{self, CHUNK_SIZE, CRH, Parameters, TwoToOneCRH}, pedersen::Window}}; +use ark_ec::{ModelParameters, TEModelParameters}; use ark_ff::Field; use ark_r1cs_std::{ alloc::AllocVar, groups::curves::twisted_edwards::AffineVar, prelude::*, uint8::UInt8, @@ -32,7 +23,7 @@ pub struct ParametersVar { type BF

=

::BaseField; type BFVar

= as FieldWithVar>::Var; -impl CRHSchemeGadget> for CRH +impl CRHWithGadget> for CRH where BF

: FieldWithVar, BFVar

: TwoBitLookupGadget, TableConstant = BF

> @@ -48,7 +39,7 @@ where type ParametersVar = ParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters, input))] - fn evaluate( + fn evaluate_gadget( parameters: &Self::ParametersVar, input: &Self::InputVar, ) -> Result { @@ -83,7 +74,7 @@ where } } -impl TwoToOneCRHSchemeGadget> for TwoToOneCRH +impl TwoToOneCRHWithGadget> for TwoToOneCRH where BF

: FieldWithVar, BFVar

: TwoBitLookupGadget, TableConstant = BF

> @@ -98,36 +89,37 @@ where type ParametersVar = ParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters))] - fn evaluate( + fn evaluate_gadget( parameters: &Self::ParametersVar, - left_input: &Self::InputVar, - right_input: &Self::InputVar, + left: &Self::InputVar, + right: &Self::InputVar, ) -> Result { - let input_size_bytes = pedersen::CRH::, W>::INPUT_SIZE_BITS / 8; + let input_size_bytes = bowe_hopwood::CRH::::INPUT_SIZE_BITS / 8; // assume equality of left and right length - assert_eq!(left_input.len(), right_input.len()); + assert_eq!(left.len(), right.len()); // assume sum of left and right length is at most the CRH length limit - assert!(left_input.len() + right_input.len() <= input_size_bytes); + assert!(left.len() + right.len() <= input_size_bytes); - let num_trailing_zeros = input_size_bytes - (left_input.len() + right_input.len()); - let chained_input: Vec<_> = left_input - .to_vec() + let num_trailing_zeros = input_size_bytes - (left.len() + right.len()); + let chained: Vec<_> = left .into_iter() - .chain(right_input.to_vec().into_iter()) + .chain(right.into_iter()) + .cloned() .chain(iter::repeat(UInt8::constant(0u8)).take(num_trailing_zeros)) .collect(); - CRH::::evaluate(parameters, &chained_input) + CRH::::evaluate_gadget(parameters, &chained) } - fn compress( + #[tracing::instrument(target = "r1cs", skip(parameters, left, right))] + fn compress_gadget( parameters: &Self::ParametersVar, - left_input: &Self::OutputVar, - right_input: &Self::OutputVar, + left: &Self::OutputVar, + right: &Self::OutputVar, ) -> Result { - let left_input_bytes = left_input.to_bytes()?; - let right_input_bytes = right_input.to_bytes()?; - Self::evaluate(parameters, &left_input_bytes, &right_input_bytes) + let left = left.to_bytes()?; + let right = right.to_bytes()?; + Self::evaluate_gadget(parameters, &left, &right) } } @@ -154,10 +146,10 @@ where mod test { use ark_std::rand::Rng; - use crate::crh::bowe_hopwood; - use crate::crh::{pedersen, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget}; - use crate::{CRHScheme, CRHSchemeGadget}; - use ark_ed_on_bls12_381::{constraints::FqVar, EdwardsParameters, Fq as Fr}; + use crate::{Gadget, crh::bowe_hopwood}; + use crate::crh::{pedersen, TwoToOneCRHScheme, TwoToOneCRHGadget}; + use crate::{CRHScheme, CRHGadget}; + use ark_ed_on_bls12_381::{EdwardsParameters, Fq as Fr}; use ark_r1cs_std::{alloc::AllocVar, uint8::UInt8, R1CSVar}; use ark_relations::r1cs::{ConstraintSystem, ConstraintSystemRef}; use ark_std::test_rng; @@ -200,7 +192,7 @@ mod test { let parameters = TestCRH::setup(rng).unwrap(); let primitive_result = TestCRH::evaluate(¶meters, input.as_slice()).unwrap(); - let parameters_var = >::ParametersVar::new_witness( + let parameters_var = as CRHGadget>::ParametersVar::new_witness( ark_relations::ns!(cs, "parameters_var"), || Ok(¶meters), ) @@ -210,7 +202,7 @@ mod test { cs.num_constraints() ); - let result_var = TestCRH::evaluate(¶meters_var, &input_var).unwrap(); + let result_var = Gadget::::evaluate(¶meters_var, &input_var).unwrap(); println!("number of constraints total: {}", cs.num_constraints()); @@ -225,22 +217,22 @@ mod test { // Max input size is 63 bytes. That leaves 31 for the left half, 31 for the right, and 1 // byte of padding. - let (left_input, left_input_var) = generate_u8_input(cs.clone(), 31, rng); - let (right_input, right_input_var) = generate_u8_input(cs.clone(), 31, rng); + let (left, left_var) = generate_u8_input(cs.clone(), 31, rng); + let (right, right_var) = generate_u8_input(cs.clone(), 31, rng); let parameters = TestTwoToOneCRH::setup(rng).unwrap(); let primitive_result = - TestTwoToOneCRH::evaluate(¶meters, left_input.as_slice(), right_input.as_slice()) + TestTwoToOneCRH::evaluate(¶meters, left.as_slice(), right.as_slice()) .unwrap(); let parameters_var = - >::ParametersVar::new_witness( + as TwoToOneCRHGadget>::ParametersVar::new_witness( ark_relations::ns!(cs, "parameters_var"), || Ok(¶meters), ) .unwrap(); let result_var = - TestTwoToOneCRH::evaluate(¶meters_var, &left_input_var, &right_input_var).unwrap(); + Gadget::::evaluate(¶meters_var, &left_var, &right_var).unwrap(); let primitive_result = primitive_result; assert_eq!(primitive_result, result_var.value().unwrap()); diff --git a/src/crh/bowe_hopwood/mod.rs b/src/crh/bowe_hopwood/mod.rs index 6fac6051..367ae6d5 100644 --- a/src/crh/bowe_hopwood/mod.rs +++ b/src/crh/bowe_hopwood/mod.rs @@ -39,6 +39,8 @@ pub struct CRH { } impl CRH { + pub(crate) const INPUT_SIZE_BITS: usize = W::WINDOW_SIZE * W::NUM_WINDOWS; + pub fn create_generators(rng: &mut R) -> Vec>> { let mut generators = Vec::new(); for _ in 0..W::NUM_WINDOWS { @@ -62,8 +64,9 @@ pub struct TwoToOneCRH { } impl TwoToOneCRH { - const INPUT_SIZE_BITS: usize = pedersen::CRH::, W>::INPUT_SIZE_BITS; - const HALF_INPUT_SIZE_BITS: usize = Self::INPUT_SIZE_BITS / 2; + pub(crate) const INPUT_SIZE_BITS: usize = W::WINDOW_SIZE * W::NUM_WINDOWS; + pub(crate) const HALF_INPUT_SIZE_BITS: usize = Self::INPUT_SIZE_BITS / 2; + pub fn create_generators(rng: &mut R) -> Vec>> { CRH::::create_generators(rng) } @@ -195,29 +198,29 @@ impl TwoToOneCRHScheme for TwoToOneCR /// A simple implementation method: just concat the left input and right input together /// - /// `evaluate` requires that `left_input` and `right_input` are of equal length. + /// `evaluate` requires that `left` and `right` are of equal length. fn evaluate>( parameters: &Self::Parameters, - left_input: T, - right_input: T, + left: T, + right: T, ) -> Result { - let left_input = left_input.borrow(); - let right_input = right_input.borrow(); + let left = left.borrow(); + let right = right.borrow(); assert_eq!( - left_input.len(), - right_input.len(), + left.len(), + right.len(), "left and right input should be of equal length" ); // check overflow - debug_assert!(left_input.len() * 8 <= Self::HALF_INPUT_SIZE_BITS); - debug_assert!(right_input.len() * 8 <= Self::HALF_INPUT_SIZE_BITS); + debug_assert!(left.len() * 8 <= Self::HALF_INPUT_SIZE_BITS); + debug_assert!(right.len() * 8 <= Self::HALF_INPUT_SIZE_BITS); let mut buffer = vec![0u8; Self::INPUT_SIZE_BITS / 8]; buffer .iter_mut() - .zip(left_input.iter().chain(right_input.iter())) + .zip(left.iter().chain(right.iter())) .for_each(|(b, l_b)| *b = *l_b); CRH::::evaluate(parameters, buffer) @@ -225,13 +228,13 @@ impl TwoToOneCRHScheme for TwoToOneCR fn compress>( parameters: &Self::Parameters, - left_input: T, - right_input: T, + left: T, + right: T, ) -> Result { Self::evaluate( parameters, - crate::to_unchecked_bytes!(left_input)?, - crate::to_unchecked_bytes!(right_input)?, + crate::to_unchecked_bytes!(left)?, + crate::to_unchecked_bytes!(right)?, ) } } diff --git a/src/crh/constraints.rs b/src/crh/constraints.rs index d32290ca..8c44e0d7 100644 --- a/src/crh/constraints.rs +++ b/src/crh/constraints.rs @@ -1,12 +1,12 @@ use ark_ff::Field; use core::fmt::Debug; -use crate::crh::{CRHScheme, TwoToOneCRHScheme}; +use crate::{Gadget, crh::{CRHScheme, TwoToOneCRHScheme}}; use ark_relations::r1cs::SynthesisError; use ark_r1cs_std::prelude::*; -pub trait CRHSchemeGadget: CRHScheme { +pub trait CRHWithGadget: CRHScheme { type InputVar: ?Sized; type OutputVar: EqGadget + ToBytesGadget @@ -18,13 +18,39 @@ pub trait CRHSchemeGadget: CRHScheme { + Sized; type ParametersVar: AllocVar + Clone; - fn evaluate( + fn evaluate_gadget( parameters: &Self::ParametersVar, input: &Self::InputVar, ) -> Result; } -pub trait TwoToOneCRHSchemeGadget: TwoToOneCRHScheme { +pub trait CRHGadget { + type Native: CRHWithGadget< + ConstraintF, + InputVar = Self::InputVar, + OutputVar = Self::OutputVar, + ParametersVar = Self::ParametersVar, + >; + type InputVar: ?Sized; + type OutputVar: EqGadget + + ToBytesGadget + + CondSelectGadget + + AllocVar<::Output, ConstraintF> + + R1CSVar + + Debug + + Clone + + Sized; + type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; + + fn evaluate( + parameters: &Self::ParametersVar, + input: &Self::InputVar, + ) -> Result { + Self::Native::evaluate_gadget(parameters, input) + } +} + +pub trait TwoToOneCRHWithGadget: TwoToOneCRHScheme { type InputVar: ?Sized; type OutputVar: EqGadget + ToBytesGadget @@ -37,15 +63,70 @@ pub trait TwoToOneCRHSchemeGadget: TwoToOneCRHScheme { type ParametersVar: AllocVar + Clone; - fn evaluate( + fn evaluate_gadget( parameters: &Self::ParametersVar, - left_input: &Self::InputVar, - right_input: &Self::InputVar, + left: &Self::InputVar, + right: &Self::InputVar, ) -> Result; - fn compress( + fn compress_gadget( parameters: &Self::ParametersVar, - left_input: &Self::OutputVar, - right_input: &Self::OutputVar, + left: &Self::OutputVar, + right: &Self::OutputVar, ) -> Result; } +pub trait TwoToOneCRHGadget { + type Native: TwoToOneCRHWithGadget< + ConstraintF, + InputVar = Self::InputVar, + OutputVar = Self::OutputVar, + ParametersVar = Self::ParametersVar, + >; + type InputVar: ?Sized; + type OutputVar: EqGadget + + ToBytesGadget + + CondSelectGadget + + AllocVar<::Output, ConstraintF> + + R1CSVar + + Debug + + Clone + + Sized; + + type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; + + fn evaluate( + parameters: &Self::ParametersVar, + left: &Self::InputVar, + right: &Self::InputVar, + ) -> Result { + Self::Native::evaluate_gadget(parameters, left, right) + } + + fn compress( + parameters: &Self::ParametersVar, + left: &Self::OutputVar, + right: &Self::OutputVar, + ) -> Result { + Self::Native::compress_gadget(parameters, left, right) + } +} + +impl CRHGadget for Gadget +where + H: CRHWithGadget, ConstraintF: Field +{ + type Native = H; + type InputVar = H::InputVar; + type ParametersVar = H::ParametersVar; + type OutputVar = H::OutputVar; +} + +impl TwoToOneCRHGadget for Gadget +where + H: TwoToOneCRHWithGadget, ConstraintF: Field +{ + type Native = H; + type InputVar = H::InputVar; + type ParametersVar = H::ParametersVar; + type OutputVar = H::OutputVar; +} \ No newline at end of file diff --git a/src/crh/injective_map/constraints.rs b/src/crh/injective_map/constraints.rs index 06b74839..3a164bb9 100644 --- a/src/crh/injective_map/constraints.rs +++ b/src/crh/injective_map/constraints.rs @@ -1,9 +1,10 @@ -use crate::crh::{ +use crate::{Gadget, crh::{ + CRHGadget, + TwoToOneCRHGadget, constraints, injective_map::{InjectiveMap, PedersenCRHCompressor, TECompressor}, pedersen::{self, constraints as ped_constraints, Window}, - TwoToOneCRHSchemeGadget, -}; +}}; use core::fmt::Debug; use crate::crh::injective_map::PedersenTwoToOneCRHCompressor; @@ -47,7 +48,7 @@ where } } -impl constraints::CRHSchemeGadget> for PedersenCRHCompressor +impl constraints::CRHWithGadget> for PedersenCRHCompressor where C: CurveWithVar>, for<'a> &'a C::Var: GroupOpsBounds<'a, C, C::Var>, @@ -60,16 +61,16 @@ where type ParametersVar = ped_constraints::CRHParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters, input))] - fn evaluate( + fn evaluate_gadget( parameters: &Self::ParametersVar, input: &Self::InputVar, ) -> Result { - let result = pedersen::CRH::::evaluate(parameters, input)?; + let result = Gadget::>::evaluate(parameters, input)?; I::evaluate(&result) } } -impl constraints::TwoToOneCRHSchemeGadget> +impl constraints::TwoToOneCRHWithGadget> for PedersenTwoToOneCRHCompressor where C: CurveWithVar>, @@ -83,28 +84,29 @@ where type ParametersVar = ped_constraints::CRHParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters))] - fn evaluate( + fn evaluate_gadget( parameters: &Self::ParametersVar, - left_input: &Self::InputVar, - right_input: &Self::InputVar, + left: &Self::InputVar, + right: &Self::InputVar, ) -> Result { // assume equality of left and right length - assert_eq!(left_input.len(), right_input.len()); - let result = pedersen::TwoToOneCRH::::evaluate(parameters, left_input, right_input)?; + assert_eq!(left.len(), right.len()); + let result = Gadget::>::evaluate(parameters, left, right)?; I::evaluate(&result) } - fn compress( + #[tracing::instrument(target = "r1cs", skip(parameters))] + fn compress_gadget( parameters: &Self::ParametersVar, - left_input: &Self::OutputVar, - right_input: &Self::OutputVar, + left: &Self::OutputVar, + right: &Self::OutputVar, ) -> Result { - let left_input_bytes = left_input.to_non_unique_bytes()?; - let right_input_bytes = right_input.to_non_unique_bytes()?; - >::evaluate( + let left= left.to_non_unique_bytes()?; + let right= right.to_non_unique_bytes()?; + Gadget::::evaluate( parameters, - &left_input_bytes, - &right_input_bytes, + &left, + &right, ) } } diff --git a/src/crh/injective_map/mod.rs b/src/crh/injective_map/mod.rs index 03c671e5..b105fd65 100644 --- a/src/crh/injective_map/mod.rs +++ b/src/crh/injective_map/mod.rs @@ -93,14 +93,14 @@ impl, W: pedersen::Window> TwoToOneCRHSch fn evaluate>( parameters: &Self::Parameters, - left_input: T, - right_input: T, + left: T, + right: T, ) -> Result { let eval_time = start_timer!(|| "PedersenCRHCompressor::Eval"); let result = I::injective_map(&pedersen::TwoToOneCRH::::evaluate( parameters, - left_input, - right_input, + left, + right, )?)?; end_timer!(eval_time); Ok(result) @@ -108,14 +108,14 @@ impl, W: pedersen::Window> TwoToOneCRHSch fn compress>( parameters: &Self::Parameters, - left_input: T, - right_input: T, + left: T, + right: T, ) -> Result { // convert output to input Self::evaluate( parameters, - crate::to_unchecked_bytes!(left_input)?, - crate::to_unchecked_bytes!(right_input)?, + crate::to_unchecked_bytes!(left)?, + crate::to_unchecked_bytes!(right)?, ) } } diff --git a/src/crh/mod.rs b/src/crh/mod.rs index 285a4241..64bf6d6a 100644 --- a/src/crh/mod.rs +++ b/src/crh/mod.rs @@ -58,13 +58,13 @@ pub trait TwoToOneCRHScheme { fn evaluate>( parameters: &Self::Parameters, - left_input: T, - right_input: T, + left: T, + right: T, ) -> Result; fn compress>( parameters: &Self::Parameters, - left_input: T, - right_input: T, + left: T, + right: T, ) -> Result; } diff --git a/src/crh/pedersen/constraints.rs b/src/crh/pedersen/constraints.rs index 7822e39a..cccf8c1e 100644 --- a/src/crh/pedersen/constraints.rs +++ b/src/crh/pedersen/constraints.rs @@ -1,7 +1,7 @@ use crate::{ crh::{ pedersen::{Parameters, TwoToOneCRH, Window, CRH}, - CRHSchemeGadget, TwoToOneCRHSchemeGadget, + CRHWithGadget, TwoToOneCRHWithGadget, }, Vec, }; @@ -10,7 +10,7 @@ use ark_ff::Field; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::{Namespace, SynthesisError}; -use core::{borrow::Borrow, marker::PhantomData}; +use core::{iter, borrow::Borrow}; type ConstraintF = <::BaseField as Field>::BasePrimeField; #[derive(Derivative)] @@ -19,7 +19,7 @@ pub struct CRHParametersVar>> { params: Parameters, } -impl CRHSchemeGadget> for CRH +impl CRHWithGadget> for CRH where C: CurveWithVar>, W: Window, @@ -30,7 +30,7 @@ where type ParametersVar = CRHParametersVar; #[tracing::instrument(target = "r1cs", skip(parameters, input))] - fn evaluate( + fn evaluate_gadget( parameters: &Self::ParametersVar, input: &Self::InputVar, ) -> Result { @@ -59,19 +59,7 @@ where } } -pub struct TwoToOneCRHGadget>, W: Window> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - #[doc(hidden)] - _group: PhantomData<*const C>, - #[doc(hidden)] - _group_var: PhantomData<*const GG>, - #[doc(hidden)] - _window: PhantomData<*const W>, -} - -impl TwoToOneCRHSchemeGadget> for TwoToOneCRH +impl TwoToOneCRHWithGadget> for TwoToOneCRH where C: CurveWithVar>, W: Window, @@ -81,32 +69,35 @@ where type OutputVar = C::Var; type ParametersVar = CRHParametersVar; - #[tracing::instrument(target = "r1cs", skip(parameters))] - fn evaluate( + #[tracing::instrument(target = "r1cs", skip(parameters, left, right))] + fn evaluate_gadget( parameters: &Self::ParametersVar, - left_input: &Self::InputVar, - right_input: &Self::InputVar, + left: &Self::InputVar, + right: &Self::InputVar, ) -> Result { // assume equality of left and right length - assert_eq!(left_input.len(), right_input.len()); - let chained_input: Vec<_> = left_input - .to_vec() - .into_iter() - .chain(right_input.to_vec().into_iter()) + assert_eq!(left.len(), right.len()); + let input_size_bytes = CRH::::INPUT_SIZE_BITS / 8; + let num_trailing_zeros = input_size_bytes - 2 * left.len(); + let chained: Vec<_> = left + .iter() + .chain(right.iter()) + .cloned() + .chain(iter::repeat(UInt8::constant(0u8)).take(num_trailing_zeros)) .collect(); - CRH::::evaluate(parameters, &chained_input) + CRH::::evaluate_gadget(parameters, &chained) } - #[tracing::instrument(target = "r1cs", skip(parameters))] - fn compress( + #[tracing::instrument(target = "r1cs", skip(parameters, left, right))] + fn compress_gadget( parameters: &Self::ParametersVar, - left_input: &Self::OutputVar, - right_input: &Self::OutputVar, + left: &Self::OutputVar, + right: &Self::OutputVar, ) -> Result { // convert output to bytes - let left_input = left_input.to_bytes()?; - let right_input = right_input.to_bytes()?; - Self::evaluate(parameters, &left_input, &right_input) + let left = left.to_bytes()?; + let right = right.to_bytes()?; + Self::evaluate_gadget(parameters, &left, &right) } } @@ -127,9 +118,9 @@ where #[cfg(test)] mod test { - use crate::crh::{ - pedersen, CRHScheme, CRHSchemeGadget, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget, - }; + use crate::{Gadget, crh::{ + pedersen, CRHScheme, CRHGadget, TwoToOneCRHScheme, TwoToOneCRHGadget, + }}; use ark_ec::ProjectiveCurve; use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq as Fr}; use ark_r1cs_std::prelude::*; @@ -138,11 +129,8 @@ mod test { use ark_std::{test_rng, UniformRand}; type TestCRH = pedersen::CRH; - type TestCRHGadget = pedersen::constraints::CRHGadget; type TestTwoToOneCRH = pedersen::TwoToOneCRH; - type TestTwoToOneCRHGadget = - pedersen::constraints::TwoToOneCRHGadget; #[derive(Clone, PartialEq, Eq, Hash)] pub(super) struct Window; @@ -192,7 +180,7 @@ mod test { ) .unwrap(); - let result_var = TestCRHGadget::evaluate(¶meters_var, &input_var).unwrap(); + let result_var = Gadget::::evaluate(¶meters_var, &input_var).unwrap(); let primitive_result = primitive_result; assert_eq!(primitive_result, result_var.value().unwrap()); @@ -204,11 +192,11 @@ mod test { let rng = &mut test_rng(); let cs = ConstraintSystem::::new_ref(); - let (left_input, left_input_var) = generate_affine(cs.clone(), rng); - let (right_input, right_input_var) = generate_affine(cs.clone(), rng); + let (left, left_var) = generate_affine(cs.clone(), rng); + let (right, right_var) = generate_affine(cs.clone(), rng); let parameters = TestTwoToOneCRH::setup(rng).unwrap(); let primitive_result = - TestTwoToOneCRH::compress(¶meters, left_input, right_input).unwrap(); + TestTwoToOneCRH::compress(¶meters, left, right).unwrap(); let parameters_var = pedersen::constraints::CRHParametersVar::new_constant( ark_relations::ns!(cs, "CRH Parameters"), @@ -217,7 +205,7 @@ mod test { .unwrap(); let result_var = - TestTwoToOneCRHGadget::compress(¶meters_var, &left_input_var, &right_input_var) + Gadget::::compress(¶meters_var, &left_var, &right_var) .unwrap(); let primitive_result = primitive_result; diff --git a/src/crh/pedersen/mod.rs b/src/crh/pedersen/mod.rs index 566831c9..4bf64eb4 100644 --- a/src/crh/pedersen/mod.rs +++ b/src/crh/pedersen/mod.rs @@ -154,25 +154,25 @@ impl TwoToOneCRHScheme for TwoToOneCRH { fn evaluate>( parameters: &Self::Parameters, - left_input: T, - right_input: T, + left: T, + right: T, ) -> Result { - let left_input = left_input.borrow(); - let right_input = right_input.borrow(); + let left = left.borrow(); + let right = right.borrow(); assert_eq!( - left_input.len(), - right_input.len(), + left.len(), + right.len(), "left and right input should be of equal length" ); // check overflow - debug_assert!(left_input.len() * 8 <= Self::HALF_INPUT_SIZE_BITS); + debug_assert!(left.len() * 8 <= Self::HALF_INPUT_SIZE_BITS); let mut buffer = vec![0u8; (Self::HALF_INPUT_SIZE_BITS + Self::HALF_INPUT_SIZE_BITS) / 8]; buffer .iter_mut() - .zip(left_input.iter().chain(right_input.iter())) + .zip(left.iter().chain(right.iter())) .for_each(|(b, l_b)| *b = *l_b); CRH::::evaluate(parameters, buffer.as_slice()) @@ -180,16 +180,16 @@ impl TwoToOneCRHScheme for TwoToOneCRH { /// A simple implementation method: just concat the left input and right input together /// - /// `evaluate` requires that `left_input` and `right_input` are of equal length. + /// `evaluate` requires that `left` and `right` are of equal length. fn compress>( parameters: &Self::Parameters, - left_input: T, - right_input: T, + left: T, + right: T, ) -> Result { Self::evaluate( parameters, - crate::to_unchecked_bytes!(left_input)?, - crate::to_unchecked_bytes!(right_input)?, + crate::to_unchecked_bytes!(left)?, + crate::to_unchecked_bytes!(right)?, ) } } diff --git a/src/crh/poseidon/constraints.rs b/src/crh/poseidon/constraints.rs index 65d6df7b..d25bb413 100644 --- a/src/crh/poseidon/constraints.rs +++ b/src/crh/poseidon/constraints.rs @@ -1,6 +1,6 @@ use crate::crh::poseidon::{TwoToOneCRH, CRH}; use crate::crh::{ - CRHSchemeGadget as CRHGadgetTrait, TwoToOneCRHSchemeGadget as TwoToOneCRHGadgetTrait, + CRHWithGadget, TwoToOneCRHWithGadget, }; use crate::{CRHScheme, Vec}; use ark_ff::PrimeField; @@ -19,12 +19,12 @@ pub struct CRHParametersVar { pub parameters: PoseidonParameters, } -impl CRHGadgetTrait for CRH { +impl CRHWithGadget for CRH { type InputVar = [FpVar]; type OutputVar = FpVar; type ParametersVar = CRHParametersVar; - fn evaluate( + fn evaluate_gadget( parameters: &Self::ParametersVar, input: &Self::InputVar, ) -> Result { @@ -44,38 +44,38 @@ impl CRHGadgetTrait for CRH { } } -impl TwoToOneCRHGadgetTrait for TwoToOneCRH { +impl TwoToOneCRHWithGadget for TwoToOneCRH { type InputVar = FpVar; type OutputVar = FpVar; type ParametersVar = CRHParametersVar; - fn evaluate( + fn evaluate_gadget( parameters: &Self::ParametersVar, - left_input: &Self::InputVar, - right_input: &Self::InputVar, + left: &Self::InputVar, + right: &Self::InputVar, ) -> Result { - Self::compress(parameters, left_input, right_input) + Self::compress_gadget(parameters, left, right) } - fn compress( + fn compress_gadget( parameters: &Self::ParametersVar, - left_input: &Self::OutputVar, - right_input: &Self::OutputVar, + left: &Self::OutputVar, + right: &Self::OutputVar, ) -> Result { - let cs = left_input.cs().or(right_input.cs()); + let cs = left.cs().or(right.cs()); if cs.is_none() { Ok(FpVar::Constant( as CRHScheme>::evaluate( ¶meters.parameters, - vec![left_input.value()?, right_input.value()?], + vec![left.value()?, right.value()?], ) .unwrap(), )) } else { let mut sponge = PoseidonSpongeVar::new(cs, ¶meters.parameters); - sponge.absorb(left_input)?; - sponge.absorb(right_input)?; + sponge.absorb(left)?; + sponge.absorb(right)?; let res = sponge.squeeze_field_elements(1)?; Ok(res[0].clone()) } @@ -98,10 +98,10 @@ impl AllocVar, F> for CRHParameter #[cfg(test)] mod test { - use crate::crh::poseidon::constraints::CRHParametersVar; + use crate::{Gadget, crh::poseidon::constraints::CRHParametersVar}; use crate::crh::poseidon::{TwoToOneCRH, CRH}; - use crate::crh::{TwoToOneCRHScheme, TwoToOneCRHSchemeGadget}; - use crate::{CRHScheme, CRHSchemeGadget}; + use crate::crh::{TwoToOneCRHScheme, TwoToOneCRHGadget}; + use crate::{CRHScheme, CRHGadget}; use ark_bls12_377::Fr; use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::{ @@ -162,9 +162,9 @@ mod test { } let params_g = CRHParametersVar::::new_witness(cs, || Ok(params)).unwrap(); - let crh_a_g = CRH::::evaluate(¶ms_g, &test_a_g).unwrap(); - let crh_b_g = CRH::::evaluate(¶ms_g, &test_b_g).unwrap(); - let crh_g = TwoToOneCRH::::compress(¶ms_g, &crh_a_g, &crh_b_g).unwrap(); + let crh_a_g = Gadget::>::evaluate(¶ms_g, &test_a_g).unwrap(); + let crh_b_g = Gadget::>::evaluate(¶ms_g, &test_b_g).unwrap(); + let crh_g = Gadget::>::compress(¶ms_g, &crh_a_g, &crh_b_g).unwrap(); assert_eq!(crh_a, crh_a_g.value().unwrap()); assert_eq!(crh_b, crh_b_g.value().unwrap()); diff --git a/src/crh/poseidon/mod.rs b/src/crh/poseidon/mod.rs index 3c1b11db..6bab9a09 100644 --- a/src/crh/poseidon/mod.rs +++ b/src/crh/poseidon/mod.rs @@ -55,23 +55,23 @@ impl TwoToOneCRHScheme for TwoToOneCRH { fn evaluate>( parameters: &Self::Parameters, - left_input: T, - right_input: T, + left: T, + right: T, ) -> Result { - Self::compress(parameters, left_input, right_input) + Self::compress(parameters, left, right) } fn compress>( parameters: &Self::Parameters, - left_input: T, - right_input: T, + left: T, + right: T, ) -> Result { - let left_input = left_input.borrow(); - let right_input = right_input.borrow(); + let left = left.borrow(); + let right = right.borrow(); let mut sponge = PoseidonSponge::new(parameters); - sponge.absorb(left_input); - sponge.absorb(right_input); + sponge.absorb(left); + sponge.absorb(right); let res = sponge.squeeze_field_elements::(1); Ok(res[0]) } From 5df3fe0aa9cf75ba99da703ab512b2854eaf3c7b Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 10:47:19 -0400 Subject: [PATCH 04/13] Update Commitment --- src/commitment/blake2s/constraints.rs | 15 +++----- src/commitment/constraints.rs | 41 ++++++++++++++++++++- src/commitment/injective_map/constraints.rs | 11 +++--- src/commitment/pedersen/constraints.rs | 15 ++++---- 4 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/commitment/blake2s/constraints.rs b/src/commitment/blake2s/constraints.rs index c87da760..37073a83 100644 --- a/src/commitment/blake2s/constraints.rs +++ b/src/commitment/blake2s/constraints.rs @@ -1,10 +1,6 @@ use ark_relations::r1cs::{Namespace, SynthesisError}; -use crate::{ - commitment::{blake2s, CommitmentGadget}, - prf::blake2s::constraints::{evaluate_blake2s, OutputVar}, - Vec, -}; +use crate::{Vec, commitment::{CommitmentWithGadget, blake2s}, prf::blake2s::constraints::{evaluate_blake2s, OutputVar}}; use ark_ff::{Field, PrimeField}; use ark_r1cs_std::prelude::*; @@ -16,13 +12,13 @@ pub struct ParametersVar; #[derive(Clone)] pub struct RandomnessVar(pub Vec>); -impl CommitmentGadget for blake2s::Commitment { +impl CommitmentWithGadget for blake2s::Commitment { type OutputVar = OutputVar; type ParametersVar = ParametersVar; type RandomnessVar = RandomnessVar; #[tracing::instrument(target = "r1cs", skip(input, r))] - fn commit( + fn commit_gadget( _: &Self::ParametersVar, input: &[UInt8], r: &Self::RandomnessVar, @@ -69,6 +65,7 @@ impl AllocVar<[u8; 32], ConstraintF> for RandomnessVar< #[cfg(test)] mod test { + use crate::Gadget; use crate::commitment::{ blake2s::{constraints::RandomnessVar, Commitment}, CommitmentGadget, CommitmentScheme, @@ -105,12 +102,12 @@ mod test { } let randomness_var = RandomnessVar(randomness_var); - let parameters_var = >::ParametersVar::new_witness( + let parameters_var = as CommitmentGadget>::ParametersVar::new_witness( ark_relations::ns!(cs, "gadget_parameters"), || Ok(¶meters), ) .unwrap(); - let result_var = >::commit( + let result_var = Gadget::::commit( ¶meters_var, &input_var, &randomness_var, diff --git a/src/commitment/constraints.rs b/src/commitment/constraints.rs index 1e27aa88..51c193c0 100644 --- a/src/commitment/constraints.rs +++ b/src/commitment/constraints.rs @@ -4,7 +4,7 @@ use ark_r1cs_std::prelude::*; use ark_relations::r1cs::SynthesisError; use core::fmt::Debug; -pub trait CommitmentGadget: CommitmentScheme { +pub trait CommitmentWithGadget: CommitmentScheme { type OutputVar: EqGadget + ToBytesGadget + AllocVar @@ -15,9 +15,46 @@ pub trait CommitmentGadget: CommitmentScheme { type ParametersVar: AllocVar + Clone; type RandomnessVar: AllocVar + Clone; - fn commit( + fn commit_gadget( parameters: &Self::ParametersVar, input: &[UInt8], r: &Self::RandomnessVar, ) -> Result; } + +pub trait CommitmentGadget { + type Native: CommitmentWithGadget< + ConstraintF, + OutputVar = Self::OutputVar, + ParametersVar = Self::ParametersVar, + RandomnessVar = Self::RandomnessVar, + >; + type OutputVar: EqGadget + + ToBytesGadget + + AllocVar<::Output, ConstraintF> + + R1CSVar + + Clone + + Sized + + Debug; + type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; + type RandomnessVar: AllocVar<::Randomness, ConstraintF> + Clone; + + fn commit( + parameters: &Self::ParametersVar, + input: &[UInt8], + r: &Self::RandomnessVar, + ) -> Result { + Self::Native::commit_gadget(parameters, input, r) + } +} + +impl CommitmentGadget for crate::Gadget +where + C: CommitmentWithGadget, + ConstraintF: Field +{ + type Native = C; + type OutputVar = C::OutputVar; + type ParametersVar = C::ParametersVar; + type RandomnessVar = C::RandomnessVar; +} \ No newline at end of file diff --git a/src/commitment/injective_map/constraints.rs b/src/commitment/injective_map/constraints.rs index 4baa4a0b..304d14d8 100644 --- a/src/commitment/injective_map/constraints.rs +++ b/src/commitment/injective_map/constraints.rs @@ -1,10 +1,11 @@ -use crate::commitment::{ +use crate::{Gadget, commitment::{ injective_map::PedersenCommCompressor, pedersen::{ constraints::{ParametersVar, RandomnessVar}, Commitment, Window, }, -}; + CommitmentGadget, +}}; pub use crate::crh::injective_map::constraints::InjectiveMapGadget; use ark_ec::ProjectiveCurve; @@ -17,7 +18,7 @@ use ark_relations::r1cs::SynthesisError; type ConstraintF = <::BaseField as Field>::BasePrimeField; -impl crate::commitment::CommitmentGadget> +impl crate::commitment::CommitmentWithGadget> for PedersenCommCompressor where C: CurveWithVar>, @@ -30,12 +31,12 @@ where type ParametersVar = ParametersVar; type RandomnessVar = RandomnessVar>; - fn commit( + fn commit_gadget( parameters: &Self::ParametersVar, input: &[UInt8>], r: &Self::RandomnessVar, ) -> Result { - let result = Commitment::::commit(parameters, input, r)?; + let result = Gadget::>::commit(parameters, input, r)?; I::evaluate(&result) } } diff --git a/src/commitment/pedersen/constraints.rs b/src/commitment/pedersen/constraints.rs index 3594a3f3..b482d863 100644 --- a/src/commitment/pedersen/constraints.rs +++ b/src/commitment/pedersen/constraints.rs @@ -24,7 +24,7 @@ pub struct ParametersVar>> { #[derive(Clone, Debug)] pub struct RandomnessVar(Vec>); -impl crate::commitment::CommitmentGadget> for Commitment +impl crate::commitment::CommitmentWithGadget> for Commitment where C: CurveWithVar>, W: Window, @@ -36,7 +36,7 @@ where type RandomnessVar = RandomnessVar>; #[tracing::instrument(target = "r1cs", skip(parameters, r))] - fn commit( + fn commit_gadget( parameters: &Self::ParametersVar, input: &[UInt8>], r: &Self::RandomnessVar, @@ -117,12 +117,13 @@ where #[cfg(test)] mod test { - use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq, Fr}; + use ark_ed_on_bls12_381::{EdwardsProjective as JubJub, Fq, Fr}; use ark_std::{test_rng, UniformRand}; use crate::{ + Gadget, commitment::{ - pedersen::{constraints::CommGadget, Commitment, Randomness}, + pedersen::{Commitment, Randomness}, CommitmentGadget, CommitmentScheme, }, crh::pedersen, @@ -159,17 +160,17 @@ mod test { input_var.push(UInt8::new_witness(cs.clone(), || Ok(*input_byte)).unwrap()); } - let randomness_var = >::RandomnessVar::new_witness( + let randomness_var = as CommitmentGadget>::RandomnessVar::new_witness( ark_relations::ns!(cs, "gadget_randomness"), || Ok(&randomness), ) .unwrap(); - let parameters_var = >::ParametersVar::new_witness( + let parameters_var = as CommitmentGadget>::ParametersVar::new_witness( ark_relations::ns!(cs, "gadget_parameters"), || Ok(¶meters), ) .unwrap(); - let result_var = TestCOMM::commit(¶meters_var, &input_var, &randomness_var).unwrap(); + let result_var = Gadget::::commit(¶meters_var, &input_var, &randomness_var).unwrap(); let primitive_result = primitive_result; assert_eq!(primitive_result, result_var.value().unwrap()); From f9b217c0dc6e075585ae3f94ed5baeb8d518601f Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 10:48:31 -0400 Subject: [PATCH 05/13] Update Enc --- src/encryption/constraints.rs | 58 +++++++-- src/encryption/elgamal/constraints.rs | 166 ++++++++++---------------- src/encryption/elgamal/mod.rs | 6 +- src/encryption/mod.rs | 2 +- 4 files changed, 115 insertions(+), 117 deletions(-) diff --git a/src/encryption/constraints.rs b/src/encryption/constraints.rs index de2a8f91..ab9a29bc 100644 --- a/src/encryption/constraints.rs +++ b/src/encryption/constraints.rs @@ -1,4 +1,4 @@ -use crate::encryption::AsymmetricEncryptionScheme; +use crate::{Gadget, encryption::AsymmetricEnc}; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::SynthesisError; @@ -6,21 +6,63 @@ use core::fmt::Debug; use ark_ff::fields::Field; -pub trait AsymmetricEncryptionGadget { - type OutputVar: AllocVar +pub trait AsymmetricEncWithGadget: AsymmetricEnc { + type CiphertextVar: AllocVar + EqGadget + Clone + Sized + Debug; - type ParametersVar: AllocVar + Clone; - type PlaintextVar: AllocVar + Clone; - type PublicKeyVar: AllocVar + Clone; - type RandomnessVar: AllocVar + Clone; + type ParametersVar: AllocVar + Clone; + type PlaintextVar: AllocVar + Clone; + type PublicKeyVar: AllocVar + Clone; + type RandomnessVar: AllocVar + Clone; + + fn encrypt_gadget( + parameters: &Self::ParametersVar, + message: &Self::PlaintextVar, + randomness: &Self::RandomnessVar, + public_key: &Self::PublicKeyVar, + ) -> Result; +} + +pub trait AsymmetricEncGadget { + type Native: AsymmetricEncWithGadget< + ConstraintF, + CiphertextVar = Self::CiphertextVar, + ParametersVar = Self::ParametersVar, + PlaintextVar = Self::PlaintextVar, + PublicKeyVar = Self::PublicKeyVar, + RandomnessVar = Self::RandomnessVar, + >; + type CiphertextVar: AllocVar<::Ciphertext, ConstraintF> + + EqGadget + + Clone + + Sized + + Debug; + type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; + type PlaintextVar: AllocVar<::Plaintext, ConstraintF> + Clone; + type PublicKeyVar: AllocVar<::PublicKey, ConstraintF> + Clone; + type RandomnessVar: AllocVar<::Randomness, ConstraintF> + Clone; fn encrypt( parameters: &Self::ParametersVar, message: &Self::PlaintextVar, randomness: &Self::RandomnessVar, public_key: &Self::PublicKeyVar, - ) -> Result; + ) -> Result { + Self::Native::encrypt_gadget(parameters, message, randomness, public_key) + } +} + +impl AsymmetricEncGadget for Gadget +where + Enc: AsymmetricEncWithGadget, + ConstraintF: Field, +{ + type Native = Enc; + type CiphertextVar = Enc::CiphertextVar; + type ParametersVar = Enc::ParametersVar; + type PlaintextVar = Enc::PlaintextVar; + type PublicKeyVar = Enc::PublicKeyVar; + type RandomnessVar = Enc::RandomnessVar; } diff --git a/src/encryption/elgamal/constraints.rs b/src/encryption/elgamal/constraints.rs index 219ec7fe..48365e9c 100644 --- a/src/encryption/elgamal/constraints.rs +++ b/src/encryption/elgamal/constraints.rs @@ -4,13 +4,13 @@ use ark_relations::r1cs::{Namespace, SynthesisError}; use crate::encryption::elgamal::{ Ciphertext, ElGamal, Parameters, Plaintext, PublicKey, Randomness, }; -use crate::encryption::AsymmetricEncryptionGadget; +use crate::encryption::AsymmetricEncWithGadget; use ark_ec::ProjectiveCurve; use ark_ff::{ fields::{Field, PrimeField}, to_bytes, Zero, }; -use ark_std::{borrow::Borrow, marker::PhantomData, vec::Vec}; +use ark_std::{borrow::Borrow, vec::Vec}; pub type ConstraintF = <::BaseField as Field>::BasePrimeField; @@ -19,7 +19,7 @@ pub struct RandomnessVar(Vec>); impl AllocVar, F> for RandomnessVar where - C: ProjectiveCurve, + C: CurveWithVar>, F: PrimeField, { fn new_variable>>( @@ -36,113 +36,84 @@ where } } + #[derive(Derivative)] -#[derivative(Clone(bound = "C: ProjectiveCurve, GG: CurveVar>"))] -pub struct ParametersVar>> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - generator: GG, - #[doc(hidden)] - _curve: PhantomData, +#[derivative(Clone(bound = "C::Var: Clone"))] +pub struct ParametersVar>> { + generator: C::Var, } -impl AllocVar, ConstraintF> for ParametersVar +impl AllocVar, ConstraintF> for ParametersVar where - C: ProjectiveCurve, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + C: CurveWithVar>, { fn new_variable>>( cs: impl Into>>, f: impl FnOnce() -> Result, - mode: AllocationMode, + _mode: AllocationMode, ) -> Result { - let generator = GG::new_variable(cs, || f().map(|g| g.borrow().generator), mode)?; + // Always allocate as constant + let generator = C::Var::new_constant(cs, f().map(|g| g.borrow().generator.into()).unwrap())?; Ok(Self { generator, - _curve: PhantomData, }) } } #[derive(Derivative)] -#[derivative(Clone(bound = "C: ProjectiveCurve, GG: CurveVar>"))] -pub struct PlaintextVar>> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - pub plaintext: GG, - #[doc(hidden)] - _curve: PhantomData, +#[derivative(Clone(bound = "C::Var: Clone"))] +pub struct PlaintextVar>> { + pub plaintext: C::Var, } -impl AllocVar, ConstraintF> for PlaintextVar +impl AllocVar, ConstraintF> for PlaintextVar where - C: ProjectiveCurve, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + C: CurveWithVar>, { fn new_variable>>( cs: impl Into>>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { - let plaintext = GG::new_variable(cs, f, mode)?; + let plaintext = C::Var::new_variable(cs, f, mode)?; Ok(Self { plaintext, - _curve: PhantomData, }) } } #[derive(Derivative)] -#[derivative(Clone(bound = "C: ProjectiveCurve, GG: CurveVar>"))] -pub struct PublicKeyVar>> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - pub pk: GG, - #[doc(hidden)] - _curve: PhantomData, +#[derivative(Clone(bound = "C::Var: Clone"))] +pub struct PublicKeyVar>> { + pub pk: C::Var, } -impl AllocVar, ConstraintF> for PublicKeyVar +impl AllocVar, ConstraintF> for PublicKeyVar where - C: ProjectiveCurve, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + C: CurveWithVar>, { fn new_variable>>( cs: impl Into>>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { - let pk = GG::new_variable(cs, f, mode)?; + let pk = C::Var::new_variable(cs, f, mode)?; Ok(Self { pk, - _curve: PhantomData, }) } } #[derive(Derivative, Debug)] -#[derivative(Clone(bound = "C: ProjectiveCurve, GG: CurveVar>"))] -pub struct OutputVar>> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - pub c1: GG, - pub c2: GG, - #[doc(hidden)] - _curve: PhantomData, +#[derivative(Clone(bound = "C::Var: Clone"))] +pub struct CiphertextVar>> { + pub c1: C::Var, + pub c2: C::Var, } -impl AllocVar, ConstraintF> for OutputVar +impl AllocVar, ConstraintF> for CiphertextVar where - C: ProjectiveCurve, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + C: CurveWithVar>, { fn new_variable>>( cs: impl Into>>, @@ -152,21 +123,18 @@ where let ns = cs.into(); let cs = ns.cs(); let prep = f().map(|g| *g.borrow()); - let c1 = GG::new_variable(cs.clone(), || prep.map(|g| g.borrow().0), mode)?; - let c2 = GG::new_variable(cs.clone(), || prep.map(|g| g.borrow().1), mode)?; + let c1 = C::Var::new_variable(cs.clone(), || prep.map(|g| g.borrow().0), mode)?; + let c2 = C::Var::new_variable(cs.clone(), || prep.map(|g| g.borrow().1), mode)?; Ok(Self { c1, c2, - _curve: PhantomData, }) } } -impl EqGadget> for OutputVar +impl EqGadget> for CiphertextVar where - C: ProjectiveCurve, - GC: CurveVar>, - for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, + C: CurveWithVar>, { #[inline] fn is_eq(&self, other: &Self) -> Result>, SynthesisError> { @@ -174,34 +142,23 @@ where } } -pub struct ElGamalEncGadget>> -where - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, -{ - #[doc(hidden)] - _curve: PhantomData<*const C>, - _group_var: PhantomData<*const GG>, -} - -impl AsymmetricEncryptionGadget, ConstraintF> for ElGamalEncGadget +impl AsymmetricEncWithGadget> for ElGamal where - C: ProjectiveCurve, - GG: CurveVar>, - for<'a> &'a GG: GroupOpsBounds<'a, C, GG>, + C: CurveWithVar>, ConstraintF: PrimeField, { - type OutputVar = OutputVar; - type ParametersVar = ParametersVar; - type PlaintextVar = PlaintextVar; - type PublicKeyVar = PublicKeyVar; + type CiphertextVar = CiphertextVar; + type ParametersVar = ParametersVar; + type PlaintextVar = PlaintextVar; + type PublicKeyVar = PublicKeyVar; type RandomnessVar = RandomnessVar>; - fn encrypt( + fn encrypt_gadget( parameters: &Self::ParametersVar, message: &Self::PlaintextVar, randomness: &Self::RandomnessVar, public_key: &Self::PublicKeyVar, - ) -> Result { + ) -> Result { // flatten randomness to little-endian bit vector let randomness = randomness .0 @@ -210,34 +167,33 @@ where .collect::>(); // compute s = randomness*pk - let s = public_key.pk.clone().scalar_mul_le(randomness.iter())?; + let s = public_key.pk.scalar_mul_le(randomness.iter())?; // compute c1 = randomness*generator let c1 = parameters .generator - .clone() .scalar_mul_le(randomness.iter())?; // compute c2 = m + s - let c2 = message.plaintext.clone() + s; + let c2 = s + &message.plaintext; - Ok(Self::OutputVar { + Ok(Self::CiphertextVar { c1, c2, - _curve: PhantomData, }) } } #[cfg(test)] mod test { - use crate::encryption::constraints::AsymmetricEncryptionGadget; + use crate::Gadget; + use crate::encryption::constraints::AsymmetricEncGadget; + use crate::encryption::elgamal::{ElGamal, Randomness}; + use crate::encryption::AsymmetricEnc; use ark_std::{test_rng, UniformRand}; - use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq}; + use ark_ed_on_bls12_381::{EdwardsProjective as JubJub, Fq}; - use crate::encryption::elgamal::{constraints::ElGamalEncGadget, ElGamal, Randomness}; - use crate::encryption::AsymmetricEncryptionScheme; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::ConstraintSystem; @@ -245,38 +201,38 @@ mod test { fn test_elgamal_gadget() { let rng = &mut test_rng(); - type MyEnc = ElGamal; - type MyGadget = ElGamalEncGadget; + type TestEnc = ElGamal; + type TestGadget = Gadget; // compute primitive result - let parameters = MyEnc::setup(rng).unwrap(); - let (pk, _) = MyEnc::keygen(¶meters, rng).unwrap(); + let parameters = TestEnc::setup(rng).unwrap(); + let (pk, _) = TestEnc::keygen(¶meters, rng).unwrap(); let msg = JubJub::rand(rng).into(); let randomness = Randomness::rand(rng); - let primitive_result = MyEnc::encrypt(¶meters, &pk, &msg, &randomness).unwrap(); + let primitive_result = TestEnc::encrypt(¶meters, &pk, &msg, &randomness).unwrap(); // construct constraint system let cs = ConstraintSystem::::new_ref(); let randomness_var = - >::RandomnessVar::new_witness( + >::RandomnessVar::new_witness( ark_relations::ns!(cs, "gadget_randomness"), || Ok(&randomness), ) .unwrap(); let parameters_var = - >::ParametersVar::new_constant( + >::ParametersVar::new_constant( ark_relations::ns!(cs, "gadget_parameters"), ¶meters, ) .unwrap(); let msg_var = - >::PlaintextVar::new_witness( + >::PlaintextVar::new_witness( ark_relations::ns!(cs, "gadget_message"), || Ok(&msg), ) .unwrap(); let pk_var = - >::PublicKeyVar::new_witness( + >::PublicKeyVar::new_witness( ark_relations::ns!(cs, "gadget_public_key"), || Ok(&pk), ) @@ -284,11 +240,11 @@ mod test { // use gadget let result_var = - MyGadget::encrypt(¶meters_var, &msg_var, &randomness_var, &pk_var).unwrap(); + TestGadget::encrypt(¶meters_var, &msg_var, &randomness_var, &pk_var).unwrap(); // check that result equals expected ciphertext in the constraint system let expected_var = - >::OutputVar::new_input( + >::CiphertextVar::new_input( ark_relations::ns!(cs, "gadget_expected"), || Ok(&primitive_result), ) diff --git a/src/encryption/elgamal/mod.rs b/src/encryption/elgamal/mod.rs index 6e471c78..edd3e4d9 100644 --- a/src/encryption/elgamal/mod.rs +++ b/src/encryption/elgamal/mod.rs @@ -1,7 +1,7 @@ #[cfg(feature = "r1cs")] pub mod constraints; -use crate::encryption::AsymmetricEncryptionScheme; +use crate::encryption::AsymmetricEnc; use crate::Error; use ark_ec::{AffineCurve, ProjectiveCurve}; use ark_ff::{fields::PrimeField, UniformRand}; @@ -36,7 +36,7 @@ pub type Ciphertext = ( ::Affine, ); -impl AsymmetricEncryptionScheme for ElGamal +impl AsymmetricEnc for ElGamal where C::ScalarField: PrimeField, { @@ -111,7 +111,7 @@ mod test { use ark_ed_on_bls12_381::EdwardsProjective as JubJub; use crate::encryption::elgamal::{ElGamal, Randomness}; - use crate::encryption::AsymmetricEncryptionScheme; + use crate::encryption::AsymmetricEnc; #[test] fn test_elgamal_encryption() { diff --git a/src/encryption/mod.rs b/src/encryption/mod.rs index d1213a76..1caafacf 100644 --- a/src/encryption/mod.rs +++ b/src/encryption/mod.rs @@ -8,7 +8,7 @@ pub mod elgamal; use crate::Error; use ark_std::rand::Rng; -pub trait AsymmetricEncryptionScheme { +pub trait AsymmetricEnc { type Parameters; type PublicKey; type SecretKey; From 5498bb26ae1fb9ecd9442caa8f130ec4c00ca698 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 10:48:46 -0400 Subject: [PATCH 06/13] Update Merkle Tree --- src/merkle_tree/constraints.rs | 48 ++++++++++------- src/merkle_tree/tests/constraints.rs | 80 +++++++++++----------------- src/merkle_tree/tests/mod.rs | 9 ++-- 3 files changed, 63 insertions(+), 74 deletions(-) diff --git a/src/merkle_tree/constraints.rs b/src/merkle_tree/constraints.rs index 29caf236..600d5026 100644 --- a/src/merkle_tree/constraints.rs +++ b/src/merkle_tree/constraints.rs @@ -1,6 +1,6 @@ -use crate::crh::TwoToOneCRHSchemeGadget; +use crate::{Gadget, crh::{CRHWithGadget, TwoToOneCRHGadget, TwoToOneCRHWithGadget}}; use crate::merkle_tree::{Config, Path}; -use crate::CRHSchemeGadget; +use crate::CRHGadget; use ark_ff::Field; use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::boolean::Boolean; @@ -12,7 +12,7 @@ use ark_std::borrow::Borrow; use ark_std::fmt::Debug; use ark_std::vec::Vec; -use super::ByteDigestConverter; +use super::{ByteDigestConverter, IdentityDigestConverter}; pub trait DigestVarConverter { type Target: Borrow; @@ -29,10 +29,20 @@ impl, ConstraintF: Field> DigestVarConverter DigestVarConverter + for IdentityDigestConverter +{ + type Target = T; + + fn convert(from: &T) -> Result { + Ok(from.clone()) + } +} + pub trait ConfigGadget: Config where - Self::LeafHash: CRHSchemeGadget, - Self::TwoToOneHash: TwoToOneCRHSchemeGadget, + Self::LeafHash: CRHWithGadget, + Self::TwoToOneHash: TwoToOneCRHWithGadget, { type LeafVar: Debug + ?Sized; @@ -43,24 +53,24 @@ where } pub type TwoToOneInputVar = - <::TwoToOneHash as TwoToOneCRHSchemeGadget>::InputVar; -pub type LeafDigestVar = <::LeafHash as CRHSchemeGadget>::OutputVar; + ::TwoToOneHash> as TwoToOneCRHGadget>::InputVar; +pub type LeafDigestVar = ::LeafHash> as CRHGadget>::OutputVar; pub type TwoToOneDigestVar = - <::TwoToOneHash as TwoToOneCRHSchemeGadget>::OutputVar; + ::TwoToOneHash> as TwoToOneCRHGadget>::OutputVar; pub type LeafParamsVar = - <::LeafHash as CRHSchemeGadget>::ParametersVar; + ::LeafHash> as CRHGadget>::ParametersVar; pub type TwoToOneParamsVar = - <::TwoToOneHash as TwoToOneCRHSchemeGadget>::ParametersVar; + ::TwoToOneHash> as TwoToOneCRHGadget>::ParametersVar; /// Represents a merkle tree path gadget. #[derive(Debug, Derivative)] #[derivative(Clone(bound = "P: ConfigGadget, ConstraintF: Field"))] pub struct PathVar, ConstraintF: Field> where - P::LeafHash: CRHSchemeGadget, - P::TwoToOneHash: TwoToOneCRHSchemeGadget, + P::LeafHash: CRHWithGadget, + P::TwoToOneHash: TwoToOneCRHWithGadget, { /// `path[i]` is 0 (false) iff ith non-leaf node from top to bottom is left. path: Vec>, @@ -75,8 +85,8 @@ where impl, ConstraintF: Field> AllocVar, ConstraintF> for PathVar where - P::LeafHash: CRHSchemeGadget, - P::TwoToOneHash: TwoToOneCRHSchemeGadget, + P::LeafHash: CRHWithGadget, + P::TwoToOneHash: TwoToOneCRHWithGadget, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( @@ -121,8 +131,8 @@ where impl, ConstraintF: Field> PathVar where - P::LeafHash: CRHSchemeGadget, - P::TwoToOneHash: TwoToOneCRHSchemeGadget, + P::LeafHash: CRHWithGadget, + P::TwoToOneHash: TwoToOneCRHWithGadget, { /// Calculate the root of the Merkle tree assuming that `leaf` is the leaf on the path defined by `self`. #[tracing::instrument(target = "r1cs", skip(self, leaf_params, two_to_one_params))] @@ -132,7 +142,7 @@ where two_to_one_params: &TwoToOneParamsVar, leaf: &P::LeafVar, ) -> Result, SynthesisError> { - let claimed_leaf_hash = P::LeafHash::evaluate(leaf_params, leaf)?; + let claimed_leaf_hash = Gadget::::evaluate(leaf_params, leaf)?; let leaf_sibling_hash = &self.leaf_sibling; // calculate hash for the bottom non_leaf_layer @@ -153,7 +163,7 @@ where let right_hash = P::LeafToInnerVarConverter::convert(&right_hash)?; let mut curr_hash = - P::TwoToOneHash::evaluate(two_to_one_params, left_hash.borrow(), &right_hash.borrow())?; + Gadget::::evaluate(two_to_one_params, left_hash.borrow(), &right_hash.borrow())?; // To traverse up a MT, we iterate over the path from bottom to top (i.e. in reverse) // At any given bit, the bit being 0 indicates our currently hashed value is the left, @@ -164,7 +174,7 @@ where let left_hash = bit.select(sibling, &curr_hash)?; let right_hash = bit.select(&curr_hash, sibling)?; - curr_hash = P::TwoToOneHash::compress(two_to_one_params, &left_hash, &right_hash)?; + curr_hash = Gadget::::compress(two_to_one_params, &left_hash, &right_hash)?; } Ok(curr_hash) diff --git a/src/merkle_tree/tests/constraints.rs b/src/merkle_tree/tests/constraints.rs index f5846d38..68f8833c 100644 --- a/src/merkle_tree/tests/constraints.rs +++ b/src/merkle_tree/tests/constraints.rs @@ -1,10 +1,10 @@ mod byte_mt_tests { - use crate::crh::{pedersen, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget}; + use crate::{Gadget, crh::{pedersen, TwoToOneCRHScheme, TwoToOneCRHGadget}}; - use crate::merkle_tree::constraints::{BytesVarDigestConverter, ConfigGadget}; + use crate::merkle_tree::constraints::ConfigGadget; use crate::merkle_tree::{ByteDigestConverter, Config}; - use crate::{CRHScheme, CRHSchemeGadget, MerkleTree, PathVar}; - use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq}; + use crate::{CRHScheme, CRHGadget, MerkleTree, PathVar}; + use ark_ed_on_bls12_381::{EdwardsProjective as JubJub, Fq}; #[allow(unused)] use ark_r1cs_std::prelude::*; #[allow(unused)] @@ -18,10 +18,9 @@ mod byte_mt_tests { } type LeafH = pedersen::CRH; - type LeafHG = pedersen::constraints::CRHGadget; type CompressH = pedersen::TwoToOneCRH; - type CompressHG = pedersen::constraints::TwoToOneCRHGadget; + type CompressHG = Gadget; type LeafVar = [UInt8]; @@ -29,24 +28,16 @@ mod byte_mt_tests { impl Config for JubJubMerkleTreeParams { type Leaf = [u8]; - type LeafDigest = ::Output; - type LeafInnerDigestConverter = ByteDigestConverter; + type LeafToInnerConverter = ByteDigestConverter; - type InnerDigest = ::Output; type LeafHash = LeafH; type TwoToOneHash = CompressH; } type ConstraintF = Fq; - struct JubJubMerkleTreeParamsVar; - impl ConfigGadget for JubJubMerkleTreeParamsVar { - type Leaf = LeafVar; - type LeafDigest = >::OutputVar; - type LeafInnerConverter = BytesVarDigestConverter; - type InnerDigest = - >::OutputVar; - type LeafHash = LeafHG; - type TwoToOneHash = CompressHG; + impl ConfigGadget for JubJubMerkleTreeParams { + type LeafVar = LeafVar; + type LeafToInnerVarConverter = ByteDigestConverter; } type JubJubMerkleTree = MerkleTree; @@ -81,7 +72,7 @@ mod byte_mt_tests { .unwrap()); // Allocate Merkle Tree Root - let root = >::OutputVar::new_witness( + let root = as CRHGadget<_>>::OutputVar::new_witness( ark_relations::ns!(cs, "new_digest"), || { if use_bad_root { @@ -98,13 +89,13 @@ mod byte_mt_tests { // Allocate Parameters for CRH let leaf_crh_params_var = - >::ParametersVar::new_constant( + as CRHGadget<_>>::ParametersVar::new_constant( ark_relations::ns!(cs, "leaf_crh_parameter"), &leaf_crh_params, ) .unwrap(); let two_to_one_crh_params_var = - >::ParametersVar::new_constant( + as TwoToOneCRHGadget<_>>::ParametersVar::new_constant( ark_relations::ns!(cs, "two_to_one_crh_parameter"), &two_to_one_crh_params, ) @@ -121,7 +112,7 @@ mod byte_mt_tests { println!("constraints from leaf: {}", constraints_from_leaf); // Allocate Merkle Tree Path - let cw: PathVar = + let cw: PathVar = PathVar::new_witness(ark_relations::ns!(cs, "new_witness"), || Ok(&proof)).unwrap(); let constraints_from_path = cs.num_constraints() @@ -161,13 +152,13 @@ mod byte_mt_tests { let cs = ConstraintSystem::::new_ref(); // allocate parameters for CRH let leaf_crh_params_var = - >::ParametersVar::new_constant( + as CRHGadget<_>>::ParametersVar::new_constant( ark_relations::ns!(cs, "leaf_crh_parameter"), &leaf_crh_params, ) .unwrap(); let two_to_one_crh_params_var = - >::ParametersVar::new_constant( + as TwoToOneCRHGadget<_>>::ParametersVar::new_constant( ark_relations::ns!(cs, "two_to_one_crh_parameter"), &two_to_one_crh_params, ) @@ -182,19 +173,19 @@ mod byte_mt_tests { // // suppose the verifier already knows old root, new root, old leaf, new leaf, and the original path (so they are public) let old_root = tree.root(); - let old_root_var = >::OutputVar::new_input( + let old_root_var = as CRHGadget<_>>::OutputVar::new_input( ark_relations::ns!(cs, "old_root"), || Ok(old_root), ) .unwrap(); let old_path = tree.generate_proof(update_query.0).unwrap(); - let old_path_var: PathVar = + let old_path_var: PathVar = PathVar::new_input(ark_relations::ns!(cs, "old_path"), || Ok(old_path)).unwrap(); let new_root = { tree.update(update_query.0, &update_query.1).unwrap(); tree.root() }; - let new_root_var = >::OutputVar::new_input( + let new_root_var = as CRHGadget<_>>::OutputVar::new_input( ark_relations::ns!(cs, "new_root"), || Ok(new_root), ) @@ -239,11 +230,11 @@ mod byte_mt_tests { } mod field_mt_tests { - use crate::crh::{poseidon, TwoToOneCRHSchemeGadget}; + use crate::{Gadget, crh::{poseidon, TwoToOneCRHGadget}}; use crate::merkle_tree::constraints::ConfigGadget; use crate::merkle_tree::tests::test_utils::poseidon_parameters; use crate::merkle_tree::{Config, IdentityDigestConverter}; - use crate::{CRHSchemeGadget, MerkleTree, PathVar}; + use crate::{CRHGadget, MerkleTree, PathVar}; use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::fields::fp::FpVar; use ark_r1cs_std::R1CSVar; @@ -252,31 +243,22 @@ mod field_mt_tests { type F = ark_ed_on_bls12_381::Fr; type H = poseidon::CRH; - type HG = poseidon::constraints::CRHGadget; type TwoToOneH = poseidon::TwoToOneCRH; - type TwoToOneHG = poseidon::constraints::TwoToOneCRHGadget; type LeafVar = [FpVar]; struct FieldMTConfig; impl Config for FieldMTConfig { type Leaf = [F]; - type LeafDigest = F; - type LeafInnerDigestConverter = IdentityDigestConverter; - type InnerDigest = F; + type LeafToInnerConverter = IdentityDigestConverter; type LeafHash = H; type TwoToOneHash = TwoToOneH; } - struct FieldMTConfigVar; - - impl ConfigGadget for FieldMTConfigVar { - type Leaf = LeafVar; - type LeafDigest = FpVar; - type LeafInnerConverter = IdentityDigestConverter>; - type InnerDigest = FpVar; - type LeafHash = HG; - type TwoToOneHash = TwoToOneHG; + impl ConfigGadget for FieldMTConfig { + type LeafVar = LeafVar; + + type LeafToInnerVarConverter = IdentityDigestConverter; } type FieldMT = MerkleTree; @@ -314,14 +296,14 @@ mod field_mt_tests { let constraints_from_digest = cs.num_constraints(); println!("constraints from digest: {}", constraints_from_digest); - let leaf_crh_params_var = >::ParametersVar::new_constant( + let leaf_crh_params_var = as CRHGadget<_>>::ParametersVar::new_constant( ark_relations::ns!(cs, "leaf_crh_params"), &leaf_crh_params, ) .unwrap(); let two_to_one_crh_params_var = - >::ParametersVar::new_constant( + as TwoToOneCRHGadget<_>>::ParametersVar::new_constant( ark_relations::ns!(cs, "two_to_one_params"), &leaf_crh_params, ) @@ -341,7 +323,7 @@ mod field_mt_tests { println!("constraints from leaf: {}", constraints_from_leaf); // Allocate MT Path - let cw = PathVar::::new_witness( + let cw = PathVar::::new_witness( ark_relations::ns!(cs, "new_witness"), || Ok(&proof), ) @@ -386,14 +368,14 @@ mod field_mt_tests { if let Some(update_query) = update_query { let cs = ConstraintSystem::::new_ref(); // allocate parameters for CRH - let leaf_crh_params_var = >::ParametersVar::new_constant( + let leaf_crh_params_var = as CRHGadget<_>>::ParametersVar::new_constant( ark_relations::ns!(cs, "leaf_crh_params"), &leaf_crh_params, ) .unwrap(); let two_to_one_crh_params_var = - >::ParametersVar::new_constant( + as TwoToOneCRHGadget<_>>::ParametersVar::new_constant( ark_relations::ns!(cs, "two_to_one_params"), &leaf_crh_params, ) @@ -413,7 +395,7 @@ mod field_mt_tests { let old_root_var = FpVar::new_input(cs.clone(), || Ok(old_root)).unwrap(); let old_path = tree.generate_proof(update_query.0).unwrap(); - let old_path_var = PathVar::::new_input( + let old_path_var = PathVar::::new_input( ark_relations::ns!(cs, "old_path"), || Ok(old_path), ) diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index 1d1296c0..00575f17 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -27,9 +27,7 @@ mod bytes_mt_tests { impl Config for JubJubMerkleTreeParams { type Leaf = [u8]; - type LeafDigest = ::Output; - type LeafInnerDigestConverter = ByteDigestConverter; - type InnerDigest = ::Output; + type LeafToInnerConverter = ByteDigestConverter; type LeafHash = LeafH; type TwoToOneHash = CompressH; @@ -132,9 +130,8 @@ mod field_mt_tests { struct FieldMTConfig; impl Config for FieldMTConfig { type Leaf = [F]; - type LeafDigest = F; - type LeafInnerDigestConverter = IdentityDigestConverter; - type InnerDigest = F; + type LeafToInnerConverter = IdentityDigestConverter; + type LeafHash = H; type TwoToOneHash = TwoToOneH; } From 0b56d3a6efd0a21315e08aee3abb7c5bce24e96c Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 10:49:03 -0400 Subject: [PATCH 07/13] Update PRF --- src/prf/blake2s/constraints.rs | 19 +++++++------ src/prf/constraints.rs | 51 +++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/prf/blake2s/constraints.rs b/src/prf/blake2s/constraints.rs index 9a68cc45..99ecf937 100644 --- a/src/prf/blake2s/constraints.rs +++ b/src/prf/blake2s/constraints.rs @@ -1,7 +1,7 @@ use ark_ff::PrimeField; use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; -use crate::{prf::PRFGadget, Vec}; +use crate::{Vec, prf::PRFWithGadget}; use ark_r1cs_std::prelude::*; use core::borrow::Borrow; @@ -362,18 +362,18 @@ impl R1CSVar for OutputVar { } } -impl PRFGadget for Blake2s { +impl PRFWithGadget for Blake2s { type OutputVar = OutputVar; #[tracing::instrument(target = "r1cs", skip(cs))] - fn new_seed(cs: impl Into>, seed: &[u8; 32]) -> Vec> { + fn new_seed_as_witness(cs: impl Into>, seed: &[u8; 32]) -> Vec> { let ns = cs.into(); let cs = ns.cs(); UInt8::new_witness_vec(ark_relations::ns!(cs, "New Blake2s seed"), seed).unwrap() } #[tracing::instrument(target = "r1cs", skip(seed, input))] - fn evaluate(seed: &[UInt8], input: &[UInt8]) -> Result { + fn evaluate_gadget(seed: &[UInt8], input: &[UInt8]) -> Result { assert_eq!(seed.len(), 32); let input: Vec<_> = seed .iter() @@ -386,6 +386,7 @@ impl PRFGadget for Blake2s { .collect(); Ok(OutputVar(result)) } + } #[cfg(test)] @@ -393,7 +394,7 @@ mod test { use ark_ed_on_bls12_381::Fq as Fr; use ark_std::rand::Rng; - use crate::prf::blake2s::{constraints::evaluate_blake2s, Blake2s as B2SPRF}; + use crate::{Gadget, prf::{PRF, PRFWithGadget, blake2s::{constraints::evaluate_blake2s, Blake2s}}}; use ark_relations::r1cs::ConstraintSystem; use blake2::VarBlake2s; @@ -414,7 +415,7 @@ mod test { #[test] fn test_blake2s_prf() { - use crate::prf::{PRFGadget, PRF}; + use crate::prf::PRFGadget; let mut rng = ark_std::test_rng(); let cs = ConstraintSystem::::new_ref(); @@ -425,17 +426,17 @@ mod test { let mut input = [0u8; 32]; rng.fill(&mut input); - let seed_var = Blake2s::new_seed(cs.clone(), &seed); + let seed_var = Blake2s::new_seed_as_witness(cs.clone(), &seed); let input_var = UInt8::new_witness_vec(ark_relations::ns!(cs, "declare_input"), &input).unwrap(); let out = Blake2s::evaluate(&seed, &input).unwrap(); - let actual_out_var = >::OutputVar::new_witness( + let actual_out_var = as PRFGadget>::OutputVar::new_witness( ark_relations::ns!(cs, "declare_output"), || Ok(out), ) .unwrap(); - let output_var = Blake2sGadget::evaluate(&seed_var, &input_var).unwrap(); + let output_var = Gadget::::evaluate(&seed_var, &input_var).unwrap(); output_var.enforce_equal(&actual_out_var).unwrap(); if !cs.is_satisfied().unwrap() { diff --git a/src/prf/constraints.rs b/src/prf/constraints.rs index 53b097f2..81196a9e 100644 --- a/src/prf/constraints.rs +++ b/src/prf/constraints.rs @@ -1,12 +1,12 @@ use ark_ff::Field; use core::fmt::Debug; -use crate::{prf::PRF, Vec}; +use crate::{Gadget, Vec, prf::PRF}; use ark_relations::r1cs::{Namespace, SynthesisError}; use ark_r1cs_std::prelude::*; -pub trait PRFGadget: PRF { +pub trait PRFWithGadget: PRF { type OutputVar: EqGadget + ToBytesGadget + AllocVar @@ -14,13 +14,56 @@ pub trait PRFGadget: PRF { + Clone + Debug; - fn new_seed( + fn new_seed_as_witness( cs: impl Into>, seed: &Self::Seed, ) -> Vec>; - fn evaluate( + fn evaluate_gadget( seed: &[UInt8], input: &[UInt8], ) -> Result; } + +pub trait PRFGadget { + type Native: PRFWithGadget< + ConstraintF, + OutputVar = Self::OutputVar, + >; + type OutputVar: EqGadget + + ToBytesGadget + + AllocVar<::Output, ConstraintF> + + Clone + + Debug; + + fn new_seed_as_witness( + cs: impl Into>, + seed: &::Seed, + ) -> Vec> { + Self::Native::new_seed_as_witness(cs, seed) + } + + fn evaluate( + seed: &[UInt8], + input: &[UInt8], + ) -> Result { + Self::Native::evaluate_gadget(seed, input) + } +} + +impl PRFGadget for Gadget

+where + P: PRFWithGadget, + ConstraintF: Field, +{ + type Native = P; + type OutputVar = P::OutputVar; + + fn evaluate( + seed: &[UInt8], + input: &[UInt8], + ) -> Result { + P::evaluate_gadget(seed, input) + } + +} \ No newline at end of file From 51fda73d067dfec26138a506d1605c7b918cb328 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 10:49:14 -0400 Subject: [PATCH 08/13] Update Signature --- src/signature/constraints.rs | 47 +++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/signature/constraints.rs b/src/signature/constraints.rs index a669c0ad..65d71564 100644 --- a/src/signature/constraints.rs +++ b/src/signature/constraints.rs @@ -2,16 +2,16 @@ use ark_ff::Field; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::SynthesisError; -use crate::signature::SignatureScheme; +use crate::{Gadget, signature::SignatureScheme}; -pub trait SigVerifyGadget { - type ParametersVar: AllocVar + Clone; +pub trait SigVerifyWithGadget: SignatureScheme { + type ParametersVar: AllocVar + Clone; - type PublicKeyVar: ToBytesGadget + AllocVar + Clone; + type PublicKeyVar: ToBytesGadget + AllocVar + Clone; - type SignatureVar: ToBytesGadget + AllocVar + Clone; + type SignatureVar: ToBytesGadget + AllocVar + Clone; - fn verify( + fn verify_gadget( parameters: &Self::ParametersVar, public_key: &Self::PublicKeyVar, // TODO: Should we make this take in bytes or something different? @@ -20,6 +20,41 @@ pub trait SigVerifyGadget { ) -> Result, SynthesisError>; } +pub trait SigVerifyGadget { + type Native: SigVerifyWithGadget< + ConstraintF, + ParametersVar = Self::ParametersVar, + PublicKeyVar = Self::PublicKeyVar, + SignatureVar = Self::SignatureVar, + >; + type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; + + type PublicKeyVar: ToBytesGadget + AllocVar<::PublicKey, ConstraintF> + Clone; + + type SignatureVar: ToBytesGadget + AllocVar<::Signature, ConstraintF> + Clone; + + fn verify( + parameters: &Self::ParametersVar, + public_key: &Self::PublicKeyVar, + // TODO: Should we make this take in bytes or something different? + message: &[UInt8], + signature: &Self::SignatureVar, + ) -> Result, SynthesisError> { + Self::Native::verify_gadget(parameters, public_key, message, signature) + } +} + +impl SigVerifyGadget for Gadget +where + S: SigVerifyWithGadget, + ConstraintF: Field, +{ + type Native = S; + type ParametersVar = S::ParametersVar; + type PublicKeyVar = S::PublicKeyVar; + type SignatureVar = S::SignatureVar; +} + pub trait SigRandomizePkGadget { type ParametersVar: AllocVar + Clone; From 67c80faec8876aa02205cc551f0f818153caaa1d Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 10:49:28 -0400 Subject: [PATCH 09/13] Update SNARK --- src/snark/constraints.rs | 169 ++++++++++++++++++++++++++++++++------- 1 file changed, 138 insertions(+), 31 deletions(-) diff --git a/src/snark/constraints.rs b/src/snark/constraints.rs index d0036e41..25f5a159 100644 --- a/src/snark/constraints.rs +++ b/src/snark/constraints.rs @@ -22,8 +22,10 @@ use ark_std::{ vec::{IntoIter, Vec}, }; +use crate::Gadget; + /// This implements constraints for SNARK verifiers. -pub trait SNARKGadget: SNARK { +pub trait SNARKWithGadget: SNARK { type ProcessedVerifyingKeyVar: AllocVar + Clone; type VerifyingKeyVar: AllocVar + ToBytesGadget @@ -80,28 +82,153 @@ pub trait SNARKGadget: SNARK { Self::VerifyingKeyVar::new_variable(cs, f, mode) } - fn verify_with_processed_vk( + fn verify_with_processed_vk_gadget( circuit_pvk: &Self::ProcessedVerifyingKeyVar, x: &Self::InputVar, proof: &Self::ProofVar, ) -> Result, SynthesisError>; - fn verify( + fn verify_gadget( circuit_vk: &Self::VerifyingKeyVar, x: &Self::InputVar, proof: &Self::ProofVar, ) -> Result, SynthesisError>; } +/// This implements constraints for SNARK verifiers. +pub trait SNARKGadget { + type Native: SNARKWithGadget< + F, + ConstraintF, + VerifierSize = Self::VerifierSize, + ProcessedVerifyingKeyVar = Self::ProcessedVerifyingKeyVar, + VerifyingKeyVar = Self::VerifyingKeyVar, + InputVar = Self::InputVar, + ProofVar = Self::ProofVar, + >; + type ProcessedVerifyingKeyVar: AllocVar<>::ProcessedVerifyingKey, ConstraintF> + Clone; + type VerifyingKeyVar: AllocVar<>::VerifyingKey, ConstraintF> + + ToBytesGadget + + Clone; + type InputVar: AllocVar, ConstraintF> + FromFieldElementsGadget + Clone; + type ProofVar: AllocVar<>::Proof, ConstraintF> + Clone; + + /// Information about the R1CS constraints required to check proofs relative + /// a given verification key. In the context of a LPCP-based pairing-based SNARK + /// like that of [[Groth16]](https://eprint.iacr.org/2016/260), + /// this is independent of the R1CS matrices, + /// whereas for more "complex" SNARKs like [[Marlin]](https://eprint.iacr.org/2019/1047), + /// this can encode information about the highest degree of polynomials + /// required to verify proofs. + type VerifierSize: PartialOrd + Clone + fmt::Debug; + + /// Returns information about the R1CS constraints required to check proofs relative + /// to the verification key `circuit_vk`. + fn verifier_size(vk: &>::VerifyingKey) -> Self::VerifierSize { + Self::Native::verifier_size(vk) + } + + /// Optionally allocates `S::Proof` in `cs` without performing + /// additional checks, such as subgroup membership checks. Use this *only* + /// if you know it is safe to do so. Such "safe" scenarios can include + /// the case where `proof` is a public input (`mode == AllocationMode::Input`), + /// and the corresponding checks are performed by the SNARK verifier outside + /// the circuit. Another example is the when `mode == AllocationMode::Constant`. + /// + /// The default implementation does not omit such checks, and just invokes + /// `Self::ProofVar::new_variable`. + #[tracing::instrument(target = "r1cs", skip(cs, f))] + fn new_proof_unchecked>::Proof>>( + cs: impl Into>, + f: impl FnOnce() -> Result, + mode: AllocationMode, + ) -> Result { + Self::Native::new_proof_unchecked(cs, f, mode) + } + + /// Optionally allocates `S::VerifyingKey` in `cs` without performing + /// additional checks, such as subgroup membership checks. Use this *only* + /// if you know it is safe to do so. Such "safe" scenarios can include + /// the case where `vk` is a public input (`mode == AllocationMode::Input`), + /// and the corresponding checks are performed by the SNARK verifier outside + /// the circuit. Another example is the when `mode == AllocationMode::Constant`. + /// + /// The default implementation does not omit such checks, and just invokes + /// `Self::VerifyingKeyVar::new_variable`. + #[tracing::instrument(target = "r1cs", skip(cs, f))] + fn new_verification_key_unchecked>::VerifyingKey>>( + cs: impl Into>, + f: impl FnOnce() -> Result, + mode: AllocationMode, + ) -> Result { + Self::Native::new_verification_key_unchecked(cs, f, mode) + } + + fn verify_with_processed_vk( + pvk: &Self::ProcessedVerifyingKeyVar, + x: &Self::InputVar, + proof: &Self::ProofVar, + ) -> Result, SynthesisError> { + Self::Native::verify_with_processed_vk_gadget(pvk, x, proof) + } + + fn verify( + vk: &Self::VerifyingKeyVar, + x: &Self::InputVar, + proof: &Self::ProofVar, + ) -> Result, SynthesisError> { + Self::Native::verify_gadget(vk, x, proof) + } +} + +impl SNARKGadget for Gadget +where + S: SNARKWithGadget, + F: PrimeField, ConstraintF: PrimeField +{ + type Native = S; + type VerifierSize = S::VerifierSize; + type ProcessedVerifyingKeyVar = S::ProcessedVerifyingKeyVar; + type VerifyingKeyVar = S::VerifyingKeyVar; + type InputVar = S::InputVar; + type ProofVar = S::ProofVar; +} + pub trait CircuitSpecificSetupSNARKGadget: - SNARKGadget + CircuitSpecificSetupSNARK + SNARKGadget +where + Self::Native: CircuitSpecificSetupSNARK +{ +} + +impl CircuitSpecificSetupSNARKGadget for Gadget +where + S: CircuitSpecificSetupSNARK + SNARKWithGadget, + F: PrimeField, + ConstraintF: PrimeField +{} + +pub trait UniversalSetupSNARKWithGadget: + SNARKWithGadget + UniversalSetupSNARK { + type BoundCircuit: From<>::ComputationBound> + ConstraintSynthesizer + Clone; } pub trait UniversalSetupSNARKGadget: - SNARKGadget + UniversalSetupSNARK + SNARKGadget +where + Self::Native: UniversalSetupSNARKWithGadget +{ + type BoundCircuit: From<>::ComputationBound> + ConstraintSynthesizer + Clone; +} + +impl UniversalSetupSNARKGadget for Gadget +where + S: UniversalSetupSNARK + UniversalSetupSNARKWithGadget, + F: PrimeField, + ConstraintF: PrimeField { - type BoundCircuit: From + ConstraintSynthesizer + Clone; + type BoundCircuit = S::BoundCircuit; } /// Gadgets to convert elements between different fields for recursive proofs @@ -369,29 +496,17 @@ impl FromFieldElementsGadget for BooleanIn /// Conversion of field elements by allocating them as nonnative field elements /// Used by Marlin -pub struct NonNativeFieldInputVar -where - F: PrimeField, - CF: PrimeField, -{ +pub struct NonNativeFieldInputVar { pub val: Vec>, } -impl NonNativeFieldInputVar -where - F: PrimeField, - CF: PrimeField, -{ +impl NonNativeFieldInputVar { pub fn new(val: Vec>) -> Self { Self { val } } } -impl IntoIterator for NonNativeFieldInputVar -where - F: PrimeField, - CF: PrimeField, -{ +impl IntoIterator for NonNativeFieldInputVar { type Item = NonNativeFieldVar; type IntoIter = IntoIter>; @@ -400,11 +515,7 @@ where } } -impl Clone for NonNativeFieldInputVar -where - F: PrimeField, - CF: PrimeField, -{ +impl Clone for NonNativeFieldInputVar { fn clone(&self) -> Self { Self { val: self.val.clone(), @@ -412,11 +523,7 @@ where } } -impl AllocVar, CF> for NonNativeFieldInputVar -where - F: PrimeField, - CF: PrimeField, -{ +impl AllocVar, CF> for NonNativeFieldInputVar { fn new_variable>>( cs: impl Into>, f: impl FnOnce() -> Result, From 60db5d81adeab4442ecfe5ea2782529f229af7d9 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 10:49:48 -0400 Subject: [PATCH 10/13] Update lib.rs --- Cargo.toml | 4 ++++ src/lib.rs | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6fa01f9f..de07a82a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,4 +47,8 @@ ark-mnt6-298 = { version = "^0.3.0", default-features = false, features = [ "r1c [patch.crates-io] ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", branch = "reduce-generics", optional = true, default-features = false } +ark-ed-on-bls12-381 = { git = "https://github.com/arkworks-rs/curves", branch = "reduce-generics", default-features = false, features = [ "r1cs" ] } +ark-bls12-377 = { git = "https://github.com/arkworks-rs/curves", branch = "reduce-generics", default-features = false, features = [ "curve", "r1cs" ] } +ark-mnt4-298 = { git = "https://github.com/arkworks-rs/curves", branch = "reduce-generics", default-features = false, features = [ "curve", "r1cs" ] } +ark-mnt6-298 = { git = "https://github.com/arkworks-rs/curves", branch = "reduce-generics", default-features = false, features = [ "curve", "r1cs" ] } ark-sponge = { git = "https://github.com/arkworks-rs/sponge", branch = "reduce-generics", default-features = false } diff --git a/src/lib.rs b/src/lib.rs index ab0f4669..7fc9e67d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,8 @@ extern crate ark_std; #[macro_use] extern crate derivative; +use std::marker::PhantomData; + pub(crate) use ark_std::{borrow::ToOwned, boxed::Box, vec::Vec}; mod macros; @@ -38,13 +40,22 @@ pub use self::{ #[cfg(feature = "r1cs")] pub use self::{ commitment::CommitmentGadget, - crh::CRHSchemeGadget, merkle_tree::constraints::PathVar, + crh::CRHGadget, merkle_tree::constraints::PathVar, prf::PRFGadget, signature::SigRandomizePkGadget, snark::SNARKGadget, }; pub type Error = Box; +#[derive(Derivative)] +#[derivative( + Clone(bound = ""), + Debug(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), +)] +pub struct Gadget(PhantomData); + #[derive(Debug)] pub enum CryptoError { IncorrectInputLength(usize), From bdec86147bb5de9c517bb866da9871ddcddffd8a Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 10:52:29 -0400 Subject: [PATCH 11/13] Format --- src/commitment/blake2s/constraints.rs | 27 ++++--- src/commitment/constraints.rs | 12 +-- src/commitment/injective_map/constraints.rs | 17 ++-- src/commitment/pedersen/constraints.rs | 27 ++++--- src/crh/bowe_hopwood/constraints.rs | 18 +++-- src/crh/constraints.rs | 16 ++-- src/crh/injective_map/constraints.rs | 26 +++--- src/crh/injective_map/mod.rs | 4 +- src/crh/pedersen/constraints.rs | 15 ++-- src/crh/poseidon/constraints.rs | 10 +-- src/encryption/constraints.rs | 6 +- src/encryption/elgamal/constraints.rs | 87 ++++++++------------- src/lib.rs | 8 +- src/merkle_tree/constraints.rs | 19 +++-- src/merkle_tree/tests/constraints.rs | 46 ++++++----- src/merkle_tree/tests/mod.rs | 4 +- src/prf/blake2s/constraints.rs | 16 +++- src/prf/constraints.rs | 12 +-- src/signature/constraints.rs | 12 ++- src/snark/constraints.rs | 39 +++++---- 20 files changed, 219 insertions(+), 202 deletions(-) diff --git a/src/commitment/blake2s/constraints.rs b/src/commitment/blake2s/constraints.rs index 37073a83..a1ce603f 100644 --- a/src/commitment/blake2s/constraints.rs +++ b/src/commitment/blake2s/constraints.rs @@ -1,6 +1,10 @@ use ark_relations::r1cs::{Namespace, SynthesisError}; -use crate::{Vec, commitment::{CommitmentWithGadget, blake2s}, prf::blake2s::constraints::{evaluate_blake2s, OutputVar}}; +use crate::{ + commitment::{blake2s, CommitmentWithGadget}, + prf::blake2s::constraints::{evaluate_blake2s, OutputVar}, + Vec, +}; use ark_ff::{Field, PrimeField}; use ark_r1cs_std::prelude::*; @@ -65,11 +69,11 @@ impl AllocVar<[u8; 32], ConstraintF> for RandomnessVar< #[cfg(test)] mod test { - use crate::Gadget; use crate::commitment::{ blake2s::{constraints::RandomnessVar, Commitment}, CommitmentGadget, CommitmentScheme, }; + use crate::Gadget; use ark_ed_on_bls12_381::Fq as Fr; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::ConstraintSystem; @@ -102,17 +106,14 @@ mod test { } let randomness_var = RandomnessVar(randomness_var); - let parameters_var = as CommitmentGadget>::ParametersVar::new_witness( - ark_relations::ns!(cs, "gadget_parameters"), - || Ok(¶meters), - ) - .unwrap(); - let result_var = Gadget::::commit( - ¶meters_var, - &input_var, - &randomness_var, - ) - .unwrap(); + let parameters_var = + as CommitmentGadget>::ParametersVar::new_witness( + ark_relations::ns!(cs, "gadget_parameters"), + || Ok(¶meters), + ) + .unwrap(); + let result_var = + Gadget::::commit(¶meters_var, &input_var, &randomness_var).unwrap(); for i in 0..32 { assert_eq!(primitive_result[i], result_var.0[i].value().unwrap()); diff --git a/src/commitment/constraints.rs b/src/commitment/constraints.rs index 51c193c0..5bfe5fb0 100644 --- a/src/commitment/constraints.rs +++ b/src/commitment/constraints.rs @@ -36,8 +36,10 @@ pub trait CommitmentGadget { + Clone + Sized + Debug; - type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; - type RandomnessVar: AllocVar<::Randomness, ConstraintF> + Clone; + type ParametersVar: AllocVar<::Parameters, ConstraintF> + + Clone; + type RandomnessVar: AllocVar<::Randomness, ConstraintF> + + Clone; fn commit( parameters: &Self::ParametersVar, @@ -50,11 +52,11 @@ pub trait CommitmentGadget { impl CommitmentGadget for crate::Gadget where - C: CommitmentWithGadget, - ConstraintF: Field + C: CommitmentWithGadget, + ConstraintF: Field, { type Native = C; type OutputVar = C::OutputVar; type ParametersVar = C::ParametersVar; type RandomnessVar = C::RandomnessVar; -} \ No newline at end of file +} diff --git a/src/commitment/injective_map/constraints.rs b/src/commitment/injective_map/constraints.rs index 304d14d8..1ee3cf42 100644 --- a/src/commitment/injective_map/constraints.rs +++ b/src/commitment/injective_map/constraints.rs @@ -1,11 +1,14 @@ -use crate::{Gadget, commitment::{ - injective_map::PedersenCommCompressor, - pedersen::{ - constraints::{ParametersVar, RandomnessVar}, - Commitment, Window, +use crate::{ + commitment::{ + injective_map::PedersenCommCompressor, + pedersen::{ + constraints::{ParametersVar, RandomnessVar}, + Commitment, Window, + }, + CommitmentGadget, }, - CommitmentGadget, -}}; + Gadget, +}; pub use crate::crh::injective_map::constraints::InjectiveMapGadget; use ark_ec::ProjectiveCurve; diff --git a/src/commitment/pedersen/constraints.rs b/src/commitment/pedersen/constraints.rs index b482d863..92cdb8d3 100644 --- a/src/commitment/pedersen/constraints.rs +++ b/src/commitment/pedersen/constraints.rs @@ -121,12 +121,12 @@ mod test { use ark_std::{test_rng, UniformRand}; use crate::{ - Gadget, commitment::{ pedersen::{Commitment, Randomness}, CommitmentGadget, CommitmentScheme, }, crh::pedersen, + Gadget, }; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::ConstraintSystem; @@ -160,17 +160,20 @@ mod test { input_var.push(UInt8::new_witness(cs.clone(), || Ok(*input_byte)).unwrap()); } - let randomness_var = as CommitmentGadget>::RandomnessVar::new_witness( - ark_relations::ns!(cs, "gadget_randomness"), - || Ok(&randomness), - ) - .unwrap(); - let parameters_var = as CommitmentGadget>::ParametersVar::new_witness( - ark_relations::ns!(cs, "gadget_parameters"), - || Ok(¶meters), - ) - .unwrap(); - let result_var = Gadget::::commit(¶meters_var, &input_var, &randomness_var).unwrap(); + let randomness_var = + as CommitmentGadget>::RandomnessVar::new_witness( + ark_relations::ns!(cs, "gadget_randomness"), + || Ok(&randomness), + ) + .unwrap(); + let parameters_var = + as CommitmentGadget>::ParametersVar::new_witness( + ark_relations::ns!(cs, "gadget_parameters"), + || Ok(¶meters), + ) + .unwrap(); + let result_var = + Gadget::::commit(¶meters_var, &input_var, &randomness_var).unwrap(); let primitive_result = primitive_result; assert_eq!(primitive_result, result_var.value().unwrap()); diff --git a/src/crh/bowe_hopwood/constraints.rs b/src/crh/bowe_hopwood/constraints.rs index bd13bb5d..ac0561ef 100644 --- a/src/crh/bowe_hopwood/constraints.rs +++ b/src/crh/bowe_hopwood/constraints.rs @@ -1,6 +1,13 @@ use core::{borrow::Borrow, iter, marker::PhantomData}; -use crate::{Vec, crh::{CRHWithGadget, TwoToOneCRHWithGadget, bowe_hopwood::{self, CHUNK_SIZE, CRH, Parameters, TwoToOneCRH}, pedersen::Window}}; +use crate::{ + crh::{ + bowe_hopwood::{self, Parameters, TwoToOneCRH, CHUNK_SIZE, CRH}, + pedersen::Window, + CRHWithGadget, TwoToOneCRHWithGadget, + }, + Vec, +}; use ark_ec::{ModelParameters, TEModelParameters}; use ark_ff::Field; use ark_r1cs_std::{ @@ -146,9 +153,9 @@ where mod test { use ark_std::rand::Rng; - use crate::{Gadget, crh::bowe_hopwood}; - use crate::crh::{pedersen, TwoToOneCRHScheme, TwoToOneCRHGadget}; - use crate::{CRHScheme, CRHGadget}; + use crate::crh::{pedersen, TwoToOneCRHGadget, TwoToOneCRHScheme}; + use crate::{crh::bowe_hopwood, Gadget}; + use crate::{CRHGadget, CRHScheme}; use ark_ed_on_bls12_381::{EdwardsParameters, Fq as Fr}; use ark_r1cs_std::{alloc::AllocVar, uint8::UInt8, R1CSVar}; use ark_relations::r1cs::{ConstraintSystem, ConstraintSystemRef}; @@ -221,8 +228,7 @@ mod test { let (right, right_var) = generate_u8_input(cs.clone(), 31, rng); let parameters = TestTwoToOneCRH::setup(rng).unwrap(); let primitive_result = - TestTwoToOneCRH::evaluate(¶meters, left.as_slice(), right.as_slice()) - .unwrap(); + TestTwoToOneCRH::evaluate(¶meters, left.as_slice(), right.as_slice()).unwrap(); let parameters_var = as TwoToOneCRHGadget>::ParametersVar::new_witness( diff --git a/src/crh/constraints.rs b/src/crh/constraints.rs index 8c44e0d7..a516b884 100644 --- a/src/crh/constraints.rs +++ b/src/crh/constraints.rs @@ -1,7 +1,10 @@ use ark_ff::Field; use core::fmt::Debug; -use crate::{Gadget, crh::{CRHScheme, TwoToOneCRHScheme}}; +use crate::{ + crh::{CRHScheme, TwoToOneCRHScheme}, + Gadget, +}; use ark_relations::r1cs::SynthesisError; use ark_r1cs_std::prelude::*; @@ -92,7 +95,8 @@ pub trait TwoToOneCRHGadget { + Clone + Sized; - type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; + type ParametersVar: AllocVar<::Parameters, ConstraintF> + + Clone; fn evaluate( parameters: &Self::ParametersVar, @@ -113,7 +117,8 @@ pub trait TwoToOneCRHGadget { impl CRHGadget for Gadget where - H: CRHWithGadget, ConstraintF: Field + H: CRHWithGadget, + ConstraintF: Field, { type Native = H; type InputVar = H::InputVar; @@ -123,10 +128,11 @@ where impl TwoToOneCRHGadget for Gadget where - H: TwoToOneCRHWithGadget, ConstraintF: Field + H: TwoToOneCRHWithGadget, + ConstraintF: Field, { type Native = H; type InputVar = H::InputVar; type ParametersVar = H::ParametersVar; type OutputVar = H::OutputVar; -} \ No newline at end of file +} diff --git a/src/crh/injective_map/constraints.rs b/src/crh/injective_map/constraints.rs index 3a164bb9..81712d53 100644 --- a/src/crh/injective_map/constraints.rs +++ b/src/crh/injective_map/constraints.rs @@ -1,10 +1,12 @@ -use crate::{Gadget, crh::{ - CRHGadget, - TwoToOneCRHGadget, - constraints, - injective_map::{InjectiveMap, PedersenCRHCompressor, TECompressor}, - pedersen::{self, constraints as ped_constraints, Window}, -}}; +use crate::{ + crh::{ + constraints, + injective_map::{InjectiveMap, PedersenCRHCompressor, TECompressor}, + pedersen::{self, constraints as ped_constraints, Window}, + CRHGadget, TwoToOneCRHGadget, + }, + Gadget, +}; use core::fmt::Debug; use crate::crh::injective_map::PedersenTwoToOneCRHCompressor; @@ -101,12 +103,8 @@ where left: &Self::OutputVar, right: &Self::OutputVar, ) -> Result { - let left= left.to_non_unique_bytes()?; - let right= right.to_non_unique_bytes()?; - Gadget::::evaluate( - parameters, - &left, - &right, - ) + let left = left.to_non_unique_bytes()?; + let right = right.to_non_unique_bytes()?; + Gadget::::evaluate(parameters, &left, &right) } } diff --git a/src/crh/injective_map/mod.rs b/src/crh/injective_map/mod.rs index b105fd65..efca7c0b 100644 --- a/src/crh/injective_map/mod.rs +++ b/src/crh/injective_map/mod.rs @@ -98,9 +98,7 @@ impl, W: pedersen::Window> TwoToOneCRHSch ) -> Result { let eval_time = start_timer!(|| "PedersenCRHCompressor::Eval"); let result = I::injective_map(&pedersen::TwoToOneCRH::::evaluate( - parameters, - left, - right, + parameters, left, right, )?)?; end_timer!(eval_time); Ok(result) diff --git a/src/crh/pedersen/constraints.rs b/src/crh/pedersen/constraints.rs index cccf8c1e..15170acb 100644 --- a/src/crh/pedersen/constraints.rs +++ b/src/crh/pedersen/constraints.rs @@ -10,7 +10,7 @@ use ark_ff::Field; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::{Namespace, SynthesisError}; -use core::{iter, borrow::Borrow}; +use core::{borrow::Borrow, iter}; type ConstraintF = <::BaseField as Field>::BasePrimeField; #[derive(Derivative)] @@ -118,9 +118,10 @@ where #[cfg(test)] mod test { - use crate::{Gadget, crh::{ - pedersen, CRHScheme, CRHGadget, TwoToOneCRHScheme, TwoToOneCRHGadget, - }}; + use crate::{ + crh::{pedersen, CRHGadget, CRHScheme, TwoToOneCRHGadget, TwoToOneCRHScheme}, + Gadget, + }; use ark_ec::ProjectiveCurve; use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective as JubJub, Fq as Fr}; use ark_r1cs_std::prelude::*; @@ -195,8 +196,7 @@ mod test { let (left, left_var) = generate_affine(cs.clone(), rng); let (right, right_var) = generate_affine(cs.clone(), rng); let parameters = TestTwoToOneCRH::setup(rng).unwrap(); - let primitive_result = - TestTwoToOneCRH::compress(¶meters, left, right).unwrap(); + let primitive_result = TestTwoToOneCRH::compress(¶meters, left, right).unwrap(); let parameters_var = pedersen::constraints::CRHParametersVar::new_constant( ark_relations::ns!(cs, "CRH Parameters"), @@ -205,8 +205,7 @@ mod test { .unwrap(); let result_var = - Gadget::::compress(¶meters_var, &left_var, &right_var) - .unwrap(); + Gadget::::compress(¶meters_var, &left_var, &right_var).unwrap(); let primitive_result = primitive_result; assert_eq!(primitive_result, result_var.value().unwrap()); diff --git a/src/crh/poseidon/constraints.rs b/src/crh/poseidon/constraints.rs index d25bb413..ac42dbc2 100644 --- a/src/crh/poseidon/constraints.rs +++ b/src/crh/poseidon/constraints.rs @@ -1,7 +1,5 @@ use crate::crh::poseidon::{TwoToOneCRH, CRH}; -use crate::crh::{ - CRHWithGadget, TwoToOneCRHWithGadget, -}; +use crate::crh::{CRHWithGadget, TwoToOneCRHWithGadget}; use crate::{CRHScheme, Vec}; use ark_ff::PrimeField; use ark_r1cs_std::alloc::{AllocVar, AllocationMode}; @@ -98,10 +96,10 @@ impl AllocVar, F> for CRHParameter #[cfg(test)] mod test { - use crate::{Gadget, crh::poseidon::constraints::CRHParametersVar}; use crate::crh::poseidon::{TwoToOneCRH, CRH}; - use crate::crh::{TwoToOneCRHScheme, TwoToOneCRHGadget}; - use crate::{CRHScheme, CRHGadget}; + use crate::crh::{TwoToOneCRHGadget, TwoToOneCRHScheme}; + use crate::{crh::poseidon::constraints::CRHParametersVar, Gadget}; + use crate::{CRHGadget, CRHScheme}; use ark_bls12_377::Fr; use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::{ diff --git a/src/encryption/constraints.rs b/src/encryption/constraints.rs index ab9a29bc..1cfe963a 100644 --- a/src/encryption/constraints.rs +++ b/src/encryption/constraints.rs @@ -1,4 +1,4 @@ -use crate::{Gadget, encryption::AsymmetricEnc}; +use crate::{encryption::AsymmetricEnc, Gadget}; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::SynthesisError; @@ -54,8 +54,8 @@ pub trait AsymmetricEncGadget { } } -impl AsymmetricEncGadget for Gadget -where +impl AsymmetricEncGadget for Gadget +where Enc: AsymmetricEncWithGadget, ConstraintF: Field, { diff --git a/src/encryption/elgamal/constraints.rs b/src/encryption/elgamal/constraints.rs index 48365e9c..089fe416 100644 --- a/src/encryption/elgamal/constraints.rs +++ b/src/encryption/elgamal/constraints.rs @@ -36,7 +36,6 @@ where } } - #[derive(Derivative)] #[derivative(Clone(bound = "C::Var: Clone"))] pub struct ParametersVar>> { @@ -53,10 +52,9 @@ where _mode: AllocationMode, ) -> Result { // Always allocate as constant - let generator = C::Var::new_constant(cs, f().map(|g| g.borrow().generator.into()).unwrap())?; - Ok(Self { - generator, - }) + let generator = + C::Var::new_constant(cs, f().map(|g| g.borrow().generator.into()).unwrap())?; + Ok(Self { generator }) } } @@ -76,9 +74,7 @@ where mode: AllocationMode, ) -> Result { let plaintext = C::Var::new_variable(cs, f, mode)?; - Ok(Self { - plaintext, - }) + Ok(Self { plaintext }) } } @@ -98,9 +94,7 @@ where mode: AllocationMode, ) -> Result { let pk = C::Var::new_variable(cs, f, mode)?; - Ok(Self { - pk, - }) + Ok(Self { pk }) } } @@ -125,10 +119,7 @@ where let prep = f().map(|g| *g.borrow()); let c1 = C::Var::new_variable(cs.clone(), || prep.map(|g| g.borrow().0), mode)?; let c2 = C::Var::new_variable(cs.clone(), || prep.map(|g| g.borrow().1), mode)?; - Ok(Self { - c1, - c2, - }) + Ok(Self { c1, c2 }) } } @@ -170,26 +161,21 @@ where let s = public_key.pk.scalar_mul_le(randomness.iter())?; // compute c1 = randomness*generator - let c1 = parameters - .generator - .scalar_mul_le(randomness.iter())?; + let c1 = parameters.generator.scalar_mul_le(randomness.iter())?; // compute c2 = m + s let c2 = s + &message.plaintext; - Ok(Self::CiphertextVar { - c1, - c2, - }) + Ok(Self::CiphertextVar { c1, c2 }) } } #[cfg(test)] mod test { - use crate::Gadget; use crate::encryption::constraints::AsymmetricEncGadget; use crate::encryption::elgamal::{ElGamal, Randomness}; use crate::encryption::AsymmetricEnc; + use crate::Gadget; use ark_std::{test_rng, UniformRand}; use ark_ed_on_bls12_381::{EdwardsProjective as JubJub, Fq}; @@ -213,42 +199,37 @@ mod test { // construct constraint system let cs = ConstraintSystem::::new_ref(); - let randomness_var = - >::RandomnessVar::new_witness( - ark_relations::ns!(cs, "gadget_randomness"), - || Ok(&randomness), - ) - .unwrap(); - let parameters_var = - >::ParametersVar::new_constant( - ark_relations::ns!(cs, "gadget_parameters"), - ¶meters, - ) - .unwrap(); - let msg_var = - >::PlaintextVar::new_witness( - ark_relations::ns!(cs, "gadget_message"), - || Ok(&msg), - ) - .unwrap(); - let pk_var = - >::PublicKeyVar::new_witness( - ark_relations::ns!(cs, "gadget_public_key"), - || Ok(&pk), - ) - .unwrap(); + let randomness_var = >::RandomnessVar::new_witness( + ark_relations::ns!(cs, "gadget_randomness"), + || Ok(&randomness), + ) + .unwrap(); + let parameters_var = >::ParametersVar::new_constant( + ark_relations::ns!(cs, "gadget_parameters"), + ¶meters, + ) + .unwrap(); + let msg_var = >::PlaintextVar::new_witness( + ark_relations::ns!(cs, "gadget_message"), + || Ok(&msg), + ) + .unwrap(); + let pk_var = >::PublicKeyVar::new_witness( + ark_relations::ns!(cs, "gadget_public_key"), + || Ok(&pk), + ) + .unwrap(); // use gadget let result_var = TestGadget::encrypt(¶meters_var, &msg_var, &randomness_var, &pk_var).unwrap(); // check that result equals expected ciphertext in the constraint system - let expected_var = - >::CiphertextVar::new_input( - ark_relations::ns!(cs, "gadget_expected"), - || Ok(&primitive_result), - ) - .unwrap(); + let expected_var = >::CiphertextVar::new_input( + ark_relations::ns!(cs, "gadget_expected"), + || Ok(&primitive_result), + ) + .unwrap(); expected_var.enforce_equal(&result_var).unwrap(); assert_eq!(primitive_result.0, result_var.c1.value().unwrap()); diff --git a/src/lib.rs b/src/lib.rs index 7fc9e67d..45c37d5d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,10 +39,8 @@ pub use self::{ #[cfg(feature = "r1cs")] pub use self::{ - commitment::CommitmentGadget, - crh::CRHGadget, merkle_tree::constraints::PathVar, - prf::PRFGadget, - signature::SigRandomizePkGadget, snark::SNARKGadget, + commitment::CommitmentGadget, crh::CRHGadget, merkle_tree::constraints::PathVar, + prf::PRFGadget, signature::SigRandomizePkGadget, snark::SNARKGadget, }; pub type Error = Box; @@ -52,7 +50,7 @@ pub type Error = Box; Clone(bound = ""), Debug(bound = ""), PartialEq(bound = ""), - Eq(bound = ""), + Eq(bound = "") )] pub struct Gadget(PhantomData); diff --git a/src/merkle_tree/constraints.rs b/src/merkle_tree/constraints.rs index 600d5026..d43c6dea 100644 --- a/src/merkle_tree/constraints.rs +++ b/src/merkle_tree/constraints.rs @@ -1,6 +1,9 @@ -use crate::{Gadget, crh::{CRHWithGadget, TwoToOneCRHGadget, TwoToOneCRHWithGadget}}; use crate::merkle_tree::{Config, Path}; use crate::CRHGadget; +use crate::{ + crh::{CRHWithGadget, TwoToOneCRHGadget, TwoToOneCRHWithGadget}, + Gadget, +}; use ark_ff::Field; use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::boolean::Boolean; @@ -29,9 +32,7 @@ impl, ConstraintF: Field> DigestVarConverter DigestVarConverter - for IdentityDigestConverter -{ +impl DigestVarConverter for IdentityDigestConverter { type Target = T; fn convert(from: &T) -> Result { @@ -162,8 +163,11 @@ where let left_hash = P::LeafToInnerVarConverter::convert(&left_hash)?; let right_hash = P::LeafToInnerVarConverter::convert(&right_hash)?; - let mut curr_hash = - Gadget::::evaluate(two_to_one_params, left_hash.borrow(), &right_hash.borrow())?; + let mut curr_hash = Gadget::::evaluate( + two_to_one_params, + left_hash.borrow(), + &right_hash.borrow(), + )?; // To traverse up a MT, we iterate over the path from bottom to top (i.e. in reverse) // At any given bit, the bit being 0 indicates our currently hashed value is the left, @@ -174,7 +178,8 @@ where let left_hash = bit.select(sibling, &curr_hash)?; let right_hash = bit.select(&curr_hash, sibling)?; - curr_hash = Gadget::::compress(two_to_one_params, &left_hash, &right_hash)?; + curr_hash = + Gadget::::compress(two_to_one_params, &left_hash, &right_hash)?; } Ok(curr_hash) diff --git a/src/merkle_tree/tests/constraints.rs b/src/merkle_tree/tests/constraints.rs index 68f8833c..7a4a3a59 100644 --- a/src/merkle_tree/tests/constraints.rs +++ b/src/merkle_tree/tests/constraints.rs @@ -1,9 +1,12 @@ mod byte_mt_tests { - use crate::{Gadget, crh::{pedersen, TwoToOneCRHScheme, TwoToOneCRHGadget}}; + use crate::{ + crh::{pedersen, TwoToOneCRHGadget, TwoToOneCRHScheme}, + Gadget, + }; use crate::merkle_tree::constraints::ConfigGadget; use crate::merkle_tree::{ByteDigestConverter, Config}; - use crate::{CRHScheme, CRHGadget, MerkleTree, PathVar}; + use crate::{CRHGadget, CRHScheme, MerkleTree, PathVar}; use ark_ed_on_bls12_381::{EdwardsProjective as JubJub, Fq}; #[allow(unused)] use ark_r1cs_std::prelude::*; @@ -88,12 +91,11 @@ mod byte_mt_tests { println!("constraints from digest: {}", constraints_from_digest); // Allocate Parameters for CRH - let leaf_crh_params_var = - as CRHGadget<_>>::ParametersVar::new_constant( - ark_relations::ns!(cs, "leaf_crh_parameter"), - &leaf_crh_params, - ) - .unwrap(); + let leaf_crh_params_var = as CRHGadget<_>>::ParametersVar::new_constant( + ark_relations::ns!(cs, "leaf_crh_parameter"), + &leaf_crh_params, + ) + .unwrap(); let two_to_one_crh_params_var = as TwoToOneCRHGadget<_>>::ParametersVar::new_constant( ark_relations::ns!(cs, "two_to_one_crh_parameter"), @@ -151,12 +153,11 @@ mod byte_mt_tests { if let Some(update_query) = update_query { let cs = ConstraintSystem::::new_ref(); // allocate parameters for CRH - let leaf_crh_params_var = - as CRHGadget<_>>::ParametersVar::new_constant( - ark_relations::ns!(cs, "leaf_crh_parameter"), - &leaf_crh_params, - ) - .unwrap(); + let leaf_crh_params_var = as CRHGadget<_>>::ParametersVar::new_constant( + ark_relations::ns!(cs, "leaf_crh_parameter"), + &leaf_crh_params, + ) + .unwrap(); let two_to_one_crh_params_var = as TwoToOneCRHGadget<_>>::ParametersVar::new_constant( ark_relations::ns!(cs, "two_to_one_crh_parameter"), @@ -230,10 +231,13 @@ mod byte_mt_tests { } mod field_mt_tests { - use crate::{Gadget, crh::{poseidon, TwoToOneCRHGadget}}; use crate::merkle_tree::constraints::ConfigGadget; use crate::merkle_tree::tests::test_utils::poseidon_parameters; use crate::merkle_tree::{Config, IdentityDigestConverter}; + use crate::{ + crh::{poseidon, TwoToOneCRHGadget}, + Gadget, + }; use crate::{CRHGadget, MerkleTree, PathVar}; use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::fields::fp::FpVar; @@ -257,7 +261,7 @@ mod field_mt_tests { impl ConfigGadget for FieldMTConfig { type LeafVar = LeafVar; - + type LeafToInnerVarConverter = IdentityDigestConverter; } @@ -395,11 +399,11 @@ mod field_mt_tests { let old_root_var = FpVar::new_input(cs.clone(), || Ok(old_root)).unwrap(); let old_path = tree.generate_proof(update_query.0).unwrap(); - let old_path_var = PathVar::::new_input( - ark_relations::ns!(cs, "old_path"), - || Ok(old_path), - ) - .unwrap(); + let old_path_var = + PathVar::::new_input(ark_relations::ns!(cs, "old_path"), || { + Ok(old_path) + }) + .unwrap(); let new_root = { tree.update(update_query.0, update_query.1.as_slice()) .unwrap(); diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index 00575f17..d8026435 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -27,7 +27,7 @@ mod bytes_mt_tests { impl Config for JubJubMerkleTreeParams { type Leaf = [u8]; - type LeafToInnerConverter = ByteDigestConverter; + type LeafToInnerConverter = ByteDigestConverter; type LeafHash = LeafH; type TwoToOneHash = CompressH; @@ -131,7 +131,7 @@ mod field_mt_tests { impl Config for FieldMTConfig { type Leaf = [F]; type LeafToInnerConverter = IdentityDigestConverter; - + type LeafHash = H; type TwoToOneHash = TwoToOneH; } diff --git a/src/prf/blake2s/constraints.rs b/src/prf/blake2s/constraints.rs index 99ecf937..b60c5e63 100644 --- a/src/prf/blake2s/constraints.rs +++ b/src/prf/blake2s/constraints.rs @@ -1,7 +1,7 @@ use ark_ff::PrimeField; use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError}; -use crate::{Vec, prf::PRFWithGadget}; +use crate::{prf::PRFWithGadget, Vec}; use ark_r1cs_std::prelude::*; use core::borrow::Borrow; @@ -373,7 +373,10 @@ impl PRFWithGadget for Blake2s { } #[tracing::instrument(target = "r1cs", skip(seed, input))] - fn evaluate_gadget(seed: &[UInt8], input: &[UInt8]) -> Result { + fn evaluate_gadget( + seed: &[UInt8], + input: &[UInt8], + ) -> Result { assert_eq!(seed.len(), 32); let input: Vec<_> = seed .iter() @@ -386,7 +389,6 @@ impl PRFWithGadget for Blake2s { .collect(); Ok(OutputVar(result)) } - } #[cfg(test)] @@ -394,7 +396,13 @@ mod test { use ark_ed_on_bls12_381::Fq as Fr; use ark_std::rand::Rng; - use crate::{Gadget, prf::{PRF, PRFWithGadget, blake2s::{constraints::evaluate_blake2s, Blake2s}}}; + use crate::{ + prf::{ + blake2s::{constraints::evaluate_blake2s, Blake2s}, + PRFWithGadget, PRF, + }, + Gadget, + }; use ark_relations::r1cs::ConstraintSystem; use blake2::VarBlake2s; diff --git a/src/prf/constraints.rs b/src/prf/constraints.rs index 81196a9e..1c112f5a 100644 --- a/src/prf/constraints.rs +++ b/src/prf/constraints.rs @@ -1,7 +1,7 @@ use ark_ff::Field; use core::fmt::Debug; -use crate::{Gadget, Vec, prf::PRF}; +use crate::{prf::PRF, Gadget, Vec}; use ark_relations::r1cs::{Namespace, SynthesisError}; use ark_r1cs_std::prelude::*; @@ -26,10 +26,7 @@ pub trait PRFWithGadget: PRF { } pub trait PRFGadget { - type Native: PRFWithGadget< - ConstraintF, - OutputVar = Self::OutputVar, - >; + type Native: PRFWithGadget; type OutputVar: EqGadget + ToBytesGadget + AllocVar<::Output, ConstraintF> @@ -51,7 +48,7 @@ pub trait PRFGadget { } } -impl PRFGadget for Gadget

+impl PRFGadget for Gadget

where P: PRFWithGadget, ConstraintF: Field, @@ -65,5 +62,4 @@ where ) -> Result { P::evaluate_gadget(seed, input) } - -} \ No newline at end of file +} diff --git a/src/signature/constraints.rs b/src/signature/constraints.rs index 65d71564..093781aa 100644 --- a/src/signature/constraints.rs +++ b/src/signature/constraints.rs @@ -2,7 +2,7 @@ use ark_ff::Field; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::SynthesisError; -use crate::{Gadget, signature::SignatureScheme}; +use crate::{signature::SignatureScheme, Gadget}; pub trait SigVerifyWithGadget: SignatureScheme { type ParametersVar: AllocVar + Clone; @@ -29,9 +29,13 @@ pub trait SigVerifyGadget { >; type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; - type PublicKeyVar: ToBytesGadget + AllocVar<::PublicKey, ConstraintF> + Clone; + type PublicKeyVar: ToBytesGadget + + AllocVar<::PublicKey, ConstraintF> + + Clone; - type SignatureVar: ToBytesGadget + AllocVar<::Signature, ConstraintF> + Clone; + type SignatureVar: ToBytesGadget + + AllocVar<::Signature, ConstraintF> + + Clone; fn verify( parameters: &Self::ParametersVar, @@ -44,7 +48,7 @@ pub trait SigVerifyGadget { } } -impl SigVerifyGadget for Gadget +impl SigVerifyGadget for Gadget where S: SigVerifyWithGadget, ConstraintF: Field, diff --git a/src/snark/constraints.rs b/src/snark/constraints.rs index 25f5a159..d84ec7da 100644 --- a/src/snark/constraints.rs +++ b/src/snark/constraints.rs @@ -98,7 +98,7 @@ pub trait SNARKWithGadget: SNARK { /// This implements constraints for SNARK verifiers. pub trait SNARKGadget { type Native: SNARKWithGadget< - F, + F, ConstraintF, VerifierSize = Self::VerifierSize, ProcessedVerifyingKeyVar = Self::ProcessedVerifyingKeyVar, @@ -106,7 +106,8 @@ pub trait SNARKGadget { InputVar = Self::InputVar, ProofVar = Self::ProofVar, >; - type ProcessedVerifyingKeyVar: AllocVar<>::ProcessedVerifyingKey, ConstraintF> + Clone; + type ProcessedVerifyingKeyVar: AllocVar<>::ProcessedVerifyingKey, ConstraintF> + + Clone; type VerifyingKeyVar: AllocVar<>::VerifyingKey, ConstraintF> + ToBytesGadget + Clone; @@ -182,9 +183,10 @@ pub trait SNARKGadget { } impl SNARKGadget for Gadget -where +where S: SNARKWithGadget, - F: PrimeField, ConstraintF: PrimeField + F: PrimeField, + ConstraintF: PrimeField, { type Native = S; type VerifierSize = S::VerifierSize; @@ -195,38 +197,43 @@ where } pub trait CircuitSpecificSetupSNARKGadget: - SNARKGadget + SNARKGadget where - Self::Native: CircuitSpecificSetupSNARK + Self::Native: CircuitSpecificSetupSNARK, { } impl CircuitSpecificSetupSNARKGadget for Gadget -where +where S: CircuitSpecificSetupSNARK + SNARKWithGadget, - F: PrimeField, - ConstraintF: PrimeField -{} + F: PrimeField, + ConstraintF: PrimeField, +{ +} pub trait UniversalSetupSNARKWithGadget: SNARKWithGadget + UniversalSetupSNARK { - type BoundCircuit: From<>::ComputationBound> + ConstraintSynthesizer + Clone; + type BoundCircuit: From<>::ComputationBound> + + ConstraintSynthesizer + + Clone; } pub trait UniversalSetupSNARKGadget: SNARKGadget where - Self::Native: UniversalSetupSNARKWithGadget + Self::Native: UniversalSetupSNARKWithGadget, { - type BoundCircuit: From<>::ComputationBound> + ConstraintSynthesizer + Clone; + type BoundCircuit: From<>::ComputationBound> + + ConstraintSynthesizer + + Clone; } impl UniversalSetupSNARKGadget for Gadget -where +where S: UniversalSetupSNARK + UniversalSetupSNARKWithGadget, - F: PrimeField, - ConstraintF: PrimeField + F: PrimeField, + ConstraintF: PrimeField, { type BoundCircuit = S::BoundCircuit; } From ffff4327f10a9bcea48ecf9b191ed2eac209a282 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 11:47:02 -0400 Subject: [PATCH 12/13] Rename `CRH` --- cp-benches/benches/crypto_primitives/crh.rs | 2 +- src/commitment/pedersen/mod.rs | 2 +- src/crh/bowe_hopwood/constraints.rs | 4 ++-- src/crh/bowe_hopwood/mod.rs | 8 ++++---- src/crh/constraints.rs | 15 +++++++-------- src/crh/injective_map/mod.rs | 10 +++++----- src/crh/mod.rs | 4 ++-- src/crh/pedersen/constraints.rs | 2 +- src/crh/pedersen/mod.rs | 6 +++--- src/crh/poseidon/constraints.rs | 20 ++++++++------------ src/crh/poseidon/mod.rs | 8 ++++---- src/lib.rs | 2 +- src/merkle_tree/mod.rs | 18 +++++++++--------- src/merkle_tree/tests/constraints.rs | 10 +++++----- src/merkle_tree/tests/mod.rs | 6 ++---- src/merkle_tree/tests/test_utils.rs | 3 --- 16 files changed, 55 insertions(+), 65 deletions(-) diff --git a/cp-benches/benches/crypto_primitives/crh.rs b/cp-benches/benches/crypto_primitives/crh.rs index 12635650..46879cc4 100644 --- a/cp-benches/benches/crypto_primitives/crh.rs +++ b/cp-benches/benches/crypto_primitives/crh.rs @@ -3,7 +3,7 @@ extern crate criterion; use ark_crypto_primitives::crh::{ pedersen::{Window, CRH as PedersenCRH}, - CRHScheme, + CRH, }; use ark_ed_on_bls12_377::EdwardsProjective as Edwards; use criterion::Criterion; diff --git a/src/commitment/pedersen/mod.rs b/src/commitment/pedersen/mod.rs index 959d9790..7d216b37 100644 --- a/src/commitment/pedersen/mod.rs +++ b/src/commitment/pedersen/mod.rs @@ -1,4 +1,4 @@ -use crate::{CRHScheme, Error, Vec}; +use crate::{Error, Vec, CRH}; use ark_ec::ProjectiveCurve; use ark_ff::{bytes::ToBytes, BitIteratorLE, Field, FpParameters, PrimeField, ToConstraintField}; use ark_std::io::{Result as IoResult, Write}; diff --git a/src/crh/bowe_hopwood/constraints.rs b/src/crh/bowe_hopwood/constraints.rs index ac0561ef..3209549b 100644 --- a/src/crh/bowe_hopwood/constraints.rs +++ b/src/crh/bowe_hopwood/constraints.rs @@ -153,9 +153,9 @@ where mod test { use ark_std::rand::Rng; - use crate::crh::{pedersen, TwoToOneCRHGadget, TwoToOneCRHScheme}; + use crate::crh::{pedersen, TwoToOneCRH, TwoToOneCRHGadget}; use crate::{crh::bowe_hopwood, Gadget}; - use crate::{CRHGadget, CRHScheme}; + use crate::{CRHGadget, CRH}; use ark_ed_on_bls12_381::{EdwardsParameters, Fq as Fr}; use ark_r1cs_std::{alloc::AllocVar, uint8::UInt8, R1CSVar}; use ark_relations::r1cs::{ConstraintSystem, ConstraintSystemRef}; diff --git a/src/crh/bowe_hopwood/mod.rs b/src/crh/bowe_hopwood/mod.rs index 367ae6d5..dc33de89 100644 --- a/src/crh/bowe_hopwood/mod.rs +++ b/src/crh/bowe_hopwood/mod.rs @@ -12,7 +12,7 @@ use ark_std::{ use rayon::prelude::*; use super::pedersen; -use crate::crh::{CRHScheme, TwoToOneCRHScheme}; +use crate::crh::{TwoToOneCRH as TwoToOneCRHTrait, CRH as CRHTrait}; use ark_ec::{ twisted_edwards_extended::GroupProjective as TEProjective, ProjectiveCurve, TEModelParameters, }; @@ -72,7 +72,7 @@ impl TwoToOneCRH { } } -impl CRHScheme for CRH { +impl CRHTrait for CRH { type Input = [u8]; type Output = P::BaseField; @@ -186,7 +186,7 @@ impl CRHScheme for CRH { } } -impl TwoToOneCRHScheme for TwoToOneCRH { +impl TwoToOneCRHTrait for TwoToOneCRH { type Input = [u8]; type Output = P::BaseField; @@ -253,7 +253,7 @@ impl Debug for Parameters

{ mod test { use crate::{ crh::{bowe_hopwood, pedersen::Window}, - CRHScheme, + CRH, }; use ark_ed_on_bls12_381::EdwardsParameters; use ark_std::test_rng; diff --git a/src/crh/constraints.rs b/src/crh/constraints.rs index a516b884..e64147bf 100644 --- a/src/crh/constraints.rs +++ b/src/crh/constraints.rs @@ -2,14 +2,14 @@ use ark_ff::Field; use core::fmt::Debug; use crate::{ - crh::{CRHScheme, TwoToOneCRHScheme}, + crh::{TwoToOneCRH, CRH}, Gadget, }; use ark_relations::r1cs::SynthesisError; use ark_r1cs_std::prelude::*; -pub trait CRHWithGadget: CRHScheme { +pub trait CRHWithGadget: CRH { type InputVar: ?Sized; type OutputVar: EqGadget + ToBytesGadget @@ -38,12 +38,12 @@ pub trait CRHGadget { type OutputVar: EqGadget + ToBytesGadget + CondSelectGadget - + AllocVar<::Output, ConstraintF> + + AllocVar<::Output, ConstraintF> + R1CSVar + Debug + Clone + Sized; - type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; + type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; fn evaluate( parameters: &Self::ParametersVar, @@ -53,7 +53,7 @@ pub trait CRHGadget { } } -pub trait TwoToOneCRHWithGadget: TwoToOneCRHScheme { +pub trait TwoToOneCRHWithGadget: TwoToOneCRH { type InputVar: ?Sized; type OutputVar: EqGadget + ToBytesGadget @@ -89,14 +89,13 @@ pub trait TwoToOneCRHGadget { type OutputVar: EqGadget + ToBytesGadget + CondSelectGadget - + AllocVar<::Output, ConstraintF> + + AllocVar<::Output, ConstraintF> + R1CSVar + Debug + Clone + Sized; - type ParametersVar: AllocVar<::Parameters, ConstraintF> - + Clone; + type ParametersVar: AllocVar<::Parameters, ConstraintF> + Clone; fn evaluate( parameters: &Self::ParametersVar, diff --git a/src/crh/injective_map/mod.rs b/src/crh/injective_map/mod.rs index efca7c0b..9d483673 100644 --- a/src/crh/injective_map/mod.rs +++ b/src/crh/injective_map/mod.rs @@ -3,7 +3,7 @@ use ark_ff::bytes::ToBytes; use ark_std::rand::Rng; use ark_std::{fmt::Debug, hash::Hash, marker::PhantomData}; -use super::{pedersen, CRHScheme, TwoToOneCRHScheme}; +use super::{pedersen, TwoToOneCRH, CRH}; use ark_ec::{ models::{ModelParameters, TEModelParameters}, twisted_edwards_extended::{GroupAffine as TEAffine, GroupProjective as TEProjective}, @@ -45,10 +45,10 @@ pub struct PedersenCRHCompressor, W: pede _window: PhantomData, } -impl, W: pedersen::Window> CRHScheme +impl, W: pedersen::Window> CRH for PedersenCRHCompressor { - type Input = as CRHScheme>::Input; + type Input = as CRH>::Input; type Output = I::Output; type Parameters = pedersen::Parameters; @@ -80,10 +80,10 @@ pub struct PedersenTwoToOneCRHCompressor< _window: PhantomData, } -impl, W: pedersen::Window> TwoToOneCRHScheme +impl, W: pedersen::Window> TwoToOneCRH for PedersenTwoToOneCRHCompressor { - type Input = as TwoToOneCRHScheme>::Input; + type Input = as TwoToOneCRH>::Input; type Output = I::Output; type Parameters = pedersen::Parameters; diff --git a/src/crh/mod.rs b/src/crh/mod.rs index 64bf6d6a..63ed3881 100644 --- a/src/crh/mod.rs +++ b/src/crh/mod.rs @@ -20,7 +20,7 @@ pub use constraints::*; /// Interface to CRH. Note that in this release, while all implementations of `CRH` have fixed length, /// variable length CRH may also implement this trait in future. -pub trait CRHScheme { +pub trait CRH { type Input: ?Sized; type Output: ToBytes + Clone @@ -40,7 +40,7 @@ pub trait CRHScheme { } /// CRH used by merkle tree inner hash. Merkle tree will convert leaf output to bytes first. -pub trait TwoToOneCRHScheme { +pub trait TwoToOneCRH { /// Raw Input type of TwoToOneCRH type Input: ?Sized; /// Raw Output type of TwoToOneCRH diff --git a/src/crh/pedersen/constraints.rs b/src/crh/pedersen/constraints.rs index 15170acb..f86e63c9 100644 --- a/src/crh/pedersen/constraints.rs +++ b/src/crh/pedersen/constraints.rs @@ -119,7 +119,7 @@ where #[cfg(test)] mod test { use crate::{ - crh::{pedersen, CRHGadget, CRHScheme, TwoToOneCRHGadget, TwoToOneCRHScheme}, + crh::{pedersen, CRHGadget, TwoToOneCRH, TwoToOneCRHGadget, CRH}, Gadget, }; use ark_ec::ProjectiveCurve; diff --git a/src/crh/pedersen/mod.rs b/src/crh/pedersen/mod.rs index 4bf64eb4..70f1a763 100644 --- a/src/crh/pedersen/mod.rs +++ b/src/crh/pedersen/mod.rs @@ -7,7 +7,7 @@ use ark_std::{ #[cfg(feature = "parallel")] use rayon::prelude::*; -use crate::crh::{CRHScheme, TwoToOneCRHScheme}; +use crate::crh::{TwoToOneCRH as TwoToOneCRHTrait, CRH as CRHTrait}; use ark_ec::ProjectiveCurve; use ark_ff::{Field, ToConstraintField}; use ark_serialize::CanonicalSerialize; @@ -53,7 +53,7 @@ impl CRH { } } -impl CRHScheme for CRH { +impl CRHTrait for CRH { type Input = [u8]; type Output = C::Affine; type Parameters = Parameters; @@ -143,7 +143,7 @@ impl TwoToOneCRH { } } -impl TwoToOneCRHScheme for TwoToOneCRH { +impl TwoToOneCRHTrait for TwoToOneCRH { type Input = [u8]; type Output = C::Affine; type Parameters = Parameters; diff --git a/src/crh/poseidon/constraints.rs b/src/crh/poseidon/constraints.rs index ac42dbc2..18dbc11d 100644 --- a/src/crh/poseidon/constraints.rs +++ b/src/crh/poseidon/constraints.rs @@ -1,6 +1,6 @@ use crate::crh::poseidon::{TwoToOneCRH, CRH}; -use crate::crh::{CRHWithGadget, TwoToOneCRHWithGadget}; -use crate::{CRHScheme, Vec}; +use crate::crh::{CRHWithGadget, TwoToOneCRHWithGadget, CRH as _}; +use crate::Vec; use ark_ff::PrimeField; use ark_r1cs_std::alloc::{AllocVar, AllocationMode}; use ark_r1cs_std::fields::fp::FpVar; @@ -31,7 +31,7 @@ impl CRHWithGadget for CRH { if cs.is_none() { let input = input.iter().map(|f| f.value().unwrap()).collect::>(); Ok(FpVar::Constant( - as CRHScheme>::evaluate(¶meters.parameters, input).unwrap(), + CRH::::evaluate(¶meters.parameters, input).unwrap(), )) } else { let mut sponge = PoseidonSpongeVar::new(cs, ¶meters.parameters); @@ -64,11 +64,8 @@ impl TwoToOneCRHWithGadget for TwoToOneCRH { if cs.is_none() { Ok(FpVar::Constant( - as CRHScheme>::evaluate( - ¶meters.parameters, - vec![left.value()?, right.value()?], - ) - .unwrap(), + CRH::::evaluate(¶meters.parameters, vec![left.value()?, right.value()?]) + .unwrap(), )) } else { let mut sponge = PoseidonSpongeVar::new(cs, ¶meters.parameters); @@ -96,10 +93,9 @@ impl AllocVar, F> for CRHParameter #[cfg(test)] mod test { - use crate::crh::poseidon::{TwoToOneCRH, CRH}; - use crate::crh::{TwoToOneCRHGadget, TwoToOneCRHScheme}; - use crate::{crh::poseidon::constraints::CRHParametersVar, Gadget}; - use crate::{CRHGadget, CRHScheme}; + use crate::crh::poseidon::{constraints::CRHParametersVar, TwoToOneCRH, CRH}; + use crate::crh::{CRHGadget, TwoToOneCRH as _, TwoToOneCRHGadget, CRH as _}; + use crate::Gadget; use ark_bls12_377::Fr; use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::{ diff --git a/src/crh/poseidon/mod.rs b/src/crh/poseidon/mod.rs index 6bab9a09..3bc80eb3 100644 --- a/src/crh/poseidon/mod.rs +++ b/src/crh/poseidon/mod.rs @@ -1,5 +1,5 @@ -use crate::crh::TwoToOneCRHScheme; -use crate::{CRHScheme, Error}; +use crate::crh::{TwoToOneCRH as TwoToOneCRHTrait, CRH as CRHTrait}; +use crate::Error; use ark_ff::PrimeField; use ark_sponge::poseidon::{PoseidonParameters, PoseidonSponge}; use ark_sponge::{Absorb, CryptographicSponge}; @@ -14,7 +14,7 @@ pub struct CRH { field_phantom: PhantomData, } -impl CRHScheme for CRH { +impl CRHTrait for CRH { type Input = [F]; type Output = F; type Parameters = PoseidonParameters; @@ -42,7 +42,7 @@ pub struct TwoToOneCRH { field_phantom: PhantomData, } -impl TwoToOneCRHScheme for TwoToOneCRH { +impl TwoToOneCRHTrait for TwoToOneCRH { type Input = F; type Output = F; type Parameters = PoseidonParameters; diff --git a/src/lib.rs b/src/lib.rs index 45c37d5d..ec96b622 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ pub mod snark; pub use self::{ commitment::CommitmentScheme, - crh::CRHScheme, + crh::CRH, merkle_tree::{MerkleTree, Path}, prf::PRF, signature::SignatureScheme, diff --git a/src/merkle_tree/mod.rs b/src/merkle_tree/mod.rs index 2cdad97b..fe4b9eff 100644 --- a/src/merkle_tree/mod.rs +++ b/src/merkle_tree/mod.rs @@ -1,8 +1,8 @@ #![allow(clippy::needless_range_loop)] -use crate::CRHScheme; +use crate::CRH; /// Defines a trait to chain two types of CRHs. -use crate::{crh::TwoToOneCRHScheme, Error}; +use crate::{crh::TwoToOneCRH, Error}; use ark_ff::ToBytes; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write}; use ark_std::borrow::Borrow; @@ -54,21 +54,21 @@ pub trait Config { // Tom's Note: in the future, if we want different hash function, we can simply add more // types of digest here and specify a digest converter. Same for constraints. - type LeafHash: CRHScheme; + type LeafHash: CRH; /// 2 inner digest -> inner digest - type TwoToOneHash: TwoToOneCRHScheme; + type TwoToOneHash: TwoToOneCRH; type LeafToInnerConverter: DigestConverter< LeafDigest, - ::Input, + ::Input, >; } -pub type LeafDigest = <::LeafHash as CRHScheme>::Output; -pub type TwoToOneDigest = <::TwoToOneHash as TwoToOneCRHScheme>::Output; +pub type LeafDigest = <::LeafHash as CRH>::Output; +pub type TwoToOneDigest = <::TwoToOneHash as TwoToOneCRH>::Output; -pub type TwoToOneParams

= <

::TwoToOneHash as TwoToOneCRHScheme>::Parameters; -pub type LeafParams

= <

::LeafHash as CRHScheme>::Parameters; +pub type TwoToOneParams

= <

::TwoToOneHash as TwoToOneCRH>::Parameters; +pub type LeafParams

= <

::LeafHash as CRH>::Parameters; /// Stores the hashes of a particular path (in order) from root to leaf. /// For example: diff --git a/src/merkle_tree/tests/constraints.rs b/src/merkle_tree/tests/constraints.rs index 26480104..c9812987 100644 --- a/src/merkle_tree/tests/constraints.rs +++ b/src/merkle_tree/tests/constraints.rs @@ -1,12 +1,12 @@ mod byte_mt_tests { use crate::{ - crh::{pedersen, TwoToOneCRHGadget, TwoToOneCRHScheme}, + crh::{pedersen, TwoToOneCRH, TwoToOneCRHGadget}, Gadget, }; use crate::merkle_tree::constraints::ConfigGadget; use crate::merkle_tree::{ByteDigestConverter, Config}; - use crate::{CRHGadget, CRHScheme, MerkleTree, PathVar}; + use crate::{CRHGadget, MerkleTree, PathVar, CRH}; use ark_ed_on_bls12_381::{EdwardsProjective as JubJub, Fq}; #[allow(unused)] use ark_r1cs_std::prelude::*; @@ -53,8 +53,8 @@ mod byte_mt_tests { ) -> () { let mut rng = ark_std::test_rng(); - let leaf_crh_params = ::setup(&mut rng).unwrap(); - let two_to_one_crh_params = ::setup(&mut rng).unwrap(); + let leaf_crh_params = ::setup(&mut rng).unwrap(); + let two_to_one_crh_params = ::setup(&mut rng).unwrap(); let mut tree = JubJubMerkleTree::new( &leaf_crh_params, &two_to_one_crh_params, @@ -79,7 +79,7 @@ mod byte_mt_tests { ark_relations::ns!(cs, "new_digest"), || { if use_bad_root { - Ok(::Output::default()) + Ok(::Output::default()) } else { Ok(root) } diff --git a/src/merkle_tree/tests/mod.rs b/src/merkle_tree/tests/mod.rs index d8026435..24a89644 100644 --- a/src/merkle_tree/tests/mod.rs +++ b/src/merkle_tree/tests/mod.rs @@ -41,10 +41,8 @@ mod bytes_mt_tests { .iter() .map(|leaf| crate::to_unchecked_bytes!(leaf).unwrap()) .collect(); - let leaf_crh_params = ::setup(&mut rng).unwrap(); - let two_to_one_params = ::setup(&mut rng) - .unwrap() - .clone(); + let leaf_crh_params = ::setup(&mut rng).unwrap(); + let two_to_one_params = ::setup(&mut rng).unwrap().clone(); let mut tree = JubJubMerkleTree::new( &leaf_crh_params.clone(), &two_to_one_params.clone(), diff --git a/src/merkle_tree/tests/test_utils.rs b/src/merkle_tree/tests/test_utils.rs index 1c847c6c..177f3e16 100644 --- a/src/merkle_tree/tests/test_utils.rs +++ b/src/merkle_tree/tests/test_utils.rs @@ -653,6 +653,3 @@ pub(crate) fn poseidon_parameters() -> PoseidonParameters::new(full_rounds, partial_rounds, alpha, mds, ark) } - -#[cfg(feature = "r1cs")] -mod constraints {} From 58630302e454d826b282f600c5d587b73ce8587e Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Thu, 7 Oct 2021 12:20:17 -0400 Subject: [PATCH 13/13] Add TODOs for rate and capacity --- src/crh/poseidon/constraints.rs | 1 + src/merkle_tree/tests/test_utils.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/crh/poseidon/constraints.rs b/src/crh/poseidon/constraints.rs index 18dbc11d..2486f0d3 100644 --- a/src/crh/poseidon/constraints.rs +++ b/src/crh/poseidon/constraints.rs @@ -134,6 +134,7 @@ mod test { test_b.push(Fr::rand(&mut test_rng)); } + // TODO: figure out appropriate rate and capacity let params = PoseidonParameters::::new(8, 24, 31, mds, ark); let crh_a = CRH::::evaluate(¶ms, test_a.clone()).unwrap(); let crh_b = CRH::::evaluate(¶ms, test_b.clone()).unwrap(); diff --git a/src/merkle_tree/tests/test_utils.rs b/src/merkle_tree/tests/test_utils.rs index 177f3e16..242adfc4 100644 --- a/src/merkle_tree/tests/test_utils.rs +++ b/src/merkle_tree/tests/test_utils.rs @@ -651,5 +651,6 @@ pub(crate) fn poseidon_parameters() -> PoseidonParameters::new(full_rounds, partial_rounds, alpha, mds, ark) }