Signed-msg extend to array of field elems
@@ -14,13 +14,11 @@ ark-ed-on-bn254 = { version = "^0.3.0", default-features = true, features = [ "r1cs" ] }
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"] }
@@ -59,6 +59,47 @@ })
} } +// TODO parametrize Msg & MsgVar length + +#[derive(Clone, Default, Debug)] +// pub struct Msg<C: ProjectiveCurve>(pub Vec<ConstraintF<C>>); +pub struct Msg<C: ProjectiveCurve>(pub [ConstraintF<C>; 3]); + +#[derive(Derivative)] +#[derivative( + Debug(bound = "C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>"), + Clone(bound = "C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>") +)] +pub struct MsgVar<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>> +where + for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, +{ + m: [FpVar<ConstraintF<C>>; 3], + _gc: PhantomData<GC>, +} +impl<C, GC> AllocVar<Msg<C>, ConstraintF<C>> for MsgVar<C, GC> +where + C: ProjectiveCurve, + GC: CurveVar<C, ConstraintF<C>>, + for<'a> &'a GC: GroupOpsBounds<'a, C, GC>, +{ + fn new_variable<T: Borrow<Msg<C>>>( + cs: impl Into<Namespace<ConstraintF<C>>>, + f: impl FnOnce() -> Result<T, SynthesisError>, + mode: AllocationMode, + ) -> Result<Self, SynthesisError> { + f().and_then(|m| { + let m = m.borrow(); + let cs = cs.into(); + let msg: Vec<FpVar<ConstraintF<C>>> = 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<C, ConstraintF<C>>"),@@ -164,7 +205,7 @@ {
fn verify( parameters: &ParametersVar<C, GC>, poseidon_hash: &PoseidonGadget<ConstraintF<C>>, - m: FpVar<ConstraintF<C>>, + m: &MsgVar<C, GC>, s: &SignatureVar<C, GC>, q: &PublicKeyVar<C, GC>, ) -> Result<Boolean<ConstraintF<C>>, SynthesisError> {@@ -175,7 +216,7 @@
// 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<ConstraintF<C>> = r.x.into();@@ -216,14 +257,14 @@ {
fn batch_verify( parameters: &ParametersVar<C, GC>, poseidon_hash: &PoseidonGadget<ConstraintF<C>>, - m: FpVar<ConstraintF<C>>, + m: &MsgVar<C, GC>, sigs: &[SignatureVar<C, GC>], q: &PublicKeyVar<C, GC>, ) -> Result<Boolean<ConstraintF<C>>, 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 @@ 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>>, + pub message: Option<Msg<C>>, } impl<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>> ConstraintSynthesizer<ConstraintF<C>>@@ -284,7 +325,7 @@ 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"), || { + let m = MsgVar::<C, GC>::new_input(ark_relations::ns!(cs, "message"), || { self.message.ok_or(SynthesisError::AssignmentMissing) })?; let signature =@@ -301,7 +342,7 @@
let v = BlindSigVerifyGadget::<C, GC>::verify( ¶meters, &poseidon_hash, - m, + &m, &signature, &pub_key, )?;@@ -323,7 +364,7 @@ pub params: Parameters<C>,
pub poseidon_hash_native: poseidon_native::Poseidon<ConstraintF<C>>, pub signatures: Option<Vec<Signature<C>>>, pub pub_key: Option<PublicKey<C>>, - pub message: Option<ConstraintF<C>>, + pub message: Option<Msg<C>>, } impl<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>, const NUM_SIGS: usize>@@ -352,7 +393,7 @@ 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"), || { + let m = MsgVar::<C, GC>::new_input(ark_relations::ns!(cs, "message"), || { self.message.ok_or(SynthesisError::AssignmentMissing) })?;@@ -377,7 +418,7 @@
let v = BlindSigBatchVerifyGadget::<C, GC, NUM_SIGS>::batch_verify( ¶meters, &poseidon_hash, - m, + &m, &signatures, &pub_key, )?;@@ -406,20 +447,20 @@ poseidon_hash: &poseidon::Poseidon<Fq>,
) -> ( Parameters<BabyJubJub>, PublicKey<BabyJubJub>, - Fq, + Msg<BabyJubJub>, Signature<BabyJubJub>, ) { 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 @@ n: usize,
) -> ( Parameters<BabyJubJub>, PublicKey<BabyJubJub>, - Fq, + Msg<BabyJubJub>, Vec<Signature<BabyJubJub>>, ) { 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<Signature<BabyJubJub>> = 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::<Fq>(Curve::Bn254, 5, 3); + // TODO N_INPUTS+1 (N_INPUTS msg_to_sign_length) + let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 4); let poseidon_hash = poseidon::Poseidon::new(poseidon_params); // create signature using native-rust lib@@ -466,14 +508,14 @@ let signature_var =
SignatureVar::<BabyJubJub, BabyJubJubVar>::new_witness(cs.clone(), || Ok(&s)).unwrap(); let pk_var = PublicKeyVar::<BabyJubJub, BabyJubJubVar>::new_witness(cs.clone(), || Ok(&pk)).unwrap(); - let m_var = FpVar::<Fq>::new_witness(cs.clone(), || Ok(&m)).unwrap(); + let m_var = MsgVar::<BabyJubJub, BabyJubJubVar>::new_witness(cs.clone(), || Ok(m)).unwrap(); let poseidon_hash_var = PoseidonGadget::<Fq>::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 @@ }
#[test] fn test_single_verify_constraint_system() { - let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 3); + let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 4); let poseidon_hash = poseidon::Poseidon::new(poseidon_params); // create signature using native-rust lib@@ -493,7 +535,7 @@
// use the constraint system to verify the signature let circuit = BlindSigVerifyCircuit::<BabyJubJub, BabyJubJubVar> { 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 @@ }
#[test] fn test_batch_verify_constraint_system() { - let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 3); + let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 4); let poseidon_hash = poseidon::Poseidon::new(poseidon_params); // create signatures using native-rust lib@@ -518,7 +560,7 @@
// use the constraint system to verify the batch of signatures let circuit = BlindSigBatchVerifyCircuit::<BabyJubJub, BabyJubJubVar, NUM_SIGS> { params, - poseidon_hash_native: poseidon_hash, + poseidon_hash_native: poseidon_hash.clone(), signatures: Some(sigs), pub_key: Some(pk), message: Some(m),
@@ -129,7 +129,7 @@ pub fn blind<R: Rng>(
parameters: &Parameters<C>, rng: &mut R, poseidon_hash: &poseidon::Poseidon<ConstraintF<C>>, - m: ConstraintF<C>, + m: &[ConstraintF<C>], signer_r: C::Affine, ) -> Result<(C::ScalarField, UserSecretData<C>), ark_crypto_primitives::Error> where@@ -144,7 +144,7 @@ let x_fr = C::ScalarField::from(r.x.into_repr());
// 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 @@
pub fn verify( parameters: &Parameters<C>, poseidon_hash: &poseidon::Poseidon<ConstraintF<C>>, - m: ConstraintF<C>, + m: &[ConstraintF<C>], s: Signature<C>, q: PublicKey<C>, ) -> bool@@ -172,7 +172,7 @@ {
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 @@ #[test]
fn test_blind_signature_flow_native() { type S = BlindSigScheme<EdwardsProjective>; - let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 3); + let poseidon_params = poseidon_setup_params::<Fq>(Curve::Bn254, 5, 4); let poseidon_hash = poseidon::Poseidon::new(poseidon_params); let mut rng = ark_std::test_rng();@@ -234,15 +234,15 @@ 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 = [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); } }