start restructuring to use groth16-similar types

This commit is contained in:
Alex Vlasov 2019-02-07 14:27:08 +03:00
parent cd00c4eaf7
commit 6059601518
9 changed files with 1689 additions and 94 deletions

@ -7,7 +7,6 @@ use pairing::{Engine};
use crate::{SynthesisError}; use crate::{SynthesisError};
use std::marker::PhantomData; use std::marker::PhantomData;
mod lc; mod lc;
pub use self::lc::{Coeff, Variable, LinearCombination}; pub use self::lc::{Coeff, Variable, LinearCombination};

@ -142,73 +142,3 @@ impl<E: Engine> Batch<E> {
])).unwrap() == E::Fqk::one() ])).unwrap() == E::Fqk::one()
} }
} }
#[derive(Clone, Debug)]
pub struct VerifyingKey<E: Engine> {
pub alpha_x: E::G2Affine,
pub alpha: E::G2Affine,
pub neg_h: E::G2Affine,
pub neg_x_n_minus_d: E::G2Affine,
pub k_map: Vec<usize>,
pub n: usize,
pub q: usize
}
impl<E: Engine> VerifyingKey<E> {
pub fn new<C: Circuit<E>, S: SynthesisDriver>(circuit: C, srs: &SRS<E>) -> Result<Self, SynthesisError> {
struct Preprocess<E: Engine> {
k_map: Vec<usize>,
n: usize,
q: usize,
_marker: PhantomData<E>
}
impl<'a, E: Engine> Backend<E> for &'a mut Preprocess<E> {
fn new_k_power(&mut self, index: usize) {
self.k_map.push(index);
}
fn new_multiplication_gate(&mut self) {
self.n += 1;
}
fn new_linear_constraint(&mut self) {
self.q += 1;
}
}
let mut preprocess = Preprocess { k_map: vec![], n: 0, q: 0, _marker: PhantomData };
S::synthesize(&mut preprocess, &circuit)?;
Ok(Self {
alpha_x: srs.h_positive_x_alpha[1],
alpha: srs.h_positive_x_alpha[0],
neg_h: {
let mut tmp = srs.h_negative_x[0];
tmp.negate();
tmp
},
neg_x_n_minus_d: {
let mut tmp = srs.h_negative_x[srs.d - preprocess.n];
tmp.negate();
tmp
},
k_map: preprocess.k_map,
n: preprocess.n,
q: preprocess.q
})
}
}

