start restructuring to use groth16-similar types
This commit is contained in:
parent
cd00c4eaf7
commit
6059601518
@ -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
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
800
src/sonic/helped/generator.rs
Normal file
800
src/sonic/helped/generator.rs
Normal file
@ -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>(¶ms.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)
|
||||||
|
// },
|
||||||
|
// ¶ms,
|
||||||
|
// 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
|
|
||||||
}
|
|
689
src/sonic/helped/parameters.rs
Normal file
689
src/sonic/helped/parameters.rs
Normal file
@ -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>(¶ms.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)
|
||||||
|
// },
|
||||||
|
// ¶ms,
|
||||||
|
// 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);
|
||||||
|
Loading…
Reference in New Issue
Block a user