diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ec1ba7..5fcf08b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ ### Bug fixes +## v0.4.0 + +- Change dependency to version `0.4.0` of other arkwork-rs crates. + ## v0.3.0 - Change dependency to version `0.3.0` of other arkworks-rs crates. diff --git a/Cargo.toml b/Cargo.toml index 4b2456c..fc4538f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ark-gm17" -version = "0.3.0" +version = "0.4.0" authors = [ "arkworks contributors" ] description = "An implementation of the Groth-Maller 2017 zkSNARK proof system" homepage = "https://arkworks.rs" @@ -10,19 +10,19 @@ keywords = [ "zero-knowledge", "cryptography", "zkSNARK", "SNARK", "Groth-Maller categories = [ "cryptography" ] include = ["Cargo.toml", "src", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] license = "MIT/Apache-2.0" -edition = "2018" +edition = "2021" ################################# Dependencies ################################ [dependencies] -ark-ff = { version = "^0.3.0", default-features = false } -ark-ec = { version = "^0.3.0", default-features = false } -ark-serialize = { version = "^0.3.0", default-features = false, features = [ "derive" ] } -ark-poly = { version = "^0.3.0", default-features = false } -ark-std = { version = "^0.3.0", default-features = false } -ark-relations = { version = "^0.3.0", default-features = false } -ark-crypto-primitives = { version = "^0.3.0", default-features = false } -ark-r1cs-std = { version = "^0.3.0", default-features = false, optional = true } +ark-ff = { version = "^0.4.0", default-features = false } +ark-ec = { version = "^0.4.0", default-features = false } +ark-serialize = { version = "^0.4.0", default-features = false, features = [ "derive" ] } +ark-poly = { version = "^0.4.0", default-features = false } +ark-std = { version = "^0.4.0", default-features = false } +ark-relations = { version = "^0.4.0", default-features = false } +ark-crypto-primitives = { version = "^0.4.0", features = ["snark"], default-features = false } +ark-r1cs-std = { version = "^0.4.0", default-features = false, optional = true } tracing = { version = "0.1", default-features = false, features = [ "attributes" ], optional = true } derivative = { version = "2.0", features = ["use_core"], optional = true } @@ -31,13 +31,13 @@ rayon = { version = "1", optional = true } [dev-dependencies] csv = { version = "1" } -ark-bls12-381 = { version = "^0.3.0", default-features = false, features = ["curve"] } -ark-bls12-377 = { version = "^0.3.0", default-features = false, features = ["curve"] } -ark-cp6-782 = { version = "^0.3.0", default-features = false } -ark-mnt4-298 = { version = "^0.3.0", default-features = false, features = ["r1cs", "curve"] } -ark-mnt6-298 = { version = "^0.3.0", default-features = false, features = ["r1cs"] } -ark-mnt4-753 = { version = "^0.3.0", default-features = false, features = ["r1cs", "curve"] } -ark-mnt6-753 = { version = "^0.3.0", default-features = false, features = ["r1cs"] } +ark-bls12-381 = { version = "^0.4.0", default-features = false, features = ["curve"] } +ark-bls12-377 = { version = "^0.4.0", default-features = false, features = ["curve"] } +ark-cp6-782 = { version = "^0.4.0", default-features = false } +ark-mnt4-298 = { version = "^0.4.0", default-features = false, features = ["r1cs", "curve"] } +ark-mnt6-298 = { version = "^0.4.0", default-features = false, features = ["r1cs"] } +ark-mnt4-753 = { version = "^0.4.0", default-features = false, features = ["r1cs", "curve"] } +ark-mnt6-753 = { version = "^0.4.0", default-features = false, features = ["r1cs"] } [features] default = ["parallel"] diff --git a/benches/bench.rs b/benches/bench.rs index a162287..a0a06f3 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,9 +1,10 @@ // For benchmark, run: -// RAYON_NUM_THREADS=N cargo bench --no-default-features --features "std parallel" -- --nocapture -// where N is the number of threads you want to use (N = 1 for single-thread). +// RAYON_NUM_THREADS=N cargo bench --no-default-features --features "std +// parallel" -- --nocapture where N is the number of threads you want to use (N +// = 1 for single-thread). use ark_bls12_381::{Bls12_381, Fr as BlsFr}; -use ark_crypto_primitives::SNARK; +use ark_crypto_primitives::snark::SNARK; use ark_ff::PrimeField; use ark_gm17::GM17; use ark_mnt4_298::{Fr as MNT4Fr, MNT4_298}; @@ -14,8 +15,11 @@ use ark_relations::{ lc, r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}, }; -use ark_std::ops::Mul; -use ark_std::UniformRand; +use ark_std::{ + ops::Mul, + rand::{rngs, Rng, SeedableRng}, + UniformRand, +}; const NUM_PROVE_REPEATITIONS: usize = 10; const NUM_VERIFY_REPEATITIONS: usize = 50; @@ -66,20 +70,21 @@ impl ConstraintSynthesizer for DummyCircuit { macro_rules! gm17_prove_bench { ($bench_name:ident, $bench_field:ty, $bench_pairing_engine:ty) => { - let rng = &mut ark_std::test_rng(); + let mut _rng = ark_std::test_rng(); + let mut rng = rngs::StdRng::from_seed(_rng.gen()); let c = DummyCircuit::<$bench_field> { - a: Some(<$bench_field>::rand(rng)), - b: Some(<$bench_field>::rand(rng)), + a: Some(<$bench_field>::rand(&mut rng)), + b: Some(<$bench_field>::rand(&mut rng)), num_variables: 10, num_constraints: 65536, }; - let (pk, _) = GM17::<$bench_pairing_engine>::circuit_specific_setup(c, rng).unwrap(); + let (pk, _) = GM17::<$bench_pairing_engine>::circuit_specific_setup(c, &mut rng).unwrap(); let start = ark_std::time::Instant::now(); for _ in 0..NUM_PROVE_REPEATITIONS { - let _ = GM17::<$bench_pairing_engine>::prove(&pk, c.clone(), rng).unwrap(); + let _ = GM17::<$bench_pairing_engine>::prove(&pk, c.clone(), &mut rng).unwrap(); } println!( @@ -92,16 +97,17 @@ macro_rules! gm17_prove_bench { macro_rules! gm17_verify_bench { ($bench_name:ident, $bench_field:ty, $bench_pairing_engine:ty) => { - let rng = &mut ark_std::test_rng(); + let mut _rng = ark_std::test_rng(); + let mut rng = rngs::StdRng::from_seed(_rng.gen()); let c = DummyCircuit::<$bench_field> { - a: Some(<$bench_field>::rand(rng)), - b: Some(<$bench_field>::rand(rng)), + a: Some(<$bench_field>::rand(&mut rng)), + b: Some(<$bench_field>::rand(&mut rng)), num_variables: 10, num_constraints: 65536, }; - let (pk, vk) = GM17::<$bench_pairing_engine>::circuit_specific_setup(c, rng).unwrap(); - let proof = GM17::<$bench_pairing_engine>::prove(&pk, c.clone(), rng).unwrap(); + let (pk, vk) = GM17::<$bench_pairing_engine>::circuit_specific_setup(c, &mut rng).unwrap(); + let proof = GM17::<$bench_pairing_engine>::prove(&pk, c.clone(), &mut rng).unwrap(); let v = c.a.unwrap().mul(c.b.unwrap()); diff --git a/examples/recursive-snark/gm17.rs b/examples/recursive-snark/gm17.rs index 40e9e4b..1578c54 100644 --- a/examples/recursive-snark/gm17.rs +++ b/examples/recursive-snark/gm17.rs @@ -21,7 +21,6 @@ unused_must_use, unused_mut, unused_unsafe, - private_in_public, unsafe_code )] diff --git a/examples/snark-scalability/gm17.rs b/examples/snark-scalability/gm17.rs index 6f73ea6..f257afa 100644 --- a/examples/snark-scalability/gm17.rs +++ b/examples/snark-scalability/gm17.rs @@ -17,13 +17,7 @@ unused_allocation, unused_comparisons )] -#![deny( - unused_must_use, - unused_mut, - unused_unsafe, - private_in_public, - unsafe_code -)] +#![deny(unused_must_use, unused_mut, unused_unsafe, unsafe_code)] use csv; diff --git a/src/constraints.rs b/src/constraints.rs index ae7d15a..8ef1304 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -1,14 +1,15 @@ use crate::{PreparedVerifyingKey, Proof, VerifyingKey, GM17}; -use ark_crypto_primitives::snark::constraints::{CircuitSpecificSetupSNARKGadget, SNARKGadget}; -use ark_crypto_primitives::snark::{BooleanInputVar, SNARK}; -use ark_ec::{AffineCurve, PairingEngine}; -use ark_r1cs_std::fields::FieldVar; -use ark_r1cs_std::groups::CurveVar; +use ark_crypto_primitives::snark::{ + constraints::{CircuitSpecificSetupSNARKGadget, SNARKGadget}, + BooleanInputVar, SNARK, +}; +use ark_ec::{pairing::Pairing, AffineRepr}; use ark_r1cs_std::{ alloc::{AllocVar, AllocationMode}, - bits::boolean::Boolean, - bits::uint8::UInt8, + bits::{boolean::Boolean, uint8::UInt8}, eq::EqGadget, + fields::FieldVar, + groups::CurveVar, pairing::PairingVar, ToBitsGadget, ToBytesGadget, }; @@ -18,7 +19,7 @@ use ark_std::{borrow::Borrow, marker::PhantomData, vec::Vec}; /// The proof variable for the GM17 construction #[derive(Derivative)] #[derivative(Clone(bound = "P::G1Var: Clone, P::G2Var: Clone"))] -pub struct ProofVar> { +pub struct ProofVar> { /// The `A` element in `G1`. pub a: P::G1Var, /// The `B` element in `G2`. @@ -33,7 +34,7 @@ pub struct ProofVar> { Clone(bound = "P::G1Var: Clone, P::GTVar: Clone, P::G1PreparedVar: Clone, \ P::G2PreparedVar: Clone, ") )] -pub struct VerifyingKeyVar> { +pub struct VerifyingKeyVar> { #[doc(hidden)] pub h_g2: P::G2Var, #[doc(hidden)] @@ -48,7 +49,7 @@ pub struct VerifyingKeyVar> { pub query: Vec, } -impl> VerifyingKeyVar { +impl> VerifyingKeyVar { /// Prepare `self` for use in proof verification. pub fn prepare(&self) -> Result, SynthesisError> { let g_alpha_pc = P::prepare_g1(&self.g_alpha_g1)?; @@ -75,7 +76,7 @@ impl> VerifyingKeyVar { Clone(bound = "P::G1Var: Clone, P::GTVar: Clone, P::G1PreparedVar: Clone, \ P::G2PreparedVar: Clone, ") )] -pub struct PreparedVerifyingKeyVar> { +pub struct PreparedVerifyingKeyVar> { #[doc(hidden)] pub g_alpha: P::G1Var, #[doc(hidden)] @@ -97,24 +98,26 @@ pub struct PreparedVerifyingKeyVar> { /// Constraints for the verifier of the SNARK of [[GM17]](https://eprint.iacr.org/2017/540.pdf). pub struct GM17VerifierGadget where - E: PairingEngine, - P: PairingVar, + E: Pairing, + P: PairingVar, { _pairing_engine: PhantomData, _pairing_gadget: PhantomData

