diff --git a/Cargo.lock b/Cargo.lock index 2b448b65..c477d522 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,8 +43,10 @@ dependencies = [ "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "group 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "pairing 0.14.2", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/bellman/Cargo.toml b/bellman/Cargo.toml index b7699cf7..6812a7fe 100644 --- a/bellman/Cargo.toml +++ b/bellman/Cargo.toml @@ -11,12 +11,20 @@ version = "0.1.0" [dependencies] rand = "0.4" bit-vec = "0.4.4" +ff = "0.4" futures = "0.1" futures-cpupool = "0.1" +group = "0.1" num_cpus = "1" crossbeam = "0.3" -pairing = { path = "../pairing" } +pairing = { path = "../pairing", optional = true } byteorder = "1" [features] -default = [] +groth16 = ["pairing"] +default = ["groth16"] + +[[test]] +name = "mimc" +path = "tests/mimc.rs" +required-features = ["groth16"] diff --git a/bellman/src/domain.rs b/bellman/src/domain.rs index ff626e5d..4606ce5a 100644 --- a/bellman/src/domain.rs +++ b/bellman/src/domain.rs @@ -10,12 +10,8 @@ //! This allows us to perform polynomial operations in O(n) //! by performing an O(n log n) FFT over such a domain. -use pairing::{ - Engine, - Field, - PrimeField, - CurveProjective -}; +use ff::{Field, PrimeField, ScalarEngine}; +use group::CurveProjective; use super::{ SynthesisError @@ -23,7 +19,7 @@ use super::{ use super::multicore::Worker; -pub struct EvaluationDomain> { +pub struct EvaluationDomain> { coeffs: Vec, exp: u32, omega: E::Fr, @@ -32,7 +28,7 @@ pub struct EvaluationDomain> { minv: E::Fr } -impl> EvaluationDomain { +impl> EvaluationDomain { pub fn as_ref(&self) -> &[G] { &self.coeffs } @@ -189,7 +185,7 @@ impl> EvaluationDomain { } } -pub trait Group: Sized + Copy + Clone + Send + Sync { +pub trait Group: Sized + Copy + Clone + Send + Sync { fn group_zero() -> Self; fn group_mul_assign(&mut self, by: &E::Fr); fn group_add_assign(&mut self, other: &Self); @@ -227,23 +223,23 @@ impl Group for Point { } } -pub struct Scalar(pub E::Fr); +pub struct Scalar(pub E::Fr); -impl PartialEq for Scalar { +impl PartialEq for Scalar { fn eq(&self, other: &Scalar) -> bool { self.0 == other.0 } } -impl Copy for Scalar { } +impl Copy for Scalar { } -impl Clone for Scalar { +impl Clone for Scalar { fn clone(&self) -> Scalar { *self } } -impl Group for Scalar { +impl Group for Scalar { fn group_zero() -> Self { Scalar(E::Fr::zero()) } @@ -258,7 +254,7 @@ impl Group for Scalar { } } -fn best_fft>(a: &mut [T], worker: &Worker, omega: &E::Fr, log_n: u32) +fn best_fft>(a: &mut [T], worker: &Worker, omega: &E::Fr, log_n: u32) { let log_cpus = worker.log_num_cpus(); @@ -269,7 +265,7 @@ fn best_fft>(a: &mut [T], worker: &Worker, omega: &E::Fr, } } -fn serial_fft>(a: &mut [T], omega: &E::Fr, log_n: u32) +fn serial_fft>(a: &mut [T], omega: &E::Fr, log_n: u32) { fn bitreverse(mut n: u32, l: u32) -> u32 { let mut r = 0; @@ -314,7 +310,7 @@ fn serial_fft>(a: &mut [T], omega: &E::Fr, log_n: u32) } } -fn parallel_fft>( +fn parallel_fft>( a: &mut [T], worker: &Worker, omega: &E::Fr, @@ -375,12 +371,13 @@ fn parallel_fft>( // Test multiplying various (low degree) polynomials together and // comparing with naive evaluations. +#[cfg(feature = "pairing")] #[test] fn polynomial_arith() { use pairing::bls12_381::Bls12; use rand::{self, Rand}; - fn test_mul(rng: &mut R) + fn test_mul(rng: &mut R) { let worker = Worker::new(); @@ -422,12 +419,13 @@ fn polynomial_arith() { test_mul::(rng); } +#[cfg(feature = "pairing")] #[test] fn fft_composition() { use pairing::bls12_381::Bls12; use rand; - fn test_comp(rng: &mut R) + fn test_comp(rng: &mut R) { let worker = Worker::new(); @@ -460,13 +458,14 @@ fn fft_composition() { test_comp::(rng); } +#[cfg(feature = "pairing")] #[test] fn parallel_fft_consistency() { use pairing::bls12_381::Bls12; use rand::{self, Rand}; use std::cmp::min; - fn test_consistency(rng: &mut R) + fn test_consistency(rng: &mut R) { let worker = Worker::new(); diff --git a/bellman/src/groth16/generator.rs b/bellman/src/groth16/generator.rs index 1eed62db..f3f3d3af 100644 --- a/bellman/src/groth16/generator.rs +++ b/bellman/src/groth16/generator.rs @@ -2,14 +2,9 @@ use rand::Rng; use std::sync::Arc; -use pairing::{ - Engine, - PrimeField, - Field, - Wnaf, - CurveProjective, - CurveAffine -}; +use ff::{Field, PrimeField}; +use group::{CurveAffine, CurveProjective, Wnaf}; +use pairing::Engine; use super::{ Parameters, diff --git a/bellman/src/groth16/mod.rs b/bellman/src/groth16/mod.rs index 3b8d6714..620f32ed 100644 --- a/bellman/src/groth16/mod.rs +++ b/bellman/src/groth16/mod.rs @@ -1,7 +1,7 @@ +use group::{CurveAffine, EncodedPoint}; use pairing::{ Engine, - CurveAffine, - EncodedPoint + PairingCurveAffine, }; use ::{ @@ -385,9 +385,9 @@ pub struct PreparedVerifyingKey { /// Pairing result of alpha*beta alpha_g1_beta_g2: E::Fqk, /// -gamma in G2 - neg_gamma_g2: ::Prepared, + neg_gamma_g2: ::Prepared, /// -delta in G2 - neg_delta_g2: ::Prepared, + neg_delta_g2: ::Prepared, /// Copy of IC from `VerifiyingKey`. ic: Vec } @@ -486,8 +486,8 @@ mod test_with_bls12_381 { use super::*; use {Circuit, SynthesisError, ConstraintSystem}; + use ff::Field; use rand::{Rand, thread_rng}; - use pairing::{Field}; use pairing::bls12_381::{Bls12, Fr}; #[test] diff --git a/bellman/src/groth16/prover.rs b/bellman/src/groth16/prover.rs index f21fcce9..c674622c 100644 --- a/bellman/src/groth16/prover.rs +++ b/bellman/src/groth16/prover.rs @@ -4,13 +4,9 @@ use std::sync::Arc; use futures::Future; -use pairing::{ - Engine, - PrimeField, - Field, - CurveProjective, - CurveAffine -}; +use ff::{Field, PrimeField}; +use group::{CurveAffine, CurveProjective}; +use pairing::Engine; use super::{ ParameterSource, diff --git a/bellman/src/groth16/tests/dummy_engine.rs b/bellman/src/groth16/tests/dummy_engine.rs index 26c89965..d5f37a97 100644 --- a/bellman/src/groth16/tests/dummy_engine.rs +++ b/bellman/src/groth16/tests/dummy_engine.rs @@ -1,16 +1,8 @@ -use pairing::{ - Engine, - PrimeField, - PrimeFieldRepr, - Field, - SqrtField, - LegendreSymbol, - CurveProjective, - CurveAffine, - PrimeFieldDecodingError, - GroupDecodingError, - EncodedPoint -}; +use ff::{ + Field, LegendreSymbol, PrimeField, PrimeFieldDecodingError, + PrimeFieldRepr, ScalarEngine, SqrtField}; +use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; +use pairing::{Engine, PairingCurveAffine}; use std::cmp::Ordering; use std::fmt; @@ -263,8 +255,11 @@ impl PrimeField for Fr { #[derive(Clone)] pub struct DummyEngine; -impl Engine for DummyEngine { +impl ScalarEngine for DummyEngine { type Fr = Fr; +} + +impl Engine for DummyEngine { type G1 = Fr; type G1Affine = Fr; type G2 = Fr; @@ -277,8 +272,8 @@ impl Engine for DummyEngine { fn miller_loop<'a, I>(i: I) -> Self::Fqk where I: IntoIterator::Prepared, - &'a ::Prepared + &'a ::Prepared, + &'a ::Prepared )> { let mut acc = ::zero(); @@ -401,11 +396,8 @@ impl EncodedPoint for FakePoint { } impl CurveAffine for Fr { - type Pair = Fr; - type PairingResult = Fr; type Compressed = FakePoint; type Uncompressed = FakePoint; - type Prepared = Fr; type Projective = Fr; type Base = Fr; type Scalar = Fr; @@ -437,6 +429,16 @@ impl CurveAffine for Fr { res } + fn into_projective(&self) -> Self::Projective { + *self + } +} + +impl PairingCurveAffine for Fr { + type Prepared = Fr; + type Pair = Fr; + type PairingResult = Fr; + fn prepare(&self) -> Self::Prepared { *self } @@ -444,8 +446,4 @@ impl CurveAffine for Fr { fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult { self.mul(*other) } - - fn into_projective(&self) -> Self::Projective { - *self - } } diff --git a/bellman/src/groth16/tests/mod.rs b/bellman/src/groth16/tests/mod.rs index a8e29147..0e05c36a 100644 --- a/bellman/src/groth16/tests/mod.rs +++ b/bellman/src/groth16/tests/mod.rs @@ -1,8 +1,5 @@ -use pairing::{ - Engine, - Field, - PrimeField -}; +use ff::{Field, PrimeField}; +use pairing::Engine; mod dummy_engine; use self::dummy_engine::*; diff --git a/bellman/src/groth16/verifier.rs b/bellman/src/groth16/verifier.rs index 083e1d02..71c74783 100644 --- a/bellman/src/groth16/verifier.rs +++ b/bellman/src/groth16/verifier.rs @@ -1,9 +1,6 @@ -use pairing::{ - Engine, - CurveProjective, - CurveAffine, - PrimeField -}; +use ff::PrimeField; +use group::{CurveAffine, CurveProjective}; +use pairing::{Engine, PairingCurveAffine}; use super::{ Proof, diff --git a/bellman/src/lib.rs b/bellman/src/lib.rs index fb8d0431..f6d71639 100644 --- a/bellman/src/lib.rs +++ b/bellman/src/lib.rs @@ -1,3 +1,6 @@ +extern crate ff; +extern crate group; +#[cfg(feature = "pairing")] extern crate pairing; extern crate rand; extern crate num_cpus; @@ -10,9 +13,10 @@ extern crate byteorder; pub mod multicore; mod multiexp; pub mod domain; +#[cfg(feature = "groth16")] pub mod groth16; -use pairing::{Engine, Field}; +use ff::{Field, ScalarEngine}; use std::ops::{Add, Sub}; use std::fmt; @@ -24,7 +28,7 @@ use std::marker::PhantomData; /// rank-1 quadratic constraint systems. The `Circuit` trait represents a /// circuit that can be synthesized. The `synthesize` method is called during /// CRS generation and during proving. -pub trait Circuit { +pub trait Circuit { /// Synthesize the circuit into a rank-1 quadratic constraint system fn synthesize>( self, @@ -61,21 +65,21 @@ pub enum Index { /// This represents a linear combination of some variables, with coefficients /// in the scalar field of a pairing-friendly elliptic curve group. #[derive(Clone)] -pub struct LinearCombination(Vec<(Variable, E::Fr)>); +pub struct LinearCombination(Vec<(Variable, E::Fr)>); -impl AsRef<[(Variable, E::Fr)]> for LinearCombination { +impl AsRef<[(Variable, E::Fr)]> for LinearCombination { fn as_ref(&self) -> &[(Variable, E::Fr)] { &self.0 } } -impl LinearCombination { +impl LinearCombination { pub fn zero() -> LinearCombination { LinearCombination(vec![]) } } -impl Add<(E::Fr, Variable)> for LinearCombination { +impl Add<(E::Fr, Variable)> for LinearCombination { type Output = LinearCombination; fn add(mut self, (coeff, var): (E::Fr, Variable)) -> LinearCombination { @@ -85,7 +89,7 @@ impl Add<(E::Fr, Variable)> for LinearCombination { } } -impl Sub<(E::Fr, Variable)> for LinearCombination { +impl Sub<(E::Fr, Variable)> for LinearCombination { type Output = LinearCombination; fn sub(self, (mut coeff, var): (E::Fr, Variable)) -> LinearCombination { @@ -95,7 +99,7 @@ impl Sub<(E::Fr, Variable)> for LinearCombination { } } -impl Add for LinearCombination { +impl Add for LinearCombination { type Output = LinearCombination; fn add(self, other: Variable) -> LinearCombination { @@ -103,7 +107,7 @@ impl Add for LinearCombination { } } -impl Sub for LinearCombination { +impl Sub for LinearCombination { type Output = LinearCombination; fn sub(self, other: Variable) -> LinearCombination { @@ -111,7 +115,7 @@ impl Sub for LinearCombination { } } -impl<'a, E: Engine> Add<&'a LinearCombination> for LinearCombination { +impl<'a, E: ScalarEngine> Add<&'a LinearCombination> for LinearCombination { type Output = LinearCombination; fn add(mut self, other: &'a LinearCombination) -> LinearCombination { @@ -123,7 +127,7 @@ impl<'a, E: Engine> Add<&'a LinearCombination> for LinearCombination { } } -impl<'a, E: Engine> Sub<&'a LinearCombination> for LinearCombination { +impl<'a, E: ScalarEngine> Sub<&'a LinearCombination> for LinearCombination { type Output = LinearCombination; fn sub(mut self, other: &'a LinearCombination) -> LinearCombination { @@ -135,7 +139,7 @@ impl<'a, E: Engine> Sub<&'a LinearCombination> for LinearCombination { } } -impl<'a, E: Engine> Add<(E::Fr, &'a LinearCombination)> for LinearCombination { +impl<'a, E: ScalarEngine> Add<(E::Fr, &'a LinearCombination)> for LinearCombination { type Output = LinearCombination; fn add(mut self, (coeff, other): (E::Fr, &'a LinearCombination)) -> LinearCombination { @@ -149,7 +153,7 @@ impl<'a, E: Engine> Add<(E::Fr, &'a LinearCombination)> for LinearCombination } } -impl<'a, E: Engine> Sub<(E::Fr, &'a LinearCombination)> for LinearCombination { +impl<'a, E: ScalarEngine> Sub<(E::Fr, &'a LinearCombination)> for LinearCombination { type Output = LinearCombination; fn sub(mut self, (coeff, other): (E::Fr, &'a LinearCombination)) -> LinearCombination { @@ -219,7 +223,7 @@ impl fmt::Display for SynthesisError { /// Represents a constraint system which can have new variables /// allocated and constrains between them formed. -pub trait ConstraintSystem: Sized { +pub trait ConstraintSystem: Sized { /// Represents the type of the "root" of this constraint system /// so that nested namespaces can minimize indirection. type Root: ConstraintSystem; @@ -291,9 +295,9 @@ pub trait ConstraintSystem: Sized { /// This is a "namespaced" constraint system which borrows a constraint system (pushing /// a namespace context) and, when dropped, pops out of the namespace context. -pub struct Namespace<'a, E: Engine, CS: ConstraintSystem + 'a>(&'a mut CS, PhantomData); +pub struct Namespace<'a, E: ScalarEngine, CS: ConstraintSystem + 'a>(&'a mut CS, PhantomData); -impl<'cs, E: Engine, CS: ConstraintSystem> ConstraintSystem for Namespace<'cs, E, CS> { +impl<'cs, E: ScalarEngine, CS: ConstraintSystem> ConstraintSystem for Namespace<'cs, E, CS> { type Root = CS::Root; fn one() -> Variable { @@ -356,7 +360,7 @@ impl<'cs, E: Engine, CS: ConstraintSystem> ConstraintSystem for Namespace< } } -impl<'a, E: Engine, CS: ConstraintSystem> Drop for Namespace<'a, E, CS> { +impl<'a, E: ScalarEngine, CS: ConstraintSystem> Drop for Namespace<'a, E, CS> { fn drop(&mut self) { self.get_root().pop_namespace() } @@ -364,7 +368,7 @@ impl<'a, E: Engine, CS: ConstraintSystem> Drop for Namespace<'a, E, CS> { /// Convenience implementation of ConstraintSystem for mutable references to /// constraint systems. -impl<'cs, E: Engine, CS: ConstraintSystem> ConstraintSystem for &'cs mut CS { +impl<'cs, E: ScalarEngine, CS: ConstraintSystem> ConstraintSystem for &'cs mut CS { type Root = CS::Root; fn one() -> Variable { diff --git a/bellman/src/multiexp.rs b/bellman/src/multiexp.rs index b1dc1f1f..d24572bf 100644 --- a/bellman/src/multiexp.rs +++ b/bellman/src/multiexp.rs @@ -1,11 +1,5 @@ -use pairing::{ - CurveAffine, - CurveProjective, - Engine, - PrimeField, - Field, - PrimeFieldRepr -}; +use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine}; +use group::{CurveAffine, CurveProjective}; use std::sync::Arc; use std::io; use bit_vec::{self, BitVec}; @@ -141,7 +135,7 @@ fn multiexp_inner( pool: &Worker, bases: S, density_map: D, - exponents: Arc::Fr as PrimeField>::Repr>>, + exponents: Arc::Fr as PrimeField>::Repr>>, mut skip: u32, c: u32, handle_trivial: bool @@ -167,8 +161,8 @@ fn multiexp_inner( // Create space for the buckets let mut buckets = vec![::Projective::zero(); (1 << c) - 1]; - let zero = ::Fr::zero().into_repr(); - let one = ::Fr::one().into_repr(); + let zero = ::Fr::zero().into_repr(); + let one = ::Fr::one().into_repr(); // Sort the bases into buckets for (&exp, density) in exponents.iter().zip(density_map.as_ref().iter()) { @@ -211,7 +205,7 @@ fn multiexp_inner( skip += c; - if skip >= ::Fr::NUM_BITS { + if skip >= ::Fr::NUM_BITS { // There isn't another region. Box::new(this) } else { @@ -238,7 +232,7 @@ pub fn multiexp( pool: &Worker, bases: S, density_map: D, - exponents: Arc::Fr as PrimeField>::Repr>> + exponents: Arc::Fr as PrimeField>::Repr>> ) -> Box::Projective, Error=SynthesisError>> where for<'a> &'a Q: QueryDensity, D: Send + Sync + 'static + Clone + AsRef, @@ -261,6 +255,7 @@ pub fn multiexp( multiexp_inner(pool, bases, density_map, exponents, 0, c, true) } +#[cfg(feature = "pairing")] #[test] fn test_with_bls12() { fn naive_multiexp( @@ -280,12 +275,12 @@ fn test_with_bls12() { } use rand::{self, Rand}; - use pairing::bls12_381::Bls12; + use pairing::{bls12_381::Bls12, Engine}; const SAMPLES: usize = 1 << 14; let rng = &mut rand::thread_rng(); - let v = Arc::new((0..SAMPLES).map(|_| ::Fr::rand(rng).into_repr()).collect::>()); + let v = Arc::new((0..SAMPLES).map(|_| ::Fr::rand(rng).into_repr()).collect::>()); let g = Arc::new((0..SAMPLES).map(|_| ::G1::rand(rng).into_affine()).collect::>()); let naive = naive_multiexp(g.clone(), v.clone()); diff --git a/bellman/tests/mimc.rs b/bellman/tests/mimc.rs index d6ff72b7..1d554a57 100644 --- a/bellman/tests/mimc.rs +++ b/bellman/tests/mimc.rs @@ -1,4 +1,5 @@ extern crate bellman; +extern crate ff; extern crate pairing; extern crate rand; @@ -9,10 +10,8 @@ use rand::{thread_rng, Rng}; use std::time::{Duration, Instant}; // Bring in some tools for using pairing-friendly curves -use pairing::{ - Engine, - Field -}; +use ff::Field; +use pairing::Engine; // We're going to use the BLS12-381 pairing-friendly elliptic curve. use pairing::bls12_381::{