Skip to content
Permalink
Browse files

gm17 works with no-std (#93)

  • Loading branch information
debris committed Feb 5, 2020
1 parent ac16584 commit 317fc336aed48a32d0611c595a0304ddffd7af59
Showing with 97 additions and 81 deletions.
  1. +5 −0 .travis.yml
  2. +14 −0 ff-fft/src/lib.rs
  3. +10 −7 gm17/Cargo.toml
  4. +9 −13 gm17/src/generator.rs
  5. +16 −2 gm17/src/lib.rs
  6. +19 −30 gm17/src/prover.rs
  7. +10 −14 gm17/src/r1cs_to_sap.rs
  8. +5 −8 gm17/src/test.rs
  9. +1 −1 gm17/src/verifier.rs
  10. +3 −3 gm17/tests/mimc.rs
  11. +5 −3 groth16/src/lib.rs
@@ -70,6 +70,11 @@ matrix:
- cargo build -p groth16 --no-default-features --target thumbv6m-none-eabi
- cargo check --examples -p groth16 --no-default-features --target thumbv6m-none-eabi
- cd ..
# test gm17
- cd gm17
- cargo build -p gm17 --no-default-features --target thumbv6m-none-eabi
- cargo check --examples -p gm17 --no-default-features --target thumbv6m-none-eabi
- cd ..

script:
- echo "script!"
@@ -61,6 +61,20 @@ macro_rules! cfg_into_iter {
}};
}

/// Returns an iterator over `chunk_size` elements of the slice at a time.
#[macro_export]
macro_rules! cfg_chunks_mut {
($e: expr, $size: expr) => {{
#[cfg(feature = "parallel")]
let result = $e.par_chunks_mut($size);

#[cfg(not(feature = "parallel"))]
let result = $e.chunks_mut($size);

result
}};
}

pub mod domain;

pub mod evaluations;
@@ -22,21 +22,24 @@ edition = "2018"
################################# Dependencies ################################

[dependencies]
algebra = { path = "../algebra", features = [ "parallel" ] }
ff-fft = { path = "../ff-fft" }
r1cs-core = { path = "../r1cs-core" }
algebra = { path = "../algebra", default-features = false }
bench-utils = { path = "../bench-utils" }

rand = { version = "0.7" }
rayon = { version = "1" }
smallvec = "1.1.0"
ff-fft = { path = "../ff-fft", default-features = false }
r1cs-core = { path = "../r1cs-core", default-features = false }
rand = { version = "0.7", default-features = false }
rayon = { version = "1", optional = true }
smallvec = "1.2"

[dev-dependencies]
csv = { version = "1" }

[features]
default = ["parallel"]
std = ["algebra/std", "ff-fft/std", "r1cs-core/std"]
parallel = ["std", "algebra/parallel", "ff-fft/parallel", "rayon"]
print-trace = [ "bench-utils/print-trace" ]

[[example]]
name = "gm17"
path = "examples/snark-scalability/gm17.rs"
required-features = ["std"]
@@ -1,16 +1,17 @@
use algebra::{
msm::FixedBaseMSM, AffineCurve, Field, PairingEngine, PrimeField, ProjectiveCurve, UniformRand,
};
use ff_fft::EvaluationDomain;
use ff_fft::{cfg_into_iter, cfg_iter, EvaluationDomain};

use algebra::{One, Zero};
use r1cs_core::{
ConstraintSynthesizer, ConstraintSystem, Index, LinearCombination, SynthesisError, Variable,
};
use rand::Rng;
#[cfg(feature = "parallel")]
use rayon::prelude::*;

use crate::{r1cs_to_sap::R1CStoSAP, Parameters, VerifyingKey};
use crate::{r1cs_to_sap::R1CStoSAP, Parameters, String, Vec, VerifyingKey};

/// Generates a random common reference string for
/// a circuit.
@@ -192,8 +193,7 @@ where
end_timer!(reduction_time);

// Compute query densities
let non_zero_a = (0..sap_num_variables)
.into_par_iter()
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();
@@ -224,7 +224,7 @@ where
scalar_bits,
g_window,
&g_table,
&a.par_iter().map(|a| *a * &gamma).collect::<Vec<_>>(),
&cfg_iter!(a).map(|a| *a * &gamma).collect::<Vec<_>>(),
);
end_timer!(a_time);