, } -impl> SNARKGadget> +impl> SNARKGadget> for GM17VerifierGadget { type ProcessedVerifyingKeyVar = PreparedVerifyingKeyVar; type VerifyingKeyVar = VerifyingKeyVar; - type InputVar = BooleanInputVar; + type InputVar = BooleanInputVar; type ProofVar = ProofVar; type VerifierSize = usize; - fn verifier_size(circuit_vk: & as SNARK>::VerifyingKey) -> Self::VerifierSize { + fn verifier_size( + circuit_vk: & as SNARK>::VerifyingKey, + ) -> Self::VerifierSize { circuit_vk.query.len() } @@ -122,7 +125,7 @@ impl> SNARKGadget>>( - cs: impl Into>, + cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { @@ -132,17 +135,17 @@ impl> SNARKGadget> SNARKGadget>>( - cs: impl Into>, + cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { @@ -163,27 +166,27 @@ impl> SNARKGadget> SNARKGadget> SNARKGadget Result, SynthesisError> { + ) -> Result, SynthesisError> { let circuit_pvk = circuit_pvk.clone(); // e(A*G^{alpha}, B*H^{beta}) = e(G^{alpha}, H^{beta}) * e(G^{psi}, H^{gamma}) * // e(C, H) where psi = \sum_{i=0}^l input_i pvk.query[i] @@ -288,27 +291,28 @@ impl> SNARKGadget Result, SynthesisError> { + ) -> Result, SynthesisError> { let pvk = circuit_vk.prepare()?; Self::verify_with_processed_vk(&pvk, x, proof) } } -impl CircuitSpecificSetupSNARKGadget> for GM17VerifierGadget +impl CircuitSpecificSetupSNARKGadget> + for GM17VerifierGadget where - E: PairingEngine, - P: PairingVar, + E: Pairing, + P: PairingVar, { } -impl AllocVar, E::Fq> for PreparedVerifyingKeyVar +impl AllocVar, E::BaseField> for PreparedVerifyingKeyVar where - E: PairingEngine, - P: PairingVar, + E: Pairing, + P: PairingVar, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( - cs: impl Into>, + cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { @@ -372,14 +376,14 @@ where } } -impl AllocVar, E::Fq> for VerifyingKeyVar +impl AllocVar, E::BaseField> for VerifyingKeyVar where - E: PairingEngine, - P: PairingVar, + E: Pairing, + P: PairingVar, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( - cs: impl Into>, + cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { @@ -427,14 +431,14 @@ where } } -impl AllocVar, E::Fq> for ProofVar +impl AllocVar, E::BaseField> for ProofVar where - E: PairingEngine, - P: PairingVar, + E: Pairing, + P: PairingVar, { #[tracing::instrument(target = "r1cs", skip(cs, f))] fn new_variable>>( - cs: impl Into>, + cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { @@ -451,14 +455,14 @@ where } } -impl ToBytesGadget for VerifyingKeyVar +impl ToBytesGadget for VerifyingKeyVar where - E: PairingEngine, - P: PairingVar, + E: Pairing, + P: PairingVar, { #[inline] #[tracing::instrument(target = "r1cs", skip(self))] - fn to_bytes(&self) -> Result>, SynthesisError> { + fn to_bytes(&self) -> Result>, SynthesisError> { let mut bytes = Vec::new(); bytes.extend_from_slice(&self.h_g2.to_bytes()?); bytes.extend_from_slice(&self.g_alpha_g1.to_bytes()?); @@ -475,22 +479,24 @@ where #[cfg(test)] mod test { use crate::{constraints::GM17VerifierGadget, GM17}; - use ark_crypto_primitives::snark::constraints::SNARKGadget; - use ark_crypto_primitives::snark::{CircuitSpecificSetupSNARK, SNARK}; - use ark_ec::PairingEngine; + use ark_crypto_primitives::snark::{ + constraints::SNARKGadget, CircuitSpecificSetupSNARK, SNARK, + }; + use ark_ec::pairing::Pairing; use ark_ff::{Field, UniformRand}; use ark_mnt4_298::{ - constraints::PairingVar as MNT4PairingVar, Fr as MNT4Fr, MNT4_298 as MNT4PairingEngine, + constraints::PairingVar as MNT4PairingVar, Fr as MNT4Fr, MNT4_298 as MNT4Pairing, }; use ark_mnt6_298::Fr as MNT6Fr; - use ark_r1cs_std::bits::boolean::Boolean; - use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget}; + use ark_r1cs_std::{alloc::AllocVar, bits::boolean::Boolean, eq::EqGadget}; use ark_relations::{ lc, ns, r1cs::{ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError}, }; - use ark_std::ops::MulAssign; - use ark_std::test_rng; + use ark_std::{ + ops::MulAssign, + rand::{rngs, Rng, SeedableRng}, + }; #[derive(Copy, Clone)] struct Circuit { @@ -527,12 +533,13 @@ mod test { } } - type TestSNARK = GM17; - type TestSNARKGadget = GM17VerifierGadget; + type TestSNARK = GM17; + type TestSNARKGadget = GM17VerifierGadget; #[test] fn gm17_snark_test() { - let mut rng = test_rng(); + let mut _rng = ark_std::test_rng(); + let mut rng = rngs::StdRng::from_seed(_rng.gen()); let a = MNT4Fr::rand(&mut rng); let b = MNT4Fr::rand(&mut rng); let mut c = a; @@ -558,26 +565,26 @@ mod test { let cs = ConstraintSystemRef::new(cs_sys); let input_gadget = ::Fr, - ::Fq, + ::ScalarField, + ::BaseField, TestSNARK, >>::InputVar::new_input(ns!(cs, "new_input"), || Ok(vec![c])) .unwrap(); let proof_gadget = ::Fr, - ::Fq, + ::ScalarField, + ::BaseField, TestSNARK, >>::ProofVar::new_witness(ns!(cs, "alloc_proof"), || Ok(proof)) .unwrap(); let vk_gadget = ::Fr, - ::Fq, + ::ScalarField, + ::BaseField, TestSNARK, >>::VerifyingKeyVar::new_constant(ns!(cs, "alloc_vk"), vk.clone()) .unwrap(); ::Fr, - ::Fq, + ::ScalarField, + ::BaseField, TestSNARK, >>::verify(&vk_gadget, &input_gadget, &proof_gadget) .unwrap() @@ -592,8 +599,8 @@ mod test { let pvk = TestSNARK::process_vk(&vk).unwrap(); let pvk_gadget = ::Fr, - ::Fq, + ::ScalarField, + ::BaseField, TestSNARK, >>::ProcessedVerifyingKeyVar::new_constant( ns!(cs, "alloc_pvk"), pvk.clone() diff --git a/src/data_structures.rs b/src/data_structures.rs index ba5ff3d..beaa568 100644 --- a/src/data_structures.rs +++ b/src/data_structures.rs @@ -1,14 +1,10 @@ -use ark_ec::PairingEngine; -use ark_ff::bytes::ToBytes; -use ark_serialize::*; -use ark_std::{ - io::{self, Result as IoResult}, - vec::Vec, -}; +use ark_ec::pairing::Pairing; +use ark_serialize::{CanonicalSerialize, *}; +use ark_std::vec::Vec; /// A proof in the GM17 SNARK. #[derive(PartialEq, Eq, Clone, Default, CanonicalSerialize, CanonicalDeserialize)] -pub struct Proof { +pub struct Proof { #[doc(hidden)] pub a: E::G1Affine, #[doc(hidden)] @@ -17,18 +13,9 @@ pub struct Proof { pub c: E::G1Affine, } -impl ToBytes for Proof { - #[inline] - fn write(&self, mut writer: W) -> io::Result<()> { - self.a.write(&mut writer)?; - self.b.write(&mut writer)?; - self.c.write(&mut writer) - } -} - /// A verification key in the GM17 SNARK. #[derive(Eq, PartialEq, Clone, CanonicalSerialize, CanonicalDeserialize)] -pub struct VerifyingKey { +pub struct VerifyingKey { #[doc(hidden)] pub h_g2: E::G2Affine, #[doc(hidden)] @@ -43,21 +30,7 @@ pub struct VerifyingKey { pub query: Vec, } -impl ToBytes for VerifyingKey { - fn write(&self, mut writer: W) -> IoResult<()> { - self.h_g2.write(&mut writer)?; - self.g_alpha_g1.write(&mut writer)?; - self.h_beta_g2.write(&mut writer)?; - self.g_gamma_g1.write(&mut writer)?; - self.h_gamma_g2.write(&mut writer)?; - for q in &self.query { - q.write(&mut writer)?; - } - Ok(()) - } -} - -impl Default for VerifyingKey { +impl Default for VerifyingKey { fn default() -> Self { Self { h_g2: E::G2Affine::default(), @@ -72,8 +45,8 @@ impl Default for VerifyingKey { /// Preprocessed verification key parameters that enable faster verification /// at the expense of larger size in memory. -#[derive(PartialEq, Eq, Clone)] -pub struct PreparedVerifyingKey { +#[derive(PartialEq, Eq, Clone, CanonicalDeserialize, CanonicalSerialize)] +pub struct PreparedVerifyingKey { #[doc(hidden)] pub vk: VerifyingKey, #[doc(hidden)] @@ -81,7 +54,7 @@ pub struct PreparedVerifyingKey { #[doc(hidden)] pub h_beta: E::G2Affine, #[doc(hidden)] - pub g_alpha_h_beta_ml: E::Fqk, + pub g_alpha_h_beta_ml: E::TargetField, #[doc(hidden)] pub g_gamma_pc: E::G1Prepared, #[doc(hidden)] @@ -92,13 +65,13 @@ pub struct PreparedVerifyingKey { pub query: Vec, } -impl Default for PreparedVerifyingKey { +impl Default for PreparedVerifyingKey { fn default() -> Self { Self { vk: VerifyingKey::default(), g_alpha: E::G1Affine::default(), h_beta: E::G2Affine::default(), - g_alpha_h_beta_ml: E::Fqk::default(), + g_alpha_h_beta_ml: E::TargetField::default(), g_gamma_pc: E::G1Prepared::default(), h_gamma_pc: E::G2Prepared::default(), h_pc: E::G2Prepared::default(), @@ -107,37 +80,21 @@ impl Default for PreparedVerifyingKey { } } -impl From> for VerifyingKey { +impl From> for VerifyingKey { fn from(other: PreparedVerifyingKey) -> Self { other.vk } } -impl From> for PreparedVerifyingKey { +impl From> for PreparedVerifyingKey { fn from(other: VerifyingKey) -> Self { crate::prepare_verifying_key(&other) } } -impl ToBytes for PreparedVerifyingKey { - fn write(&self, mut writer: W) -> IoResult<()> { - self.vk.write(&mut writer)?; - self.g_alpha.write(&mut writer)?; - self.h_beta.write(&mut writer)?; - self.g_alpha_h_beta_ml.write(&mut writer)?; - self.g_gamma_pc.write(&mut writer)?; - self.h_gamma_pc.write(&mut writer)?; - self.h_pc.write(&mut writer)?; - for q in &self.query { - q.write(&mut writer)?; - } - Ok(()) - } -} - /// Full public (prover and verifier) parameters for the GM17 zkSNARK. #[derive(PartialEq, Eq, Clone, CanonicalSerialize, CanonicalDeserialize)] -pub struct ProvingKey { +pub struct ProvingKey { #[doc(hidden)] pub vk: VerifyingKey, #[doc(hidden)] diff --git a/src/generator.rs b/src/generator.rs index 5a19386..628a741 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -1,4 +1,6 @@ -use ark_ec::{msm::FixedBaseMSM, PairingEngine, ProjectiveCurve}; +use core::ops::Mul; + +use ark_ec::{pairing::Pairing, scalar_mul::fixed_base::FixedBase, CurveGroup}; use ark_ff::{Field, One, PrimeField, UniformRand, Zero}; use ark_poly::{EvaluationDomain, GeneralEvaluationDomain}; use ark_relations::r1cs::{ @@ -18,15 +20,15 @@ use crate::{r1cs_to_sap::R1CStoSAP, ProvingKey, VerifyingKey}; #[inline] pub fn generate_random_parameters(circuit: C, rng: &mut R) -> R1CSResult> where - E: PairingEngine, - C: ConstraintSynthesizer, + E: Pairing, + C: ConstraintSynthesizer, R: Rng, { - let alpha = E::Fr::rand(rng); - let beta = E::Fr::rand(rng); - let gamma = E::Fr::one(); - let g = E::G1Projective::rand(rng); - let h = E::G2Projective::rand(rng); + let alpha = E::ScalarField::rand(rng); + let beta = E::ScalarField::rand(rng); + let gamma = E::ScalarField::one(); + let g = E::G1::rand(rng); + let h = E::G2::rand(rng); generate_parameters::(circuit, alpha, beta, gamma, g, h, rng) } @@ -34,16 +36,16 @@ where /// Create parameters for a circuit, given some toxic waste. pub fn generate_parameters( circuit: C, - alpha: E::Fr, - beta: E::Fr, - gamma: E::Fr, - g: E::G1Projective, - h: E::G2Projective, + alpha: E::ScalarField, + beta: E::ScalarField, + gamma: E::ScalarField, + g: E::G1, + h: E::G2, rng: &mut R, ) -> R1CSResult> where - E: PairingEngine, - C: ConstraintSynthesizer, + E: Pairing, + C: ConstraintSynthesizer, R: Rng, { type D = GeneralEvaluationDomain; @@ -76,8 +78,10 @@ where /////////////////////////////////////////////////////////////////////////// let reduction_time = start_timer!(|| "R1CS to SAP Instance Map with Evaluation"); - let (a, c, zt, sap_num_variables, m_raw) = - R1CStoSAP::instance_map_with_evaluation::>(cs.clone(), &t)?; + let (a, c, zt, sap_num_variables, m_raw) = R1CStoSAP::instance_map_with_evaluation::< + E::ScalarField, + D, + >(cs.clone(), &t)?; end_timer!(reduction_time); drop(cs); @@ -85,11 +89,11 @@ where let non_zero_a = cfg_into_iter!(0..sap_num_variables) .map(|i| (!a[i].is_zero()) as usize) .sum(); - let scalar_bits = E::Fr::size_in_bits(); + let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize; // Compute G window table let g_window_time = start_timer!(|| "Compute G window table"); - let g_window = FixedBaseMSM::get_mul_window_size( + let g_window = FixedBase::get_mul_window_size( // Verifier query num_inputs // A query @@ -101,7 +105,7 @@ where // G gamma2 Z t + m_raw + 1, ); - let g_table = FixedBaseMSM::get_window_table::(scalar_bits, g_window, g); + let g_table = FixedBase::get_window_table::(scalar_bits, g_window, g); end_timer!(g_window_time); // Generate the R1CS proving key @@ -109,7 +113,7 @@ where // Compute the A-query let a_time = start_timer!(|| "Calculate A"); - let a_query = FixedBaseMSM::multi_scalar_mul::( + let a_query = FixedBase::msm::( scalar_bits, g_window, &g_table, @@ -122,16 +126,16 @@ where let gamma_z = zt * γ let alpha_beta = alpha + β let ab_gamma_z = alpha_beta * &gamma * &zt; - let g_gamma = g.mul(&gamma.into_repr()); - let g_gamma_z = g.mul(&gamma_z.into_repr()); - let h_gamma = h.mul(&gamma.into_repr()); - let h_gamma_z = h_gamma.mul(&zt.into_repr()); - let g_ab_gamma_z = g.mul(&ab_gamma_z.into_repr()); - let g_gamma2_z2 = g.mul(&gamma_z.square().into_repr()); + let g_gamma = g.mul(&gamma); + let g_gamma_z = g.mul(&gamma_z); + let h_gamma = h.mul(&gamma); + let h_gamma_z = h_gamma.mul(&zt); + let g_ab_gamma_z = g.mul(&ab_gamma_z); + let g_gamma2_z2 = g.mul(&gamma_z.square()); // Compute the vector G_gamma2_z_t := Z(t) * t^i * gamma^2 * G let gamma2_z_t = gamma_z * γ - let g_gamma2_z_t = FixedBaseMSM::multi_scalar_mul::( + let g_gamma2_z_t = FixedBase::msm::( scalar_bits, g_window, &g_table, @@ -143,7 +147,7 @@ where // Compute the C_1-query let c1_time = start_timer!(|| "Calculate C1"); - let result = FixedBaseMSM::multi_scalar_mul::( + let result = FixedBase::msm::( scalar_bits, g_window, &g_table, @@ -157,7 +161,7 @@ where // Compute the C_2-query let c2_time = start_timer!(|| "Calculate C2"); let double_gamma2_z = (zt * &gamma.square()).double(); - let c_query_2 = FixedBaseMSM::multi_scalar_mul::( + let c_query_2 = FixedBase::msm::( scalar_bits, g_window, &g_table, @@ -170,19 +174,13 @@ where // Compute H_gamma window table let h_gamma_time = start_timer!(|| "Compute H table"); - let h_gamma_window = FixedBaseMSM::get_mul_window_size(non_zero_a); - let h_gamma_table = - FixedBaseMSM::get_window_table::(scalar_bits, h_gamma_window, h_gamma); + let h_gamma_window = FixedBase::get_mul_window_size(non_zero_a); + let h_gamma_table = FixedBase::get_window_table::(scalar_bits, h_gamma_window, h_gamma); end_timer!(h_gamma_time); // Compute the B-query let b_time = start_timer!(|| "Calculate B"); - let b_query = FixedBaseMSM::multi_scalar_mul::( - scalar_bits, - h_gamma_window, - &h_gamma_table, - &a, - ); + let b_query = FixedBase::msm::(scalar_bits, h_gamma_window, &h_gamma_table, &a); drop(h_gamma_table); end_timer!(b_time); @@ -190,8 +188,8 @@ where // Generate R1CS verification key let verifying_key_time = start_timer!(|| "Generate the R1CS verification key"); - let g_alpha = g.mul(&alpha.into_repr()); - let h_beta = h.mul(&beta.into_repr()); + let g_alpha = g.mul(&alpha); + let h_beta = h.mul(&beta); end_timer!(verifying_key_time); let vk = VerifyingKey:: { @@ -200,15 +198,15 @@ where h_beta_g2: h_beta.into_affine(), g_gamma_g1: g_gamma.into_affine(), h_gamma_g2: h_gamma.into_affine(), - query: E::G1Projective::batch_normalization_into_affine(&verifier_query), + query: E::G1::normalize_batch(&verifier_query), }; let batch_normalization_time = start_timer!(|| "Convert proving key elements to affine"); - let a_query = E::G1Projective::batch_normalization_into_affine(&a_query); - let b_query = E::G2Projective::batch_normalization_into_affine(&b_query); - let c_query_1 = E::G1Projective::batch_normalization_into_affine(&c_query_1); - let c_query_2 = E::G1Projective::batch_normalization_into_affine(&c_query_2); - let g_gamma2_z_t = E::G1Projective::batch_normalization_into_affine(&g_gamma2_z_t); + let a_query = E::G1::normalize_batch(&a_query); + let b_query = E::G2::normalize_batch(&b_query); + let c_query_1 = E::G1::normalize_batch(&c_query_1); + let c_query_2 = E::G1::normalize_batch(&c_query_2); + let g_gamma2_z_t = E::G1::normalize_batch(&g_gamma2_z_t); end_timer!(batch_normalization_time); end_timer!(setup_time); diff --git a/src/lib.rs b/src/lib.rs index d956c68..aae4cf0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,14 +2,7 @@ //! //! [`Groth-Maller`]: https://eprint.iacr.org/2017/540 #![cfg_attr(not(feature = "std"), no_std)] -#![deny( - warnings, - unused, - future_incompatible, - nonstandard_style, - rust_2018_idioms, - missing_docs -)] +#![deny(future_incompatible, nonstandard_style, rust_2018_idioms, missing_docs)] #![allow(clippy::many_single_char_names, clippy::op_ref)] #![forbid(unsafe_code)] @@ -42,28 +35,29 @@ pub mod constraints; #[cfg(test)] mod test; -pub use self::data_structures::*; -pub use self::{generator::*, prover::*, verifier::*}; +pub use self::{data_structures::*, generator::*, prover::*, verifier::*}; use ark_crypto_primitives::snark::{CircuitSpecificSetupSNARK, SNARK}; -use ark_ec::PairingEngine; +use ark_ec::pairing::Pairing; use ark_relations::r1cs::{ConstraintSynthesizer, SynthesisError}; -use ark_std::marker::PhantomData; -use ark_std::rand::RngCore; +use ark_std::{ + marker::PhantomData, + rand::{CryptoRng, RngCore}, +}; /// The SNARK of [[GrothMaller17]](https://eprint.iacr.org/2017/540). -pub struct GM17 { +pub struct GM17 { e_phantom: PhantomData, } -impl SNARK for GM17 { +impl SNARK for GM17 { type ProvingKey = ProvingKey; type VerifyingKey = VerifyingKey; type Proof = Proof; type ProcessedVerifyingKey = PreparedVerifyingKey; type Error = SynthesisError; - fn circuit_specific_setup, R: RngCore>( + fn circuit_specific_setup, R: RngCore + CryptoRng>( circuit: C, rng: &mut R, ) -> Result<(Self::ProvingKey, Self::VerifyingKey), Self::Error> { @@ -73,7 +67,7 @@ impl SNARK for GM17 { Ok((pk, vk)) } - fn prove, R: RngCore>( + fn prove, R: RngCore + CryptoRng>( pk: &Self::ProvingKey, circuit: C, rng: &mut R, @@ -89,11 +83,11 @@ impl SNARK for GM17 { fn verify_with_processed_vk( circuit_pvk: &Self::ProcessedVerifyingKey, - x: &[E::Fr], + x: &[E::ScalarField], proof: &Self::Proof, ) -> Result { Ok(verify_proof(&circuit_pvk, proof, &x)?) } } -impl CircuitSpecificSetupSNARK for GM17 {} +impl CircuitSpecificSetupSNARK for GM17 {} diff --git a/src/prover.rs b/src/prover.rs index ea273e5..5130ae6 100644 --- a/src/prover.rs +++ b/src/prover.rs @@ -1,9 +1,12 @@ -use ark_std::rand::Rng; +use ark_std::{borrow::ToOwned, rand::Rng}; +use core::ops::Mul; #[cfg(feature = "parallel")] use rayon::prelude::*; -use ark_ec::{msm::VariableBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve}; -use ark_ff::{PrimeField, UniformRand}; +use ark_ec::{ + pairing::Pairing, scalar_mul::variable_base::VariableBaseMSM, AffineRepr, CurveGroup, +}; +use ark_ff::UniformRand; use ark_poly::GeneralEvaluationDomain; use ark_std::{cfg_into_iter, vec::Vec}; @@ -21,13 +24,13 @@ pub fn create_random_proof( rng: &mut R, ) -> Result, SynthesisError> where - E: PairingEngine, - C: ConstraintSynthesizer, + E: Pairing, + C: ConstraintSynthesizer, R: Rng, { - let d1 = E::Fr::rand(rng); - let d2 = E::Fr::rand(rng); - let r = E::Fr::rand(rng); + let d1 = E::ScalarField::rand(rng); + let d2 = E::ScalarField::rand(rng); + let r = E::ScalarField::rand(rng); create_proof::(circuit, params, d1, d2, r) } @@ -36,13 +39,13 @@ where pub fn create_proof( circuit: C, params: &ProvingKey, - d1: E::Fr, - d2: E::Fr, - r: E::Fr, + d1: E::ScalarField, + d2: E::ScalarField, + r: E::ScalarField, ) -> Result, SynthesisError> where - E: PairingEngine, - C: ConstraintSynthesizer, + E: Pairing, + C: ConstraintSynthesizer, { type D = GeneralEvaluationDomain; @@ -63,41 +66,42 @@ where let witness_map_time = start_timer!(|| "R1CS to SAP witness map"); let (full_input_assignment, h, _) = - R1CStoSAP::witness_map::>(cs.clone(), &d1, &d2)?; + R1CStoSAP::witness_map::>(cs.clone(), &d1, &d2)?; end_timer!(witness_map_time); let prover = cs.borrow().unwrap(); let num_inputs = prover.num_instance_variables; let input_assignment = full_input_assignment[1..num_inputs] .iter() - .map(|s| s.into_repr()) + .map(|s| s.to_owned()) .collect::>(); let aux_assignment = cfg_into_iter!(full_input_assignment[num_inputs..]) - .map(|s| s.into_repr()) + .map(|s| s.to_owned()) .collect::>(); drop(full_input_assignment); let h_input = h[0..num_inputs] .iter() - .map(|s| s.into_repr()) + .map(|s| s.to_owned()) .collect::>(); + let h_aux = cfg_into_iter!(h[num_inputs..]) - .map(|s| s.into_repr()) + .map(|s| s.to_owned()) .collect::>(); drop(h); // Compute A let a_acc_time = start_timer!(|| "Compute A"); let (a_inputs, a_aux) = params.a_query.split_at(num_inputs); - let a_inputs_acc = VariableBaseMSM::multi_scalar_mul(&a_inputs[1..], &input_assignment); - let a_aux_acc = VariableBaseMSM::multi_scalar_mul(a_aux, &aux_assignment); + let a_inputs_acc: E::G1 = VariableBaseMSM::msm(&a_inputs[1..], &input_assignment).unwrap(); + let a_aux_acc: E::G1 = VariableBaseMSM::msm(a_aux, &aux_assignment).unwrap(); let r_g = params.g_gamma_z.mul(r); let d1_g = params.g_gamma_z.mul(d1); let mut g_a = r_g; - g_a += ¶ms.a_query[0].into_projective(); + g_a += ¶ms.a_query[0].into_group(); g_a += &d1_g; g_a += &a_inputs_acc; g_a += &a_aux_acc; @@ -107,14 +111,14 @@ where let b_acc_time = start_timer!(|| "Compute B"); let (b_inputs, b_aux) = params.b_query.split_at(num_inputs); - let b_inputs_acc = VariableBaseMSM::multi_scalar_mul(&b_inputs[1..], &input_assignment); - let b_aux_acc = VariableBaseMSM::multi_scalar_mul(b_aux, &aux_assignment); + let b_inputs_acc: E::G2 = VariableBaseMSM::msm(&b_inputs[1..], &input_assignment).unwrap(); + let b_aux_acc: E::G2 = VariableBaseMSM::msm(b_aux, &aux_assignment).unwrap(); let r_h = params.h_gamma_z.mul(r); let d1_h = params.h_gamma_z.mul(d1); let mut g_b = r_h; - g_b += ¶ms.b_query[0].into_projective(); + g_b += ¶ms.b_query[0].into_group(); g_b += &d1_h; g_b += &b_inputs_acc; g_b += &b_aux_acc; @@ -127,14 +131,14 @@ where let d1_r_2 = d1 * &r_2; let c1_acc_time = start_timer!(|| "Compute C1"); - let c1_acc = VariableBaseMSM::multi_scalar_mul(¶ms.c_query_1, &aux_assignment); + let c1_acc: E::G1 = VariableBaseMSM::msm(¶ms.c_query_1, &aux_assignment).unwrap(); end_timer!(c1_acc_time); let c2_acc_time = start_timer!(|| "Compute C2"); let (c2_inputs, c2_aux) = params.c_query_2.split_at(num_inputs); - let c2_inputs_acc = VariableBaseMSM::multi_scalar_mul(&c2_inputs[1..], &input_assignment); - let c2_aux_acc = VariableBaseMSM::multi_scalar_mul(c2_aux, &aux_assignment); + let c2_inputs_acc: E::G1 = VariableBaseMSM::msm(&c2_inputs[1..], &input_assignment).unwrap(); + let c2_aux_acc: E::G1 = VariableBaseMSM::msm(c2_aux, &aux_assignment).unwrap(); let c2_acc = c2_inputs_acc + &c2_aux_acc; end_timer!(c2_acc_time); @@ -143,8 +147,8 @@ where let g_acc_time = start_timer!(|| "Compute G"); let (g_inputs, g_aux) = params.g_gamma2_z_t.split_at(num_inputs); - let g_inputs_acc = VariableBaseMSM::multi_scalar_mul(g_inputs, &h_input); - let g_aux_acc = VariableBaseMSM::multi_scalar_mul(g_aux, &h_aux); + let g_inputs_acc: E::G1 = VariableBaseMSM::msm(g_inputs, &h_input).unwrap(); + let g_aux_acc: E::G1 = VariableBaseMSM::msm(g_aux, &h_aux).unwrap(); let g_acc = g_inputs_acc + &g_aux_acc; end_timer!(g_acc_time); diff --git a/src/r1cs_to_sap.rs b/src/r1cs_to_sap.rs index 0e12871..8947da0 100644 --- a/src/r1cs_to_sap.rs +++ b/src/r1cs_to_sap.rs @@ -134,6 +134,8 @@ impl R1CStoSAP { .ok_or(SynthesisError::PolynomialDegreeTooLarge)?; let domain_size = domain.size(); + let coset_domain = domain.get_coset(F::GENERATOR).unwrap(); + let extra_constr_offset = 2 * num_constraints; let extra_var_offset = num_inputs + num_aux; let extra_var_offset2 = num_inputs + num_aux + num_constraints - 1; @@ -165,7 +167,7 @@ impl R1CStoSAP { h[0] -= &d1d1; h.push(d1d1); - domain.coset_fft_in_place(&mut a); + coset_domain.fft_in_place(&mut a); let mut aa = domain.mul_polynomials_in_evaluation_domain(&a, &a); drop(a); @@ -194,14 +196,18 @@ impl R1CStoSAP { } domain.ifft_in_place(&mut c); - domain.coset_fft_in_place(&mut c); + coset_domain.fft_in_place(&mut c); cfg_iter_mut!(aa) .zip(c) .for_each(|(aa_i, c_i)| *aa_i -= &c_i); - domain.divide_by_vanishing_poly_on_coset_in_place(&mut aa); - domain.coset_ifft_in_place(&mut aa); + let i = domain + .evaluate_vanishing_polynomial(F::GENERATOR) + .inverse() + .unwrap(); + ark_std::cfg_iter_mut!(aa).for_each(|eval| *eval *= &i); + coset_domain.ifft_in_place(&mut aa); cfg_iter_mut!(h[..domain_size - 1]) .enumerate() diff --git a/src/verifier.rs b/src/verifier.rs index 9c149db..36b334b 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -1,16 +1,20 @@ -use ark_ec::{AffineCurve, PairingEngine, ProjectiveCurve}; -use ark_ff::One; +use ark_ec::{ + pairing::{MillerLoopOutput, Pairing}, + AffineRepr, CurveGroup, +}; use ark_relations::r1cs::{Result as R1CSResult, SynthesisError}; +use ark_std::{borrow::ToOwned, Zero}; +use core::ops::{AddAssign, Mul}; use super::{PreparedVerifyingKey, Proof, VerifyingKey}; /// Prepare the verifying key `vk` for use in proof verification. -pub fn prepare_verifying_key(vk: &VerifyingKey) -> PreparedVerifyingKey { +pub fn prepare_verifying_key(vk: &VerifyingKey) -> PreparedVerifyingKey { PreparedVerifyingKey { vk: vk.clone(), g_alpha: vk.g_alpha_g1, h_beta: vk.h_beta_g2, - g_alpha_h_beta_ml: E::miller_loop([(vk.g_alpha_g1.into(), vk.h_beta_g2.into())].iter()), + g_alpha_h_beta_ml: E::miller_loop(vk.g_alpha_g1, vk.h_beta_g2).0, g_gamma_pc: vk.g_gamma_g1.into(), h_gamma_pc: vk.h_gamma_g2.into(), h_pc: vk.h_g2.into(), @@ -18,12 +22,12 @@ pub fn prepare_verifying_key(vk: &VerifyingKey) -> Prepared } } -/// Verify a GrothMaller17 proof `proof` against the prepared verification key `pvk`, -/// with respect to the instance `public_inputs`. -pub fn verify_proof( +/// Verify a GrothMaller17 proof `proof` against the prepared verification key +/// `pvk`, with respect to the instance `public_inputs`. +pub fn verify_proof( pvk: &PreparedVerifyingKey, proof: &Proof, - public_inputs: &[E::Fr], + public_inputs: &[E::ScalarField], ) -> R1CSResult { if (public_inputs.len() + 1) != pvk.query.len() { return Err(SynthesisError::MalformedVerifyingKey); @@ -32,38 +36,47 @@ pub fn verify_proof( // e(A*G^{alpha}, B*H^{beta}) = e(G^{alpha}, H^{beta}) * e(G^{psi}, H^{gamma}) * // e(C, H) where psi = \sum_{i=0}^l input_i pvk.query[i] - let mut g_psi = pvk.query[0].into_projective(); + let mut g_psi = pvk.query[0].into_group(); for (i, b) in public_inputs.iter().zip(pvk.query.iter().skip(1)) { g_psi += &b.mul(*i); } - let mut test1_a_g_alpha = proof.a.into_projective(); - test1_a_g_alpha.add_assign_mixed(&pvk.g_alpha); + let mut test1_a_g_alpha = proof.a.into_group(); + test1_a_g_alpha.add_assign(&pvk.g_alpha); let test1_a_g_alpha = test1_a_g_alpha.into_affine(); - let mut test1_b_h_beta = proof.b.into_projective(); - test1_b_h_beta.add_assign_mixed(&pvk.h_beta); + let mut test1_b_h_beta = proof.b.into_group(); + test1_b_h_beta.add_assign(&pvk.h_beta); let test1_b_h_beta = test1_b_h_beta.into_affine(); let test1_r1 = pvk.g_alpha_h_beta_ml; - let test1_r2_input: &[(E::G1Prepared, E::G2Prepared)] = &[ - ((-test1_a_g_alpha).into(), test1_b_h_beta.into()), - (g_psi.into().into(), pvk.h_gamma_pc.clone()), - (proof.c.into(), pvk.h_pc.clone()), + let test1_r2_input_g1 = [ + -test1_a_g_alpha.into_group(), + g_psi.into().into(), + proof.c.into(), ]; - let test1_r2 = E::miller_loop(test1_r2_input.iter()); - let test1 = E::final_exponentiation(&(test1_r2 * &test1_r1)).unwrap(); + let test1_r2_input_g2 = [ + test1_b_h_beta.into(), + pvk.h_gamma_pc.clone(), + pvk.h_pc.clone(), + ]; + + let test1_r2 = E::multi_miller_loop(test1_r2_input_g1.to_owned(), test1_r2_input_g2.to_owned()); + let mlo = MillerLoopOutput(test1_r1 * test1_r2.0); + let test1 = E::final_exponentiation(mlo).unwrap(); // e(A, H^{gamma}) = e(G^{gamma}, B) - let test2_exp_input: &[(E::G1Prepared, E::G2Prepared)] = &[ - (proof.a.into(), pvk.h_gamma_pc.clone()), - (pvk.g_gamma_pc.clone(), (-proof.b).into()), + let test2_exp_input_g1 = [proof.a.into(), pvk.g_gamma_pc.clone()]; + let test2_exp_input_g2 = [ + pvk.h_gamma_pc.clone(), + (-proof.b.into_group()).into().into(), ]; - let test2_exp = E::miller_loop(test2_exp_input.iter()); - let test2 = E::final_exponentiation(&test2_exp).unwrap(); + let test2_exp = + E::multi_miller_loop(test2_exp_input_g1.to_owned(), test2_exp_input_g2.to_owned()); + let test2 = E::final_exponentiation(test2_exp).unwrap(); - Ok(test1.is_one() && test2.is_one()) + Ok(test1.is_zero() && test2.is_zero()) } diff --git a/tests/mimc.rs b/tests/mimc.rs index afd3dd6..1b35574 100644 --- a/tests/mimc.rs +++ b/tests/mimc.rs @@ -17,13 +17,7 @@ unused_allocation, unused_comparisons )] -#![deny( - unused_must_use, - unused_mut, - unused_unsafe, - private_in_public, - unsafe_code -)] +#![deny(unused_must_use, unused_mut, unused_unsafe, unsafe_code)] // For randomness (during paramgen and proof generation) use ark_std::rand::Rng;