diff --git a/src/sonic/cs/mod.rs b/src/sonic/cs/mod.rs index 3138c06..342d408 100644 --- a/src/sonic/cs/mod.rs +++ b/src/sonic/cs/mod.rs @@ -7,7 +7,6 @@ use pairing::{Engine}; use crate::{SynthesisError}; use std::marker::PhantomData; - mod lc; pub use self::lc::{Coeff, Variable, LinearCombination}; diff --git a/src/sonic/helped/batch.rs b/src/sonic/helped/batch.rs index 17f9871..3a7e23a 100644 --- a/src/sonic/helped/batch.rs +++ b/src/sonic/helped/batch.rs @@ -141,74 +141,4 @@ impl Batch { (&neg_x_n_minus_d, &self.neg_x_n_minus_d_precomp), ])).unwrap() == E::Fqk::one() } -} - -#[derive(Clone, Debug)] -pub struct VerifyingKey { - 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, - - pub n: usize, - - pub q: usize -} - -impl VerifyingKey { - pub fn new, S: SynthesisDriver>(circuit: C, srs: &SRS) -> Result { - struct Preprocess { - k_map: Vec, - n: usize, - q: usize, - _marker: PhantomData - } - - impl<'a, E: Engine> Backend for &'a mut Preprocess { - 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 - }) - } } \ No newline at end of file diff --git a/src/sonic/helped/generator.rs b/src/sonic/helped/generator.rs new file mode 100644 index 0000000..e385781 --- /dev/null +++ b/src/sonic/helped/generator.rs @@ -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( + circuit: C, + rng: &mut R +) -> Result, SynthesisError> + where E: Engine, C: Circuit, R: Rng +{ + let alpha = rng.gen(); + let x = rng.gen(); + + generate_parameters::( + circuit, + alpha, + x + ) +} + +/// This is our assembly structure that we'll use to synthesize the +/// circuit into +#[derive(Clone, Debug)] +pub struct CircuitParameters { + pub num_inputs: usize, + pub num_aux: usize, + pub num_constraints: usize, + pub k_map: Vec, + pub n: usize, + pub q: usize, + _marker: PhantomData +} + +/// This is our assembly structure that we'll use to synthesize the +/// circuit into +struct GeneratorAssembly<'a, E: Engine, CS: SonicConstraintSystem + 'a> { + cs: &'a mut CS, + num_inputs: usize, + num_aux: usize, + num_constraints: usize, + _marker: PhantomData +} + +impl<'a, E: Engine, CS: SonicConstraintSystem + 'a> crate::ConstraintSystem + 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(&mut self, _: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, + { + 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( + &mut self, + _: A, + f: F, + ) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, + { + 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(&mut self, _: A, a: LA, b: LB, c: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(crate::LinearCombination) -> crate::LinearCombination, + LB: FnOnce(crate::LinearCombination) -> crate::LinearCombination, + LC: FnOnce(crate::LinearCombination) -> crate::LinearCombination, + { + fn convert(lc: crate::LinearCombination) -> SonicLinearCombination { + 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>( + lc: &SonicLinearCombination, + cs: &CS, + ) -> Option { + 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(&mut self, _: N) + where + NR: Into, + 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( + circuit: C, +) -> Result, SynthesisError> + where E: Engine, C: Circuit + +{ + struct NonassigningSynthesizer> { + backend: B, + current_variable: Option, + _marker: PhantomData, + q: usize, + n: usize, + } + + impl> SonicConstraintSystem for NonassigningSynthesizer { + const ONE: SonicVariable = SonicVariable::A(1); + + fn alloc(&mut self, value: F) -> Result + where + F: FnOnce() -> Result + { + 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(&mut self, value: F) -> Result + where + F: FnOnce() -> Result + { + 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) + { + self.q += 1; + self.backend.new_linear_constraint(); + + for (var, coeff) in lc.as_ref() { + self.backend.insert_coefficient(*var, *coeff); + } + } + + fn multiply(&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 { + self.backend.get_var(var).ok_or(()) + } + } + + struct Preprocess { + k_map: Vec, + n: usize, + q: usize, + _marker: PhantomData + } + + impl<'a, E: Engine> Backend for &'a mut Preprocess { + 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> = 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, > as SonicConstraintSystem>::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( + circuit: C, + alpha: E::Fr, + x: E::Fr +) -> Result, SynthesisError> + where E: Engine, C: Circuit +{ + let circuit_parameters = get_circuit_parameters::(circuit)?; + let min_d = circuit_parameters.n * 3; + + let srs = generate_srs(alpha, x, min_d)?; + + let parameters = generate_parameters_on_srs_and_information::(&srs, circuit_parameters)?; + + Ok(parameters) +} + +pub fn generate_parameters_on_srs( + circuit: C, + srs: &SRS, +) -> Result, SynthesisError> + where E: Engine, C: Circuit +{ + let circuit_parameters = get_circuit_parameters::(circuit)?; + let parameters = generate_parameters_on_srs_and_information(&srs, circuit_parameters)?; + + Ok(parameters) +} + +pub fn generate_parameters_on_srs_and_information( + srs: &SRS, + information: CircuitParameters +) -> Result, SynthesisError> +{ + assert!(srs.d >= information.n * 3); + let min_d = information.n * 3; + + let trimmed_srs: SRS = 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( + alpha: E::Fr, + x: E::Fr, + d: usize +) -> Result, 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::Fr::zero()); d]; + let mut x_powers_negative = vec![Scalar::(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( + // wNAF window tables + g1_wnaf: &Wnaf>, + g2_wnaf: &Wnaf>, + + powers_of_x: &[Scalar], + + 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 { + a: Option, + b: Option + } + + impl Circuit for MySillyCircuit { + fn synthesize>( + 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::(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::(MySillyCircuit { a: None, b: None }, alpha, x).unwrap(); + let srs = generate_srs::(alpha, x, info.n * 100).unwrap(); + let naive_srs = SRS::::new( + info.n * 100, + x, + alpha, + ); + + assert!(srs == naive_srs); + + let params_on_srs = generate_parameters_on_srs_and_information::(&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::(¶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()); + // } +} \ No newline at end of file diff --git a/src/sonic/helped/mod.rs b/src/sonic/helped/mod.rs index b330fed..6f82c79 100644 --- a/src/sonic/helped/mod.rs +++ b/src/sonic/helped/mod.rs @@ -10,25 +10,11 @@ mod prover; mod batch; mod poly; 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::verifier::{MultiVerifier}; pub use self::prover::{create_proof, create_advice}; - -#[derive(Clone, Debug)] -pub struct SxyAdvice { - pub s: E::G1Affine, - pub opening: E::G1Affine, - pub szy: E::Fr, -} - -#[derive(Clone, Debug)] -pub struct Proof { - 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 -} \ No newline at end of file +pub use self::parameters::{Proof, SxyAdvice, Parameters, VerifyingKey, PreparedVerifyingKey}; \ No newline at end of file diff --git a/src/sonic/helped/parameters.rs b/src/sonic/helped/parameters.rs new file mode 100644 index 0000000..edb7361 --- /dev/null +++ b/src/sonic/helped/parameters.rs @@ -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 { + pub s: E::G1Affine, + pub opening: E::G1Affine, + pub szy: E::Fr, +} + + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Proof { + 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 Proof { + pub fn 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( + mut reader: R + ) -> io::Result + { + let mut g1_repr = ::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 { + 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, + + pub n: usize, + + pub q: usize +} + +impl PartialEq for VerifyingKey { + fn eq(&self, other: &VerifyingKey) -> 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 VerifyingKey { + pub fn 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::(self.k_map.len() as u32)?; + for k in &self.k_map { + writer.write_u32::(*k as u32)?; + } + writer.write_u32::(self.n as u32)?; + writer.write_u32::(self.q as u32)?; + + Ok(()) + } + + pub fn read( + mut reader: R + ) -> io::Result + { + let mut g2_repr = ::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::()? as usize; + + let mut k_map = vec![]; + + for _ in 0..k_map_len { + let k = reader.read_u32::()? as usize; + + k_map.push(k); + } + + let n = reader.read_u32::()? as usize; + + let q = reader.read_u32::()? 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 VerifyingKey { + pub fn new, S: SynthesisDriver>(circuit: C, srs: &SRS) -> Result { + struct Preprocess { + k_map: Vec, + n: usize, + q: usize, + _marker: PhantomData + } + + impl<'a, E: Engine> Backend for &'a mut Preprocess { + 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 { + alpha_x: ::Prepared, + alpha: ::Prepared, + neg_h: ::Prepared, + neg_x_n_minus_d: ::Prepared, + k_map: Vec, + n: usize, + q: usize +} + +#[derive(Clone, Eq)] +pub struct Parameters { + pub vk: VerifyingKey, + + pub d: usize, + + // g^{x^0}, g^{x^{-1}}, g^{x^{-2}}, ..., g^{x^{-d}} + pub g_negative_x: Arc>, + + // g^{x^0}, g^{x^{1}}, g^{x^{2}}, ..., g^{x^{d}} + pub g_positive_x: Arc>, + + // g^{x^0}, g^{x^{-1}}, g^{x^{-2}}, ..., g^{x^{-d}} + pub h_negative_x: Arc>, + + // g^{x^0}, g^{x^{1}}, g^{x^{2}}, ..., g^{x^{d}} + pub h_positive_x: Arc>, + + // alpha*(g^{x^{-1}}, g^{x^{-2}}, ..., g^{x^{-d}}) + pub g_negative_x_alpha: Arc>, + + // alpha*(g^{x^{1}}, g^{x^{2}}, ..., g^{x^{d}}) + pub g_positive_x_alpha: Arc>, + + // alpha*(h^{x^0}, h^{x^{-1}}, g^{x^{-2}}, ..., g^{x^{-d}}) + pub h_negative_x_alpha: Arc>, + + // alpha*(h^{x^0}, g^{x^{1}}, g^{x^{2}}, ..., g^{x^{d}}) + pub h_positive_x_alpha: Arc>, +} + +impl PartialEq for Parameters { + fn eq(&self, other: &Parameters) -> 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 Parameters { + pub fn 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::(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( + mut reader: R, + checked: bool + ) -> io::Result + { + let read_g1 = |reader: &mut R| -> io::Result { + let mut repr = ::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 { + let mut repr = ::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::::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::()? 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 { +// type G1Builder: SourceBuilder; +// type G2Builder: SourceBuilder; + +// fn get_vk( +// &mut self, +// num_ic: usize +// ) -> Result, SynthesisError>; +// fn get_h( +// &mut self, +// num_h: usize +// ) -> Result; +// fn get_l( +// &mut self, +// num_l: usize +// ) -> Result; +// 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 for &'a Parameters { +// type G1Builder = (Arc>, usize); +// type G2Builder = (Arc>, usize); + +// fn get_vk( +// &mut self, +// _: usize +// ) -> Result, SynthesisError> +// { +// Ok(self.vk.clone()) +// } + +// fn get_h( +// &mut self, +// _: usize +// ) -> Result +// { +// Ok((self.h.clone(), 0)) +// } + +// fn get_l( +// &mut self, +// _: usize +// ) -> Result +// { +// 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 { +// a: Option, +// b: Option +// } + +// impl Circuit for MySillyCircuit { +// fn synthesize>( +// 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::( +// 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::(¶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()); +// } +// } +// } \ No newline at end of file diff --git a/src/sonic/sonic/adaptor.rs b/src/sonic/sonic/adaptor.rs index 6bed160..cf96240 100644 --- a/src/sonic/sonic/adaptor.rs +++ b/src/sonic/sonic/adaptor.rs @@ -16,10 +16,9 @@ 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::cs::synthesis::*; use std::marker::PhantomData; -struct Adaptor<'a, E: Engine, CS: SonicConstraintSystem + 'a> { +pub struct Adaptor<'a, E: Engine, CS: SonicConstraintSystem + 'a> { cs: &'a mut CS, _marker: PhantomData, } @@ -112,7 +111,7 @@ impl<'a, E: Engine, CS: SonicConstraintSystem + 'a> crate::ConstraintSystem { pub d: usize, @@ -29,6 +34,20 @@ pub struct SRS { pub h_positive_x_alpha: Vec, } +impl PartialEq for SRS { + fn eq(&self, other: &SRS) -> 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 SRS { pub fn dummy(d: usize, _: E::Fr, _: E::Fr) -> Self { SRS { @@ -93,3 +112,163 @@ impl SRS { } } } + +impl SRS { + pub fn 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::(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( + mut reader: R, + checked: bool + ) -> io::Result + { + use pairing::EncodedPoint; + + let read_g1 = |reader: &mut R| -> io::Result { + let mut repr = ::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 { + let mut repr = ::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::()? 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 + }) + } +} \ No newline at end of file diff --git a/tests/mimc.rs b/tests/mimc.rs index 3be384d..0037cd1 100644 --- a/tests/mimc.rs +++ b/tests/mimc.rs @@ -634,11 +634,24 @@ fn test_inputs_into_sonic_mimc() { } println!("done in {:?}", start.elapsed()); } - + { let mut verifier = MultiVerifier::::new(AdaptorCircuit(circuit.clone()), &srs).unwrap(); println!("verifying 100 proofs with advice"); 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::::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 { verifier.add_proof_with_advice(proof, &[image], advice);