@ -0,0 +1,800 @@
use rand::Rng;
use std::sync::Arc;
use pairing::{
Engine,
Wnaf,
CurveProjective,
CurveAffine
};
use ff::{
PrimeField,
Field
};
use super::{
Parameters,
VerifyingKey
};
use ::{
SynthesisError,
Circuit,
ConstraintSystem,
LinearCombination,
Variable,
Index
};
use crate::domain::{
Scalar
};
use ::multicore::{
Worker
};
use std::marker::PhantomData;
use crate::sonic::cs::{Backend, Basic, SynthesisDriver};
use crate::sonic::srs::SRS;
use crate::sonic::cs::LinearCombination as SonicLinearCombination;
use crate::sonic::cs::Circuit as SonicCircuit;
use crate::sonic::cs::ConstraintSystem as SonicConstraintSystem;
use crate::sonic::cs::Variable as SonicVariable;
use crate::sonic::cs::Coeff;
use crate::sonic::sonic::{AdaptorCircuit};
use crate::verbose_flag;
/// Generates a random common reference string for
/// a circuit.
pub fn generate_random_parameters<E, C, R>(
circuit: C,
rng: &mut R
) -> Result<Parameters<E>, SynthesisError>
where E: Engine, C: Circuit<E>, R: Rng
{
let alpha = rng.gen();
let x = rng.gen();
generate_parameters::<E, C>(
circuit,
alpha,
x
)
}
/// This is our assembly structure that we'll use to synthesize the
/// circuit into
#[derive(Clone, Debug)]
pub struct CircuitParameters<E: Engine> {
pub num_inputs: usize,
pub num_aux: usize,
pub num_constraints: usize,
pub k_map: Vec<usize>,
pub n: usize,
pub q: usize,
_marker: PhantomData<E>
}
/// This is our assembly structure that we'll use to synthesize the
/// circuit into
struct GeneratorAssembly<'a, E: Engine, CS: SonicConstraintSystem<E> + 'a> {
cs: &'a mut CS,
num_inputs: usize,
num_aux: usize,
num_constraints: usize,
_marker: PhantomData<E>
}
impl<'a, E: Engine, CS: SonicConstraintSystem<E> + 'a> crate::ConstraintSystem<E>
for GeneratorAssembly<'a, E, CS>
{
type Root = Self;
// this is an important change
fn one() -> crate::Variable {
crate::Variable::new_unchecked(crate::Index::Input(1))
}
fn alloc<F, A, AR>(&mut self, _: A, f: F) -> Result<crate::Variable, crate::SynthesisError>
where
F: FnOnce() -> Result<E::Fr, crate::SynthesisError>,
A: FnOnce() -> AR,
AR: Into<String>,
{
self.num_aux += 1;
let var = self.cs.alloc(|| {
f().map_err(|_| crate::SynthesisError::AssignmentMissing)
}).map_err(|_| crate::SynthesisError::AssignmentMissing)?;
Ok(match var {
SonicVariable::A(index) => crate::Variable::new_unchecked(crate::Index::Input(index)),
SonicVariable::B(index) => crate::Variable::new_unchecked(crate::Index::Aux(index)),
_ => unreachable!(),
})
}
fn alloc_input<F, A, AR>(
&mut self,
_: A,
f: F,
) -> Result<crate::Variable, crate::SynthesisError>
where
F: FnOnce() -> Result<E::Fr, crate::SynthesisError>,
A: FnOnce() -> AR,
AR: Into<String>,
{
self.num_inputs += 1;
let var = self.cs.alloc_input(|| {
f().map_err(|_| crate::SynthesisError::AssignmentMissing)
}).map_err(|_| crate::SynthesisError::AssignmentMissing)?;
Ok(match var {
SonicVariable::A(index) => crate::Variable::new_unchecked(crate::Index::Input(index)),
SonicVariable::B(index) => crate::Variable::new_unchecked(crate::Index::Aux(index)),
_ => unreachable!(),
})
}
fn enforce<A, AR, LA, LB, LC>(&mut self, _: A, a: LA, b: LB, c: LC)
where
A: FnOnce() -> AR,
AR: Into<String>,
LA: FnOnce(crate::LinearCombination<E>) -> crate::LinearCombination<E>,
LB: FnOnce(crate::LinearCombination<E>) -> crate::LinearCombination<E>,
LC: FnOnce(crate::LinearCombination<E>) -> crate::LinearCombination<E>,
{
fn convert<E: Engine>(lc: crate::LinearCombination<E>) -> SonicLinearCombination<E> {
let mut ret = SonicLinearCombination::zero();
for &(v, coeff) in lc.as_ref().iter() {
let var = match v.get_unchecked() {
crate::Index::Input(i) => SonicVariable::A(i),
crate::Index::Aux(i) => SonicVariable::B(i),
};
ret = ret + (Coeff::Full(coeff), var);
}
ret
}
fn eval<E: Engine, CS: SonicConstraintSystem<E>>(
lc: &SonicLinearCombination<E>,
cs: &CS,
) -> Option<E::Fr> {
let mut ret = E::Fr::zero();
for &(v, coeff) in lc.as_ref().iter() {
let mut tmp = match cs.get_value(v) {
Ok(tmp) => tmp,
Err(_) => return None,
};
coeff.multiply(&mut tmp);
ret.add_assign(&tmp);
}
Some(ret)
}
self.num_constraints += 1;
let a_lc = convert(a(crate::LinearCombination::zero()));
let a_value = eval(&a_lc, &*self.cs);
let b_lc = convert(b(crate::LinearCombination::zero()));
let b_value = eval(&b_lc, &*self.cs);
let c_lc = convert(c(crate::LinearCombination::zero()));
let c_value = eval(&c_lc, &*self.cs);
let (a, b, c) = self
.cs
.multiply(|| Ok((a_value.unwrap(), b_value.unwrap(), c_value.unwrap())))
.unwrap();
self.cs.enforce_zero(a_lc - a);
self.cs.enforce_zero(b_lc - b);
self.cs.enforce_zero(c_lc - c);
}
fn push_namespace<NR, N>(&mut self, _: N)
where
NR: Into<String>,
N: FnOnce() -> NR,
{
// Do nothing; we don't care about namespaces in this context.
}
fn pop_namespace(&mut self) {
// Do nothing; we don't care about namespaces in this context.
}
fn get_root(&mut self) -> &mut Self::Root {
self
}
}
/// Create parameters for a circuit, given some toxic waste.
fn get_circuit_parameters<E, C>(
circuit: C,
) -> Result<CircuitParameters<E>, SynthesisError>
where E: Engine, C: Circuit<E>
{
struct NonassigningSynthesizer<E: Engine, B: Backend<E>> {
backend: B,
current_variable: Option<usize>,
_marker: PhantomData<E>,
q: usize,
n: usize,
}
impl<E: Engine, B: Backend<E>> SonicConstraintSystem<E> for NonassigningSynthesizer<E, B> {
const ONE: SonicVariable = SonicVariable::A(1);
fn alloc<F>(&mut self, value: F) -> Result<SonicVariable, SynthesisError>
where
F: FnOnce() -> Result<E::Fr, SynthesisError>
{
match self.current_variable.take() {
Some(index) => {
let var_b = SonicVariable::B(index);
self.current_variable = None;
Ok(var_b)
},
None => {
self.n += 1;
let index = self.n;
self.backend.new_multiplication_gate();
let var_a = SonicVariable::A(index);
self.current_variable = Some(index);
Ok(var_a)
}
}
}
fn alloc_input<F>(&mut self, value: F) -> Result<SonicVariable, SynthesisError>
where
F: FnOnce() -> Result<E::Fr, SynthesisError>
{
let input_var = self.alloc(value)?;
self.enforce_zero(SonicLinearCombination::zero() + input_var);
self.backend.new_k_power(self.q);
Ok(input_var)
}
fn enforce_zero(&mut self, lc: SonicLinearCombination<E>)
{
self.q += 1;
self.backend.new_linear_constraint();
for (var, coeff) in lc.as_ref() {
self.backend.insert_coefficient(*var, *coeff);
}
}
fn multiply<F>(&mut self, values: F) -> Result<(SonicVariable, SonicVariable, SonicVariable), SynthesisError>
where
F: FnOnce() -> Result<(E::Fr, E::Fr, E::Fr), SynthesisError>
{
self.n += 1;
let index = self.n;
self.backend.new_multiplication_gate();
let a = SonicVariable::A(index);
let b = SonicVariable::B(index);
let c = SonicVariable::C(index);
Ok((a, b, c))
}
fn get_value(&self, var: SonicVariable) -> Result<E::Fr, ()> {
self.backend.get_var(var).ok_or(())
}
}
struct Preprocess<E: Engine> {
k_map: Vec<usize>,
n: usize,
q: usize,
_marker: PhantomData<E>
}
impl<'a, E: Engine> Backend<E> for &'a mut Preprocess<E> {
fn new_k_power(&mut self, index: usize) {
self.k_map.push(index);
}
fn new_multiplication_gate(&mut self) {
self.n += 1;
}
fn new_linear_constraint(&mut self) {
self.q += 1;
}
}
let mut preprocess = Preprocess { k_map: vec![], n: 0, q: 0, _marker: PhantomData };
let (num_inputs, num_aux, num_constraints) = {
let mut cs: NonassigningSynthesizer<E, &'_ mut Preprocess<E>> = NonassigningSynthesizer {
backend: &mut preprocess,
current_variable: None,
_marker: PhantomData,
q: 0,
n: 0,
};
let one = cs.alloc_input(|| Ok(E::Fr::one())).expect("should have no issues");
match (one, <NonassigningSynthesizer<E, &'_ mut Preprocess<E>> as SonicConstraintSystem<E>>::ONE) {
(SonicVariable::A(1), SonicVariable::A(1)) => {},
_ => return Err(SynthesisError::UnconstrainedVariable)
}
// let adapted_circuit = AdaptorCircuit(circuit);
let mut assembly = GeneratorAssembly::<'_, E, _> {
cs: &mut cs,
num_inputs: 0,
num_aux: 0,
num_constraints: 0,
_marker: PhantomData
};
circuit.synthesize(&mut assembly)?;
(assembly.num_inputs, assembly.num_aux, assembly.num_constraints)
};
Ok(CircuitParameters {
num_inputs: num_inputs,
num_aux: num_aux,
num_constraints: num_constraints,
k_map: preprocess.k_map,
n: preprocess.n,
q: preprocess.q,
_marker: PhantomData
})
}
pub fn generate_parameters<E, C>(
circuit: C,
alpha: E::Fr,
x: E::Fr
) -> Result<Parameters<E>, SynthesisError>
where E: Engine, C: Circuit<E>
{
let circuit_parameters = get_circuit_parameters::<E, C>(circuit)?;
let min_d = circuit_parameters.n * 3;
let srs = generate_srs(alpha, x, min_d)?;
let parameters = generate_parameters_on_srs_and_information::<E>(&srs, circuit_parameters)?;
Ok(parameters)
}
pub fn generate_parameters_on_srs<E, C>(
circuit: C,
srs: &SRS<E>,
) -> Result<Parameters<E>, SynthesisError>
where E: Engine, C: Circuit<E>
{
let circuit_parameters = get_circuit_parameters::<E, C>(circuit)?;
let parameters = generate_parameters_on_srs_and_information(&srs, circuit_parameters)?;
Ok(parameters)
}
pub fn generate_parameters_on_srs_and_information<E: Engine>(
srs: &SRS<E>,
information: CircuitParameters<E>
) -> Result<Parameters<E>, SynthesisError>
{
assert!(srs.d >= information.n * 3);
let min_d = information.n * 3;
let trimmed_srs: SRS<E> = SRS {
d: min_d,
g_negative_x: srs.g_negative_x[0..min_d+1].to_vec(),
g_positive_x: srs.g_positive_x[0..min_d+1].to_vec().clone(),
h_negative_x: srs.h_negative_x[0..min_d+1].to_vec(),
h_positive_x: srs.h_positive_x[0..min_d+1].to_vec(),
g_negative_x_alpha: srs.g_negative_x_alpha[0..min_d].to_vec(),
g_positive_x_alpha: srs.g_positive_x_alpha[0..min_d].to_vec(),
h_negative_x_alpha: srs.h_negative_x_alpha[0..min_d+1].to_vec(),
h_positive_x_alpha: srs.h_positive_x_alpha[0..min_d+1].to_vec(),
};
let vk = VerifyingKey {
alpha_x: trimmed_srs.h_positive_x_alpha[1],
alpha: trimmed_srs.h_positive_x_alpha[0],
neg_h: {
let mut tmp = trimmed_srs.h_negative_x[0];
tmp.negate();
tmp
},
neg_x_n_minus_d: {
let mut tmp = trimmed_srs.h_negative_x[trimmed_srs.d - information.n];
tmp.negate();
tmp
},
k_map: information.k_map,
n: information.n,
q: information.q
};
Ok(Parameters{
vk: vk,
d: trimmed_srs.d,
g_negative_x: Arc::new(trimmed_srs.g_negative_x),
g_positive_x: Arc::new(trimmed_srs.g_positive_x),
h_negative_x: Arc::new(trimmed_srs.h_negative_x),
h_positive_x: Arc::new(trimmed_srs.h_positive_x),
g_negative_x_alpha: Arc::new(trimmed_srs.g_negative_x_alpha),
g_positive_x_alpha: Arc::new(trimmed_srs.g_positive_x_alpha),
h_negative_x_alpha: Arc::new(trimmed_srs.h_negative_x_alpha),
h_positive_x_alpha: Arc::new(trimmed_srs.h_positive_x_alpha)
})
}
pub fn generate_srs<E: Engine>(
alpha: E::Fr,
x: E::Fr,
d: usize
) -> Result<SRS<E>, SynthesisError> {
let verbose = verbose_flag();
let g1 = E::G1Affine::one().into_projective();
let g2 = E::G2Affine::one().into_projective();
// Compute G1 window table
let mut g1_wnaf = Wnaf::new();
let g1_wnaf = g1_wnaf.base(g1, 4*d);
// Compute G2 window table
let mut g2_wnaf = Wnaf::new();
let g2_wnaf = g2_wnaf.base(g2, 4*d);
let x_inverse = x.inverse().ok_or(SynthesisError::UnexpectedIdentity)?;
let worker = Worker::new();
let mut x_powers_positive = vec![Scalar::<E>(E::Fr::zero()); d];
let mut x_powers_negative = vec![Scalar::<E>(E::Fr::zero()); d];
{
// Compute powers of tau
if verbose {eprintln!("computing powers of tau...")};
let start = std::time::Instant::now();
{
worker.scope(d, |scope, chunk| {
for (i, x_powers) in x_powers_positive.chunks_mut(chunk).enumerate()
{
scope.spawn(move |_| {
let mut current_power = x.pow(&[(i*chunk + 1) as u64]);
for p in x_powers {
p.0 = current_power;
current_power.mul_assign(&x);
}
});
}
});
}
{
worker.scope(d, |scope, chunk| {
for (i, x_powers) in x_powers_negative.chunks_mut(chunk).enumerate()
{
scope.spawn(move |_| {
let mut current_power = x_inverse.pow(&[(i*chunk + 1) as u64]);
for p in x_powers {
p.0 = current_power;
current_power.mul_assign(&x_inverse);
}
});
}
});
}
if verbose {eprintln!("powers of x done in {} s", start.elapsed().as_millis() as f64 / 1000.0);};
}
// we will later add zero powers to g_x, h_x, h_x_alpha
let mut g_negative_x = vec![E::G1::one(); d];
let mut g_positive_x = vec![E::G1::one(); d];
let mut h_negative_x = vec![E::G2::one(); d];
let mut h_positive_x = vec![E::G2::one(); d];
let mut g_negative_x_alpha = vec![E::G1::one(); d];
let mut g_positive_x_alpha = vec![E::G1::one(); d];
let mut h_negative_x_alpha = vec![E::G2::one(); d];
let mut h_positive_x_alpha = vec![E::G2::one(); d];
fn eval<E: Engine>(
// wNAF window tables
g1_wnaf: &Wnaf<usize, &[E::G1], &mut Vec<i64>>,
g2_wnaf: &Wnaf<usize, &[E::G2], &mut Vec<i64>>,
powers_of_x: &[Scalar<E>],
g_x: &mut [E::G1],
g_x_alpha: &mut [E::G1],
h_x: &mut [E::G2],
h_x_alpha: &mut [E::G2],
// Trapdoors
alpha: &E::Fr,
// Worker
worker: &Worker
)
{
// Sanity check
assert_eq!(g_x.len(), powers_of_x.len());
assert_eq!(g_x.len(), g_x_alpha.len());
assert_eq!(g_x.len(), h_x.len());
assert_eq!(g_x.len(), h_x_alpha.len());
// Evaluate polynomials in multiple threads
worker.scope(g_x.len(), |scope, chunk| {
for ((((x, g_x), g_x_alpha), h_x), h_x_alpha) in powers_of_x.chunks(chunk)
.zip(g_x.chunks_mut(chunk))
.zip(g_x_alpha.chunks_mut(chunk))
.zip(h_x.chunks_mut(chunk))
.zip(h_x_alpha.chunks_mut(chunk))
{
let mut g1_wnaf = g1_wnaf.shared();
let mut g2_wnaf = g2_wnaf.shared();
scope.spawn(move |_| {
for ((((x, g_x), g_x_alpha), h_x), h_x_alpha) in x.iter()
.zip(g_x.iter_mut())
.zip(g_x_alpha.iter_mut())
.zip(h_x.iter_mut())
.zip(h_x_alpha.iter_mut())
{
let mut x_alpha = x.0;
x_alpha.mul_assign(&alpha);
*g_x = g1_wnaf.scalar(x.0.into_repr());
*h_x = g2_wnaf.scalar(x.0.into_repr());
*g_x_alpha = g1_wnaf.scalar(x_alpha.into_repr());
*h_x_alpha = g2_wnaf.scalar(x_alpha.into_repr());
}
// Batch normalize
E::G1::batch_normalization(g_x);
E::G1::batch_normalization(g_x_alpha);
E::G2::batch_normalization(h_x);
E::G2::batch_normalization(h_x_alpha);
});
};
});
}
let start = std::time::Instant::now();
// Evaluate for positive powers.
eval(
&g1_wnaf,
&g2_wnaf,
&x_powers_positive,
&mut g_positive_x[..],
&mut g_positive_x_alpha[..],
&mut h_positive_x[..],
&mut h_positive_x_alpha[..],
&alpha,
&worker
);
// Evaluate for auxillary variables.
eval(
&g1_wnaf,
&g2_wnaf,
&x_powers_negative,
&mut g_negative_x[..],
&mut g_negative_x_alpha[..],
&mut h_negative_x[..],
&mut h_negative_x_alpha[..],
&alpha,
&worker
);
if verbose {eprintln!("evaluating points done in {} s", start.elapsed().as_millis() as f64 / 1000.0);};
let g1 = g1.into_affine();
let g2 = g2.into_affine();
let h_alpha = g2.mul(alpha.into_repr()).into_affine();
let g_negative_x = {
let mut tmp = vec![g1];
tmp.extend(g_negative_x.into_iter().map(|e| e.into_affine()));
tmp
};
let g_positive_x = {
let mut tmp = vec![g1];
tmp.extend(g_positive_x.into_iter().map(|e| e.into_affine()));
tmp
};
let h_negative_x = {
let mut tmp = vec![g2];
tmp.extend(h_negative_x.into_iter().map(|e| e.into_affine()));
tmp
};
let h_positive_x = {
let mut tmp = vec![g2];
tmp.extend(h_positive_x.into_iter().map(|e| e.into_affine()));
tmp
};
let g_negative_x_alpha = g_negative_x_alpha.into_iter().map(|e| e.into_affine()).collect();
let g_positive_x_alpha = g_positive_x_alpha.into_iter().map(|e| e.into_affine()).collect();
let h_negative_x_alpha = {
let mut tmp = vec![h_alpha];
tmp.extend(h_negative_x_alpha.into_iter().map(|e| e.into_affine()));
tmp
};
let h_positive_x_alpha = {
let mut tmp = vec![h_alpha];
tmp.extend(h_positive_x_alpha.into_iter().map(|e| e.into_affine()));
tmp
};
Ok(SRS {
d: d,
g_negative_x: g_negative_x,
g_positive_x: g_positive_x,
h_negative_x: h_negative_x,
h_positive_x: h_positive_x,
g_negative_x_alpha: g_negative_x_alpha,
g_positive_x_alpha: g_positive_x_alpha,
h_negative_x_alpha: h_negative_x_alpha,
h_positive_x_alpha: h_positive_x_alpha,
}
)
}
#[test]
fn parameters_generation() {
use pairing::bls12_381::{Bls12, Fr};
struct MySillyCircuit<E: Engine> {
a: Option<E::Fr>,
b: Option<E::Fr>
}
impl<E: Engine> Circuit<E> for MySillyCircuit<E> {
fn synthesize<CS: ConstraintSystem<E>>(
self,
cs: &mut CS
) -> Result<(), SynthesisError>
{
let a = cs.alloc(|| "a", || self.a.ok_or(SynthesisError::AssignmentMissing))?;
let b = cs.alloc(|| "b", || self.b.ok_or(SynthesisError::AssignmentMissing))?;
let c = cs.alloc_input(|| "c", || {
let mut a = self.a.ok_or(SynthesisError::AssignmentMissing)?;
let b = self.b.ok_or(SynthesisError::AssignmentMissing)?;
a.mul_assign(&b);
Ok(a)
})?;
cs.enforce(
|| "a*b=c",
|lc| lc + a,
|lc| lc + b,
|lc| lc + c
);
Ok(())
}
}
use rand::{Rand, thread_rng};
let info = get_circuit_parameters::<Bls12, _>(MySillyCircuit { a: None, b: None }).expect("Must get circuit info");
let rng = &mut thread_rng();
let x: Fr = rng.gen();
let alpha: Fr = rng.gen();
let params = generate_parameters::<Bls12, _>(MySillyCircuit { a: None, b: None }, alpha, x).unwrap();
let srs = generate_srs::<Bls12>(alpha, x, info.n * 100).unwrap();
let naive_srs = SRS::<Bls12>::new(
info.n * 100,
x,
alpha,
);
assert!(srs == naive_srs);
let params_on_srs = generate_parameters_on_srs_and_information::<Bls12>(&srs, info.clone()).unwrap();
assert!(params == params_on_srs);
{
let mut v = vec![];
params.write(&mut v).unwrap();
let de_params = Parameters::read(&v[..], true).unwrap();
assert!(params == de_params);
let de_params = Parameters::read(&v[..], false).unwrap();
assert!(params == de_params);
}
// let pvk = prepare_verifying_key::<Bls12>(&params.vk);
// for _ in 0..100 {
// let a = Fr::rand(rng);
// let b = Fr::rand(rng);
// let mut c = a;
// c.mul_assign(&b);
// let proof = create_random_proof(
// MySillyCircuit {
// a: Some(a),
// b: Some(b)
// },
// &params,
// rng
// ).unwrap();
// let mut v = vec![];
// proof.write(&mut v).unwrap();
// assert_eq!(v.len(), 192);
// let de_proof = Proof::read(&v[..]).unwrap();
// assert!(proof == de_proof);
// assert!(verify_proof(&pvk, &proof, &[c]).unwrap());
// assert!(!verify_proof(&pvk, &proof, &[a]).unwrap());
// }
}