@@ -246,8 +246,7 @@ where
scalar_bits,
g_window,
&g_table,
&(0..m_raw + 1)
.into_par_iter()
&cfg_into_iter!(0..m_raw + 1)
.map(|i| gamma2_z_t * &(t.pow([i as u64])))
.collect::<Vec<_>>(),
);
@@ -259,8 +258,7 @@ where
scalar_bits,
g_window,
&g_table,
&(0..sap_num_variables + 1)
.into_par_iter()
&cfg_into_iter!(0..sap_num_variables + 1)
.map(|i| c[i] * &gamma + &(a[i] * &alpha_beta))
.collect::<Vec<_>>(),
);
@@ -274,8 +272,7 @@ where
scalar_bits,
g_window,
&g_table,
&(0..sap_num_variables + 1)
.into_par_iter()
&cfg_into_iter!(0..sap_num_variables + 1)
.map(|i| a[i] * &double_gamma2_z)
.collect::<Vec<_>>(),
);
@@ -313,8 +310,7 @@ where
h_beta_g2: h_beta.into_affine(),
g_gamma_g1: g_gamma.into_affine(),
h_gamma_g2: h_gamma.into_affine(),
query: verifier_query
.into_par_iter()
query: cfg_into_iter!(verifier_query)
.map(|e| e.into_affine())
.collect(),
};
@@ -1,6 +1,7 @@
//! An implementation of the [`Groth-Maller`] simulation extractable zkSNARK.
//!
//! [`Groth-Maller`]: https://eprint.iacr.org/2017/540
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(unused_import_braces, unused_qualifications, trivial_casts)]
#![deny(trivial_numeric_casts, private_in_public, variant_size_differences)]
#![deny(stable_features, unreachable_pub, non_shorthand_field_patterns)]
@@ -12,9 +13,22 @@
#[macro_use]
extern crate bench_utils;

use algebra::{bytes::ToBytes, PairingCurve, PairingEngine};
#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;

#[cfg(not(feature = "std"))]
use alloc::{string::String, vec::Vec};

#[cfg(feature = "std")]
use std::{string::String, vec::Vec};

use algebra::{
bytes::ToBytes,
io::{self, Read, Result as IoResult, Write},
PairingCurve, PairingEngine,
};
use r1cs_core::SynthesisError;
use std::io::{self, Read, Result as IoResult, Write};

/// Reduce an R1CS instance to a *Square Arithmetic Program* instance.
pub mod r1cs_to_sap;
@@ -1,11 +1,13 @@
use rand::Rng;
#[cfg(feature = "parallel")]
use rayon::prelude::*;

use algebra::{
msm::VariableBaseMSM, AffineCurve, PairingEngine, PrimeField, ProjectiveCurve, UniformRand,
};

use crate::{r1cs_to_sap::R1CStoSAP, Parameters, Proof};
use crate::{r1cs_to_sap::R1CStoSAP, Parameters, Proof, String, Vec};
use ff_fft::cfg_into_iter;

