From 80d97d69b5143aad6d7093d73baf30066571d594 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Wed, 19 Oct 2022 21:26:26 +0200 Subject: [PATCH] Add BlindSigVerifyCircuit w generate_constraints & CS test --- src/constraints.rs | 135 ++++++++++++++++++++++++++++++++++++++------- src/lib.rs | 26 ++++----- 2 files changed, 126 insertions(+), 35 deletions(-) diff --git a/src/constraints.rs b/src/constraints.rs index 125bdc8..6fceb7a 100644 --- a/src/constraints.rs +++ b/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 @@ where for i in 0..s_bytes.len() { s.push(UInt8::>::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 @@ where ) -> Result { 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 @@ where } } +// example of circuit using BlindSigVerifyGadget +#[derive(Clone)] +pub struct BlindSigVerifyCircuit>> +where + ::BaseField: PrimeField, +{ + _group: PhantomData<*const GC>, + pub params: Parameters, + pub poseidon_hash_native: poseidon_native::Poseidon>, + pub signature: Option>, + pub pub_key: Option>, + pub message: Option>, +} + +impl>> ConstraintSynthesizer> + for BlindSigVerifyCircuit +where + C: ProjectiveCurve, + GC: CurveVar>, + for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, + ark_r1cs_std::groups::curves::twisted_edwards::AffineVar< + EdwardsParameters, + FpVar>, + >: From, + ::BaseField: PrimeField, + FpVar<::BaseField>: Mul>>, + FpVar<::BaseField>: From>>, +{ + #[tracing::instrument(target = "r1cs", skip(self, cs))] + fn generate_constraints( + self, + cs: ConstraintSystemRef>, + ) -> Result<(), SynthesisError> { + let parameters = + ParametersVar::new_constant(ark_relations::ns!(cs, "parameters"), &self.params)?; + + let pub_key = + PublicKeyVar::::new_input(ark_relations::ns!(cs, "public key"), || { + self.pub_key.ok_or(SynthesisError::AssignmentMissing) + })?; + let m = FpVar::>::new_input(ark_relations::ns!(cs, "message"), || { + self.message.ok_or(SynthesisError::AssignmentMissing) + })?; + let signature = + SignatureVar::::new_witness(ark_relations::ns!(cs, "signature"), || { + self.signature.ok_or(SynthesisError::AssignmentMissing) + })?; + let poseidon_hash = PoseidonGadget::>::from_native( + &mut cs.clone(), + self.poseidon_hash_native, + ) + .unwrap(); + + let v = BlindSigVerifyGadget::::verify( + ¶meters, + &poseidon_hash, + m, + &signature, + &pub_key, + )?; + v.enforce_equal(&Boolean::TRUE) + } +} + #[cfg(test)] mod test { use super::*; @@ -208,13 +269,15 @@ mod test { // type Fr = ::ScalarField; type S = BlindSigScheme; - #[test] - fn test_verify() { - let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 3); - let poseidon_hash = poseidon::Poseidon::new(poseidon_params); + fn generate_native_data( + poseidon_hash: &poseidon::Poseidon, + ) -> ( + Parameters, + PublicKey, + Fq, + Signature, + ) { 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 @@ mod test { 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::(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; @@ -250,4 +323,28 @@ mod test { valid_sig.enforce_equal(&Boolean::::TRUE).unwrap(); assert!(cs.is_satisfied().unwrap()); } + + #[test] + fn test_constraint_system() { + let poseidon_params = poseidon_setup_params::(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:: { + params, + poseidon_hash_native: poseidon_hash, + signature: Some(s), + pub_key: Some(pk), + message: Some(m), + _group: PhantomData, + }; + let cs = ConstraintSystem::::new_ref(); + circuit.generate_constraints(cs.clone()).unwrap(); + let is_satisfied = cs.is_satisfied().unwrap(); + assert!(is_satisfied); + println!("num_cnstraints={:?}", cs.num_constraints()); + } } diff --git a/src/lib.rs b/src/lib.rs index c4b303b..c141b16 100644 --- a/src/lib.rs +++ b/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 = <::BaseField as Field>::BasePrimeField; pub type SecretKey = ::ScalarField; @@ -51,8 +43,8 @@ pub struct UserSecretData { impl UserSecretData { fn new_empty(parameters: &Parameters) -> 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 @@ where 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 @@ pub fn poseidon_setup_params( #[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