diff --git a/src/constraints.rs b/src/constraints.rs index 0814fd4..c629ed0 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -35,7 +35,7 @@ pub struct PublicKeyVar>> where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { - pub_key: GC, + pub pub_key: GC, #[doc(hidden)] _group: PhantomData<*const C>, } @@ -59,31 +59,43 @@ where } } -// TODO parametrize Msg & MsgVar length - #[derive(Clone, Default, Debug)] -// pub struct Msg(pub Vec>); -pub struct Msg(pub [ConstraintF; 3]); +pub struct Msg(pub [ConstraintF; 3]); #[derive(Derivative)] #[derivative( Debug(bound = "C: ProjectiveCurve, GC: CurveVar>"), Clone(bound = "C: ProjectiveCurve, GC: CurveVar>") )] -pub struct MsgVar>> +pub struct MsgVar>> where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { - m: [FpVar>; 3], + m: [FpVar>; MSG_LEN], _gc: PhantomData, } -impl AllocVar, ConstraintF> for MsgVar +impl MsgVar where C: ProjectiveCurve, GC: CurveVar>, for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { - fn new_variable>>( + pub fn new(m: [FpVar>; MSG_LEN]) -> Self { + Self { + m, + _gc: PhantomData, + } + } +} + +impl AllocVar, ConstraintF> + for MsgVar +where + C: ProjectiveCurve, + GC: CurveVar>, + for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, +{ + fn new_variable>>( cs: impl Into>>, f: impl FnOnce() -> Result, mode: AllocationMode, @@ -91,9 +103,21 @@ where f().and_then(|m| { let m = m.borrow(); let cs = cs.into(); - let msg: Vec>> = Vec::new_variable(cs, || Ok(m.clone().0), mode)?; + let msg_vec: Vec>> = + Vec::new_variable(cs, || Ok(m.clone().0), mode)?; + let m: [FpVar>; MSG_LEN] = + msg_vec + .try_into() + .unwrap_or_else(|v: Vec>>| { + // WIP + panic!( + "Expected Vec of length: {}, actual length: {}", + MSG_LEN, + v.len() + ) + }); Ok(Self { - m: [msg[0].clone(), msg[1].clone(), msg[2].clone()], + m, _gc: PhantomData, }) }) @@ -181,15 +205,19 @@ where } } -pub struct BlindSigVerifyGadget>> -where +pub struct BlindSigVerifyGadget< + const MSG_LEN: usize, + C: ProjectiveCurve, + GC: CurveVar>, +> where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { _params: Parameters, // TODO review if needed, maybe delete _gc: PhantomData, } -impl>> BlindSigVerifyGadget +impl>> + BlindSigVerifyGadget where C: ProjectiveCurve, GC: CurveVar>, @@ -202,10 +230,10 @@ where FpVar<::BaseField>: Mul>>, FpVar<::BaseField>: From>>, { - fn verify( + pub fn verify( parameters: &ParametersVar, poseidon_hash: &PoseidonGadget>, - m: &MsgVar, + m: &MsgVar, s: &SignatureVar, q: &PublicKeyVar, ) -> Result>, SynthesisError> { @@ -230,9 +258,10 @@ where } pub struct BlindSigBatchVerifyGadget< + const NUM_SIGS: usize, + const MSG_LEN: usize, C: ProjectiveCurve, GC: CurveVar>, - const NUM_SIGS: usize, > where for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, { @@ -240,8 +269,12 @@ pub struct BlindSigBatchVerifyGadget< _gc: PhantomData, } -impl>, const NUM_SIGS: usize> - BlindSigBatchVerifyGadget +impl< + const NUM_SIGS: usize, + const MSG_LEN: usize, + C: ProjectiveCurve, + GC: CurveVar>, + > BlindSigBatchVerifyGadget where C: ProjectiveCurve, GC: CurveVar>, @@ -254,10 +287,10 @@ where FpVar<::BaseField>: Mul>>, FpVar<::BaseField>: From>>, { - fn batch_verify( + pub fn batch_verify( parameters: &ParametersVar, poseidon_hash: &PoseidonGadget>, - m: &MsgVar, + m: &MsgVar, sigs: &[SignatureVar], q: &PublicKeyVar, ) -> Result>, SynthesisError> { @@ -287,8 +320,11 @@ where // example of circuit using BlindSigVerifyGadget to verify a single blind signature #[derive(Clone)] -pub struct BlindSigVerifyCircuit>> -where +pub struct BlindSigVerifyCircuit< + const MSG_LEN: usize, + C: ProjectiveCurve, + GC: CurveVar>, +> where ::BaseField: PrimeField, { _group: PhantomData<*const GC>, @@ -296,11 +332,11 @@ where pub poseidon_hash_native: poseidon_native::Poseidon>, pub signature: Option>, pub pub_key: Option>, - pub message: Option>, + pub message: Option>, } -impl>> ConstraintSynthesizer> - for BlindSigVerifyCircuit +impl>> + ConstraintSynthesizer> for BlindSigVerifyCircuit where C: ProjectiveCurve, GC: CurveVar>, @@ -325,7 +361,7 @@ where PublicKeyVar::::new_input(ark_relations::ns!(cs, "public key"), || { self.pub_key.ok_or(SynthesisError::AssignmentMissing) })?; - let m = MsgVar::::new_input(ark_relations::ns!(cs, "message"), || { + let m = MsgVar::::new_input(ark_relations::ns!(cs, "message"), || { self.message.ok_or(SynthesisError::AssignmentMissing) })?; let signature = @@ -339,7 +375,7 @@ where ) .unwrap(); - let v = BlindSigVerifyGadget::::verify( + let v = BlindSigVerifyGadget::::verify( ¶meters, &poseidon_hash, &m, @@ -353,9 +389,10 @@ where // example of circuit using BlindSigVerifyGadget to verify a batch of blind signatures #[derive(Clone)] pub struct BlindSigBatchVerifyCircuit< + const NUM_SIGS: usize, + const MSG_LEN: usize, C: ProjectiveCurve, GC: CurveVar>, - const NUM_SIGS: usize, > where ::BaseField: PrimeField, { @@ -364,11 +401,15 @@ pub struct BlindSigBatchVerifyCircuit< pub poseidon_hash_native: poseidon_native::Poseidon>, pub signatures: Option>>, pub pub_key: Option>, - pub message: Option>, + pub message: Option>, } -impl>, const NUM_SIGS: usize> - ConstraintSynthesizer> for BlindSigBatchVerifyCircuit +impl< + const NUM_SIGS: usize, + const MSG_LEN: usize, + C: ProjectiveCurve, + GC: CurveVar>, + > ConstraintSynthesizer> for BlindSigBatchVerifyCircuit where C: ProjectiveCurve, GC: CurveVar>, @@ -393,7 +434,7 @@ where PublicKeyVar::::new_input(ark_relations::ns!(cs, "public key"), || { self.pub_key.ok_or(SynthesisError::AssignmentMissing) })?; - let m = MsgVar::::new_input(ark_relations::ns!(cs, "message"), || { + let m = MsgVar::::new_input(ark_relations::ns!(cs, "message"), || { self.message.ok_or(SynthesisError::AssignmentMissing) })?; @@ -415,7 +456,7 @@ where ) .unwrap(); - let v = BlindSigBatchVerifyGadget::::batch_verify( + let v = BlindSigBatchVerifyGadget::::batch_verify( ¶meters, &poseidon_hash, &m, @@ -447,7 +488,7 @@ mod test { ) -> ( Parameters, PublicKey, - Msg, + Msg<3, BabyJubJub>, Signature, ) { let mut rng = ark_std::test_rng(); @@ -457,7 +498,7 @@ mod test { let m = [Fq::from(1234), Fq::from(5689), Fq::from(3456)]; let (m_blinded, u) = S::blind(¶ms, &mut rng, &poseidon_hash, &m, signer_r).unwrap(); let s_blinded = S::blind_sign(sk, k, m_blinded); - let s = S::unblind(s_blinded, u); + let s = S::unblind(s_blinded, &u); let verified = S::verify(¶ms, &poseidon_hash, &m, s.clone(), pk); assert!(verified); (params, pk, Msg(m), s) @@ -469,7 +510,7 @@ mod test { ) -> ( Parameters, PublicKey, - Msg, + Msg<3, BabyJubJub>, Vec>, ) { let mut rng = ark_std::test_rng(); @@ -481,7 +522,7 @@ mod test { let (k, signer_r) = S::new_request_params(¶ms, &mut rng); let (m_blinded, u) = S::blind(¶ms, &mut rng, &poseidon_hash, &m, signer_r).unwrap(); let s_blinded = S::blind_sign(sk, k, m_blinded); - let s = S::unblind(s_blinded, u); + let s = S::unblind(s_blinded, &u); let verified = S::verify(¶ms, &poseidon_hash, &m, s.clone(), pk); assert!(verified); signatures.push(s); @@ -491,15 +532,15 @@ mod test { #[test] fn test_single_verify() { - // TODO N_INPUTS+1 (N_INPUTS msg_to_sign_length) let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 4); let poseidon_hash = poseidon::Poseidon::new(poseidon_params); + const MSG_LEN: usize = 3; // create signature using native-rust lib let (params, pk, m, s) = generate_single_sig_native_data(&poseidon_hash); // use the constraint system to verify the signature - type SG = BlindSigVerifyGadget; + type SG = BlindSigVerifyGadget; let cs = ConstraintSystem::::new_ref(); let params_var = @@ -508,7 +549,8 @@ mod test { SignatureVar::::new_witness(cs.clone(), || Ok(&s)).unwrap(); let pk_var = PublicKeyVar::::new_witness(cs.clone(), || Ok(&pk)).unwrap(); - let m_var = MsgVar::::new_witness(cs.clone(), || Ok(m)).unwrap(); + let m_var = MsgVar::::new_witness(cs.clone(), || Ok(m)) + .unwrap(); let poseidon_hash_var = PoseidonGadget::::from_native(&mut cs.clone(), poseidon_hash).unwrap(); @@ -528,12 +570,13 @@ mod test { fn test_single_verify_constraint_system() { let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 4); let poseidon_hash = poseidon::Poseidon::new(poseidon_params); + const MSG_LEN: usize = 3; // create signature using native-rust lib let (params, pk, m, s) = generate_single_sig_native_data(&poseidon_hash); // use the constraint system to verify the signature - let circuit = BlindSigVerifyCircuit:: { + let circuit = BlindSigVerifyCircuit:: { params, poseidon_hash_native: poseidon_hash.clone(), signature: Some(s), @@ -552,13 +595,14 @@ mod test { fn test_batch_verify_constraint_system() { let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 4); let poseidon_hash = poseidon::Poseidon::new(poseidon_params); + const MSG_LEN: usize = 3; // create signatures using native-rust lib const NUM_SIGS: usize = 5; let (params, pk, m, sigs) = generate_batch_sig_native_data(&poseidon_hash, NUM_SIGS); // use the constraint system to verify the batch of signatures - let circuit = BlindSigBatchVerifyCircuit:: { + let circuit = BlindSigBatchVerifyCircuit:: { params, poseidon_hash_native: poseidon_hash.clone(), signatures: Some(sigs), diff --git a/src/lib.rs b/src/lib.rs index 4ef44f7..e6cd6f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub struct Signature { r: ::Affine, } -#[derive(Debug)] +#[derive(Clone, Default, Debug)] pub struct UserSecretData { a: C::ScalarField, b: C::ScalarField, @@ -153,7 +153,7 @@ where Ok((m_blinded, u)) } - pub fn unblind(s_blinded: C::ScalarField, u: UserSecretData) -> Signature { + pub fn unblind(s_blinded: C::ScalarField, u: &UserSecretData) -> Signature { // s = a s' + b let s = u.a * s_blinded + u.b; Signature { s, r: u.r } @@ -240,7 +240,7 @@ mod tests { let s_blinded = S::blind_sign(sk, k, m_blinded); - let s = S::unblind(s_blinded, u); + let s = S::unblind(s_blinded, &u); let verified = S::verify(¶ms, &poseidon_hash, &m, s, pk); assert!(verified);