Add BlindSigVerifyCircuit w generate_constraints & CS test
arnaucube root@arnaucube.com
Wed, 19 Oct 2022 21:26:26 +0200
2 files changed,
126 insertions(+),
35 deletions(-)
M
src/constraints.rs
→
src/constraints.rs
@@ -1,31 +1,28 @@
use crate::{Parameters, PublicKey, Signature}; -use ark_ec::{AffineCurve, ProjectiveCurve}; +use ark_ec::ProjectiveCurve; use ark_ed_on_bn254::{constraints::EdwardsVar, EdwardsParameters, FqParameters}; -use ark_ff::{ - fields::{Field, Fp256}, - to_bytes, PrimeField, ToConstraintField, -}; +use ark_ff::{fields::Fp256, to_bytes, PrimeField}; use ark_r1cs_std::{ alloc::{AllocVar, AllocationMode}, bits::uint8::UInt8, boolean::Boolean, eq::EqGadget, - fields::{fp::FpVar, FieldVar}, - groups::{curves::twisted_edwards::AffineVar, GroupOpsBounds}, + fields::fp::FpVar, + groups::GroupOpsBounds, prelude::CurveVar, ToBitsGadget, }; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, Namespace, SynthesisError}; -use ark_std::ops::{Add, Mul}; +use ark_std::ops::Mul; use core::{borrow::Borrow, marker::PhantomData}; use derivative::Derivative; // hash use arkworks_native_gadgets::poseidon as poseidon_native; -use arkworks_r1cs_gadgets::poseidon; -use arkworks_r1cs_gadgets::poseidon::{FieldHasherGadget, PoseidonGadget, PoseidonParametersVar}; +// use arkworks_r1cs_gadgets::poseidon; +use arkworks_r1cs_gadgets::poseidon::{FieldHasherGadget, PoseidonGadget}; use crate::ConstraintF;@@ -95,12 +92,12 @@ let s_bytes = to_bytes![val.borrow().s].unwrap();
for i in 0..s_bytes.len() { s.push(UInt8::<ConstraintF<C>>::new_variable( cs.clone(), - || Ok(s_bytes[i].clone()), + || Ok(s_bytes[i]), mode, )?); } - let r = GC::new_variable(cs.clone(), || Ok(val.borrow().r), mode)?; + let r = GC::new_variable(cs, || Ok(val.borrow().r), mode)?; Ok(Self { s,@@ -133,7 +130,7 @@ mode: AllocationMode,
) -> Result<Self, SynthesisError> { f().and_then(|val| { let cs = cs.into(); - let generator = GC::new_variable(cs.clone(), || Ok(val.borrow().generator), mode)?; + let generator = GC::new_variable(cs, || Ok(val.borrow().generator), mode)?; Ok(Self { generator, _curve: PhantomData,@@ -192,6 +189,70 @@ sG.is_eq(&RHS)
} } +// example of circuit using BlindSigVerifyGadget +#[derive(Clone)] +pub struct BlindSigVerifyCircuit<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>> +where + <C as ProjectiveCurve>::BaseField: PrimeField, +{ + _group: PhantomData<*const GC>, + pub params: Parameters<C>, + pub poseidon_hash_native: poseidon_native::Poseidon<ConstraintF<C>>, + pub signature: Option<Signature<C>>, + pub pub_key: Option<PublicKey<C>>, + pub message: Option<ConstraintF<C>>, +} + +impl<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>> ConstraintSynthesizer<ConstraintF<C>> + for BlindSigVerifyCircuit<C, GC> +where + C: ProjectiveCurve, + GC: CurveVar<C, ConstraintF<C>>, + for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, + ark_r1cs_std::groups::curves::twisted_edwards::AffineVar< + EdwardsParameters, + FpVar<Fp256<FqParameters>>, + >: From<GC>, + <C as ProjectiveCurve>::BaseField: PrimeField, + FpVar<<C as ProjectiveCurve>::BaseField>: Mul<FpVar<Fp256<FqParameters>>>, + FpVar<<C as ProjectiveCurve>::BaseField>: From<FpVar<Fp256<FqParameters>>>, +{ + #[tracing::instrument(target = "r1cs", skip(self, cs))] + fn generate_constraints( + self, + cs: ConstraintSystemRef<ConstraintF<C>>, + ) -> Result<(), SynthesisError> { + let parameters = + ParametersVar::new_constant(ark_relations::ns!(cs, "parameters"), &self.params)?; + + let pub_key = + PublicKeyVar::<C, GC>::new_input(ark_relations::ns!(cs, "public key"), || { + self.pub_key.ok_or(SynthesisError::AssignmentMissing) + })?; + let m = FpVar::<ConstraintF<C>>::new_input(ark_relations::ns!(cs, "message"), || { + self.message.ok_or(SynthesisError::AssignmentMissing) + })?; + let signature = + SignatureVar::<C, GC>::new_witness(ark_relations::ns!(cs, "signature"), || { + self.signature.ok_or(SynthesisError::AssignmentMissing) + })?; + let poseidon_hash = PoseidonGadget::<ConstraintF<C>>::from_native( + &mut cs.clone(), + self.poseidon_hash_native, + ) + .unwrap(); + + let v = BlindSigVerifyGadget::<C, GC>::verify( + ¶meters, + &poseidon_hash, + m, + &signature, + &pub_key, + )?; + v.enforce_equal(&Boolean::TRUE) + } +} + #[cfg(test)] mod test { use super::*;@@ -208,13 +269,15 @@ type Fq = <BabyJubJub as ProjectiveCurve>::BaseField;
// type Fr = <BabyJubJub as ProjectiveCurve>::ScalarField; type S = BlindSigScheme<BabyJubJub>; - #[test] - fn test_verify() { - let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 3); - let poseidon_hash = poseidon::Poseidon::new(poseidon_params); + fn generate_native_data( + poseidon_hash: &poseidon::Poseidon<Fq>, + ) -> ( + Parameters<BabyJubJub>, + PublicKey<BabyJubJub>, + Fq, + Signature<BabyJubJub>, + ) { let mut rng = ark_std::test_rng(); - - // create signature using native-rust lib let params = S::setup(); let (pk, sk) = S::keygen(¶ms, &mut rng); let (k, signer_r) = S::new_request_params(¶ms, &mut rng);@@ -224,6 +287,16 @@ let s_blinded = S::blind_sign(sk, k, m_blinded);
let s = S::unblind(s_blinded, u); let verified = S::verify(¶ms, &poseidon_hash, m, s.clone(), pk); assert!(verified); + (params, pk, m, s) + } + + #[test] + fn test_verify() { + let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 3); + let poseidon_hash = poseidon::Poseidon::new(poseidon_params); + + // create signature using native-rust lib + let (params, pk, m, s) = generate_native_data(&poseidon_hash); // use the constraint system to verify the signature type SG = BlindSigVerifyGadget<BabyJubJub, BabyJubJubVar>;@@ -249,5 +322,29 @@ )
.unwrap(); valid_sig.enforce_equal(&Boolean::<Fq>::TRUE).unwrap(); assert!(cs.is_satisfied().unwrap()); + } + + #[test] + fn test_constraint_system() { + let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 3); + let poseidon_hash = poseidon::Poseidon::new(poseidon_params); + + // create signature using native-rust lib + let (params, pk, m, s) = generate_native_data(&poseidon_hash); + + // use the constraint system to verify the signature + let circuit = BlindSigVerifyCircuit::<BabyJubJub, BabyJubJubVar> { + params, + poseidon_hash_native: poseidon_hash, + signature: Some(s), + pub_key: Some(pk), + message: Some(m), + _group: PhantomData, + }; + let cs = ConstraintSystem::<Fq>::new_ref(); + circuit.generate_constraints(cs.clone()).unwrap(); + let is_satisfied = cs.is_satisfied().unwrap(); + assert!(is_satisfied); + println!("num_cnstraints={:?}", cs.num_constraints()); } }
M
src/lib.rs
→
src/lib.rs
@@ -4,31 +4,23 @@
// #[cfg(feature="r1cs")] pub mod constraints; -use ark_ec::{ - models::twisted_edwards_extended::GroupAffine, AffineCurve, ProjectiveCurve, TEModelParameters, -}; +use ark_ec::{models::twisted_edwards_extended::GroupAffine, AffineCurve, ProjectiveCurve}; -use ark_ff::{ - to_bytes, BigInteger, BigInteger256, Field, Fp256, FpParameters, FromBytes, One, PrimeField, - Zero, -}; +use ark_ff::{to_bytes, BigInteger256, Field, FpParameters, PrimeField}; use ark_std::marker::PhantomData; -use ark_std::rand::{CryptoRng, RngCore}; -use ark_std::{ops::Mul, rand::Rng, UniformRand}; +use ark_std::{rand::Rng, UniformRand}; use derivative::Derivative; // hash use arkworks_native_gadgets::poseidon; use arkworks_native_gadgets::poseidon::FieldHasher; use arkworks_utils::{ - bytes_matrix_to_f, bytes_vec_to_f, parse_vec, poseidon_params::setup_poseidon_params, Curve, + bytes_matrix_to_f, bytes_vec_to_f, poseidon_params::setup_poseidon_params, Curve, }; // WIP -use ark_ed_on_bn254::{ - EdwardsAffine, EdwardsParameters, EdwardsProjective, FqParameters, Fr, FrParameters, -}; +use ark_ed_on_bn254::{EdwardsAffine, EdwardsParameters}; pub type ConstraintF<C> = <<C as ProjectiveCurve>::BaseField as Field>::BasePrimeField; pub type SecretKey<C> = <C as ProjectiveCurve>::ScalarField;@@ -51,8 +43,8 @@ }
impl<C: ProjectiveCurve> UserSecretData<C> { fn new_empty(parameters: &Parameters<C>) -> Self { UserSecretData { - a: C::ScalarField::from(0 as u32), - b: C::ScalarField::from(0 as u32), + a: C::ScalarField::from(0_u32), + b: C::ScalarField::from(0_u32), r: parameters.generator, // WIP } }@@ -154,7 +146,8 @@ // TODO hash(m) must be \in Fr
let hm = poseidon_hash.hash(&[m])?; // let hm_fr = C::ScalarField::from_repr(hm.into_repr()).unwrap(); let hm_fr = C::ScalarField::from_le_bytes_mod_order(&to_bytes!(hm)?); // WIP TMP - let m_blinded = C::ScalarField::from(u.a.inverse().unwrap() * x_fr) * hm_fr; + let m_blinded = u.a.inverse().unwrap() * x_fr * hm_fr; + // let m_blinded = C::ScalarField::from(u.a.inverse().unwrap() * x_fr) * hm_fr; Ok((m_blinded, u)) }@@ -223,6 +216,7 @@
#[cfg(test)] mod tests { use super::*; + use ark_ed_on_bn254::EdwardsProjective; pub type Fq = ark_ed_on_bn254::Fq; // base field // pub type Fr = ark_ed_on_bn254::Fr; // scalar field