use r1cs_core::{
ConstraintSynthesizer, ConstraintSystem, Index, LinearCombination, SynthesisError, Variable,
@@ -14,10 +16,7 @@ use r1cs_core::{
use algebra::{One, Zero};
use smallvec::SmallVec;

use std::{
ops::{AddAssign, MulAssign},
sync::Arc,
};
use core::ops::{AddAssign, MulAssign};

type CoeffVec<T> = SmallVec<[T; 2]>;

@@ -234,33 +233,23 @@ where
let (full_input_assignment, h, _) = R1CStoSAP::witness_map::<E>(&prover, &d1, &d2)?;
end_timer!(witness_map_time);

let input_assignment = Arc::new(
full_input_assignment[1..prover.num_inputs]
.iter()
.map(|s| s.into_repr())
.collect::<Vec<_>>(),
);

let aux_assignment = Arc::new(
full_input_assignment[prover.num_inputs..]
.into_par_iter()
.map(|s| s.into_repr())
.collect::<Vec<_>>(),
);
let input_assignment = full_input_assignment[1..prover.num_inputs]
.iter()
.map(|s| s.into_repr())
.collect::<Vec<_>>();

let aux_assignment = cfg_into_iter!(full_input_assignment[prover.num_inputs..])
.map(|s| s.into_repr())
.collect::<Vec<_>>();
drop(full_input_assignment);

let h_input = Arc::new(
h[0..prover.num_inputs]
.iter()
.map(|s| s.into_repr())
.collect::<Vec<_>>(),
);
let h_aux = Arc::new(
h[prover.num_inputs..]
.into_par_iter()
.map(|s| s.into_repr())
.collect::<Vec<_>>(),
);
let h_input = h[0..prover.num_inputs]
.iter()
.map(|s| s.into_repr())
.collect::<Vec<_>>();
let h_aux = cfg_into_iter!(h[prover.num_inputs..])
.map(|s| s.into_repr())
.collect::<Vec<_>>();
drop(h);

// Compute A
@@ -1,12 +1,13 @@
use algebra::{Field, PairingEngine};
use ff_fft::EvaluationDomain;
use ff_fft::{cfg_chunks_mut, cfg_iter, cfg_iter_mut, EvaluationDomain};

use crate::{generator::KeypairAssembly, prover::ProvingAssignment};
use crate::{generator::KeypairAssembly, prover::ProvingAssignment, Vec};
use algebra::{One, Zero};
use r1cs_core::{Index, SynthesisError};

use core::ops::{AddAssign, SubAssign};
#[cfg(feature = "parallel")]
use rayon::prelude::*;
use std::ops::{AddAssign, SubAssign};

pub(crate) struct R1CStoSAP;

@@ -126,9 +127,7 @@ impl R1CStoSAP {
let mut full_input_assignment = prover.input_assignment.clone();
full_input_assignment.extend(prover.aux_assignment.clone());

let temp = prover
.at
.par_iter()
let temp = cfg_iter!(prover.at)
.zip(&prover.bt)
.map(|(a_i, b_i)| {
let mut extra_var: E::Fr =
@@ -162,8 +161,7 @@ impl R1CStoSAP {
let extra_var_offset2 = prover.num_inputs + prover.num_aux + prover.num_constraints - 1;

let mut a = vec![zero; domain_size];
a[..2 * prover.num_constraints]
.par_chunks_mut(2)
cfg_chunks_mut!(a[..2 * prover.num_constraints], 2)
.zip(&prover.at)
.zip(&prover.bt)
.for_each(|((chunk, at_i), bt_i)| {
@@ -193,7 +191,7 @@ impl R1CStoSAP {

let d1_double = d1.double();
let mut h: Vec<E::Fr> = vec![d1_double; domain_size];
h.par_iter_mut().zip(&a).for_each(|(h_i, a_i)| *h_i *= a_i);
cfg_iter_mut!(h).zip(&a).for_each(|(h_i, a_i)| *h_i *= a_i);
h[0].sub_assign(&d2);
let d1d1 = d1.square();
h[0].sub_assign(&d1d1);
@@ -205,8 +203,7 @@ impl R1CStoSAP {
drop(a);

let mut c = vec![zero; domain_size];
c[..2 * prover.num_constraints]
.par_chunks_mut(2)
cfg_chunks_mut!(c[..2 * prover.num_constraints], 2)
.enumerate()
.for_each(|(i, chunk)| {
let mut tmp: E::Fr = evaluate_constraint::<E>(
@@ -235,15 +232,14 @@ impl R1CStoSAP {
domain.ifft_in_place(&mut c);
domain.coset_fft_in_place(&mut c);

aa.par_iter_mut()
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);

h[..domain_size - 1]
.par_iter_mut()
cfg_iter_mut!(h[..domain_size - 1])
.enumerate()
.for_each(|(i, e)| e.add_assign(&aa[i]));

@@ -36,13 +36,12 @@ mod bls12_377 {
create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof,
};

use algebra::{curves::bls12_377::Bls12_377, fields::bls12_377::Fr, UniformRand};
use rand::thread_rng;
use std::ops::MulAssign;
use algebra::{curves::bls12_377::Bls12_377, fields::bls12_377::Fr, test_rng, UniformRand};
use core::ops::MulAssign;

#[test]
fn prove_and_verify() {
let rng = &mut thread_rng();
let rng = &mut test_rng();

let params =
generate_random_parameters::<Bls12_377, _, _>(MySillyCircuit { a: None, b: None }, rng)
@@ -78,13 +77,11 @@ mod sw6 {
create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof,
};

use rand::thread_rng;

use algebra::{curves::sw6::SW6, fields::sw6::Fr as SW6Fr, UniformRand};
use algebra::{curves::sw6::SW6, fields::sw6::Fr as SW6Fr, test_rng, UniformRand};

#[test]
fn prove_and_verify() {
let rng = &mut thread_rng();
let rng = &mut test_rng();

let params =
generate_random_parameters::<SW6, _, _>(MySillyCircuit { a: None, b: None }, rng)
@@ -4,7 +4,7 @@ use super::{PreparedVerifyingKey, Proof, VerifyingKey};

use crate::SynthesisError;

use std::ops::{AddAssign, MulAssign, Neg};
use core::ops::{AddAssign, MulAssign, Neg};

pub fn prepare_verifying_key<E: PairingEngine>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {
PreparedVerifyingKey {
@@ -26,13 +26,13 @@
)]

// For randomness (during paramgen and proof generation)
use rand::{thread_rng, Rng};
use rand::Rng;

// For benchmarking
use std::time::{Duration, Instant};

// Bring in some tools for using pairing-friendly curves
use algebra::{curves::bls12_381::Bls12_381, fields::bls12_381::fr::Fr, Field};
use algebra::{curves::bls12_381::Bls12_381, fields::bls12_381::fr::Fr, test_rng, Field};

// We're going to use the BLS12-381 pairing-friendly elliptic curve.

@@ -178,7 +178,7 @@ fn test_mimc_groth_maller_17() {

// This may not be cryptographically safe, use
// `OsRng` (for example) in production software.
let rng = &mut thread_rng();
let rng = &mut test_rng();

// Generate the MiMC round constants
let constants = (0..MIMC_ROUNDS).map(|_| rng.gen()).collect::<Vec<_>>();

0 comments on commit 317fc33

Please sign in to comment.
You can’t perform that action at this time.