@ -10,25 +10,11 @@ mod prover;
mod batch; mod batch;
mod poly; mod poly;
mod helper; mod helper;
mod parameters;
mod generator;
pub use self::batch::{Batch, VerifyingKey}; pub use self::batch::{Batch};
pub use self::helper::{Aggregate, create_aggregate}; pub use self::helper::{Aggregate, create_aggregate};
pub use self::verifier::{MultiVerifier}; pub use self::verifier::{MultiVerifier};
pub use self::prover::{create_proof, create_advice}; pub use self::prover::{create_proof, create_advice};
pub use self::parameters::{Proof, SxyAdvice, Parameters, VerifyingKey, PreparedVerifyingKey};
#[derive(Clone, Debug)]
pub struct SxyAdvice<E: Engine> {
pub s: E::G1Affine,
pub opening: E::G1Affine,
pub szy: E::Fr,
}
#[derive(Clone, Debug)]
pub struct Proof<E: Engine> {
pub r: E::G1Affine,
pub t: E::G1Affine,
pub rz: E::Fr,
pub rzy: E::Fr,
pub z_opening: E::G1Affine,
pub zy_opening: E::G1Affine
}

@ -0,0 +1,689 @@
use ff::{
Field,
PrimeField,
PrimeFieldRepr
};
use pairing::{
Engine,
CurveAffine,
EncodedPoint
};
use ::{
SynthesisError
};
use multiexp::SourceBuilder;
use std::io::{self, Read, Write};
use std::sync::Arc;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SxyAdvice<E: Engine> {
pub s: E::G1Affine,
pub opening: E::G1Affine,
pub szy: E::Fr,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Proof<E: Engine> {
pub r: E::G1Affine,
pub t: E::G1Affine,
pub rz: E::Fr,
pub rzy: E::Fr,
pub z_opening: E::G1Affine,
pub zy_opening: E::G1Affine
}
impl<E: Engine> Proof<E> {
pub fn write<W: Write>(
&self,
mut writer: W
) -> io::Result<()>
{
use ff::{PrimeField, PrimeFieldRepr};
writer.write_all(self.r.into_compressed().as_ref())?;
writer.write_all(self.t.into_compressed().as_ref())?;
let mut buffer = vec![];
self.rz.into_repr().write_be(&mut buffer)?;
writer.write_all(&buffer[..])?;
self.rzy.into_repr().write_be(&mut buffer)?;
writer.write_all(&buffer[..])?;
writer.write_all(self.z_opening.into_compressed().as_ref())?;
writer.write_all(self.zy_opening.into_compressed().as_ref())?;
Ok(())
}
pub fn read<R: Read>(
mut reader: R
) -> io::Result<Self>
{
let mut g1_repr = <E::G1Affine as CurveAffine>::Compressed::empty();
let mut fr_repr = E::Fr::zero().into_repr();
reader.read_exact(g1_repr.as_mut())?;
let r = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| if e.is_zero() {
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
} else {
Ok(e)
})?;
reader.read_exact(g1_repr.as_mut())?;
let t = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| if e.is_zero() {
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
} else {
Ok(e)
})?;
fr_repr.read_be(&mut reader)?;
let rz = E::Fr::from_repr(fr_repr)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| if e.is_zero() {
Err(io::Error::new(io::ErrorKind::InvalidData, "field element is zero"))
} else {
Ok(e)
})?;
fr_repr.read_be(&mut reader)?;
let rzy = E::Fr::from_repr(fr_repr)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| if e.is_zero() {
Err(io::Error::new(io::ErrorKind::InvalidData, "field element is zero"))
} else {
Ok(e)
})?;
reader.read_exact(g1_repr.as_mut())?;
let z_opening = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| if e.is_zero() {
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
} else {
Ok(e)
})?;
reader.read_exact(g1_repr.as_mut())?;
let zy_opening = g1_repr
.into_affine()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| if e.is_zero() {
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
} else {
Ok(e)
})?;
Ok(Proof {
r: r,
t: t,
rz: rz,
rzy: rzy,
z_opening: z_opening,
zy_opening: zy_opening
})
}
}
#[derive(Clone, Debug, Eq)]
pub struct VerifyingKey<E: Engine> {
pub alpha_x: E::G2Affine,
pub alpha: E::G2Affine,
pub neg_h: E::G2Affine,
pub neg_x_n_minus_d: E::G2Affine,
pub k_map: Vec<usize>,
pub n: usize,
pub q: usize
}
impl<E: Engine> PartialEq for VerifyingKey<E> {
fn eq(&self, other: &VerifyingKey<E>) -> bool {
self.alpha_x == other.alpha_x &&
self.alpha == other.alpha &&
self.neg_h == other.neg_h &&
self.neg_x_n_minus_d == other.neg_x_n_minus_d &&
self.k_map == other.k_map &&
self.n == other.n &&
self.q == other.q
}
}
impl<E: Engine> VerifyingKey<E> {
pub fn write<W: Write>(
&self,
mut writer: W
) -> io::Result<()>
{
writer.write_all(self.alpha_x.into_uncompressed().as_ref())?;
writer.write_all(self.alpha.into_uncompressed().as_ref())?;
writer.write_all(self.neg_h.into_uncompressed().as_ref())?;
writer.write_all(self.neg_x_n_minus_d.into_uncompressed().as_ref())?;
writer.write_u32::<BigEndian>(self.k_map.len() as u32)?;
for k in &self.k_map {
writer.write_u32::<BigEndian>(*k as u32)?;
}
writer.write_u32::<BigEndian>(self.n as u32)?;
writer.write_u32::<BigEndian>(self.q as u32)?;
Ok(())
}
pub fn read<R: Read>(
mut reader: R
) -> io::Result<Self>
{
let mut g2_repr = <E::G2Affine as CurveAffine>::Uncompressed::empty();
reader.read_exact(g2_repr.as_mut())?;
let alpha_x = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
reader.read_exact(g2_repr.as_mut())?;
let alpha = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
reader.read_exact(g2_repr.as_mut())?;
let neg_h = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
reader.read_exact(g2_repr.as_mut())?;
let neg_x_n_minus_d = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
let k_map_len = reader.read_u32::<BigEndian>()? as usize;
let mut k_map = vec![];
for _ in 0..k_map_len {
let k = reader.read_u32::<BigEndian>()? as usize;
k_map.push(k);
}
let n = reader.read_u32::<BigEndian>()? as usize;
let q = reader.read_u32::<BigEndian>()? as usize;
Ok(VerifyingKey {
alpha_x: alpha_x,
alpha: alpha,
neg_h: neg_h,
neg_x_n_minus_d: neg_x_n_minus_d,
k_map: k_map,
n: n,
q: q
})
}
}
use crate::sonic::cs::{Backend, Basic, SynthesisDriver};
use crate::sonic::srs::SRS;
use crate::sonic::cs::Circuit as SonicCircuit;
use std::marker::PhantomData;
impl<E: Engine> VerifyingKey<E> {
pub fn new<C: SonicCircuit<E>, S: SynthesisDriver>(circuit: C, srs: &SRS<E>) -> Result<Self, SynthesisError> {
struct Preprocess<E: Engine> {
k_map: Vec<usize>,
n: usize,
q: usize,
_marker: PhantomData<E>
}
impl<'a, E: Engine> Backend<E> for &'a mut Preprocess<E> {
fn new_k_power(&mut self, index: usize) {
self.k_map.push(index);
}
fn new_multiplication_gate(&mut self) {
self.n += 1;
}
fn new_linear_constraint(&mut self) {
self.q += 1;
}
}
let mut preprocess = Preprocess { k_map: vec![], n: 0, q: 0, _marker: PhantomData };
S::synthesize(&mut preprocess, &circuit)?;
Ok(Self {
alpha_x: srs.h_positive_x_alpha[1],
alpha: srs.h_positive_x_alpha[0],
neg_h: {
let mut tmp = srs.h_negative_x[0];
tmp.negate();
tmp
},
neg_x_n_minus_d: {
let mut tmp = srs.h_negative_x[srs.d - preprocess.n];
tmp.negate();
tmp
},
k_map: preprocess.k_map,
n: preprocess.n,
q: preprocess.q
})
}
}
pub struct PreparedVerifyingKey<E: Engine> {
alpha_x: <E::G2Affine as CurveAffine>::Prepared,
alpha: <E::G2Affine as CurveAffine>::Prepared,
neg_h: <E::G2Affine as CurveAffine>::Prepared,
neg_x_n_minus_d: <E::G2Affine as CurveAffine>::Prepared,
k_map: Vec<usize>,
n: usize,
q: usize
}
#[derive(Clone, Eq)]
pub struct Parameters<E: Engine> {
pub vk: VerifyingKey<E>,
pub d: usize,
// g^{x^0}, g^{x^{-1}}, g^{x^{-2}}, ..., g^{x^{-d}}
pub g_negative_x: Arc<Vec<E::G1Affine>>,
// g^{x^0}, g^{x^{1}}, g^{x^{2}}, ..., g^{x^{d}}
pub g_positive_x: Arc<Vec<E::G1Affine>>,
// g^{x^0}, g^{x^{-1}}, g^{x^{-2}}, ..., g^{x^{-d}}
pub h_negative_x: Arc<Vec<E::G2Affine>>,
// g^{x^0}, g^{x^{1}}, g^{x^{2}}, ..., g^{x^{d}}
pub h_positive_x: Arc<Vec<E::G2Affine>>,
// alpha*(g^{x^{-1}}, g^{x^{-2}}, ..., g^{x^{-d}})
pub g_negative_x_alpha: Arc<Vec<E::G1Affine>>,
// alpha*(g^{x^{1}}, g^{x^{2}}, ..., g^{x^{d}})
pub g_positive_x_alpha: Arc<Vec<E::G1Affine>>,
// alpha*(h^{x^0}, h^{x^{-1}}, g^{x^{-2}}, ..., g^{x^{-d}})
pub h_negative_x_alpha: Arc<Vec<E::G2Affine>>,
// alpha*(h^{x^0}, g^{x^{1}}, g^{x^{2}}, ..., g^{x^{d}})
pub h_positive_x_alpha: Arc<Vec<E::G2Affine>>,
}
impl<E: Engine> PartialEq for Parameters<E> {
fn eq(&self, other: &Parameters<E>) -> bool {
self.vk == other.vk &&
self.d == other.d &&
self.g_negative_x == other.g_negative_x &&
self.g_positive_x == other.g_positive_x &&
self.h_negative_x == other.h_negative_x &&
self.h_positive_x == other.h_positive_x &&
self.g_negative_x_alpha == other.g_negative_x_alpha &&
self.g_positive_x_alpha == other.g_positive_x_alpha &&
self.h_negative_x_alpha == other.h_negative_x_alpha &&
self.h_positive_x_alpha == other.h_positive_x_alpha
}
}
impl<E: Engine> Parameters<E> {
pub fn write<W: Write>(
&self,
mut writer: W
) -> io::Result<()>
{
self.vk.write(&mut writer)?;
assert_eq!(self.d + 1, self.g_negative_x.len());
assert_eq!(self.d + 1, self.g_positive_x.len());
assert_eq!(self.d + 1, self.h_negative_x.len());
assert_eq!(self.d + 1, self.h_positive_x.len());
assert_eq!(self.d, self.g_negative_x_alpha.len());
assert_eq!(self.d, self.g_positive_x_alpha.len());
assert_eq!(self.d + 1, self.h_negative_x_alpha.len());
assert_eq!(self.d + 1, self.h_positive_x_alpha.len());
writer.write_u32::<BigEndian>(self.d as u32)?;
for g in &self.g_negative_x[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.g_positive_x[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.h_negative_x[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.h_positive_x[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.g_negative_x_alpha[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.g_positive_x_alpha[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.h_negative_x_alpha[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.h_positive_x_alpha[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
Ok(())
}
pub fn read<R: Read>(
mut reader: R,
checked: bool
) -> io::Result<Self>
{
let read_g1 = |reader: &mut R| -> io::Result<E::G1Affine> {
let mut repr = <E::G1Affine as CurveAffine>::Uncompressed::empty();
reader.read_exact(repr.as_mut())?;
if checked {
repr
.into_affine()
} else {
repr
.into_affine_unchecked()
}
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| if e.is_zero() {
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
} else {
Ok(e)
})
};
let read_g2 = |reader: &mut R| -> io::Result<E::G2Affine> {
let mut repr = <E::G2Affine as CurveAffine>::Uncompressed::empty();
reader.read_exact(repr.as_mut())?;
if checked {
repr
.into_affine()
} else {
repr
.into_affine_unchecked()
}
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| if e.is_zero() {
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
} else {
Ok(e)
})
};
let vk = VerifyingKey::<E>::read(&mut reader)?;
let mut g_negative_x = vec![];
let mut g_positive_x = vec![];
let mut h_negative_x = vec![];
let mut h_positive_x = vec![];
let mut g_negative_x_alpha = vec![];
let mut g_positive_x_alpha = vec![];
let mut h_negative_x_alpha = vec![];
let mut h_positive_x_alpha = vec![];
let d = reader.read_u32::<BigEndian>()? as usize;
{
for _ in 0..(d+1) {
g_negative_x.push(read_g1(&mut reader)?);
}
for _ in 0..(d+1) {
g_positive_x.push(read_g1(&mut reader)?);
}
}
{
for _ in 0..(d+1) {
h_negative_x.push(read_g2(&mut reader)?);
}
for _ in 0..(d+1) {
h_positive_x.push(read_g2(&mut reader)?);
}
}
{
for _ in 0..d {
g_negative_x_alpha.push(read_g1(&mut reader)?);
}
for _ in 0..d {
g_positive_x_alpha.push(read_g1(&mut reader)?);
}
}
{
for _ in 0..(d+1) {
h_negative_x_alpha.push(read_g2(&mut reader)?);
}
for _ in 0..(d+1) {
h_positive_x_alpha.push(read_g2(&mut reader)?);
}
}
Ok(Parameters {
vk: vk,
d: d,
g_negative_x: Arc::new(g_negative_x),
g_positive_x: Arc::new(g_positive_x),
h_negative_x: Arc::new(h_negative_x),
h_positive_x: Arc::new(h_positive_x),
g_negative_x_alpha: Arc::new(g_negative_x_alpha),
g_positive_x_alpha: Arc::new(g_positive_x_alpha),
h_negative_x_alpha: Arc::new(h_negative_x_alpha),
h_positive_x_alpha: Arc::new(h_positive_x_alpha)
})
}
}
// pub trait ParameterSource<E: Engine> {
// type G1Builder: SourceBuilder<E::G1Affine>;
// type G2Builder: SourceBuilder<E::G2Affine>;
// fn get_vk(
// &mut self,
// num_ic: usize
// ) -> Result<VerifyingKey<E>, SynthesisError>;
// fn get_h(
// &mut self,
// num_h: usize
// ) -> Result<Self::G1Builder, SynthesisError>;
// fn get_l(
// &mut self,
// num_l: usize
// ) -> Result<Self::G1Builder, SynthesisError>;
// fn get_a(
// &mut self,
// num_inputs: usize,
// num_aux: usize
// ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError>;
// fn get_b_g1(
// &mut self,
// num_inputs: usize,
// num_aux: usize
// ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError>;
// fn get_b_g2(
// &mut self,
// num_inputs: usize,
// num_aux: usize
// ) -> Result<(Self::G2Builder, Self::G2Builder), SynthesisError>;
// }
// impl<'a, E: Engine> ParameterSource<E> for &'a Parameters<E> {
// type G1Builder = (Arc<Vec<E::G1Affine>>, usize);
// type G2Builder = (Arc<Vec<E::G2Affine>>, usize);
// fn get_vk(
// &mut self,
// _: usize
// ) -> Result<VerifyingKey<E>, SynthesisError>
// {
// Ok(self.vk.clone())
// }
// fn get_h(
// &mut self,
// _: usize
// ) -> Result<Self::G1Builder, SynthesisError>
// {
// Ok((self.h.clone(), 0))
// }
// fn get_l(
// &mut self,
// _: usize
// ) -> Result<Self::G1Builder, SynthesisError>
// {
// Ok((self.l.clone(), 0))
// }
// fn get_a(
// &mut self,
// num_inputs: usize,
// _: usize
// ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError>
// {
// Ok(((self.a.clone(), 0), (self.a.clone(), num_inputs)))
// }
// fn get_b_g1(
// &mut self,
// num_inputs: usize,
// _: usize
// ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError>
// {
// Ok(((self.b_g1.clone(), 0), (self.b_g1.clone(), num_inputs)))
// }
// fn get_b_g2(
// &mut self,
// num_inputs: usize,
// _: usize
// ) -> Result<(Self::G2Builder, Self::G2Builder), SynthesisError>
// {
// Ok(((self.b_g2.clone(), 0), (self.b_g2.clone(), num_inputs)))
// }
// }
// #[cfg(test)]
// mod test_with_bls12_381 {
// use super::*;
// use {Circuit, SynthesisError, ConstraintSystem};
// use rand::{Rand, thread_rng};
// use ff::{Field};
// use pairing::bls12_381::{Bls12, Fr};
// #[test]
// fn serialization() {
// struct MySillyCircuit<E: Engine> {
// a: Option<E::Fr>,
// b: Option<E::Fr>
// }
// impl<E: Engine> Circuit<E> for MySillyCircuit<E> {
// fn synthesize<CS: ConstraintSystem<E>>(
// self,
// cs: &mut CS
// ) -> Result<(), SynthesisError>
// {
// let a = cs.alloc(|| "a", || self.a.ok_or(SynthesisError::AssignmentMissing))?;
// let b = cs.alloc(|| "b", || self.b.ok_or(SynthesisError::AssignmentMissing))?;
// let c = cs.alloc_input(|| "c", || {
// let mut a = self.a.ok_or(SynthesisError::AssignmentMissing)?;
// let b = self.b.ok_or(SynthesisError::AssignmentMissing)?;
// a.mul_assign(&b);
// Ok(a)
// })?;
// cs.enforce(
// || "a*b=c",
// |lc| lc + a,
// |lc| lc + b,
// |lc| lc + c
// );
// Ok(())
// }
// }
// let rng = &mut thread_rng();
// let params = generate_random_parameters::<Bls12, _, _>(
// MySillyCircuit { a: None, b: None },
// rng
// ).unwrap();
// {
// let mut v = vec![];
// params.write(&mut v).unwrap();
// assert_eq!(v.len(), 2136);
// let de_params = Parameters::read(&v[..], true).unwrap();
// assert!(params == de_params);
// let de_params = Parameters::read(&v[..], false).unwrap();
// assert!(params == de_params);
// }
// let pvk = prepare_verifying_key::<Bls12>(&params.vk);
// for _ in 0..100 {
// let a = Fr::rand(rng);
// let b = Fr::rand(rng);
// let mut c = a;
// c.mul_assign(&b);
// let proof = create_random_proof(
// MySillyCircuit {
// a: Some(a),
// b: Some(b)
// },
// &params,
// rng
// ).unwrap();
// let mut v = vec![];
// proof.write(&mut v).unwrap();
// assert_eq!(v.len(), 192);
// let de_proof = Proof::read(&v[..]).unwrap();
// assert!(proof == de_proof);
// assert!(verify_proof(&pvk, &proof, &[c]).unwrap());
// assert!(!verify_proof(&pvk, &proof, &[a]).unwrap());
// }
// }
// }

@ -16,10 +16,9 @@ use crate::sonic::cs::Circuit as SonicCircuit;
use crate::sonic::cs::ConstraintSystem as SonicConstraintSystem; use crate::sonic::cs::ConstraintSystem as SonicConstraintSystem;
use crate::sonic::cs::Variable as SonicVariable; use crate::sonic::cs::Variable as SonicVariable;
use crate::sonic::cs::Coeff; use crate::sonic::cs::Coeff;
// use crate::sonic::cs::synthesis::*;
use std::marker::PhantomData; use std::marker::PhantomData;
struct Adaptor<'a, E: Engine, CS: SonicConstraintSystem<E> + 'a> { pub struct Adaptor<'a, E: Engine, CS: SonicConstraintSystem<E> + 'a> {
cs: &'a mut CS, cs: &'a mut CS,
_marker: PhantomData<E>, _marker: PhantomData<E>,
} }

@ -3,4 +3,4 @@ extern crate pairing;
mod adaptor; mod adaptor;
pub use self::adaptor::{AdaptorCircuit}; pub use self::adaptor::{Adaptor, AdaptorCircuit};

@ -1,6 +1,11 @@
use ff::{Field, PrimeField}; use ff::{Field, PrimeField};
use pairing::{CurveAffine, CurveProjective, Engine, Wnaf}; use pairing::{CurveAffine, CurveProjective, Engine, Wnaf};
use std::io::{self, Read, Write};
use std::sync::Arc;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};
#[derive(Clone, Eq)]
pub struct SRS<E: Engine> { pub struct SRS<E: Engine> {
pub d: usize, pub d: usize,
@ -29,6 +34,20 @@ pub struct SRS<E: Engine> {
pub h_positive_x_alpha: Vec<E::G2Affine>, pub h_positive_x_alpha: Vec<E::G2Affine>,
} }
impl<E: Engine> PartialEq for SRS<E> {
fn eq(&self, other: &SRS<E>) -> bool {
self.d == other.d &&
self.g_negative_x == other.g_negative_x &&
self.g_positive_x == other.g_positive_x &&
self.h_negative_x == other.h_negative_x &&
self.h_positive_x == other.h_positive_x &&
self.g_negative_x_alpha == other.g_negative_x_alpha &&
self.g_positive_x_alpha == other.g_positive_x_alpha &&
self.h_negative_x_alpha == other.h_negative_x_alpha &&
self.h_positive_x_alpha == other.h_positive_x_alpha
}
}
impl<E: Engine> SRS<E> { impl<E: Engine> SRS<E> {
pub fn dummy(d: usize, _: E::Fr, _: E::Fr) -> Self { pub fn dummy(d: usize, _: E::Fr, _: E::Fr) -> Self {
SRS { SRS {
@ -93,3 +112,163 @@ impl<E: Engine> SRS<E> {
} }
} }
} }
impl<E: Engine> SRS<E> {
pub fn write<W: Write>(
&self,
mut writer: W
) -> io::Result<()>
{
assert_eq!(self.d + 1, self.g_negative_x.len());
assert_eq!(self.d + 1, self.g_positive_x.len());
assert_eq!(self.d + 1, self.h_negative_x.len());
assert_eq!(self.d + 1, self.h_positive_x.len());
assert_eq!(self.d, self.g_negative_x_alpha.len());
assert_eq!(self.d, self.g_positive_x_alpha.len());
assert_eq!(self.d + 1, self.h_negative_x_alpha.len());
assert_eq!(self.d + 1, self.h_positive_x_alpha.len());
writer.write_u32::<BigEndian>(self.d as u32)?;
for g in &self.g_negative_x[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.g_positive_x[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.h_negative_x[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.h_positive_x[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.g_negative_x_alpha[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.g_positive_x_alpha[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.h_negative_x_alpha[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
for g in &self.h_positive_x_alpha[..] {
writer.write_all(g.into_uncompressed().as_ref())?;
}
Ok(())
}
pub fn read<R: Read>(
mut reader: R,
checked: bool
) -> io::Result<Self>
{
use pairing::EncodedPoint;
let read_g1 = |reader: &mut R| -> io::Result<E::G1Affine> {
let mut repr = <E::G1Affine as CurveAffine>::Uncompressed::empty();
reader.read_exact(repr.as_mut())?;
if checked {
repr
.into_affine()
} else {
repr
.into_affine_unchecked()
}
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| if e.is_zero() {
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
} else {
Ok(e)
})
};
let read_g2 = |reader: &mut R| -> io::Result<E::G2Affine> {
let mut repr = <E::G2Affine as CurveAffine>::Uncompressed::empty();
reader.read_exact(repr.as_mut())?;
if checked {
repr
.into_affine()
} else {
repr
.into_affine_unchecked()
}
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
.and_then(|e| if e.is_zero() {
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
} else {
Ok(e)
})
};
let mut g_negative_x = vec![];
let mut g_positive_x = vec![];
let mut h_negative_x = vec![];
let mut h_positive_x = vec![];
let mut g_negative_x_alpha = vec![];
let mut g_positive_x_alpha = vec![];
let mut h_negative_x_alpha = vec![];
let mut h_positive_x_alpha = vec![];
let d = reader.read_u32::<BigEndian>()? as usize;
{
for _ in 0..(d+1) {
g_negative_x.push(read_g1(&mut reader)?);
}
for _ in 0..(d+1) {
g_positive_x.push(read_g1(&mut reader)?);
}
}
{
for _ in 0..(d+1) {
h_negative_x.push(read_g2(&mut reader)?);
}
for _ in 0..(d+1) {
h_positive_x.push(read_g2(&mut reader)?);
}
}
{
for _ in 0..d {
g_negative_x_alpha.push(read_g1(&mut reader)?);
}
for _ in 0..d {
g_positive_x_alpha.push(read_g1(&mut reader)?);
}
}
{
for _ in 0..(d+1) {
h_negative_x_alpha.push(read_g2(&mut reader)?);
}
for _ in 0..(d+1) {
h_positive_x_alpha.push(read_g2(&mut reader)?);
}
}
Ok(Self {
d: d,
g_negative_x: g_negative_x,
g_positive_x: g_positive_x,
h_negative_x: h_negative_x,
h_positive_x: h_positive_x,
g_negative_x_alpha: g_negative_x_alpha,
g_positive_x_alpha: g_positive_x_alpha,
h_negative_x_alpha: h_negative_x_alpha,
h_positive_x_alpha: h_positive_x_alpha
})
}
}

@ -639,6 +639,19 @@ fn test_inputs_into_sonic_mimc() {
let mut verifier = MultiVerifier::<Bn256, _, Basic>::new(AdaptorCircuit(circuit.clone()), &srs).unwrap(); let mut verifier = MultiVerifier::<Bn256, _, Basic>::new(AdaptorCircuit(circuit.clone()), &srs).unwrap();
println!("verifying 100 proofs with advice"); println!("verifying 100 proofs with advice");
let start = Instant::now(); let start = Instant::now();
{
for _ in 0..samples {
verifier.add_proof_with_advice(&proof, &[image], &advice);
}
assert_eq!(verifier.check_all(), true); // TODO
}
println!("done in {:?}", start.elapsed());
}
{
let mut verifier = MultiVerifier::<Bn256, _, Basic>::new(AdaptorCircuit(circuit.clone()), &srs).unwrap();
println!("verifying 100 proofs with advice and aggregate");
let start = Instant::now();
{ {
for (ref proof, ref advice) in &proofs { for (ref proof, ref advice) in &proofs {
verifier.add_proof_with_advice(proof, &[image], advice); verifier.add_proof_with_advice(proof, &[image], advice);