diff --git a/Cargo.toml b/Cargo.toml index 5e433dd..4575721 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,13 +14,11 @@ ark-ed-on-bn254 = { version = "^0.3.0", default-features = true, features = [ "r ark-crypto-primitives = { version = "^0.3.0", default-features = true, features = [ "r1cs" ] } # ark-sponge = { version = "^0.3.0", default-features = true, features = [ "r1cs" ] } # ark-sponge = { git = "https://github.com/arkworks-rs/sponge.git", rev = "41843d179dc4655869955297833d096d1962120f", default-features=true, features=["r1cs"] } -arkworks-utils = { git = "https://github.com/webb-tools/arkworks-gadgets", name="arkworks-utils", features=["poseidon_bn254_x5_3"] } -arkworks-native-gadgets = { git = "https://github.com/webb-tools/arkworks-gadgets", name="arkworks-native-gadgets"} -arkworks-r1cs-gadgets = { git = "https://github.com/webb-tools/arkworks-gadgets", name="arkworks-r1cs-gadgets"} +arkworks-utils = { git = "https://github.com/aragonzkresearch/arkworks-gadgets", name="arkworks-utils", features=["poseidon_bn254_x5_4"] } +arkworks-native-gadgets = { git = "https://github.com/aragonzkresearch/arkworks-gadgets", name="arkworks-native-gadgets"} +arkworks-r1cs-gadgets = { git = "https://github.com/aragonzkresearch/arkworks-gadgets", name="arkworks-r1cs-gadgets"} ark-relations = { version = "^0.3.0", default-features = false } ark-snark = { version = "^0.3.0", default-features = false } -ark-groth16 = { version = "^0.3.0" } tracing = { version = "0.1", default-features = false, features = [ "attributes" ] } tracing-subscriber = { version = "0.2" } -lazy_static = "1.4.0" derivative = { version = "2.0", features = ["use_core"] } diff --git a/src/constraints.rs b/src/constraints.rs index b52c6c1..0814fd4 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -59,6 +59,47 @@ where } } +// TODO parametrize Msg & MsgVar length + +#[derive(Clone, Default, Debug)] +// pub struct Msg(pub Vec>); +pub struct Msg(pub [ConstraintF; 3]); + +#[derive(Derivative)] +#[derivative( + Debug(bound = "C: ProjectiveCurve, GC: CurveVar>"), + Clone(bound = "C: ProjectiveCurve, GC: CurveVar>") +)] +pub struct MsgVar>> +where + for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, +{ + m: [FpVar>; 3], + _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, + ) -> Result { + f().and_then(|m| { + let m = m.borrow(); + let cs = cs.into(); + let msg: Vec>> = Vec::new_variable(cs, || Ok(m.clone().0), mode)?; + Ok(Self { + m: [msg[0].clone(), msg[1].clone(), msg[2].clone()], + _gc: PhantomData, + }) + }) + } +} + #[derive(Derivative)] #[derivative( Debug(bound = "C: ProjectiveCurve, GC: CurveVar>"), @@ -164,7 +205,7 @@ where fn verify( parameters: &ParametersVar, poseidon_hash: &PoseidonGadget>, - m: FpVar>, + m: &MsgVar, s: &SignatureVar, q: &PublicKeyVar, ) -> Result>, SynthesisError> { @@ -175,7 +216,7 @@ where // Note: in a circuit that aggregates multiple verifications, the hashing step could be // done outside the signature verification, once for all 1 votes and once for all 0 votes, // saving lots of constraints - let hm = poseidon_hash.hash(&[m])?; + let hm = poseidon_hash.hash(&m.m)?; let r = EdwardsVar::from(s.r.clone()); // WIP let rx_fpvar: FpVar> = r.x.into(); @@ -216,14 +257,14 @@ where fn batch_verify( parameters: &ParametersVar, poseidon_hash: &PoseidonGadget>, - m: FpVar>, + m: &MsgVar, sigs: &[SignatureVar], q: &PublicKeyVar, ) -> Result>, SynthesisError> { // Note: in a circuit that aggregates multiple verifications, the hashing step could be // done outside the signature verification, once for all 1 votes and once for all 0 votes, // saving lots of constraints - let hm = poseidon_hash.hash(&[m])?; + let hm = poseidon_hash.hash(&m.m)?; #[allow(clippy::needless_range_loop)] for i in 0..NUM_SIGS { @@ -255,7 +296,7 @@ where pub poseidon_hash_native: poseidon_native::Poseidon>, pub signature: Option>, pub pub_key: Option>, - pub message: Option>, + pub message: Option>, } impl>> ConstraintSynthesizer> @@ -284,7 +325,7 @@ where 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"), || { + let m = MsgVar::::new_input(ark_relations::ns!(cs, "message"), || { self.message.ok_or(SynthesisError::AssignmentMissing) })?; let signature = @@ -301,7 +342,7 @@ where let v = BlindSigVerifyGadget::::verify( ¶meters, &poseidon_hash, - m, + &m, &signature, &pub_key, )?; @@ -323,7 +364,7 @@ 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> @@ -352,7 +393,7 @@ where 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"), || { + let m = MsgVar::::new_input(ark_relations::ns!(cs, "message"), || { self.message.ok_or(SynthesisError::AssignmentMissing) })?; @@ -377,7 +418,7 @@ where let v = BlindSigBatchVerifyGadget::::batch_verify( ¶meters, &poseidon_hash, - m, + &m, &signatures, &pub_key, )?; @@ -406,20 +447,20 @@ mod test { ) -> ( Parameters, PublicKey, - Fq, + Msg, Signature, ) { let mut rng = ark_std::test_rng(); let params = S::setup(); let (pk, sk) = S::keygen(¶ms, &mut rng); let (k, signer_r) = S::new_request_params(¶ms, &mut rng); - let m = Fq::from(1234); - let (m_blinded, u) = S::blind(¶ms, &mut rng, &poseidon_hash, m, signer_r).unwrap(); + 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 verified = S::verify(¶ms, &poseidon_hash, m, s.clone(), pk); + let verified = S::verify(¶ms, &poseidon_hash, &m, s.clone(), pk); assert!(verified); - (params, pk, m, s) + (params, pk, Msg(m), s) } fn generate_batch_sig_native_data( @@ -428,29 +469,30 @@ mod test { ) -> ( Parameters, PublicKey, - Fq, + Msg, Vec>, ) { let mut rng = ark_std::test_rng(); let params = S::setup(); let (pk, sk) = S::keygen(¶ms, &mut rng); - let m = Fq::from(1234); + let m = [Fq::from(1234), Fq::from(5689), Fq::from(3456)]; let mut signatures: Vec> = Vec::new(); for _ in 0..n { 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 (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 verified = S::verify(¶ms, &poseidon_hash, m, s.clone(), pk); + let verified = S::verify(¶ms, &poseidon_hash, &m, s.clone(), pk); assert!(verified); signatures.push(s); } - (params, pk, m, signatures) + (params, pk, Msg(m), signatures) } #[test] fn test_single_verify() { - let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 3); + // 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); // create signature using native-rust lib @@ -466,14 +508,14 @@ mod test { SignatureVar::::new_witness(cs.clone(), || Ok(&s)).unwrap(); let pk_var = PublicKeyVar::::new_witness(cs.clone(), || Ok(&pk)).unwrap(); - let m_var = FpVar::::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(); let valid_sig = SG::verify( ¶ms_var, &poseidon_hash_var, - m_var, + &m_var, &signature_var, &pk_var, ) @@ -484,7 +526,7 @@ mod test { #[test] fn test_single_verify_constraint_system() { - let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 3); + let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 4); let poseidon_hash = poseidon::Poseidon::new(poseidon_params); // create signature using native-rust lib @@ -493,7 +535,7 @@ mod test { // use the constraint system to verify the signature let circuit = BlindSigVerifyCircuit:: { params, - poseidon_hash_native: poseidon_hash, + poseidon_hash_native: poseidon_hash.clone(), signature: Some(s), pub_key: Some(pk), message: Some(m), @@ -508,7 +550,7 @@ mod test { #[test] fn test_batch_verify_constraint_system() { - let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 3); + let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 4); let poseidon_hash = poseidon::Poseidon::new(poseidon_params); // create signatures using native-rust lib @@ -518,7 +560,7 @@ mod test { // use the constraint system to verify the batch of signatures let circuit = BlindSigBatchVerifyCircuit:: { params, - poseidon_hash_native: poseidon_hash, + poseidon_hash_native: poseidon_hash.clone(), signatures: Some(sigs), pub_key: Some(pk), message: Some(m), diff --git a/src/lib.rs b/src/lib.rs index 2fbc236..4ef44f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -129,7 +129,7 @@ where parameters: &Parameters, rng: &mut R, poseidon_hash: &poseidon::Poseidon>, - m: ConstraintF, + m: &[ConstraintF], signer_r: C::Affine, ) -> Result<(C::ScalarField, UserSecretData), ark_crypto_primitives::Error> where @@ -144,7 +144,7 @@ where // m' = a^-1 rx h(m) // TODO hash(m) must be \in Fr - let hm = poseidon_hash.hash(&[m])?; + 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 = u.a.inverse().unwrap() * x_fr * hm_fr; @@ -162,7 +162,7 @@ where pub fn verify( parameters: &Parameters, poseidon_hash: &poseidon::Poseidon>, - m: ConstraintF, + m: &[ConstraintF], s: Signature, q: PublicKey, ) -> bool @@ -172,7 +172,7 @@ where let sG = parameters.generator.mul(s.s.into_repr()); // TODO the output of hash(m) must be \in Fr - let hm = poseidon_hash.hash(&[m]).unwrap(); + let hm = poseidon_hash.hash(m).unwrap(); // let hm_fr = C::ScalarField::from_repr(hm.into_repr()).unwrap(); let hm_fr = C::ScalarField::from_le_bytes_mod_order(&to_bytes!(hm).unwrap()); // WIP TMP @@ -225,7 +225,7 @@ mod tests { fn test_blind_signature_flow_native() { type S = BlindSigScheme; - let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 3); + let poseidon_params = poseidon_setup_params::(Curve::Bn254, 5, 4); let poseidon_hash = poseidon::Poseidon::new(poseidon_params); let mut rng = ark_std::test_rng(); @@ -234,15 +234,15 @@ mod tests { let (pk, sk) = S::keygen(¶ms, &mut rng); let (k, signer_r) = S::new_request_params(¶ms, &mut rng); - let m = Fq::from(1234); + 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 (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 verified = S::verify(¶ms, &poseidon_hash, m, s, pk); + let verified = S::verify(¶ms, &poseidon_hash, &m, s, pk); assert!(verified); } }