diff --git a/Cargo.lock b/Cargo.lock index dea6fd1c88..cd659fb1e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,18 +127,6 @@ dependencies = [ "rayon", ] -[[package]] -name = "commitment_pairing" -version = "0.1.0" -dependencies = [ - "algebra", - "colored 1.9.3", - "ff-fft", - "oracle", - "rand", - "rand_core", -] - [[package]] name = "constant_time_eq" version = "0.1.5" @@ -231,6 +219,7 @@ name = "dlog" version = "0.1.0" dependencies = [ "algebra", + "array-init", "colored 1.9.3", "commitment_dlog", "ff-fft", @@ -374,21 +363,6 @@ dependencies = [ "sprs 0.7.1", ] -[[package]] -name = "marlin_protocol_pairing" -version = "0.1.0" -dependencies = [ - "algebra", - "colored 1.9.3", - "commitment_pairing", - "ff-fft", - "marlin_circuits", - "oracle", - "rand", - "rand_core", - "sprs 0.7.1", -] - [[package]] name = "matrixmultiply" version = "0.2.4" @@ -530,24 +504,6 @@ dependencies = [ "rayon", ] -[[package]] -name = "pairing" -version = "0.1.0" -dependencies = [ - "algebra", - "colored 1.9.3", - "commitment_pairing", - "ff-fft", - "marlin_circuits", - "marlin_protocol_pairing", - "oracle", - "plonk_5_wires_circuits", - "plonk_protocol_pairing", - "rand", - "rand_core", - "sprs 0.7.1", -] - [[package]] name = "plonk_15_wires_circuits" version = "0.1.0" @@ -707,22 +663,6 @@ dependencies = [ "sprs 0.7.1", ] -[[package]] -name = "plonk_protocol_pairing" -version = "0.1.0" -dependencies = [ - "algebra", - "array-init", - "colored 1.9.3", - "commitment_pairing", - "ff-fft", - "oracle", - "plonk_circuits", - "rand", - "rand_core", - "sprs 0.7.1", -] - [[package]] name = "ppv-lite86" version = "0.2.10" diff --git a/Cargo.toml b/Cargo.toml index ab721ab7c1..8f29dd52ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ "dlog", - "pairing", "oracle", "dlog_solver", ] diff --git a/circuits/plonk-15-wires/src/gates/poseidon.rs b/circuits/plonk-15-wires/src/gates/poseidon.rs index 885ef34bef..36a8a18cf3 100644 --- a/circuits/plonk-15-wires/src/gates/poseidon.rs +++ b/circuits/plonk-15-wires/src/gates/poseidon.rs @@ -9,21 +9,33 @@ Constraint vector format: *****************************************************************************************************************/ use algebra::FftField; -use oracle::poseidon::{ArithmeticSpongeParams, Plonk15SpongeConstants, sbox}; -use crate::{wires::GateWires, wires::{COLUMNS, WIRES}, nolookup::constraints::ConstraintSystem}; +use oracle::poseidon::{SpongeConstants, Plonk15SpongeConstants, sbox}; +use crate::{wires::GateWires, wires::{COLUMNS}, nolookup::constraints::ConstraintSystem}; use crate::gate::{CircuitGate, GateType}; use array_init::array_init; +use std::ops::Range; -pub const SPONGE_WIDTH: usize = SPONGE_WIDTH; +pub const SPONGE_WIDTH: usize = Plonk15SpongeConstants::SPONGE_WIDTH; pub const ROUNDS_PER_ROW: usize = COLUMNS / SPONGE_WIDTH; +// There are 5 round states per row. We put the first state first, followed by the last state +// so that they are both accessible by the permutation argument. +pub const STATE_ORDER : [usize; ROUNDS_PER_ROW] = [0, 2, 3, 4, 1]; + +pub fn round_range(i : usize) -> Range { + let slot = STATE_ORDER[i]; + let start = slot * SPONGE_WIDTH; + start..(start + SPONGE_WIDTH) +} + impl CircuitGate { pub fn create_poseidon ( row: usize, wires: GateWires, - c: Vec + // Coefficients are passed in in the logical order + c: [[F; SPONGE_WIDTH]; ROUNDS_PER_ROW] ) -> Self { CircuitGate @@ -31,21 +43,27 @@ impl CircuitGate row, typ: GateType::Poseidon, wires, - c + c: c.iter().flatten().map(|x| *x).collect() } } pub fn verify_poseidon(&self, witness: &[Vec; COLUMNS], cs: &ConstraintSystem) -> bool { - let this: [[F; SPONGE_WIDTH]; ROUNDS_PER_ROW] = array_init(|i| array_init(|j| witness[ROUNDS_PER_ROW*i+j][self.row])); - let next: [F; SPONGE_WIDTH] = array_init(|i| witness[i][self.row+1]); + // TODO: Needs to be fixed + + let this: [[F; SPONGE_WIDTH]; ROUNDS_PER_ROW] = array_init(|round| { + let wire = STATE_ORDER[round]; + array_init(|col| witness[col + wire * SPONGE_WIDTH][self.row]) + }); + let next: [F; SPONGE_WIDTH] = array_init(|i| witness[i + STATE_ORDER[0] * SPONGE_WIDTH][self.row+1]); + let rc = self.rc(); let perm: [Vec; ROUNDS_PER_ROW] = array_init ( - |j| + |round| cs.fr_sponge_params.mds.iter().enumerate(). - map(|(i, m)| rc[j][i] + &this[j].iter().zip(m.iter()).fold(F::zero(), |x, (s, &m)| m * sbox::(*s) + x)).collect::>() + map(|(i, m)| rc[round][i] + &this[round].iter().zip(m.iter()).fold(F::zero(), |x, (s, &m)| m * sbox::(*s) + x)).collect::>() ); self.typ == GateType::Poseidon @@ -56,8 +74,18 @@ impl CircuitGate } pub fn ps(&self) -> F {if self.typ == GateType::Poseidon {F::one()} else {F::zero()}} + + // Coefficients are output here in the logical order pub fn rc(&self) -> [[F; SPONGE_WIDTH]; ROUNDS_PER_ROW] { - array_init(|i| array_init(|j| if self.typ == GateType::Poseidon {self.c[WIRES[ROUNDS_PER_ROW*i+j]]} else {F::zero()})) + array_init(|round| { + array_init(|col| { + if self.typ == GateType::Poseidon { + self.c[SPONGE_WIDTH*round+col] + } else { + F::zero() + } + }) + }) } } diff --git a/circuits/plonk-15-wires/src/nolookup/constraints.rs b/circuits/plonk-15-wires/src/nolookup/constraints.rs index c962208361..c5c98cb6a1 100644 --- a/circuits/plonk-15-wires/src/nolookup/constraints.rs +++ b/circuits/plonk-15-wires/src/nolookup/constraints.rs @@ -170,9 +170,8 @@ impl ConstraintSystem map(|gate| if gate.typ == GateType::Generic {gate.c[COLUMNS+1]} else {F::zero()}).collect(), domain.d1).interpolate(), // poseidon constraint polynomials - rcm: array_init(|j| {array_init(|i| E::>::from_vec_and_domain(gates.iter(). - map(|gate| if gate.typ == GateType::Poseidon {gate.rc()[i][j]} else {F::zero()}).collect(), domain.d1).interpolate())}), - + rcm: array_init(|round| {array_init(|col| E::>::from_vec_and_domain(gates.iter(). + map(|gate| if gate.typ == GateType::Poseidon {gate.rc()[round][col]} else {F::zero()}).collect(), domain.d1).interpolate())}), ps4: psm.evaluate_over_domain_by_ref(domain.d4), ps8: psm.evaluate_over_domain_by_ref(domain.d8), diff --git a/circuits/plonk-15-wires/src/nolookup/scalars.rs b/circuits/plonk-15-wires/src/nolookup/scalars.rs index 11f9281a93..a77d747584 100644 --- a/circuits/plonk-15-wires/src/nolookup/scalars.rs +++ b/circuits/plonk-15-wires/src/nolookup/scalars.rs @@ -6,7 +6,7 @@ This source file implements Plonk prover polynomial evaluations primitive. use crate::wires::*; use algebra::{FftField, Field}; -use oracle::{sponge_5_wires::ScalarChallenge, utils::PolyUtils}; +use oracle::{sponge::ScalarChallenge, utils::PolyUtils}; use ff_fft::DensePolynomial; use array_init::array_init; diff --git a/circuits/plonk-15-wires/src/polynomials/generic.rs b/circuits/plonk-15-wires/src/polynomials/generic.rs index eaaf846a4a..0667dec917 100644 --- a/circuits/plonk-15-wires/src/polynomials/generic.rs +++ b/circuits/plonk-15-wires/src/polynomials/generic.rs @@ -9,6 +9,7 @@ use ff_fft::{Evaluations, DensePolynomial, Radix2EvaluationDomain as D}; use crate::polynomial::WitnessOverDomains; use crate::nolookup::constraints::ConstraintSystem; use crate::nolookup::scalars::ProofEvaluations; +use crate::wires::GENERICS; use oracle::utils::PolyUtils; impl ConstraintSystem @@ -26,7 +27,12 @@ impl ConstraintSystem pub fn gnrc_scalars(evals: &ProofEvaluations) -> Vec { - vec![evals.w[0] * &evals.w[1], evals.w[0], evals.w[1], evals.w[2], evals.w[3], evals.w[4], F::one()] + let mut res = vec![evals.w[0] * &evals.w[1]]; + for i in 0..GENERICS { + res.push(evals.w[i]); + } + res.push(F::one()); + return res; } // generic constraint linearization poly contribution computation diff --git a/circuits/plonk-15-wires/src/polynomials/permutation.rs b/circuits/plonk-15-wires/src/polynomials/permutation.rs index b3ec24a62e..fca4ea697d 100644 --- a/circuits/plonk-15-wires/src/polynomials/permutation.rs +++ b/circuits/plonk-15-wires/src/polynomials/permutation.rs @@ -47,11 +47,11 @@ impl ConstraintSystem &lagrange.d8.this.w.iter().zip(self.sigmal8.iter()). map(|(p, s)| p + &(l0 + &s.scale(oracles.beta))). fold(lagrange.d8.next.z.clone(), |x, y| &x * &y)). - scale(oracles.alpha) + scale(alpha[0]) * &self.zkpl , - &bnd1.scale(alpha[0]) + &bnd2.scale(alpha[1]) + &bnd1.scale(alpha[1]) + &bnd2.scale(alpha[2]) )) } @@ -60,21 +60,23 @@ impl ConstraintSystem ( &self, e: &Vec>, oracles: &RandomOracles, + alpha: &[F], ) -> DensePolynomial { - self.sigmam[PERMUTS-1].scale(Self::perm_scalars(e, oracles, self.zkpm.evaluate(oracles.zeta))) + self.sigmam[PERMUTS-1].scale(Self::perm_scalars(e, oracles, alpha, self.zkpm.evaluate(oracles.zeta))) } pub fn perm_scalars ( e: &Vec>, oracles: &RandomOracles, + alpha: &[F], z: F, ) -> F { -e[0].w.iter().zip(e[0].s.iter()). map(|(w, s)| oracles.gamma + &(oracles.beta * s) + w). - fold(e[1].z * &oracles.beta * &oracles.alpha * &z, |x, y| x * y) + fold(e[1].z * &oracles.beta * alpha[0] * &z, |x, y| x * y) } // permutation aggregation polynomial computation diff --git a/circuits/plonk-15-wires/src/polynomials/poseidon.rs b/circuits/plonk-15-wires/src/polynomials/poseidon.rs index 0c54c6605b..8c15826381 100644 --- a/circuits/plonk-15-wires/src/polynomials/poseidon.rs +++ b/circuits/plonk-15-wires/src/polynomials/poseidon.rs @@ -14,9 +14,31 @@ use crate::nolookup::scalars::ProofEvaluations; use crate::gates::poseidon::*; use crate::wires::COLUMNS; +enum CurrOrNext { + Curr, Next +} + +// An equation of the form: +// (curr | next)[i] = round(curr[j]) +struct RoundEquation { + source: usize, + target: (CurrOrNext, usize) +} + +const ROUND_EQUATIONS : [RoundEquation; ROUNDS_PER_ROW] = + [ RoundEquation { source: 0, target: (CurrOrNext::Curr, 1) } + , RoundEquation { source: 1, target: (CurrOrNext::Curr, 2) } + , RoundEquation { source: 2, target: (CurrOrNext::Curr, 3) } + , RoundEquation { source: 3, target: (CurrOrNext::Curr, 4) } + , RoundEquation { source: 4, target: (CurrOrNext::Next, 0) } + ]; + impl ConstraintSystem { // poseidon quotient poly contribution computation f^7 + c(x) - f(wx) + // + // optimization: shuffle the intra-row rounds so that the final state is in one of the + // permutation columns pub fn psdn_quot ( &self, polys: &WitnessOverDomains, @@ -26,22 +48,92 @@ impl ConstraintSystem { if self.psm.is_zero() {return (self.zero4.clone(), self.zero8.clone(), DensePolynomial::::zero())} - // segregate into prtmutation section - let mut alp: [[F; SPONGE_WIDTH]; ROUNDS_PER_ROW] = array_init(|j| {array_init(|i| alpha[j*ROUNDS_PER_ROW+i])}); - let mut state: [[Evaluations>; SPONGE_WIDTH]; ROUNDS_PER_ROW] = array_init(|i| {array_init(|j| polys.d8.this.w[i*ROUNDS_PER_ROW+j].clone())}); + // Conjunction of: + // curr[round_range(1)] = round(curr[round_range(0)]) + // curr[round_range(2)] = round(curr[round_range(1)]) + // curr[round_range(3)] = round(curr[round_range(2)]) + // curr[round_range(4)] = round(curr[round_range(3)]) + // next[round_range(0)] = round(curr[round_range(4)]) + // + // which expands e.g., to + // curr[round_range(1)][0] = + // mds[0][0] * curr[round_range(0)][0] + // + mds[0][1] * curr[round_range(0)][1] + // + mds[0][2] * curr[round_range(0)][2] + // + rcm[round_range(1)][0] + // curr[round_range(1)][1] = + // mds[1][0] * curr[round_range(0)][0] + // + mds[1][1] * curr[round_range(0)][1] + // + mds[1][2] * curr[round_range(0)][2] + // + rcm[round_range(1)][1] + // .... + + // The rth position in this array contains the alphas used for the equations that + // constrain the values of the (r+1)th state. + + /* + let alp : [[F; SPONGE_WIDTH]; ROUNDS_PER_ROW] = array_init(|r| { + let range = round_range(r); + array_init(|i| alpha[range][i]) + }); */ + // let alp : [[F; SPONGE_WIDTH]; ROUNDS_PER_ROW] = array_init(|r| array_init(|i| alpha[r * SPONGE_WIDTH + i])); + + // In the logical order + let sboxed: [[Evaluations>; SPONGE_WIDTH]; ROUNDS_PER_ROW] = array_init(|r| { + let mut x : [_; SPONGE_WIDTH] = array_init(|i| polys.d8.this.w[round_range(r)][i].clone()); + x.iter_mut().for_each(|p| p.evals.iter_mut().for_each(|p| *p = sbox::(*p))); + x + }); - // this is the current state - let mut perm = state.clone(); + /* + let sboxed: [Evaluations>; COLUMNS] = array_init(|i| { + let mut x = array_init(|i| polys.d8.this.w[i].clone()); + x.iter_mut().for_each(|p| p.evals.iter_mut().for_each(|p| *p = sbox::(*p))); + x + }); - // permute the cuccent state - perm.iter_mut().for_each(|p| p.iter_mut().for_each(|r| *r = sbox::(*r))); + let sboxed_scalars : [F; COLUMNS] = array_init(|i| { + // find out what round i corresponds to, then look at + round_range + }); */ - let p4: [Evaluations>; ROUNDS_PER_ROW] = array_init(|i| {polys.d4.next.w.iter().zip(alpha[i][0..COLUMNS].iter()).map(|(p, a)| p.scale(-*a)). - fold(self.zero4.clone(), |x, y| &x + &y)}); - let p8: [Evaluations>; ROUNDS_PER_ROW] = array_init(|i| {}); + // Each round equation has SPONGE_WIDTH many equations within it. + // This ordering of alphas is somewhat arbitrary and maybe should be + // changed depending on circuit efficiency. + let alp : [[F; SPONGE_WIDTH]; ROUNDS_PER_ROW] = array_init(|r| array_init(|i| alpha[r * SPONGE_WIDTH + i])); + let lhs = ROUND_EQUATIONS.iter().fold(self.zero4.clone(), |acc, eq| { + let (target_row, target_round) = &eq.target; + let cols = + match target_row { + CurrOrNext::Curr => &polys.d4.this.w, + CurrOrNext::Next => &polys.d4.next.w, + }; + cols[round_range(*target_round)].iter() + .zip(alp[eq.source].iter()) + .map(|(p, a)| p.scale(-*a)) + .fold(acc, |x, y| &x + &y) + }); + let mut rhs = self.zero8.clone(); + for eq in ROUND_EQUATIONS.iter() { + for (i, p) in sboxed[eq.source].iter().enumerate() { + // Each of these contributes to the right hand side of SPONGE_WIDTH cell equations + let coeff = (0..SPONGE_WIDTH).fold(F::zero(), |acc, j| acc + alp[eq.source][j] * params.mds[j][i]); + rhs += &p.scale(coeff); + } + } + let rc = alp.iter().enumerate().fold(DensePolynomial::::zero(), |acc0, (round, als)| { + als.iter().enumerate().fold(acc0, |acc, (col, a)| &acc + &self.rcm[round][col].scale(*a)) + }); + + ( + &self.ps4 * &lhs, + &self.ps8 * &rhs, + rc + ) + /* ( &self.ps4 * &polys.d4.next.w.iter().zip(alpha[0..COLUMNS].iter()).map(|(p, a)| p.scale(-*a)). fold(self.zero4.clone(), |x, y| &x + &y), @@ -50,7 +142,8 @@ impl ConstraintSystem self.rcm.iter().zip(alpha[0..COLUMNS].iter()).map(|(p, a)| p.scale(*a)). fold(DensePolynomial::::zero(), |x, y| &x + &y), ) - } + */ + } pub fn psdn_scalars ( @@ -59,17 +152,44 @@ impl ConstraintSystem alpha: &[F] ) -> Vec { - let sbox = evals[0].w.iter().map(|&w| sbox::(w)).collect::>(); - let lro = params.mds.iter().map - ( - |m| sbox.iter().zip(m.iter()).fold(F::zero(), |x, (s, &m)| m * s + x) - ).collect::>(); - - vec! - [ - (0..lro.len()).fold(F::zero(), |x, i| x + alpha[i] * (lro[i] - evals[1].w[i])), - alpha[0], alpha[1], alpha[2], alpha[3], alpha[4] - ] + let sboxed: [[F; SPONGE_WIDTH]; ROUNDS_PER_ROW] = array_init(|r| { + array_init(|i| { + sbox::( + evals[0].w[round_range(r)][i]) + }) + }); + let alp : [[F; SPONGE_WIDTH]; ROUNDS_PER_ROW] = array_init(|r| array_init(|i| alpha[r * SPONGE_WIDTH + i])); + + /* + let lhs = ROUND_EQUATIONS.iter().fold(F::zero(), |acc, eq| { + let (target_row, target_round) = &eq.target; + let this_or_next = + match target_row { + CurrOrNext::Curr => 0, + CurrOrNext::Next => 1, + }; + evals[this_or_next].w[round_range(*target_round)].iter() + .zip(alp[eq.source].iter()) + .map(|(p, a)| -*a * p) + .fold(acc, |x, y| x + &y) + }); */ + + let mut rhs = F::zero(); + for eq in ROUND_EQUATIONS.iter() { + for (i, p) in sboxed[eq.source].iter().enumerate() { + // Each of these contributes to the right hand side of SPONGE_WIDTH cell equations + let coeff = (0..SPONGE_WIDTH).fold(F::zero(), |acc, j| acc + alp[eq.source][j] * params.mds[j][i]); + rhs += coeff * p; + } + } + + + let mut res = vec![rhs]; + for i in 0..COLUMNS { + res.push(alpha[i]); + } + println!("psdn_scalars {:?}", res); + res } // poseidon linearization poly contribution computation f^7 + c(x) - f(wx) @@ -81,6 +201,9 @@ impl ConstraintSystem alpha: &[F] ) -> DensePolynomial { - DensePolynomial::::zero() + println!("psdn_lnrz"); + let scalars = Self::psdn_scalars(evals, params, alpha); + self.rcm.iter().flatten().zip(alpha[0..COLUMNS].iter()).map(|(r, a)| r.scale(*a)). + fold(self.psm.scale(scalars[0]), |x, y| &x + &y) } } diff --git a/circuits/plonk-5-wires/src/polynomials/poseidon.rs b/circuits/plonk-5-wires/src/polynomials/poseidon.rs index 13f3836986..3b514b9d3b 100644 --- a/circuits/plonk-5-wires/src/polynomials/poseidon.rs +++ b/circuits/plonk-5-wires/src/polynomials/poseidon.rs @@ -33,9 +33,9 @@ impl ConstraintSystem collect::>(); ( &self.ps4 * &polys.d4.next.w.iter().zip(alpha[0..COLUMNS].iter()).map(|(p, a)| p.scale(-*a)). - fold(self.zero4.clone(), |x, y| &x + &y), + fold(self.zero4.clone(), |x, y| &x + &y), // next row on other side of equality &self.ps8 * &lro.iter().zip(scalers.iter()).map(|(p, s)| p.scale(*s)). - fold(self.zero8.clone(), |x, y| &x + &y), + fold(self.zero8.clone(), |x, y| &x + &y), // self.rcm.iter().zip(alpha[0..COLUMNS].iter()).map(|(p, a)| p.scale(*a)). fold(DensePolynomial::::zero(), |x, y| &x + &y), ) diff --git a/dlog/Cargo.toml b/dlog/Cargo.toml index 8d5c5c2b99..7ca8ed04ce 100644 --- a/dlog/Cargo.toml +++ b/dlog/Cargo.toml @@ -25,3 +25,4 @@ colored = "1.9.2" rand = "0.7.3" sprs = "0.7.1" rayon = { version = "1" } +array-init = "1.0.0" diff --git a/dlog/commitment/src/commitment.rs b/dlog/commitment/src/commitment.rs index f774e72fae..4d148034d7 100644 --- a/dlog/commitment/src/commitment.rs +++ b/dlog/commitment/src/commitment.rs @@ -24,6 +24,7 @@ use rand_core::RngCore; use rayon::prelude::*; use std::iter::Iterator; pub use crate::CommitmentField; +use core::ops::{Add, Sub}; type Fr = ::ScalarField; type Fq = ::BaseField; @@ -57,19 +58,91 @@ pub fn shift_scalar(x : F) -> F { x - two.pow(&[F::Params::MODULUS_BITS as u64]) } +impl<'a, 'b, C: AffineCurve> Add<&'a PolyComm> for &'b PolyComm { + type Output = PolyComm; + + fn add(self, other: &'a PolyComm) -> PolyComm { + let mut unshifted = vec![]; + let n1 = self.unshifted.len(); + let n2 = other.unshifted.len(); + for i in 0..std::cmp::max(n1, n2) { + let pt = + if i < n1 && i < n2 { + self.unshifted[i] + other.unshifted[i] + } else if i < n1 { + self.unshifted[i] + } else { + other.unshifted[i] + }; + unshifted.push(pt); + } + let shifted = + match (self.shifted, other.shifted) { + (None, _) => other.shifted, + (_, None) => self.shifted, + (Some(p1), Some(p2)) => Some(p1 + p2) + }; + PolyComm { unshifted, shifted } + } +} + +impl<'a, 'b, C: AffineCurve> Sub<&'a PolyComm> for &'b PolyComm { + type Output = PolyComm; + + fn sub(self, other: &'a PolyComm) -> PolyComm { + let mut unshifted = vec![]; + let n1 = self.unshifted.len(); + let n2 = other.unshifted.len(); + for i in 0..std::cmp::max(n1, n2) { + let pt = + if i < n1 && i < n2 { + self.unshifted[i] + (- other.unshifted[i]) + } else if i < n1 { + self.unshifted[i] + } else { + other.unshifted[i] + }; + unshifted.push(pt); + } + let shifted = + match (self.shifted, other.shifted) { + (None, _) => other.shifted, + (_, None) => self.shifted, + (Some(p1), Some(p2)) => Some(p1 + (- p2)) + }; + PolyComm { unshifted, shifted } + } +} + impl PolyComm { + pub fn scale(&self, c: C::ScalarField) -> PolyComm { + PolyComm { + unshifted: + self.unshifted.iter() + .map(|g| g.mul(c).into_affine()).collect(), + shifted: self.shifted.map(|g| g.mul(c).into_affine()) + } + } + pub fn multi_scalar_mul(com: &Vec<&PolyComm>, elm: &Vec) -> Self { + assert_eq!(com.len(), elm.len()); PolyComm:: { shifted: { - if com.len() == 0 || elm.len() == 0 || com[0].shifted == None {None} + let pairs = com.iter().zip(elm.iter()).filter_map(|(c, s)| { + match c.shifted { + Some(c) => Some((c, s)), + None => None, + } + }).collect::>(); + if pairs.len() == 0 { None } else { - let points = com.iter().map(|c| {assert!(c.shifted.is_some()); c.shifted.unwrap()}).collect::>(); - let scalars = elm.iter().map(|s| {s.into_repr()}).collect::>(); + let points = pairs.iter().map(|(c, _)| *c).collect::>(); + let scalars = pairs.iter().map(|(_, s)| s.into_repr()).collect::>(); Some(VariableBaseMSM::multi_scalar_mul(&points, &scalars).into_affine()) } }, diff --git a/dlog/plonk-15-wires-plookup/src/index.rs b/dlog/plonk-15-wires-plookup/src/index.rs index 9e4406f09d..9fd7cbce5b 100644 --- a/dlog/plonk-15-wires-plookup/src/index.rs +++ b/dlog/plonk-15-wires-plookup/src/index.rs @@ -7,7 +7,7 @@ This source file implements Plonk Protocol Index primitive. use ff_fft::{DensePolynomial, Radix2EvaluationDomain as D}; use commitment_dlog::{srs::SRS, CommitmentField, commitment::{CommitmentCurve, PolyComm}}; use oracle::poseidon::{ArithmeticSpongeParams, SpongeConstants, Plonk15SpongeConstants}; -use plonk_15_wires_circuits::{lookup::constraints::{ConstraintSystem}, wires::*}; +use plonk_15_wires_circuits::{gates::poseidon::{ROUNDS_PER_ROW}, lookup::constraints::{ConstraintSystem}, wires::*}; use algebra::{AffineCurve, PrimeField}; use array_init::array_init; @@ -79,7 +79,7 @@ pub struct VerifierIndex<'a, G: CommitmentCurve> pub qc_comm: PolyComm, // constant wire commitment // poseidon polynomial commitments - pub rcm_comm: [PolyComm; Plonk15SpongeConstants::SPONGE_WIDTH], // round constant polynomial commitment array + pub rcm_comm: [[PolyComm; Plonk15SpongeConstants::SPONGE_WIDTH]; ROUNDS_PER_ROW], // round constant polynomial commitment array pub psm_comm: PolyComm, // poseidon constraint selector polynomial commitment // ECC arithmetic polynomial commitments @@ -119,7 +119,7 @@ impl<'a, G: CommitmentCurve> Index<'a, G> where G::BaseField: PrimeField, G::Sca qm_comm: srs.get_ref().commit_non_hiding(&self.pcs.cs.qmm, None), qc_comm: srs.get_ref().commit_non_hiding(&self.pcs.cs.qc, None), - rcm_comm: array_init(|i| srs.get_ref().commit_non_hiding(&self.pcs.cs.rcm[i], None)), + rcm_comm: array_init(|i| array_init(|j| srs.get_ref().commit_non_hiding(&self.pcs.cs.rcm[i][j], None))), psm_comm: srs.get_ref().commit_non_hiding(&self.pcs.cs.psm, None), add_comm: srs.get_ref().commit_non_hiding(&self.pcs.cs.addm, None), diff --git a/dlog/plonk-15-wires-plookup/src/plonk_sponge.rs b/dlog/plonk-15-wires-plookup/src/plonk_sponge.rs index 69887ee89c..5acdc1f495 100644 --- a/dlog/plonk-15-wires-plookup/src/plonk_sponge.rs +++ b/dlog/plonk-15-wires-plookup/src/plonk_sponge.rs @@ -2,9 +2,9 @@ use plonk_15_wires_circuits::lookup::scalars::ProofEvaluations; use algebra::{ Field, PrimeField, }; -use oracle::poseidon_5_wires::{ArithmeticSponge, PlonkSpongeConstants as SC}; +use oracle::poseidon::{ArithmeticSponge, Plonk15SpongeConstants as SC}; use oracle::poseidon::{ArithmeticSpongeParams, Sponge}; -use oracle::sponge_5_wires::{DefaultFrSponge, ScalarChallenge}; +use oracle::sponge::{DefaultFrSponge, ScalarChallenge}; pub trait FrSponge { fn new(p: ArithmeticSpongeParams) -> Self; diff --git a/dlog/plonk-15-wires-plookup/src/prover.rs b/dlog/plonk-15-wires-plookup/src/prover.rs index eab22e3620..3f244739e0 100644 --- a/dlog/plonk-15-wires-plookup/src/prover.rs +++ b/dlog/plonk-15-wires-plookup/src/prover.rs @@ -14,7 +14,7 @@ use plonk_15_wires_circuits:: wires::COLUMNS, polynomial::LookupPolys }; -use oracle::{FqSponge, utils::PolyUtils, rndoracle::ProofError, sponge_5_wires::ScalarChallenge}; +use oracle::{FqSponge, utils::PolyUtils, rndoracle::ProofError, sponge::ScalarChallenge}; pub use super::{index::Index, range}; use crate::plonk_sponge::FrSponge; use array_init::array_init; @@ -332,7 +332,7 @@ impl ProverProof where G::ScalarField : CommitmentField &index.pcs.cs.endomul_lnrz(&pe, &alpha[range::ENDML])) + &index.pcs.cs.vbmul_lnrz(&pe, &alpha[range::MUL])) + &index.pcs.lookup_lnrz(&pe, &alpha[range::LKP])) + - &index.pcs.cs.perm_lnrz(&pe, &oracles.po); + &index.pcs.cs.perm_lnrz(&pe, &oracles.po, &alpha[range::PERM]); evals[0].pe.f = f.eval(evlp[0], index.max_poly_size); evals[1].pe.f = f.eval(evlp[1], index.max_poly_size); diff --git a/dlog/plonk-15-wires-plookup/src/verifier.rs b/dlog/plonk-15-wires-plookup/src/verifier.rs index a64deb72d8..51b224413e 100644 --- a/dlog/plonk-15-wires-plookup/src/verifier.rs +++ b/dlog/plonk-15-wires-plookup/src/verifier.rs @@ -7,7 +7,7 @@ This source file implements zk-proof batch verifier functionality. use crate::plonk_sponge::FrSponge; pub use super::prover::{ProverProof, range}; pub use super::index::VerifierIndex as Index; -use oracle::{FqSponge, rndoracle::ProofError, sponge_5_wires::ScalarChallenge}; +use oracle::{FqSponge, rndoracle::ProofError, sponge::ScalarChallenge}; use plonk_15_wires_circuits:: { wires::*, @@ -218,7 +218,7 @@ impl ProverProof where G::ScalarField : CommitmentField // permutation let zkp = index.zkpm.evaluate(oracles.po.zeta); let mut p = vec![&index.sigma_comm[PERMUTS-1]]; - let mut s = vec![CS::perm_scalars(&pevals, &oracles.po, zkp)]; + let mut s = vec![CS::perm_scalars(&pevals, &oracles.po, &alpha[range::PERM], zkp)]; // generic p.push(&index.qm_comm); @@ -229,7 +229,7 @@ impl ProverProof where G::ScalarField : CommitmentField // poseidon s.extend(&CS::psdn_scalars(&pevals, &index.fr_sponge_params, &alpha[range::PSDN])); p.push(&index.psm_comm); - p.extend(index.rcm_comm.iter().map(|c| c).collect::>()); + p.extend(index.rcm_comm.iter().flatten().map(|c| c).collect::>()); // EC addition s.push(CS::ecad_scalars(&pevals, &alpha[range::ADD])); @@ -268,11 +268,11 @@ impl ProverProof where G::ScalarField : CommitmentField - pevals[0].w.iter().zip(pevals[0].s.iter()). map(|(w, s)| (oracles.po.beta * s) + w + oracles.po.gamma). - fold((pevals[0].w[PERMUTS-1] + oracles.po.gamma) * pevals[1].z * oracles.po.alpha * zkp, |x, y| x * y) + fold((pevals[0].w[PERMUTS-1] + oracles.po.gamma) * pevals[1].z * alpha[range::PERM][0] * zkp, |x, y| x * y) + pevals[0].w.iter().zip(index.shift.iter()). map(|(w, s)| oracles.po.gamma + (oracles.po.beta * oracles.po.zeta * s) + w). - fold(oracles.po.alpha * zkp * pevals[0].z, |x, y| x * y) + fold(alpha[range::PERM][0] * zkp * pevals[0].z, |x, y| x * y) + ((((evals[0].l * beta1 * (oracles.gamma + evals[0].lw)) * (gammabeta1 + (evals[0].tb + evals[1].tb * oracles.beta))) @@ -289,9 +289,9 @@ impl ProverProof where G::ScalarField : CommitmentField * zetam1 * zetamw1 * zetamw3 != - (zm1 * zetamw1 * zetamw3 * alpha[range::PERM][0]) + (zm1 * zetamw1 * zetamw3 * alpha[range::PERM][1]) + - (zm1 * zetam1 * zetamw1 * alpha[range::PERM][1]) + (zm1 * zetam1 * zetamw1 * alpha[range::PERM][2]) + (lm1 * zetamw1 * zetamw3 * alpha[range::TABLE][1]) + diff --git a/dlog/plonk-15-wires/src/index.rs b/dlog/plonk-15-wires/src/index.rs index b71cad8ded..684fa22c0f 100644 --- a/dlog/plonk-15-wires/src/index.rs +++ b/dlog/plonk-15-wires/src/index.rs @@ -7,7 +7,7 @@ This source file implements Plonk Protocol Index primitive. use ff_fft::{DensePolynomial, Radix2EvaluationDomain as D}; use commitment_dlog::{srs::SRS, CommitmentField, commitment::{CommitmentCurve, PolyComm}}; use oracle::poseidon::{ArithmeticSpongeParams, SpongeConstants, Plonk15SpongeConstants}; -use plonk_15_wires_circuits::{nolookup::constraints::{zk_w3, ConstraintSystem}, wires::*}; +use plonk_15_wires_circuits::{gates::poseidon::{ROUNDS_PER_ROW}, nolookup::constraints::{zk_w3, ConstraintSystem}, wires::*}; use array_init::array_init; use algebra::AffineCurve; use algebra::PrimeField; @@ -79,7 +79,7 @@ pub struct VerifierIndex<'a, G: CommitmentCurve> pub qc_comm: PolyComm, // constant wire commitment // poseidon polynomial commitments - pub rcm_comm: [COLUMNS], // round constant polynomial commitment array + pub rcm_comm: [[PolyComm; Plonk15SpongeConstants::SPONGE_WIDTH]; ROUNDS_PER_ROW], // round constant polynomial commitment array pub psm_comm: PolyComm, // poseidon constraint selector polynomial commitment // ECC arithmetic polynomial commitments @@ -116,7 +116,7 @@ impl<'a, G: CommitmentCurve> Index<'a, G> where G::BaseField: PrimeField, G::Sca qm_comm: srs.get_ref().commit_non_hiding(&self.cs.qmm, None), qc_comm: srs.get_ref().commit_non_hiding(&self.cs.qc, None), - rcm_comm: array_init(|i| srs.get_ref().commit_non_hiding(&self.cs.rcm[i], None)), + rcm_comm: array_init(|i| array_init(|j| srs.get_ref().commit_non_hiding(&self.cs.rcm[i][j], None))), psm_comm: srs.get_ref().commit_non_hiding(&self.cs.psm, None), add_comm: srs.get_ref().commit_non_hiding(&self.cs.addm, None), diff --git a/dlog/plonk-15-wires/src/plonk_sponge.rs b/dlog/plonk-15-wires/src/plonk_sponge.rs index 7dced009ed..294e122c74 100644 --- a/dlog/plonk-15-wires/src/plonk_sponge.rs +++ b/dlog/plonk-15-wires/src/plonk_sponge.rs @@ -2,9 +2,9 @@ use plonk_15_wires_circuits::nolookup::scalars::ProofEvaluations; use algebra::{ Field, PrimeField, }; -use oracle::poseidon_5_wires::{ArithmeticSponge, PlonkSpongeConstants as SC}; -use oracle::poseidon::{ArithmeticSpongeParams, Sponge}; -use oracle::sponge_5_wires::{DefaultFrSponge, ScalarChallenge}; +// use oracle::poseidon_5_wires::{ArithmeticSponge, PlonkSpongeConstants as SC}; +use oracle::poseidon::{ArithmeticSponge, ArithmeticSpongeParams, Sponge, Plonk15SpongeConstants as SC}; +use oracle::sponge::{DefaultFrSponge, ScalarChallenge}; pub trait FrSponge { fn new(p: ArithmeticSpongeParams) -> Self; diff --git a/dlog/plonk-15-wires/src/prover.rs b/dlog/plonk-15-wires/src/prover.rs index 245c2bd30b..48298fece1 100644 --- a/dlog/plonk-15-wires/src/prover.rs +++ b/dlog/plonk-15-wires/src/prover.rs @@ -7,8 +7,8 @@ This source file implements prover's zk-proof primitive. use algebra::{Field, AffineCurve, Zero}; use ff_fft::{DensePolynomial, Evaluations, Radix2EvaluationDomain as D}; use commitment_dlog::commitment::{CommitmentField, CommitmentCurve, PolyComm, OpeningProof, b_poly_coefficients}; -use oracle::{FqSponge, utils::PolyUtils, rndoracle::ProofError, sponge_5_wires::ScalarChallenge}; -use plonk_15_wires_circuits::{nolookup::scalars::{ProofEvaluations, RandomOracles}, wires::COLUMNS}; +use oracle::{FqSponge, utils::PolyUtils, rndoracle::ProofError, sponge::ScalarChallenge}; +use plonk_15_wires_circuits::{nolookup::scalars::{ProofEvaluations, RandomOracles}, wires::{COLUMNS, PERMUTS}}; pub use super::{index::Index, range}; use crate::plonk_sponge::{FrSponge}; use array_init::array_init; @@ -246,7 +246,7 @@ impl ProverProof where G::ScalarField : CommitmentField ( |e| ProofEvaluations::>> { - s: array_init(|i| index.cs.sigmam[0..COLUMNS-1][i].eval(*e, index.max_poly_size)), + s: array_init(|i| index.cs.sigmam[0..PERMUTS-1][i].eval(*e, index.max_poly_size)), w: array_init(|i| w[i].eval(*e, index.max_poly_size)), z: z.eval(*e, index.max_poly_size), t: t.eval(*e, index.max_poly_size), @@ -270,6 +270,25 @@ impl ProverProof where G::ScalarField : CommitmentField // compute and evaluate linearization polynomial + /* + { + let f = index.cs.perm_lnrz(&e, &oracles, &alpha[range::PERM]); + println!("p{} f_comm {:?}", line!(), index.srs.get_ref().commit_non_hiding(&f, None)); + let f = &f + &index.cs.gnrc_lnrz(&e[0]); + println!("p{} f_comm {:?}", line!(), index.srs.get_ref().commit_non_hiding(&f, None)); + let f = &f + &index.cs.psdn_lnrz(&e, &index.cs.fr_sponge_params, &alpha[range::PSDN]); + println!("p{} psm_comm {:?}", line!(), index.srs.get_ref().commit_non_hiding(&index.cs.psm, None)); + println!("p{} f_comm {:?}", line!(), index.srs.get_ref().commit_non_hiding(&f, None)); + let f = &f + &index.cs.ecad_lnrz(&e, &alpha[range::ADD]); + println!("p{} f_comm {:?}", line!(), index.srs.get_ref().commit_non_hiding(&f, None)); + let f = &f + &index.cs.double_lnrz(&e, &alpha[range::DBL]); + println!("p{} f_comm {:?}", line!(), index.srs.get_ref().commit_non_hiding(&f, None)); + let f = &f + &index.cs.endomul_lnrz(&e, &alpha[range::ENDML]); + println!("p{} f_comm {:?}", line!(), index.srs.get_ref().commit_non_hiding(&f, None)); + let f = &f + &index.cs.vbmul_lnrz(&e, &alpha[range::MUL]); + println!("p{} f_comm {:?}", line!(), index.srs.get_ref().commit_non_hiding(&f, None)); + } */ + let f = &(&(&(&(&(&index.cs.gnrc_lnrz(&e[0]) + &index.cs.psdn_lnrz(&e, &index.cs.fr_sponge_params, &alpha[range::PSDN])) + @@ -277,7 +296,7 @@ impl ProverProof where G::ScalarField : CommitmentField &index.cs.double_lnrz(&e, &alpha[range::DBL])) + &index.cs.endomul_lnrz(&e, &alpha[range::ENDML])) + &index.cs.vbmul_lnrz(&e, &alpha[range::MUL])) + - &index.cs.perm_lnrz(&e, &oracles); + &index.cs.perm_lnrz(&e, &oracles, &alpha[range::PERM]); evals[0].f = f.eval(evlp[0], index.max_poly_size); evals[1].f = f.eval(evlp[1], index.max_poly_size); @@ -317,7 +336,7 @@ impl ProverProof where G::ScalarField : CommitmentField (&f, None, non_hiding(1)), ] ); - polynoms.extend(index.cs.sigmam[0..COLUMNS-1].iter().map(|w| (w, None, non_hiding(1))).collect::>()); + polynoms.extend(index.cs.sigmam[0..PERMUTS-1].iter().map(|w| (w, None, non_hiding(1))).collect::>()); polynoms.extend(vec![(&t, Some(index.max_quot_size), t_comm.1)]); Ok(Self diff --git a/dlog/plonk-15-wires/src/range.rs b/dlog/plonk-15-wires/src/range.rs index 8233b329c7..0b3265cd84 100644 --- a/dlog/plonk-15-wires/src/range.rs +++ b/dlog/plonk-15-wires/src/range.rs @@ -1,17 +1,17 @@ use algebra::Field; use std::ops::Range; -pub const PSDN : Range = 0..5; -pub const PERM : Range = 5..7; -pub const ADD : Range = 7..10; -pub const DBL : Range = 10..13; -pub const ENDML : Range = 13..19; -pub const PACK : Range = 19..24; -pub const MUL : Range = 24..29; -pub const MLPCK : Range = 29..34; +pub const PSDN : Range = 0..15; +pub const PERM : Range = 15..18; +pub const ADD : Range = 18..21; +pub const DBL : Range = 21..24; +pub const ENDML : Range = 24..35; +// pub const PACK : Range = 19..24; // todo +pub const MUL : Range = 35..58; +// pub const MLPCK : Range = 29..34; pub fn alpha_powers(x: F) -> Vec { let mut y = x; - (PSDN.start..MLPCK.end).map(|_| {y *= x; y}).collect() + (PSDN.start..MUL.end).map(|_| {y *= x; y}).collect() } diff --git a/dlog/plonk-15-wires/src/verifier.rs b/dlog/plonk-15-wires/src/verifier.rs index 9ca35ed6bb..b4ac9ef81c 100644 --- a/dlog/plonk-15-wires/src/verifier.rs +++ b/dlog/plonk-15-wires/src/verifier.rs @@ -7,7 +7,7 @@ This source file implements zk-proof batch verifier functionality. use crate::plonk_sponge::FrSponge; pub use super::prover::{ProverProof, range}; pub use super::index::VerifierIndex as Index; -use oracle::{FqSponge, rndoracle::ProofError, sponge_5_wires::ScalarChallenge}; +use oracle::{FqSponge, rndoracle::ProofError, sponge::ScalarChallenge}; use plonk_15_wires_circuits::{wires::*, nolookup::{scalars::RandomOracles, constraints::ConstraintSystem}}; use commitment_dlog::commitment::{CommitmentField, CommitmentCurve, PolyComm, b_poly, b_poly_coefficients, combined_inner_product}; use algebra::{Field, AffineCurve, Zero, One}; @@ -205,7 +205,7 @@ impl ProverProof where G::ScalarField : CommitmentField // permutation let zkp = index.zkpm.evaluate(oracles.zeta); let mut p = vec![&index.sigma_comm[PERMUTS-1]]; - let mut s = vec![ConstraintSystem::perm_scalars(&evals, &oracles, zkp)]; + let mut s = vec![ConstraintSystem::perm_scalars(&evals, &oracles, &alpha[range::PERM], zkp)]; // generic p.push(&index.qm_comm); @@ -216,7 +216,7 @@ impl ProverProof where G::ScalarField : CommitmentField // poseidon s.extend(&ConstraintSystem::psdn_scalars(&evals, &index.fr_sponge_params, &alpha[range::PSDN])); p.push(&index.psm_comm); - p.extend(index.rcm_comm.iter().map(|c| c).collect::>()); + p.extend(index.rcm_comm.iter().flatten().map(|c| c).collect::>()); // EC addition s.push(ConstraintSystem::ecad_scalars(&evals, &alpha[range::ADD])); @@ -243,20 +243,23 @@ impl ProverProof where G::ScalarField : CommitmentField - evals[0].w.iter().zip(evals[0].s.iter()). map(|(w, s)| (oracles.beta * s) + w + &oracles.gamma). - fold((evals[0].w[PERMUTS-1] + &oracles.gamma) * &evals[1].z * &oracles.alpha * &zkp, |x, y| x * y) + fold((evals[0].w[PERMUTS-1] + &oracles.gamma) * &evals[1].z * &alpha[range::PERM][0] * &zkp, |x, y| x * y) + evals[0].w.iter().zip(index.shift.iter()). map(|(w, s)| oracles.gamma + &(oracles.beta * &oracles.zeta * s) + w). - fold(oracles.alpha * &zkp * &evals[0].z, |x, y| x * y) + fold(alpha[range::PERM][0] * &zkp * &evals[0].z, |x, y| x * y) - - evals[0].t * &zeta1m1) * &(oracles.zeta - &index.w) * &(oracles.zeta - &Fr::::one()) + evals[0].t * &zeta1m1) + * &(oracles.zeta - &index.w) * &(oracles.zeta - &Fr::::one()) != - ((zeta1m1 * &alpha[range::PERM][0] * &(oracles.zeta - &index.w)) + ((zeta1m1 * &alpha[range::PERM][1] * &(oracles.zeta - &index.w)) + - (zeta1m1 * &alpha[range::PERM][1] * &(oracles.zeta - &Fr::::one()))) + (zeta1m1 * &alpha[range::PERM][2] * &(oracles.zeta - &Fr::::one()))) * &(Fr::::one() - evals[0].z) - {return Err(ProofError::ProofVerification)} + { + return Err(ProofError::ProofVerification) + } Ok((p_eval, p_comm, f_comm, fq_sponge, oracles, polys)) } diff --git a/dlog/tests/poseidon_tweedledee.rs b/dlog/tests/poseidon_tweedledee.rs index 1de082dcbe..61ef24a78e 100644 --- a/dlog/tests/poseidon_tweedledee.rs +++ b/dlog/tests/poseidon_tweedledee.rs @@ -17,10 +17,10 @@ use colored::Colorize; use rand_core::OsRng; const PERIOD: usize = PlonkSpongeConstants::ROUNDS_FULL + 1; -const MAX_SIZE: usize = 40000; // max size of poly chunks -const NUM_POS: usize = 256; // number of Poseidon hashes in the circuit +const NUM_POS: usize = 1024; // number of Poseidon hashes in the circuit const N: usize = PERIOD * NUM_POS; // Plonk domain size const M: usize = PERIOD * (NUM_POS-1); +const MAX_SIZE: usize = N; // max size of poly chunks const PUBLIC : usize = 0; #[test] diff --git a/dlog/tests/poseidon_vesta_15_wires.rs b/dlog/tests/poseidon_vesta_15_wires.rs new file mode 100644 index 0000000000..8b8fe578d8 --- /dev/null +++ b/dlog/tests/poseidon_vesta_15_wires.rs @@ -0,0 +1,204 @@ +use plonk_15_wires_circuits::wires::Wire; +use oracle::{poseidon::{ArithmeticSponge, SpongeConstants, Sponge, Plonk15SpongeConstants}, sponge::{DefaultFqSponge, DefaultFrSponge}}; +use commitment_dlog::{srs::{SRS, endos}, commitment::{CommitmentCurve, ceil_log2, b_poly_coefficients}}; +use algebra::{pasta::{pallas::{Affine as Other}, vesta::{Affine, VestaParameters}, fp::Fp}, UniformRand, Zero}; +use plonk_15_wires_protocol_dlog::{prover::{ProverProof}, index::{Index, SRSSpec}}; +use plonk_15_wires_circuits::{gate::CircuitGate, nolookup::constraints::ConstraintSystem, gates::poseidon::{SPONGE_WIDTH, ROUNDS_PER_ROW, round_range}}; +use ff_fft::DensePolynomial; +use std::{io, io::Write}; +use groupmap::GroupMap; +use std::time::Instant; +use colored::Colorize; +use rand_core::OsRng; +use array_init::array_init; + +// const PERIOD: usize = Plonk15SpongeConstants::ROUNDS_FULL + 1; +// const M: usize = PERIOD * (NUM_POS-1); +// const MAX_SIZE: usize = N; // max size of poly chunks +const PUBLIC : usize = 0; + +const NUM_POS: usize = 1; // 1360; // number of Poseidon hashes in the circuit +const ROUNDS_PER_HASH : usize = Plonk15SpongeConstants::ROUNDS_FULL; +const POS_ROWS_PER_HASH : usize = ROUNDS_PER_HASH / ROUNDS_PER_ROW; +const N_LOWER_BOUND: usize = (POS_ROWS_PER_HASH + 1) * NUM_POS; // Plonk domain size + +#[test] +fn poseidon_vesta_15_wires() +{ + let N = 1 << ceil_log2(N_LOWER_BOUND); + println!("N = {}", N); + println!("{} {}", ROUNDS_PER_HASH, ROUNDS_PER_ROW); + assert_eq!(ROUNDS_PER_HASH % ROUNDS_PER_ROW, 0); + + let c = &oracle::pasta::fp::params().round_constants; + + // circuit gates + + let mut i = 0; + let mut gates: Vec> = Vec::with_capacity(N); + + // custom constraints for Poseidon hash function permutation + + for _ in 0..NUM_POS + { + // ROUNDS_FULL full rounds constraint gates + for j in 0..POS_ROWS_PER_HASH + { + let wires = array_init(|col| Wire { col, row: i }); + let coeffs = array_init(|r| { + let round = j * ROUNDS_PER_ROW + r + 1; + array_init(|k| c[round][k]) + }); + gates.push(CircuitGate::::create_poseidon(i, wires, coeffs)); + i+=1; + } + let wires = array_init(|col| Wire { col, row: i }); + gates.push(CircuitGate::::zero(i, wires)); + i+=1; + } + + /* + for j in 0..Plonk15SpongeConstants::ROUNDS_FULL-2 + { + gates.push(CircuitGate::::create_poseidon(i, [Wire{col:0, row:i}, Wire{col:1, row:i}, Wire{col:2, row:i}, Wire{col:3, row:i}, Wire{col:4, row:i}], c[j].clone())); + i+=1; + } + gates.push(CircuitGate::::zero(i, [Wire{col:0, row:i}, Wire{col:1, row:i}, Wire{col:2, row:i}, Wire{col:3, row:i}, Wire{col:4, row:i}])); + i+=1; + gates.push(CircuitGate::::zero(i, [Wire{col:0, row:i}, Wire{col:1, row:i}, Wire{col:2, row:i}, Wire{col:3, row:i}, Wire{col:4, row:i}])); + i+=1; + gates.push(CircuitGate::::zero(i, [Wire{col:0, row:i}, Wire{col:1, row:i}, Wire{col:2, row:i}, Wire{col:3, row:i}, Wire{col:4, row:i}])); + */ + + let MAX_SIZE = N; + let srs = SRS::create(MAX_SIZE); + + let (endo_q, _endo_r) = endos::(); + let index = Index::::create + ( + ConstraintSystem::::create(gates, oracle::pasta::fp::params(), PUBLIC).unwrap(), + oracle::pasta::fq::params(), + endo_q, + SRSSpec::Use(&srs) + ); + + positive(&index); +} + +fn positive(index: &Index) +{ + let rng = &mut OsRng; + + let params = oracle::pasta::fp::params(); + let mut sponge = ArithmeticSponge::::new(); + + let mut batch = Vec::new(); + let group_map = ::Map::setup(); + + let N = 1 << ceil_log2(N_LOWER_BOUND); + let MAX_SIZE = N; + + println!("{}{:?}", "Circuit size: ".yellow(), N); + println!("{}{:?}", "Polycommitment chunk size: ".yellow(), MAX_SIZE); + println!("{}{:?}", "Number oh Poseidon hashes in the circuit: ".yellow(), NUM_POS); + println!("{}{:?}", "Full rounds: ".yellow(), Plonk15SpongeConstants::ROUNDS_FULL); + println!("{}{:?}", "Sbox alpha: ".yellow(), Plonk15SpongeConstants::SPONGE_BOX); + println!("{}", "Base curve: vesta".green()); + println!(); + println!("{}", "Prover zk-proof computation".green()); + let mut start = Instant::now(); + + for test in 0..1 + { + // witness for Poseidon permutation custom constraints + let mut w = + [ + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + vec![Fp::zero(); N], + ]; + + let init = vec![Fp::rand(rng), Fp::rand(rng), Fp::rand(rng), Fp::rand(rng), Fp::rand(rng)]; + for h in 0..NUM_POS + { + let base = h * (POS_ROWS_PER_HASH + 1); + for i in 0..SPONGE_WIDTH { + w[round_range(0)][i][base] = init[i]; + } + + sponge.state = init.clone(); + + for i in 0..POS_ROWS_PER_HASH { + let row = i + base; + for r in 0..ROUNDS_PER_ROW { + let next_row = if r == ROUNDS_PER_ROW - 1 { row + 1 } else { row }; + let abs_round = r + i * ROUNDS_PER_ROW; + sponge.full_round(abs_round, ¶ms); + w[round_range((r + 1) % ROUNDS_PER_ROW)].iter_mut().zip(sponge.state.iter()).for_each(|(w, s)| w[next_row] = *s); + } + } + } + + /* + sponge.state = init.clone(); + w.iter_mut().zip(sponge.state.iter()).for_each(|(w, s)| w.push(*s)); + + // ROUNDS_FULL full rounds + for j in 0..Plonk15SpongeConstants::ROUNDS_FULL-2 + { + sponge.full_round(j, ¶ms); + w.iter_mut().zip(sponge.state.iter()).for_each(|(w, s)| w.push(*s)); + } + + w.iter_mut().for_each(|w| {w.push(Fp::rand(rng)); w.push(Fp::rand(rng))}); */ + + // verify the circuit satisfiability by the computed witness + assert_eq!(index.cs.verify(&w), true); + + let prev = { + let k = ceil_log2(index.srs.get_ref().g.len()); + let chals : Vec<_> = (0..k).map(|_| Fp::rand(rng)).collect(); + let comm = { + let b = DensePolynomial::from_coefficients_vec(b_poly_coefficients(&chals)); + index.srs.get_ref().commit_non_hiding(&b, None) + }; + ( chals, comm ) + }; + + println!("n vs domain{} {}", N, index.cs.domain.d1.size); + + // add the proof to the batch + batch.push(ProverProof::create::, DefaultFrSponge>( + &group_map, &w, &index, vec![prev]).unwrap()); + + print!("{:?}\r", test); + io::stdout().flush().unwrap(); + } + println!("{}{:?}", "Execution time: ".yellow(), start.elapsed()); + + let verifier_index = index.verifier_index(); + + let lgr_comms = vec![]; + let batch : Vec<_> = batch.iter().map(|p| (&verifier_index, &lgr_comms, p)).collect(); + + // verify the proofs in batch + println!("{}", "Verifier zk-proofs verification".green()); + start = Instant::now(); + match ProverProof::verify::, DefaultFrSponge>(&group_map, &batch) + { + Err(error) => {panic!("Failure verifying the prover's proofs in batch: {}", error)}, + Ok(_) => {println!("{}{:?}", "Execution time: ".yellow(), start.elapsed());} + } +} diff --git a/pairing/Cargo.toml b/pairing/Cargo.toml deleted file mode 100644 index 8cae924de0..0000000000 --- a/pairing/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "pairing" -version = "0.1.0" -edition = "2018" - -[dependencies] -algebra = { path = "../zexe/algebra", features = [ "parallel", "bn_382", "tweedle", "asm" ] } -ff-fft = { path = "../zexe/ff-fft" } -commitment_pairing = { path = "commitment" } -marlin_circuits = { path = "../circuits/marlin" } -marlin_protocol_pairing = { path = "marlin" } -plonk_5_wires_circuits = { path = "../circuits/plonk-5-wires" } -plonk_protocol_pairing = { path = "plonk" } -oracle = { path = "../oracle" } -rand_core = { version = "0.5" } -colored = "1.9.2" -rand = "0.7.3" -sprs = "0.7.1" diff --git a/pairing/commitment/BUILD.bazel b/pairing/commitment/BUILD.bazel deleted file mode 100644 index 0a45893308..0000000000 --- a/pairing/commitment/BUILD.bazel +++ /dev/null @@ -1,19 +0,0 @@ -load("@io_bazel_rules_rust//rust:rust.bzl", "rust_library") - -rust_library( - name = "commitment_pairing", - visibility = ["//visibility:public"], - edition = "2018", - srcs = glob(["src/**/*.rs"]), - # aliases = { - # "@zexe//ff-fft": "ff_fft", - # }, - deps = [ - "@zexe//algebra", - "@zexe//ff-fft", - "//oracle", - "//bzl/cargo:rand", - "//bzl/cargo:rand_core", - "//bzl/cargo:colored", - ] -) diff --git a/pairing/commitment/Cargo.toml b/pairing/commitment/Cargo.toml deleted file mode 100644 index 046f99ed6b..0000000000 --- a/pairing/commitment/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "commitment_pairing" -version = "0.1.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -algebra = { path = "../../zexe/algebra", features = [ "parallel", "bn_382", "tweedle", "asm" ] } -ff-fft = { path = "../../zexe/ff-fft" } -oracle = { path = "../../oracle" } -rand_core = { version = "0.5" } -colored = "1.9.2" -rand = "0.7.3" diff --git a/pairing/commitment/src/commitment.rs b/pairing/commitment/src/commitment.rs deleted file mode 100644 index e30be085c7..0000000000 --- a/pairing/commitment/src/commitment.rs +++ /dev/null @@ -1,253 +0,0 @@ -/***************************************************************************************************************** - -This source file implements the polynomial commitment batch primitive. The primitive provides the following zero- -knowledge protocol: - -1. Commit to the batch of vectors of polynomials against the URS instance -2. Evaluate the vector of polynomials at the given base field element -3. Open the polynomial commitment batch at the given random base field element producing the opening proof - with the masking base field element -4. Verify the commitment opening proof against the following; - a. the URS instance - b. Polynomial evaluations at the given base field element - c. The given base field element - d. The given masking base field element - e. Commitment opening proof - -*****************************************************************************************************************/ - -use oracle::rndoracle::ProofError; -use algebra::{AffineCurve, ProjectiveCurve, Field, PrimeField, PairingEngine, UniformRand, VariableBaseMSM, One, Zero}; -use std::collections::HashMap; -use oracle::utils::PolyUtils; -use ff_fft::DensePolynomial; -pub use super::urs::URS; -use rand_core::RngCore; - -impl URS -{ - // This function commits a polynomial against URS instance - // plnm: polynomial to commit to - // RETURN: tuple of: unbounded commitment - pub fn commit - ( - &self, - plnm: &DensePolynomial, - ) -> Result - { - if plnm.coeffs.len() > self.depth {return Err(ProofError::PolyCommit)} - Ok ( - VariableBaseMSM::multi_scalar_mul - ( - &self.gp[0..plnm.len()], - &plnm.coeffs.iter().map(|s| s.into_repr()).collect::>() - ).into_affine() ) - } - - // This function commits a polynomial against URS instance - // plnm: polynomial to commit to - // max: maximal degree of the polynomial, if none , no degree bound - // RETURN: tuple of: unbounded commitment, optional bounded commitment - pub fn commit_with_degree_bound - ( - &self, - plnm: &DensePolynomial, - max: usize, - ) -> Result<(E::G1Affine, E::G1Affine), ProofError> - { - let unshifted = self.commit(plnm)?; - - if self.depth < max || plnm.coeffs.len() > max {return Err(ProofError::PolyCommitWithBound)} - let shifted = VariableBaseMSM::multi_scalar_mul - ( - &self.gp[self.depth - max..plnm.len() + self.depth - max], - &plnm.coeffs.iter().map(|s| s.into_repr()).collect::>(), - ).into_affine(); - - Ok((unshifted, shifted)) - } - - pub fn exponentiate_sub_domain - ( - &self, - plnm: &DensePolynomial, - ratio : usize, - ) -> Result - { - if plnm.coeffs.len() > self.depth {return Err(ProofError::PolyExponentiate)} - - Ok(VariableBaseMSM::multi_scalar_mul - ( - &(0..plnm.len()).map(|i| self.gp[ratio * i]).collect::>(), - &plnm.coeffs.iter().map(|s| s.into_repr()).collect::>() - ).into_affine()) - } - - // This function opens the polynomial commitment batch - // polys: commited polynomials with no degree bound - // mask: base field element masking value - // elm: base field element to open the commitment at - // RETURN: commitment opening proof - pub fn open - ( - &self, - polys: Vec<&DensePolynomial>, - mask: E::Fr, - elm: E::Fr - ) -> Result - { - let mut acc = DensePolynomial::::zero(); - let mut scale = E::Fr::one(); - - for p in polys.iter().rev() - { - acc += &(p.scale(scale)); - scale *= &mask; - } - self.commit(&acc.divide(elm)) - } - - // This function verifies the batch polynomial commitment proofs of vectors of polynomials - // base field element to open the commitment at - // base field element masking value - // polynomial commitment batch of - // commitment value - // polynomial evaluation - // max positive powers size of the polynomial - // polynomial commitment opening proof - // randomness source context - // RETURN: verification status - pub fn verify - ( - &self, - batch: &Vec - <( - E::Fr, - E::Fr, - Vec<(E::G1Affine, E::Fr, Option<(E::G1Affine, usize)>)>, - E::G1Affine, - )>, - rng: &mut dyn RngCore - ) -> bool - { - let mut table : Vec<(E::G1Prepared, E::G2Prepared)> = vec![]; - - // verify commitment opening proofs against unshifted commitments: - // e(prf, h^x) * e(g^eval * prf^(-chal), h^0)) = e(unshComm, h^0) - - let mut open_scalar = Vec::new(); - let mut open_point = Vec::new(); - let mut openy_scalar = Vec::new(); - let mut openy_point = Vec::new(); - let mut eval = E::Fr::zero(); - - for x in batch.iter() - { - let rnd = E::Fr::rand(rng); - open_scalar.push(rnd.into_repr()); - open_point.push(x.3); - openy_scalar.push((-rnd * &x.0).into_repr()); - openy_point.push(x.3); - let mut scale = E::Fr::one(); - let mut v = E::Fr::zero(); - - for z in x.2.iter().rev() - { - v += &(z.1 * &scale); - openy_point.push(z.0); - openy_scalar.push((-rnd * &scale).into_repr()); - scale *= &x.1; - } - v *= &rnd; - eval += &v; - } - openy_scalar.push(eval.into_repr()); - openy_point.push(self.gp[0]); - - // verify shifted commitments against unshifted commitments: - // e(ushComm, h^0) = e(shComm, h^x^(max-d)) - - let mut shifted: HashMap> = HashMap::new(); - for x1 in batch.iter() - { - for x2 in x1.2.iter() - { - match x2.2 - { - Some((p, m)) => - { - let rnd = E::Fr::rand(rng); - openy_point.push(x2.0); - openy_scalar.push(rnd.into_repr()); - if !shifted.contains_key(&m) {shifted.insert(m, Vec::new());} - shifted.get_mut(&m).unwrap().push((p, rnd)) - } - None => continue - } - } - } - - for max in shifted.keys() - { - if !self.hn.contains_key(&(self.depth-max)) {return false} - table.push - (( - VariableBaseMSM::multi_scalar_mul - ( - &shifted[max].iter().map(|p| p.0).collect::>(), - &shifted[max].iter().map(|s| s.1.into_repr()).collect::>(), - ).into_affine().into(), - (-self.hn[&(self.depth-max)]).into() - )); - } - table.push - (( - VariableBaseMSM::multi_scalar_mul - ( - &open_point, - &open_scalar - ).into_affine().into(), - self.hx.into() - )); - table.push - (( - VariableBaseMSM::multi_scalar_mul - ( - &openy_point, - &openy_scalar - ).into_affine().into(), - E::G2Affine::prime_subgroup_generator().into() - )); - - E::final_exponentiation(&E::miller_loop(table.iter())).unwrap() == E::Fqk::one() - } -} - -pub trait Divide -{ - fn divide(&self, elm: F) -> Self; -} - -impl Divide for DensePolynomial -{ - // This function divides this polynomial difference: (F(x)-F(elm))/(x-elm) - // elm: base field element - // RETURN: resulting polynomial - fn divide - ( - &self, - mut elm: F - ) -> Self - { - // do polynomial division (F(x)-F(elm))/(x-elm) - elm = -elm; - let mut pos = vec![F::zero(); self.coeffs.len() - 1]; - let mut rcff = F::zero(); - for (x, y) in self.coeffs.iter().rev().zip(pos.iter_mut().rev()) - { - *y = *x - &rcff; - rcff = *y * &elm; - } - Self::from_coefficients_vec(pos) - } -} diff --git a/pairing/commitment/src/lib.rs b/pairing/commitment/src/lib.rs deleted file mode 100644 index 599b37904b..0000000000 --- a/pairing/commitment/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod urs; -pub mod commitment; diff --git a/pairing/commitment/src/urs.rs b/pairing/commitment/src/urs.rs deleted file mode 100644 index 340306cb93..0000000000 --- a/pairing/commitment/src/urs.rs +++ /dev/null @@ -1,212 +0,0 @@ -/***************************************************************************************************************** - -This source file implements the Marlin universal reference string primitive - -*****************************************************************************************************************/ - -use algebra::{ToBytes, FromBytes, VariableBaseMSM, FixedBaseMSM, AffineCurve, ProjectiveCurve, Field, PrimeField, PairingEngine, One, UniformRand}; -use std::collections::HashMap; -use rand_core::RngCore; -use std::io::{Read, Write, Result as IoResult}; - -// check pairing of a&b vs c -macro_rules! pairing_check -{ - ($a:expr, $b:expr, $c:expr) => {if ::pairing($a, $b) != $c {return false;}}; -} - -#[derive(Clone)] -pub struct URS -{ - pub depth: usize, - pub gp: Vec, // g^(x^i) for 0 <= i < d - pub hn: HashMap, // h^(x^-i) for 0 <= i < d - pub hx: E::G2Affine, - pub prf: E::G1Affine -} - -impl URS -{ - // empty default calback, use as >::callback - pub fn callback(_i: usize) {} - - pub fn max_degree(&self) -> usize { - self.depth - } - - pub fn write(&self, mut writer : W) -> IoResult<()> { - u64::write(&(self.depth as u64), &mut writer)?; - - u64::write(&(self.gp.len() as u64), &mut writer)?; - for x in &self.gp { - E::G1Affine::write(x, &mut writer)?; - } - - let m = self.hn.len(); - u64::write(&(m as u64), &mut writer)?; - for (&key, value) in &self.hn { - u64::write(&(key as u64), &mut writer)?; - E::G2Affine::write(value, &mut writer)?; - } - - E::G2Affine::write(&self.hx, &mut writer)?; - E::G1Affine::write(&self.prf, &mut writer)?; - - Ok(()) - } - - pub fn read(mut reader : R) -> IoResult { - let depth = u64::read(&mut reader)? as usize; - - let n = u64::read(&mut reader)?; - let mut gp = vec![]; - for _ in 0..n { - gp.push(E::G1Affine::read(&mut reader)?); - } - - let m = u64::read(&mut reader)?; - let mut hn = HashMap::new(); - for _ in 0..m { - let key = u64::read(&mut reader)?; - let value = E::G2Affine::read(&mut reader)?; - let _ = hn.insert(key as usize, value); - } - - let hx = E::G2Affine::read(&mut reader)?; - let prf = E::G1Affine::read(&mut reader)?; - - Ok( URS { depth, gp, hn, hx, prf } ) - } - - // This function creates URS instance for circuits up to depth d - // depth: maximal depth of the supported circuits - // commitment degrees of the committed polynomials for supported circuits - // rng: randomness source context - pub fn create - ( - depth: usize, - degrees: Vec, - rng: &mut dyn RngCore - ) -> Self - { - let mut x = E::Fr::rand(rng); - let size_in_bits = E::Fr::size_in_bits(); - let window_size = FixedBaseMSM::get_mul_window_size(depth+1); - - let mut cur = E::Fr::one(); - let mut gp = FixedBaseMSM::multi_scalar_mul:: - ( - size_in_bits, - window_size, - &FixedBaseMSM::get_window_table - ( - size_in_bits, - window_size, - E::G1Projective::prime_subgroup_generator() - ), - &(0..depth).map(|_| {let s = cur; cur *= &x; s}).collect::>(), - ); - ProjectiveCurve::batch_normalization(&mut gp); - - let mut gx = E::G1Projective::prime_subgroup_generator(); - gx *= x; - let mut hx = E::G2Projective::prime_subgroup_generator(); - hx *= x; - - let window_size = FixedBaseMSM::get_mul_window_size(degrees.len()+1); - x = x.inverse().unwrap(); - let mut hn = FixedBaseMSM::multi_scalar_mul:: - ( - size_in_bits, - window_size, - &FixedBaseMSM::get_window_table - ( - size_in_bits, - window_size, - E::G2Projective::prime_subgroup_generator() - ), - °rees.iter().map(|i| x.pow([(depth - *i) as u64])).collect::>(), - ); - ProjectiveCurve::batch_normalization(&mut hn); - let mut hnh: HashMap = HashMap::new(); - for (i, p) in degrees.iter().zip(hn.iter()) {hnh.insert(depth - *i, p.into_affine());} - - URS - { - hn: hnh, - gp: gp.into_iter().map(|e| e.into_affine()).collect(), - prf: E::G1Affine::from(gx), - hx: E::G2Affine::from(hx), - depth - } - } - - // This function updates URS instance and computes the update proof - // rng: randomness source context - // RETURN: computed zk-proof - pub fn update - ( - &mut self, - rng: &mut dyn RngCore - ) - { - let mut x = E::Fr::rand(rng); - let mut cur = E::Fr::one(); - for i in 0..self.gp.len() - { - self.gp[i] = self.gp[i].mul(cur).into_affine(); - cur *= &x; - } - - self.prf = E::G1Affine::prime_subgroup_generator().mul(x).into_affine(); - self.hx = self.hx.mul(x).into_affine(); - - x = x.inverse().unwrap(); - for p in self.hn.iter_mut() - { - *p.1 = p.1.mul(x.pow([*p.0 as u64])).into_affine(); - } - } - - // This function verifies the updated URS against the zk-proof and the previous URS instance - // hn1: previous URS gp[1] - // randomness source context - // RETURN: zk-proof verification status - pub fn check - ( - &mut self, - hp1: E::G2Affine, - rng: &mut dyn RngCore - ) -> bool - { - let xy = ::pairing(self.prf, hp1); - // verify hx consistency with zk-proof - pairing_check!(E::G1Projective::prime_subgroup_generator(), E::G2Projective::from(self.hx), xy); - // verify gp[1] consistency with zk-proof - pairing_check!(E::G1Projective::from(self.gp[1]), E::G2Projective::prime_subgroup_generator(), xy); - - let fk = ::pairing(E::G1Affine::prime_subgroup_generator(), E::G2Affine::prime_subgroup_generator()); - for x in self.hn.iter() - { - // verify hn: e(g^x^i, h^x^-i) = e(g, h) - if ::pairing(self.gp[*x.0], *x.1) != fk {return false} - } - - let rand = (1..self.gp.len()).map(|_| E::Fr::rand(rng).into_repr()).collect::>(); - E::final_exponentiation(&E::miller_loop( - [ - (VariableBaseMSM::multi_scalar_mul - ( - &(1..self.gp.len()).map(|i| self.gp[i]).collect::>(), - &rand - ).into_affine().into(), E::G2Affine::prime_subgroup_generator().into() - ), - (VariableBaseMSM::multi_scalar_mul - ( - &(1..self.gp.len()).map(|i| self.gp[i-1]).collect::>(), - &rand - ).into_affine().into(), (-self.hx).into() - ), - ].iter())).unwrap() == E::Fqk::one() - } -} diff --git a/pairing/marlin/BUILD.bazel b/pairing/marlin/BUILD.bazel deleted file mode 100644 index d29751bdf1..0000000000 --- a/pairing/marlin/BUILD.bazel +++ /dev/null @@ -1,24 +0,0 @@ -load("@io_bazel_rules_rust//rust:rust.bzl", "rust_library") - -rust_library( - name = "marlin_protocol_pairing", - visibility = ["//visibility:public"], - edition = "2018", - srcs = glob(["src/**/*.rs"]), - # aliases = { - # "@zexe//ff-fft": "ff_fft", - # }, - deps = [ - "@zexe//algebra", - "@zexe//ff-fft", - - "//pairing/commitment:commitment_pairing", - "//circuits/marlin:marlin_circuits", - "//oracle", - - "//bzl/cargo:rand", - "//bzl/cargo:rand_core", - "//bzl/cargo:colored", - "//bzl/cargo:sprs", - ] -) diff --git a/pairing/marlin/Cargo.toml b/pairing/marlin/Cargo.toml deleted file mode 100644 index 48b9f3bffa..0000000000 --- a/pairing/marlin/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "marlin_protocol_pairing" -version = "0.1.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -algebra = { path = "../../zexe/algebra", features = [ "parallel", "bn_382", "tweedle", "asm" ] } -ff-fft = { path = "../../zexe/ff-fft" } -commitment_pairing = { path = "../commitment" } -marlin_circuits = { path = "../../circuits/marlin" } -oracle = { path = "../../oracle" } -rand_core = { version = "0.5" } -colored = "1.9.2" -rand = "0.7.3" -sprs = "0.7.1" diff --git a/pairing/marlin/README.md b/pairing/marlin/README.md deleted file mode 100644 index 6152dfa08b..0000000000 --- a/pairing/marlin/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Marlin (https://eprint.iacr.org/2019/1047.pdf) presents a new zk-SNARKs protocol with the benefit of the updateability of its Universal SRS (structured reference string) with the size linear in the size of the arithmetic circuit that describes the computational statement being proven. URS is statement/circuit independent and can be used for the proofing system of many circuits whose size (depth) is limited by the URS size. Marlin provides the benefit of succinctness of the proofs and of the proof verification. - -The source code under this dirctory implements the succinct pairing-based Marlin proofing system. diff --git a/pairing/marlin/src/compiled.rs b/pairing/marlin/src/compiled.rs deleted file mode 100644 index dde1ccd7bf..0000000000 --- a/pairing/marlin/src/compiled.rs +++ /dev/null @@ -1,136 +0,0 @@ -/***************************************************************************************************************** - -This source file implements the compiled constraints primitive. - -*****************************************************************************************************************/ - -use sprs::CsMat; -use commitment_pairing::urs::URS; -use oracle::rndoracle::ProofError; -use algebra::{Field, PairingEngine, Zero}; -use ff_fft::{DensePolynomial, Evaluations, Radix2EvaluationDomain as D, EvaluationDomain, GeneralEvaluationDomain}; -pub use super::index::Index; - -pub struct Compiled -{ - // constraint system coefficients in dense form - pub constraints: CsMat, - - // compiled polynomial commitments - pub col_comm: E::G1Affine, - pub row_comm: E::G1Affine, - pub val_comm: E::G1Affine, - pub rc_comm: E::G1Affine, - - // compiled polynomials and evaluations - pub rc : DensePolynomial, - pub row : DensePolynomial, - pub col : DensePolynomial, - pub val : DensePolynomial, - pub row_eval_k: Evaluations, - pub col_eval_k: Evaluations, - pub val_eval_k: Evaluations, - pub row_eval_b: Evaluations, - pub col_eval_b: Evaluations, - pub val_eval_b: Evaluations, - pub rc_eval_b : Evaluations, -} - -impl Compiled -{ - // this function compiles the constraints - // urs: universal reference string - // h_group: evaluation domain for degere h (constrtraint matrix linear size) - // k_group: evaluation domain for degere k (constrtraint matrix number of non-zero elements) - // b_group: evaluation domain for degere b (h_group*6-6) - // constraints: constraint matrix in dense form - pub fn compile - ( - urs: &URS, - h_group: D, - k_group: D, - b_group: D, - constraints: CsMat, - ) -> Result - { - let mut col_eval_k = vec![E::Fr::zero(); k_group.size as usize]; - let mut row_eval_k = vec![E::Fr::zero(); k_group.size as usize]; - let mut val_eval_k = vec![E::Fr::zero(); k_group.size as usize]; - - let h_elems: Vec = h_group.elements().map(|elm| {elm}).collect(); - - for (c, (val, (row, col))) in - constraints.iter().zip( - val_eval_k.iter_mut().zip( - row_eval_k.iter_mut().zip( - col_eval_k.iter_mut()))) - { - *row = h_elems[(c.1).0]; - *col = h_elems[(c.1).1]; - *val = h_group.size_as_field_element.square() * - // Lagrange polynomial evaluation trick - &h_elems[if (c.1).0 == 0 {0} else {h_group.size() - (c.1).0}] * - &h_elems[if (c.1).1 == 0 {0} else {h_group.size() - (c.1).1}]; - } - algebra::fields::batch_inversion::(&mut val_eval_k); - for (c, val) in constraints.iter().zip(val_eval_k.iter_mut()) - { - *val = *c.0 * val; - } - - let k_group = GeneralEvaluationDomain::Radix2(k_group); - let b_group = GeneralEvaluationDomain::Radix2(b_group); - - let row_eval_k = Evaluations::::from_vec_and_domain(row_eval_k, k_group); - let col_eval_k = Evaluations::::from_vec_and_domain(col_eval_k, k_group); - let val_eval_k = Evaluations::::from_vec_and_domain(val_eval_k, k_group); - - // interpolate the evaluations - let row = row_eval_k.clone().interpolate(); - let col = col_eval_k.clone().interpolate(); - let val = val_eval_k.clone().interpolate(); - let rc = (&row_eval_k * &col_eval_k).interpolate(); - - // commit to the index polynomials - Ok(Compiled:: - { - constraints, - rc_comm: urs.commit(&rc)?, - row_comm: urs.commit(&row)?, - col_comm: urs.commit(&col)?, - val_comm: urs.commit(&val)?, - row_eval_b: Evaluations::::from_vec_and_domain(b_group.fft(&row), b_group), - col_eval_b: Evaluations::::from_vec_and_domain(b_group.fft(&col), b_group), - val_eval_b: Evaluations::::from_vec_and_domain(b_group.fft(&val), b_group), - rc_eval_b: Evaluations::::from_vec_and_domain(b_group.fft(&rc), b_group), - row_eval_k, - col_eval_k, - val_eval_k, - row, - col, - val, - rc - }) - } - - // this function computes (row(X)-oracle1)*(col(X)-oracle2) - // evaluations over b_group for this compilation of constraints - pub fn compute_row_2_col_1 - ( - &self, - oracle1: E::Fr, - oracle2: E::Fr, - ) -> Vec - { - self.row_eval_b.evals.iter(). - zip(self.col_eval_b.evals.iter()). - zip(self.rc_eval_b.evals.iter()). - map - ( - |((row, col), rc)| - { - oracle2 * &oracle1 - &(oracle1 * &row) - &(oracle2 * &col) + &rc - } - ).collect() - } -} \ No newline at end of file diff --git a/pairing/marlin/src/index.rs b/pairing/marlin/src/index.rs deleted file mode 100644 index 54242d3f58..0000000000 --- a/pairing/marlin/src/index.rs +++ /dev/null @@ -1,285 +0,0 @@ -/***************************************************************************************************************** - -This source file implements Marlin Protocol Index primitive. - -*****************************************************************************************************************/ - -use sprs::CsMat; -use std::collections::HashMap; -use rand_core::RngCore; -use commitment_pairing::urs::URS; -use marlin_circuits::{gate::CircuitGate, domains::EvaluationDomains}; -use algebra::{AffineCurve, PairingEngine, curves::models::short_weierstrass_jacobian::{GroupAffine as SWJAffine}}; -use oracle::rndoracle::ProofError; -use oracle::poseidon::ArithmeticSpongeParams; -pub use super::compiled::Compiled; -use ff_fft::EvaluationDomain; - -pub trait CoordinatesCurve: AffineCurve { - fn to_coordinates(&self) -> Option<(Self::BaseField, Self::BaseField)>; - fn of_coordinates(x:Self::BaseField, y:Self::BaseField) -> Self; -} - -impl CoordinatesCurve for SWJAffine

{ - fn to_coordinates(&self) -> Option<(Self::BaseField, Self::BaseField)>{ - if self.infinity { - None - } else { - Some((self.x, self.y)) - } - } - - fn of_coordinates(x:Self::BaseField, y:Self::BaseField) -> Self { - SWJAffine::

::new(x, y, false) - } -} - -pub enum URSValue<'a, E : PairingEngine> { - Value(URS), - Ref(&'a URS) -} - -impl<'a, E : PairingEngine> URSValue<'a, E> { - pub fn get_ref(&self) -> & URS { - match self { - URSValue::Value(x) => &x, - URSValue::Ref(x) => x - } - } -} - -pub enum URSSpec <'a, 'b, E:PairingEngine>{ - Use(&'a URS), - Generate(&'b mut dyn RngCore) -} - -impl<'a, E: PairingEngine> URSValue<'a, E> { - pub fn generate<'b>( - ds: EvaluationDomains, - rng : &'b mut dyn RngCore) -> URS { - let max_degree = *[3*ds.h.size()-1, ds.b.size()].iter().max().unwrap(); - - URS::::create - ( - max_degree, - vec! - [ - ds.h.size()-1, - ds.k.size()-1, - ], - rng ) - } - - pub fn create<'b>(ds: EvaluationDomains, spec : URSSpec<'a, 'b, E>) -> URSValue<'a, E>{ - match spec { - URSSpec::Use(x) => URSValue::Ref(x), - URSSpec::Generate(rng) => URSValue::Value(Self::generate(ds, rng)) - } - } -} - -pub struct Index<'a, E: PairingEngine> -{ - // constraint system compilation - pub compiled: [Compiled; 3], - - // evaluation domains as multiplicative groups of roots of unity - pub domains : EvaluationDomains, - - // number of public inputs - pub public_inputs: usize, - - // polynomial commitment keys - pub urs: URSValue<'a, E>, - - // random oracle argument parameters - pub fr_sponge_params: ArithmeticSpongeParams, - pub fq_sponge_params: ArithmeticSpongeParams, - - // Coefficients for the curve endomorphism - pub endo_r: E::Fr, - pub endo_q: E::Fq, -} - -pub struct MatrixValues { - pub row : A, - pub col : A, - pub val : A, - pub rc : A, -} - -pub struct VerifierIndex -{ - // constraint system compilation - pub matrix_commitments: [MatrixValues; 3], - - // evaluation domains as multiplicative groups of roots of unity - pub domains : EvaluationDomains, - - // number of public inputs - pub public_inputs: usize, - - // maximal degree of the committed polynomials - pub max_degree: usize, - - // polynomial commitment keys, trimmed - pub urs: URS, - - // random oracle argument parameters - pub fr_sponge_params: ArithmeticSpongeParams, - pub fq_sponge_params: ArithmeticSpongeParams, - - // Coefficients for the curve endomorphism - pub endo_r: E::Fr, - pub endo_q: E::Fq, -} - -pub fn endos() -> (E::Fq, E::Fr) where E::G1Affine : CoordinatesCurve { - let endo_q : E::Fq = oracle::sponge::endo_coefficient(); - let endo_r = { - let potential_endo_r : E::Fr = oracle::sponge::endo_coefficient(); - let t = E::G1Affine::prime_subgroup_generator(); - let (x, y) = t.to_coordinates().unwrap(); - let phi_t = E::G1Affine::of_coordinates(x * &endo_q, y); - if t.mul(potential_endo_r) == phi_t.into_projective() { - potential_endo_r - } else { - potential_endo_r * &potential_endo_r - } - }; - (endo_q, endo_r) -} - -impl<'a, E: PairingEngine> Index<'a, E> -where E::G1Affine: CoordinatesCurve -{ - // this function compiles the circuit from constraints - pub fn create<'b> - ( - a: CsMat, - b: CsMat, - c: CsMat, - public_inputs: usize, - fr_sponge_params: ArithmeticSpongeParams, - fq_sponge_params: ArithmeticSpongeParams, - urs : URSSpec<'a, 'b, E> - ) -> Result - { - if a.shape() != b.shape() || - a.shape() != c.shape() || - a.shape().0 != a.shape().1 || - public_inputs == a.shape().0 || - public_inputs == 0 - { - return Err(ProofError::ConstraintInconsist) - } - - let nonzero_entries : usize = - [&a, &b, &c].iter().map(|x| x.nnz()).max() - .map_or(Err(ProofError::RuntimeEnv), |s| Ok(s))?; - - let domains = EvaluationDomains::create( - a.shape().0, - a.shape().1, - public_inputs, - nonzero_entries) - .map_or(Err(ProofError::EvaluationGroup), |s| Ok(s))?; - - let urs = URSValue::create(domains, urs); - - let (endo_q, endo_r) = endos::(); - - Ok(Index:: - { - compiled: - [ - Compiled::::compile(urs.get_ref(), domains.h, domains.k, domains.b, a)?, - Compiled::::compile(urs.get_ref(), domains.h, domains.k, domains.b, b)?, - Compiled::::compile(urs.get_ref(), domains.h, domains.k, domains.b, c)?, - ], - fr_sponge_params, - fq_sponge_params, - public_inputs, - domains, - urs, - endo_q, - endo_r - }) - } - -} - -impl<'a, E: PairingEngine> Index<'a, E> -{ - fn matrix_values(c : &Compiled) -> MatrixValues { - MatrixValues { - row: c.row_comm, - col: c.col_comm, - val: c.val_comm, - rc: c.rc_comm, - } - } - - pub fn verifier_index(&self) -> VerifierIndex { - let [ a, b, c ] = & self.compiled; - - let max_degree = self.urs.get_ref().max_degree(); - let mut hn : HashMap = HashMap::new(); - for i in - [ - self.domains.h.size()-1, - self.domains.k.size()-1, - ].iter() { - let i = max_degree - i; - hn.insert(i, self.urs.get_ref().hn.get(&i).unwrap().clone()); - } - - let urs = { - let gp = (0..self.domains.x.size()).map(|i| self.urs.get_ref().gp[i]).collect(); - URS:: { - gp, - hn, - hx: self.urs.get_ref().hx, - prf: self.urs.get_ref().prf, - depth: self.urs.get_ref().max_degree(), - } - }; - - VerifierIndex { - matrix_commitments : [ Self::matrix_values(a), Self::matrix_values(b), Self::matrix_values(c) ], - domains: self.domains, - max_degree, - public_inputs: self.public_inputs, - fr_sponge_params: self.fr_sponge_params.clone(), - fq_sponge_params: self.fq_sponge_params.clone(), - urs, - endo_q: self.endo_q, - endo_r: self.endo_r, - } - } - - // This function verifies the consistency of the wire assignements (witness) against the constraints - // witness: wire assignement witness - // RETURN: verification status - pub fn verify - ( - &self, - witness: &Vec - ) -> bool - { - if self.compiled[0].constraints.shape().1 != witness.len() {return false} - let mut gates = vec![CircuitGate::::zero(); self.domains.h.size()]; - for i in 0..3 - { - for val in self.compiled[i].constraints.iter() - { - gates[(val.1).0].wire[i] += &(witness[(val.1).1] * val.0) - } - } - for gate in gates.iter() - { - if gate.wire[0] * &gate.wire[1] != gate.wire[2] {return false} - } - true - } -} diff --git a/pairing/marlin/src/lib.rs b/pairing/marlin/src/lib.rs deleted file mode 100644 index b8eba75f87..0000000000 --- a/pairing/marlin/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod prover; -pub mod verifier; -pub mod marlin_sponge; -pub mod compiled; -pub mod index; diff --git a/pairing/marlin/src/marlin_sponge.rs b/pairing/marlin/src/marlin_sponge.rs deleted file mode 100644 index 11d75fbd42..0000000000 --- a/pairing/marlin/src/marlin_sponge.rs +++ /dev/null @@ -1,70 +0,0 @@ -use crate::prover::ProofEvaluations; -use algebra::{ - Field, PairingEngine, PrimeField, -}; - -use oracle::{sponge::{DefaultFrSponge, FqSponge, ScalarChallenge}, poseidon::{ArithmeticSponge, ArithmeticSpongeParams, Sponge, MarlinSpongeConstants}}; - -pub trait FrSponge { - fn new(p: ArithmeticSpongeParams) -> Self; - fn absorb(&mut self, x: &Fr); - fn challenge(&mut self) -> ScalarChallenge; - fn absorb_evaluations(&mut self, x_hat: &Fr, e: &ProofEvaluations); -} - -pub trait SpongePairingEngine: PairingEngine { - type FqSponge: FqSponge; - type FrSponge: FrSponge; -} - -impl FrSponge for DefaultFrSponge { - fn new(params: ArithmeticSpongeParams) -> DefaultFrSponge { - DefaultFrSponge { - params, - sponge: ArithmeticSponge::new(), - last_squeezed: vec![], - } - } - - fn absorb(&mut self, x: &Fr) { - self.last_squeezed = vec![]; - self.sponge.absorb(&self.params, &[*x]); - } - - fn challenge(&mut self) -> ScalarChallenge { - ScalarChallenge(self.squeeze(oracle::sponge::CHALLENGE_LENGTH_IN_LIMBS)) - } - - fn absorb_evaluations(&mut self, x_hat: &Fr, e: &ProofEvaluations) { - self.last_squeezed = vec![]; - - let points = [ - *x_hat, - e.w, - e.za, - e.zb, - e.h1, - e.h2, - e.h3, - e.row[0], - e.row[1], - e.row[2], - e.col[0], - e.col[1], - e.col[2], - e.val[0], - e.val[1], - e.val[2], - e.rc[0], - e.rc[1], - e.rc[2], - e.g1, - e.g2, - e.g3, - ]; - - for p in &points { - self.sponge.absorb(&self.params, &[*p]); - } - } -} diff --git a/pairing/marlin/src/prover.rs b/pairing/marlin/src/prover.rs deleted file mode 100644 index 7b71a5e162..0000000000 --- a/pairing/marlin/src/prover.rs +++ /dev/null @@ -1,551 +0,0 @@ -/******************************************************************************************** - -This source file implements prover's zk-proof primitive. - -*********************************************************************************************/ - -use oracle::rndoracle::{ProofError}; -use algebra::{Field, PairingEngine, Zero, One}; -use ff_fft::{DensePolynomial, EvaluationDomain}; -use oracle::sponge::{FqSponge, ScalarChallenge}; -use marlin_circuits::domains::EvaluationDomains; -use crate::marlin_sponge::{FrSponge}; -use oracle::utils::PolyUtils; -pub use super::index::Index; - -#[derive(Clone)] -pub struct ProofEvaluations { - pub w: Fr, - pub za: Fr, - pub zb: Fr, - pub h1: Fr, - pub g1: Fr, - pub h2: Fr, - pub g2: Fr, - pub h3: Fr, - pub g3: Fr, - pub row: [Fr; 3], - pub col: [Fr; 3], - pub val: [Fr; 3], - pub rc: [Fr; 3], -} - -#[derive(Clone)] -pub struct ProverProof -{ - // polynomial commitments - pub w_comm: E::G1Affine, - pub za_comm: E::G1Affine, - pub zb_comm: E::G1Affine, - pub h1_comm: E::G1Affine, - pub g1_comm: (E::G1Affine, E::G1Affine), - pub h2_comm: E::G1Affine, - pub g2_comm: (E::G1Affine, E::G1Affine), - pub h3_comm: E::G1Affine, - pub g3_comm: (E::G1Affine, E::G1Affine), - - // batched commitment opening proofs - pub proof1: E::G1Affine, - pub proof2: E::G1Affine, - pub proof3: E::G1Affine, - - // polynomial evaluations - pub evals : ProofEvaluations, - - // prover's scalars - pub sigma2: E::Fr, - pub sigma3: E::Fr, - - // public part of the witness - pub public: Vec -} - -impl ProverProof -{ - // This function constructs prover's zk-proof from the witness & the Index against URS instance - // witness: computation witness - // index: Index - // RETURN: prover's zk-proof - pub fn create - , - EFrSponge: FrSponge, - > - ( - witness: &Vec::, - index: &Index - ) -> Result - { - // random oracles have to be retrieved from the non-interactive argument - // context sequentually with adding argument-specific payload to the context - - let mut oracles = RandomOracles::::zero(); - - // prover computes z polynomial - let z = EvaluationDomains::evals_from_coeffs(witness.clone(), index.domains.h).interpolate(); - - // extract/save public part of the padded witness - let mut witness = witness.clone(); - witness.extend(vec![E::Fr::zero(); index.domains.h.size() - witness.len()]); - let ratio = index.domains.h.size() / index.domains.x.size(); - let public: Vec = (0..index.public_inputs).map(|i| {witness[i * ratio]}).collect(); - - // evaluate public input polynomial over domains.h - let public_evals = index.domains.h.fft - ( - &EvaluationDomains::evals_from_coeffs(public.clone(), - index.domains.x - ).interpolate()); - - // prover computes w polynomial from the witness by subtracting the public polynomial evaluations - let (w, r) = EvaluationDomains::evals_from_coeffs - ( - witness.iter().enumerate().map - ( - |elm| {*elm.1 - &public_evals[elm.0]} - ).collect(), - index.domains.h - ).interpolate().divide_by_vanishing_poly(index.domains.x).map_or(Err(ProofError::PolyDivision), |s| Ok(s))?; - if !r.is_zero() {return Err(ProofError::PolyDivision)} - - // prover computes za, zb polynomials - let mut zv = vec![vec![E::Fr::zero(); index.domains.h.size()]; 2]; - - for i in 0..2 - { - for constraint in index.compiled[i].constraints.iter() - { - zv[i][(constraint.1).0] += &(*constraint.0 * &witness[(constraint.1).1]); - } - } - - let urs = index.urs.get_ref(); - - let x_hat = - EvaluationDomains::evals_from_coeffs(public.clone(), index.domains.x).interpolate(); - let x_hat_comm = urs.commit(&x_hat)?; - - // prover interpolates the vectors and computes the evaluation polynomial - let za = EvaluationDomains::evals_from_coeffs(zv[0].to_vec(), index.domains.h).interpolate(); - let zb = EvaluationDomains::evals_from_coeffs(zv[1].to_vec(), index.domains.h).interpolate(); - - // substitute ZC with ZA*ZB - let zv = [za.clone(), zb.clone(), &za * &zb]; - - // commit to W, ZA, ZB polynomials - let w_comm = urs.commit(&w.clone())?; - let za_comm = urs.commit(&za.clone())?; - let zb_comm = urs.commit(&zb.clone())?; - - // the transcript of the random oracle non-interactive argument - let mut fq_sponge = EFqSponge::new(index.fq_sponge_params.clone()); - - // absorb the public input iand W, ZA, ZB polycommitments nto the argument - fq_sponge.absorb_g(& [x_hat_comm, w_comm, za_comm, zb_comm]); - - // sample alpha, eta oracles - oracles.alpha = fq_sponge.challenge(); - oracles.eta_a = fq_sponge.challenge(); - oracles.eta_b = fq_sponge.challenge(); - oracles.eta_c = fq_sponge.challenge(); - - let mut apow = E::Fr::one(); - let mut r: Vec = (0..index.domains.h.size()).map - ( - |i| - { - if i > 0 {apow *= &oracles.alpha} - apow - } - ).collect(); - r.reverse(); - let ra = DensePolynomial::::from_coefficients_vec(r); - - // compute first sumcheck argument polynomials - // -------------------------------------------------------------------- - - let (h1, mut g1) = Self::sumcheck_1_compute (index, &ra, &zv, &z, &oracles)?; - if !g1.coeffs[0].is_zero() {return Err(ProofError::SumCheck)} - g1.coeffs.remove(0); - - // commit to H1 & G1 polynomials and - let h1_comm = urs.commit(&h1)?; - let g1_comm = urs.commit_with_degree_bound(&g1, index.domains.h.size()-1)?; - - // absorb H1, G1 polycommitments - fq_sponge.absorb_g(&[g1_comm.0, g1_comm.1, h1_comm]); - // sample beta[0] oracle - oracles.beta[0] = ScalarChallenge(fq_sponge.challenge()); - - // compute second sumcheck argument polynomials - // -------------------------------------------------------------------- - - let (h2, mut g2) = Self::sumcheck_2_compute (index, &ra, &oracles)?; - let sigma2 = g2.coeffs[0]; - g2.coeffs.remove(0); - let h2_comm = urs.commit(&h2)?; - let g2_comm = urs.commit_with_degree_bound(&g2, index.domains.h.size()-1)?; - - // absorb sigma2, g2, h2 - fq_sponge.absorb_fr(&[sigma2]); - fq_sponge.absorb_g(&[g2_comm.0, g2_comm.1, h2_comm]); - // sample beta[1] oracle - oracles.beta[1] = ScalarChallenge(fq_sponge.challenge()); - - // compute third sumcheck argument polynomials - // -------------------------------------------------------------------- - - let (h3, mut g3) = Self::sumcheck_3_compute (index, &oracles)?; - let sigma3 = g3.coeffs[0]; - g3.coeffs.remove(0); - let h3_comm = urs.commit(&h3)?; - let g3_comm = urs.commit_with_degree_bound(&g3, index.domains.k.size()-1)?; - - // absorb sigma3, g3, h3 - fq_sponge.absorb_fr(&[sigma3]); - fq_sponge.absorb_g(&[g3_comm.0, g3_comm.1, h3_comm]); - // sample beta[2] & batch oracles - oracles.beta[2] = ScalarChallenge(fq_sponge.challenge()); - oracles.r_k = ScalarChallenge(fq_sponge.challenge()); - - let digest_before_evaluations = fq_sponge.digest(); - oracles.digest_before_evaluations = digest_before_evaluations; - - let mut fr_sponge = { - let mut s = EFrSponge::new(index.fr_sponge_params.clone()); - s.absorb(&digest_before_evaluations); - s - }; - - let endo = &index.endo_r; - let beta : Vec<_> = oracles.beta.iter().map(|x| x.to_field(endo)).collect(); - - let evals = ProofEvaluations { - w : w.evaluate(beta[0]), - za : za.evaluate(beta[0]), - zb : zb.evaluate(beta[0]), - h1 : h1.evaluate(beta[0]), - g1 : g1.evaluate(beta[0]), - h2 : h2.evaluate(beta[1]), - g2 : g2.evaluate(beta[1]), - h3 : h3.evaluate(beta[2]), - g3 : g3.evaluate(beta[2]), - row: - [ - index.compiled[0].row.evaluate(beta[2]), - index.compiled[1].row.evaluate(beta[2]), - index.compiled[2].row.evaluate(beta[2]), - ], - col: - [ - index.compiled[0].col.evaluate(beta[2]), - index.compiled[1].col.evaluate(beta[2]), - index.compiled[2].col.evaluate(beta[2]), - ], - val: - [ - index.compiled[0].val.evaluate(beta[2]), - index.compiled[1].val.evaluate(beta[2]), - index.compiled[2].val.evaluate(beta[2]), - ], - rc: - [ - index.compiled[0].rc.evaluate(beta[2]), - index.compiled[1].rc.evaluate(beta[2]), - index.compiled[2].rc.evaluate(beta[2]), - ], - }; - - let x_hat_beta1 = x_hat.evaluate(beta[0]); - oracles.x_hat_beta1 = x_hat_beta1; - - fr_sponge.absorb_evaluations(&x_hat_beta1, &evals); - - oracles.batch = fr_sponge.challenge(); - oracles.r = fr_sponge.challenge(); - - // construct the proof - // -------------------------------------------------------------------- - - let batch_chal = oracles.batch.to_field(endo); - - Ok(ProverProof - { - // polynomial commitments - w_comm, - za_comm, - zb_comm, - h1_comm, - g1_comm, - h2_comm, - g2_comm, - h3_comm, - g3_comm, - - // polynomial commitment batched opening proofs - proof1: urs.open - ( - vec! - [ - &x_hat, - &w, - &za, - &zb, - &g1, - &h1, - ], - batch_chal, - beta[0] - )?, - proof2: urs.open - ( - vec! - [ - &g2, - &h2, - ], - batch_chal, - beta[1] - )?, - proof3: urs.open - ( - vec! - [ - &g3, - &h3, - &index.compiled[0].row, - &index.compiled[1].row, - &index.compiled[2].row, - &index.compiled[0].col, - &index.compiled[1].col, - &index.compiled[2].col, - &index.compiled[0].val, - &index.compiled[1].val, - &index.compiled[2].val, - &index.compiled[0].rc, - &index.compiled[1].rc, - &index.compiled[2].rc, - ], - batch_chal, - beta[2] - )?, - - // polynomial evaluations - evals, - - // prover's scalars - sigma2, - sigma3, - - // public part of the witness - public - }) - } - - // This function computes polynomials for the first sumchek protocol - // RETURN: prover's H1 & G1 polynomials - pub fn sumcheck_1_compute - ( - index: &Index, - ra: &DensePolynomial, - zm: &[DensePolynomial; 3], - z: &DensePolynomial, - oracles: &RandomOracles - ) -> Result<(DensePolynomial, DensePolynomial), ProofError> - { - // precompute Lagrange polynomial denominators - let mut lagrng: Vec = index.domains.h.elements().map(|elm| {oracles.alpha - &elm}).collect(); - algebra::fields::batch_inversion::(&mut lagrng); - let vanish = index.domains.h.evaluate_vanishing_polynomial(oracles.alpha); - - // compute and return H1 & G1 polynomials - (0..3).map - ( - |i| - { - let mut ram = EvaluationDomains::evals_from_coeffs(vec![E::Fr::zero(); index.domains.h.size()], index.domains.h); - for val in index.compiled[i].constraints.iter() - { - ram.evals[(val.1).1] += &(vanish * val.0 * &lagrng[(val.1).0]); - } - (i, ram) - } - ).fold - ( - DensePolynomial::::zero(), - |x, (i, y)| - // scale with eta's and add up - &x + &(&(ra * &zm[i]) - &(&y.interpolate() * &z)).scale([oracles.eta_a, oracles.eta_b, oracles.eta_c][i]) - // compute quotient and remainder - ).divide_by_vanishing_poly(index.domains.h).map_or(Err(ProofError::PolyDivision), |s| Ok(s)) - } - - // This function computes polynomials for the second sumchek protocol - // RETURN: prover's H2 & G2 polynomials - pub fn sumcheck_2_compute - ( - index: &Index, - ra: &DensePolynomial, - oracles: &RandomOracles - ) -> Result<(DensePolynomial, DensePolynomial), ProofError> - { - // precompute Lagrange polynomial evaluations - let lagrng = index.domains.h.evaluate_all_lagrange_coefficients(oracles.beta[0].to_field(&index.endo_r)); - - // compute and return H2 & G2 polynomials - // use the precomputed normalized Lagrange evaluations for interpolation evaluations - (0..3).map - ( - |i| - { - let mut ramxbval = EvaluationDomains::evals_from_coeffs(vec![E::Fr::zero(); index.domains.h.size()], index.domains.h); - for val in index.compiled[i].constraints.iter() - { - ramxbval.evals[(val.1).0] += &(*val.0 * &lagrng[(val.1).1]); - } - (i, ramxbval) - } - ).fold - ( - DensePolynomial::::zero(), - |x, (i, y)| - // scale with eta's and add up - &x + &(&(ra * &y.interpolate()).scale([oracles.eta_a, oracles.eta_b, oracles.eta_c][i])) - // compute quotient and remainder - ).divide_by_vanishing_poly(index.domains.h).map_or(Err(ProofError::PolyDivision), |s| Ok(s)) - } - - // This function computes polynomials for the third sumchek protocol - // RETURN: prover's H3 & G3 polynomials - pub fn sumcheck_3_compute - ( - index: &Index, - oracles: &RandomOracles - ) -> Result<(DensePolynomial, DensePolynomial), ProofError> - { - let beta0 = oracles.beta[0].to_field(&index.endo_r); - let beta1 = oracles.beta[1].to_field(&index.endo_r); - - let vanish = index.domains.h.evaluate_vanishing_polynomial(beta0) * - &index.domains.h.evaluate_vanishing_polynomial(beta1); - - // compute polynomial f3 - let f3 = (0..3).map - ( - |i| - { - EvaluationDomains::evals_from_coeffs - ( - { - let mut fractions: Vec = (0..index.domains.k.size()).map - ( - |j| - { - (beta0 - &index.compiled[i].col_eval_k[j]) * - &(beta1 - &index.compiled[i].row_eval_k[j]) - } - ).collect(); - algebra::fields::batch_inversion::(&mut fractions); - fractions.iter().enumerate().map - ( - |(j, elm)| - { - vanish * &index.compiled[i].val_eval_k[j] * - // scale with eta's - &[oracles.eta_a, oracles.eta_b, oracles.eta_c][i] * elm - } - ).collect() - }, - index.domains.k - ) - } - ).fold - ( - EvaluationDomains::evals_from_coeffs(vec![E::Fr::zero(); index.domains.k.size()], index.domains.k), - |x, y| &x + &y - ).interpolate(); - - // precompute polynomials (row(X)-oracle1)*(col(X)-oracle2) in evaluation form over domains.b - let crb: Vec> = - (0..3).map(|i| index.compiled[i].compute_row_2_col_1(beta0, beta1)).collect(); - - // compute polynomial a - let a = (0..3).map - ( - |i| - { - EvaluationDomains::evals_from_coeffs - ( - index.compiled[i].val_eval_b.evals.iter().enumerate().map - ( - |(k, val)| - { - let mut eval = [oracles.eta_a, oracles.eta_b, oracles.eta_c][i] * val * &vanish; - for j in 0..3 {if i != j {eval *= &crb[j][k]}} - eval - } - ).collect(), - index.domains.b - ) - } - ).fold - ( - EvaluationDomains::evals_from_coeffs(vec![E::Fr::zero(); index.domains.b.size()], index.domains.b), - |x, y| &x + &y - ).interpolate(); - - // compute polynomial b - let b = EvaluationDomains::evals_from_coeffs - ( - (0..index.domains.b.size()).map - ( - |i| crb[0][i] * &crb[1][i] * &crb[2][i] - ).collect(), - index.domains.b - ).interpolate(); - - // compute quotient and remainder - match (&a - &(&b * &f3)).divide_by_vanishing_poly(index.domains.k) - { - Some((q, r)) => {if r.coeffs.len() > 0 {return Err(ProofError::PolyDivision)} else {return Ok((q, f3))}} - _ => return Err(ProofError::PolyDivision) - } - } -} - -pub struct RandomOracles -{ - pub alpha: F, - pub eta_a: F, - pub eta_b: F, - pub eta_c: F, - pub beta: [ScalarChallenge; 3], - pub r_k : ScalarChallenge, - - pub x_hat_beta1: F, - pub digest_before_evaluations: F, - - // Sampled using the other sponge - pub batch: ScalarChallenge, - pub r: ScalarChallenge, -} - -impl RandomOracles -{ - pub fn zero () -> Self - { - let c = ScalarChallenge(F::zero()); - Self - { - alpha: F::zero(), - eta_a: F::zero(), - eta_b: F::zero(), - eta_c: F::zero(), - batch: c, - beta: [c, c, c], - r: c, - x_hat_beta1: F::zero(), - digest_before_evaluations: F::zero(), - r_k: c, - } - } -} diff --git a/pairing/marlin/src/verifier.rs b/pairing/marlin/src/verifier.rs deleted file mode 100644 index 63cab1b29f..0000000000 --- a/pairing/marlin/src/verifier.rs +++ /dev/null @@ -1,275 +0,0 @@ -/******************************************************************************************** - -This source file implements zk-proof batch verifier functionality. - -*********************************************************************************************/ - -use rand_core::RngCore; -pub use super::index::{VerifierIndex as Index}; -use oracle::rndoracle::{ProofError}; -pub use super::prover::{ProverProof, RandomOracles}; -use algebra::{Field, PairingEngine, Zero}; -use ff_fft::{DensePolynomial, Evaluations, EvaluationDomain, GeneralEvaluationDomain}; -use oracle::sponge::{FqSponge, ScalarChallenge}; -use crate::marlin_sponge::{FrSponge}; - -impl ProverProof -{ - // This function verifies the prover's first sumcheck argument values - // index: Index - // oracles: random oracles of the argument - // RETURN: verification status - pub fn sumcheck_1_verify - ( - &self, - index: &Index, - oracles: &RandomOracles, - ) -> bool - { - let beta0 = oracles.beta[0].to_field(&index.endo_r); - // compute ra*zm - ram*z ?= h*v + b*g to verify the first sumcheck argument - (oracles.alpha.pow([index.domains.h.size]) - &beta0.pow([index.domains.h.size])) * - &(0..3).map - ( - |i| - { - match i - { - 0 => {self.evals.za * &oracles.eta_a} - 1 => {self.evals.zb * &oracles.eta_b} - 2 => {self.evals.za * &self.evals.zb * &oracles.eta_c} - _ => {E::Fr::zero()} - } - } - ).fold(E::Fr::zero(), |x, y| x + &y) - == - (oracles.alpha - &beta0) * - &( - self.evals.h1 * &index.domains.h.evaluate_vanishing_polynomial(beta0) + - &(beta0 * &self.evals.g1) + - &(self.sigma2 * &index.domains.h.size_as_field_element * - &(self.evals.w * &index.domains.x.evaluate_vanishing_polynomial(beta0) + - &oracles.x_hat_beta1)) - ) - } - - // This function verifies the prover's second sumcheck argument values - // index: Index - // oracles: random oracles of the argument - // RETURN: verification status - pub fn sumcheck_2_verify - ( - &self, - index: &Index, - oracles: &RandomOracles, - ) -> bool - { - let beta1 = oracles.beta[1].to_field(&index.endo_r); - self.sigma3 * &index.domains.k.size_as_field_element * - &((oracles.alpha.pow([index.domains.h.size]) - &beta1.pow([index.domains.h.size]))) - == - (oracles.alpha - &beta1) * &(self.evals.h2 * - &index.domains.h.evaluate_vanishing_polynomial(beta1) + - &self.sigma2 + &(self.evals.g2 * &beta1)) - } - - // This function verifies the prover's third sumcheck argument values - // index: Index - // oracles: random oracles of the argument - // RETURN: verification status - pub fn sumcheck_3_verify - ( - &self, - index: &Index, - oracles: &RandomOracles - ) -> bool - { - let beta0 = oracles.beta[0].to_field(&index.endo_r); - let beta1 = oracles.beta[1].to_field(&index.endo_r); - let beta2 = oracles.beta[2].to_field(&index.endo_r); - - let crb: Vec = (0..3).map - ( - |i| - { - beta1 * &beta0 - - &(beta0 * &self.evals.row[i]) - - &(beta1 * &self.evals.col[i]) + - &self.evals.rc[i] - } - ).collect(); - - let acc = (0..3).map - ( - |i| - { - let mut x = self.evals.val[i] * &[oracles.eta_a, oracles.eta_b, oracles.eta_c][i]; - for j in 0..3 {if i != j {x *= &crb[j]}} - x - } - ).fold(E::Fr::zero(), |x, y| x + &y); - - index.domains.k.evaluate_vanishing_polynomial(beta2) * &self.evals.h3 - == - index.domains.h.evaluate_vanishing_polynomial(beta0) * - &(index.domains.h.evaluate_vanishing_polynomial(beta1)) * - &acc - &((beta2 * &self.evals.g3 + &self.sigma3) * - &crb[0] * &crb[1] * &crb[2]) - } - - // This function verifies the batch of zk-proofs - // proofs: vector of Marlin proofs - // index: Index - // rng: randomness source context - // RETURN: verification status - pub fn verify - , - EFrSponge: FrSponge, - > - ( - proofs: &Vec>, - index: &Index, - rng: &mut dyn RngCore - ) -> Result - { - let mut batch = Vec::new(); - for proof in proofs.iter() - { - let proof = proof.clone(); - // TODO: Cache this interpolated polynomial. - let x_hat = Evaluations::::from_vec_and_domain( - proof.public.clone(), GeneralEvaluationDomain::Radix2(index.domains.x) - ).interpolate(); - let x_hat_comm = index.urs.commit(&x_hat)?; - - let oracles = proof.oracles::(index, x_hat_comm, &x_hat)?; - - // first, verify the sumcheck argument values - if - !proof.sumcheck_1_verify (index, &oracles) || - !proof.sumcheck_2_verify (index, &oracles) || - !proof.sumcheck_3_verify (index, &oracles) - { - return Err(ProofError::ProofVerification) - } - - let batch_chal = oracles.batch.to_field(&index.endo_r); - - batch.push - (( - oracles.beta[0].to_field(&index.endo_r), - batch_chal, - vec! - [ - (x_hat_comm, oracles.x_hat_beta1, None), - (proof.w_comm, proof.evals.w, None), - (proof.za_comm, proof.evals.za, None), - (proof.zb_comm, proof.evals.zb, None), - (proof.g1_comm.0, proof.evals.g1, Some((proof.g1_comm.1, index.domains.h.size()-1))), - (proof.h1_comm, proof.evals.h1, None), - ], - proof.proof1 - )); - batch.push - (( - oracles.beta[1].to_field(&index.endo_r), - batch_chal, - vec! - [ - (proof.g2_comm.0, proof.evals.g2, Some((proof.g2_comm.1, index.domains.h.size()-1))), - (proof.h2_comm, proof.evals.h2, None), - ], - proof.proof2 - )); - batch.push - (( - oracles.beta[2].to_field(&index.endo_r), - batch_chal, - vec! - [ - (proof.g3_comm.0, proof.evals.g3, Some((proof.g3_comm.1, index.domains.k.size()-1))), - (proof.h3_comm, proof.evals.h3, None), - (index.matrix_commitments[0].row, proof.evals.row[0], None), - (index.matrix_commitments[1].row, proof.evals.row[1], None), - (index.matrix_commitments[2].row, proof.evals.row[2], None), - (index.matrix_commitments[0].col, proof.evals.col[0], None), - (index.matrix_commitments[1].col, proof.evals.col[1], None), - (index.matrix_commitments[2].col, proof.evals.col[2], None), - (index.matrix_commitments[0].val, proof.evals.val[0], None), - (index.matrix_commitments[1].val, proof.evals.val[1], None), - (index.matrix_commitments[2].val, proof.evals.val[2], None), - (index.matrix_commitments[0].rc, proof.evals.rc[0], None), - (index.matrix_commitments[1].rc, proof.evals.rc[1], None), - (index.matrix_commitments[2].rc, proof.evals.rc[2], None), - ], - proof.proof3 - )); - } - // second, verify the commitment opening proofs - match index.urs.verify(&batch, rng) - { - false => Err(ProofError::OpenProof), - true => Ok(true) - } - } - - // This function queries random oracle values from non-interactive - // argument context by verifier - pub fn oracles - , - EFrSponge: FrSponge, - > - ( - &self, - index: &Index, - x_hat_comm: E::G1Affine, - x_hat: &DensePolynomial - ) -> Result, ProofError> - { - let mut oracles = RandomOracles::::zero(); - let mut fq_sponge = EFqSponge::new(index.fq_sponge_params.clone()); - - // TODO: absorb previous proof context into the argument - // absorb the public input and W, ZA, ZB polycommitments into the argument - fq_sponge.absorb_g(&[x_hat_comm, self.w_comm, self.za_comm, self.zb_comm]); - // sample alpha, eta[0..3] oracles - oracles.alpha = fq_sponge.challenge(); - oracles.eta_a = fq_sponge.challenge(); - oracles.eta_b = fq_sponge.challenge(); - oracles.eta_c = fq_sponge.challenge(); - // absorb H1, G1 polycommitments - fq_sponge.absorb_g(&[self.g1_comm.0, self.g1_comm.1, self.h1_comm]); - // sample beta[0] oracle - oracles.beta[0] = ScalarChallenge(fq_sponge.challenge()); - // absorb sigma2 scalar - fq_sponge.absorb_fr(&[self.sigma2]); - fq_sponge.absorb_g(&[self.g2_comm.0, self.g2_comm.1, self.h2_comm]); - // sample beta[1] oracle - oracles.beta[1] = ScalarChallenge(fq_sponge.challenge()); - // absorb sigma3 scalar - fq_sponge.absorb_fr(&[self.sigma3]); - fq_sponge.absorb_g(&[self.g3_comm.0, self.g3_comm.1, self.h3_comm]); - // sample beta[2] & batch oracles - oracles.beta[2] = ScalarChallenge(fq_sponge.challenge()); - oracles.r_k = ScalarChallenge(fq_sponge.challenge()); - - let digest_before_evaluations = fq_sponge.digest(); - oracles.digest_before_evaluations = digest_before_evaluations; - - let mut fr_sponge = { - let mut s = EFrSponge::new(index.fr_sponge_params.clone()); - s.absorb(&digest_before_evaluations); - s - }; - - let x_hat_beta1 = x_hat.evaluate(oracles.beta[0].to_field(&index.endo_r)); - oracles.x_hat_beta1 = x_hat_beta1; - - fr_sponge.absorb_evaluations(&x_hat_beta1,&self.evals); - - oracles.batch = fr_sponge.challenge(); - oracles.r = fr_sponge.challenge(); - - Ok(oracles) - } -} diff --git a/pairing/plonk/BUILD.bazel b/pairing/plonk/BUILD.bazel deleted file mode 100644 index 3a4a8de02a..0000000000 --- a/pairing/plonk/BUILD.bazel +++ /dev/null @@ -1,23 +0,0 @@ -load("@io_bazel_rules_rust//rust:rust.bzl", "rust_library") - -rust_library( - name = "plonk_protocol_pairing", - visibility = ["//visibility:public"], - edition = "2018", - srcs = glob(["src/**/*.rs"]), - # aliases = {"@zexe//ff-fft": "ff_fft"}, - deps = [ - "@zexe//algebra", - "@zexe//ff-fft", - - "//pairing/commitment:commitment_pairing", - "//circuits/plonk:plonk_circuits", - "//oracle", - - "//bzl/cargo:rand", - "//bzl/cargo:rand_core", - "//bzl/cargo:colored", - "//bzl/cargo:sprs", - "//bzl/cargo:array_init" - ] -) diff --git a/pairing/plonk/Cargo.toml b/pairing/plonk/Cargo.toml deleted file mode 100644 index 0fed6b9bfe..0000000000 --- a/pairing/plonk/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "plonk_protocol_pairing" -version = "0.1.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -algebra = { path = "../../zexe/algebra", features = [ "parallel", "bn_382", "tweedle", "asm" ] } -ff-fft = { path = "../../zexe/ff-fft" } -commitment_pairing = { path = "../commitment" } -plonk_circuits = { path = "../../circuits/plonk" } -oracle = { path = "../../oracle" } -rand_core = { version = "0.5" } -colored = "1.9.2" -rand = "0.7.3" -sprs = "0.7.1" -array-init = "1.0.0" diff --git a/pairing/plonk/README.md b/pairing/plonk/README.md deleted file mode 100644 index 3717f4f962..0000000000 --- a/pairing/plonk/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Plonk (https://eprint.iacr.org/2019/953.pdf) presents a new zk-SNARKs protocol with the benefit of the updateability of its Universal SRS (structured reference string) with the size linear in the size of the arithmetic circuit that describes the computational statement being proven. URS is statement/circuit independent and can be used for the proofing system of many circuits whose size (depth) is limited by the URS size. Plonk provides the benefit of succinctness of the proofs and of the proof verification. - -The source code under this dirctory implements the succinct pairing-based Plonk proofing system. diff --git a/pairing/plonk/src/index.rs b/pairing/plonk/src/index.rs deleted file mode 100644 index 0f43aa42fc..0000000000 --- a/pairing/plonk/src/index.rs +++ /dev/null @@ -1,187 +0,0 @@ -/***************************************************************************************************************** - -This source file implements Plonk Protocol Index primitive. - -*****************************************************************************************************************/ - -use rand_core::RngCore; -use commitment_pairing::urs::URS; -use oracle::poseidon::ArithmeticSpongeParams; -use plonk_circuits::constraints::ConstraintSystem; -use ff_fft::{DensePolynomial, EvaluationDomain, Radix2EvaluationDomain as D}; -use algebra::{AffineCurve, PairingEngine, curves::models::short_weierstrass_jacobian::{GroupAffine as SWJAffine}, Zero, One}; -use oracle::rndoracle::ProofError; - -pub trait CoordinatesCurve: AffineCurve { - fn to_coordinates(&self) -> Option<(Self::BaseField, Self::BaseField)>; - fn of_coordinates(x:Self::BaseField, y:Self::BaseField) -> Self; -} - -impl CoordinatesCurve for SWJAffine

{ - fn to_coordinates(&self) -> Option<(Self::BaseField, Self::BaseField)>{ - if self.infinity { - None - } else { - Some((self.x, self.y)) - } - } - - fn of_coordinates(x:Self::BaseField, y:Self::BaseField) -> Self { - SWJAffine::

::new(x, y, false) - } -} - -pub enum URSValue<'a, E : PairingEngine> { - Value(URS), - Ref(&'a URS) -} - -impl<'a, E : PairingEngine> URSValue<'a, E> { - pub fn get_ref(&self) -> & URS { - match self { - URSValue::Value(x) => &x, - URSValue::Ref(x) => x - } - } -} - -pub enum URSSpec <'a, 'b, E:PairingEngine>{ - Use(&'a URS), - Generate(&'b mut dyn RngCore) -} - -impl<'a, E: PairingEngine> URSValue<'a, E> { - pub fn generate<'b>( - degree: usize, - rng : &'b mut dyn RngCore) -> URS { - - URS::::create - ( - - degree, - vec![], - rng ) - } - - pub fn create<'b>(degree: usize, spec : URSSpec<'a, 'b, E>) -> URSValue<'a, E>{ - match spec { - URSSpec::Use(x) => URSValue::Ref(x), - URSSpec::Generate(rng) => URSValue::Value(Self::generate(degree, rng)) - } - } -} - -pub struct Index<'a, E: PairingEngine> -{ - // constraints as Lagrange-based polynoms - pub cs: ConstraintSystem, - - // polynomial commitment keys - pub urs: URSValue<'a, E>, - - // random oracle argument parameters - pub fq_sponge_params: ArithmeticSpongeParams, - - // Coefficients for the curve endomorphism - pub endo_r: E::Fr, - pub endo_q: E::Fq, -} - -pub struct VerifierIndex -{ - pub domain: D, // evaluation domain - - // index polynomial commitments - pub sigma_comm: [E::G1Affine; 3], // permutation commitment array - pub sid_comm: E::G1Affine, // SID commitment - pub ql_comm: E::G1Affine, // left input wire commitment - pub qr_comm: E::G1Affine, // right input wire commitment - pub qo_comm: E::G1Affine, // output wire commitment - pub qm_comm: E::G1Affine, // multiplication commitment - pub qc_comm: E::G1Affine, // constant wire commitment - - pub r: E::Fr, // coordinate shift for right wires - pub o: E::Fr, // coordinate shift for output wires - - // polynomial commitment keys, trimmed - pub urs: URS, - - // random oracle argument parameters - pub fr_sponge_params: ArithmeticSpongeParams, - pub fq_sponge_params: ArithmeticSpongeParams, - - // Coefficients for the curve endomorphism - pub endo_r: E::Fr, - pub endo_q: E::Fq, -} - -pub fn endos() -> (E::Fq, E::Fr) where E::G1Affine : CoordinatesCurve { - let endo_q : E::Fq = oracle::sponge::endo_coefficient(); - let endo_r = { - let potential_endo_r : E::Fr = oracle::sponge::endo_coefficient(); - let t = E::G1Affine::prime_subgroup_generator(); - let (x, y) = t.to_coordinates().unwrap(); - let phi_t = E::G1Affine::of_coordinates(x * &endo_q, y); - if t.mul(potential_endo_r) == phi_t.into_projective() { - potential_endo_r - } else { - potential_endo_r * &potential_endo_r - } - }; - (endo_q, endo_r) -} - -impl<'a, E: PairingEngine> Index<'a, E> -where E::G1Affine: CoordinatesCurve -{ - // this function compiles the circuit from constraints - pub fn create<'b> - ( - cs: ConstraintSystem, - fq_sponge_params: ArithmeticSpongeParams, - urs : URSSpec<'a, 'b, E> - ) -> Self - { - let urs = URSValue::create(cs.domain.d1.size()+3, urs); - let (endo_q, endo_r) = endos::(); - - Index - { - fq_sponge_params, - endo_q, - endo_r, - urs, - cs, - } - } - - pub fn verifier_index(&self) -> Result, ProofError> - { - let urs = self.urs.get_ref().clone(); - Ok(VerifierIndex - { - domain: self.cs.domain.d1, - - sid_comm: urs.commit(&DensePolynomial::from_coefficients_slice(&[E::Fr::zero(), E::Fr::one()]))?, - sigma_comm: - [ - urs.commit(&self.cs.sigmam[0])?, - urs.commit(&self.cs.sigmam[1])?, - urs.commit(&self.cs.sigmam[2])?, - ], - ql_comm: urs.commit(&self.cs.qlm)?, - qr_comm: urs.commit(&self.cs.qrm)?, - qo_comm: urs.commit(&self.cs.qom)?, - qm_comm: urs.commit(&self.cs.qmm)?, - qc_comm: urs.commit(&self.cs.qc)?, - - fr_sponge_params: self.cs.fr_sponge_params.clone(), - fq_sponge_params: self.fq_sponge_params.clone(), - endo_q: self.endo_q, - endo_r: self.endo_r, - urs, - r: self.cs.r, - o: self.cs.o, - }) - } -} diff --git a/pairing/plonk/src/lib.rs b/pairing/plonk/src/lib.rs deleted file mode 100644 index 7689e928a8..0000000000 --- a/pairing/plonk/src/lib.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod prover; -pub mod verifier; -pub mod plonk_sponge; -pub mod index; diff --git a/pairing/plonk/src/plonk_sponge.rs b/pairing/plonk/src/plonk_sponge.rs deleted file mode 100644 index f84091998e..0000000000 --- a/pairing/plonk/src/plonk_sponge.rs +++ /dev/null @@ -1,55 +0,0 @@ -use plonk_circuits::scalars::ProofEvaluations; -use algebra::{ - Field, PairingEngine, PrimeField, -}; - -use oracle::{sponge::{DefaultFrSponge, FqSponge, ScalarChallenge}, poseidon::{ArithmeticSponge, ArithmeticSpongeParams, Sponge, PlonkSpongeConstants as SC}}; - -pub trait FrSponge { - fn new(p: ArithmeticSpongeParams) -> Self; - fn absorb(&mut self, x: &Fr); - fn challenge(&mut self) -> ScalarChallenge; - fn absorb_evaluations(&mut self, e: &ProofEvaluations); -} - -pub trait SpongePairingEngine: PairingEngine { - type FqSponge: FqSponge; - type FrSponge: FrSponge; -} - -impl FrSponge for DefaultFrSponge { - fn new(params: ArithmeticSpongeParams) -> DefaultFrSponge { - DefaultFrSponge { - params, - sponge: ArithmeticSponge::new(), - last_squeezed: vec![], - } - } - - fn absorb(&mut self, x: &Fr) { - self.last_squeezed = vec![]; - self.sponge.absorb(&self.params, &[*x]); - } - - fn challenge(&mut self) -> ScalarChallenge { - ScalarChallenge(self.squeeze(oracle::sponge::CHALLENGE_LENGTH_IN_LIMBS)) - } - - fn absorb_evaluations(&mut self, e: &ProofEvaluations) { - self.last_squeezed = vec![]; - - let points = [ - e.l, - e.r, - e.o, - e.sigma1, - e.sigma2, - e.r, - e.z, - ]; - - for p in &points { - self.sponge.absorb(&self.params, &[*p]); - } - } -} diff --git a/pairing/plonk/src/prover.rs b/pairing/plonk/src/prover.rs deleted file mode 100644 index 830895ce75..0000000000 --- a/pairing/plonk/src/prover.rs +++ /dev/null @@ -1,255 +0,0 @@ -/******************************************************************************************** - -This source file implements prover's zk-proof primitive. - -*********************************************************************************************/ - -use rand_core::OsRng; -use algebra::{Field, PairingEngine, Zero, One}; -use ff_fft::{DensePolynomial, DenseOrSparsePolynomial, EvaluationDomain, Evaluations, Radix2EvaluationDomain as D}; -use oracle::{utils::PolyUtils, sponge::FqSponge, rndoracle::ProofError}; -use plonk_circuits::scalars::{ProofEvaluations, RandomOracles}; -use crate::plonk_sponge::FrSponge; -pub use super::index::Index; - -#[derive(Clone)] -pub struct ProverProof -{ - // polynomial commitments - pub l_comm: E::G1Affine, - pub r_comm: E::G1Affine, - pub o_comm: E::G1Affine, - pub z_comm: E::G1Affine, - pub tlow_comm: E::G1Affine, - pub tmid_comm: E::G1Affine, - pub thgh_comm: E::G1Affine, - - // batched commitment opening proofs - pub proof1: E::G1Affine, - pub proof2: E::G1Affine, - - // polynomial evaluations - pub evals : ProofEvaluations, - - // public part of the witness - pub public: Vec -} - -impl ProverProof -{ - // This function constructs prover's zk-proof from the witness & the Index against URS instance - // witness: computation witness - // index: Index - // RETURN: prover's zk-proof - pub fn create - , - EFrSponge: FrSponge, - > - ( - witness: &Vec::, - index: &Index - ) -> Result - { - let n = index.cs.domain.d1.size(); - if witness.len() != 3*n {return Err(ProofError::WitnessCsInconsistent)} - - let mut oracles = RandomOracles::::zero(); - let mut evals = ProofEvaluations:: - { - l: E::Fr::zero(), - r: E::Fr::zero(), - o: E::Fr::zero(), - sigma1: E::Fr::zero(), - sigma2: E::Fr::zero(), - f: E::Fr::zero(), - z: E::Fr::zero(), - t: E::Fr::zero(), - }; - - // the transcript of the random oracle non-interactive argument - let mut fq_sponge = EFqSponge::new(index.fq_sponge_params.clone()); - - // compute public input polynomial - let public = witness[0..index.cs.public].to_vec(); - let p = -Evaluations::>::from_vec_and_domain(public.clone(), index.cs.domain.d1).interpolate(); - - // compute witness polynomials - let l = &Evaluations::>::from_vec_and_domain(index.cs.gates.iter().map(|gate| witness[gate.wires.l.0]).collect(), index.cs.domain.d1).interpolate() - + &DensePolynomial::rand(1, &mut OsRng).mul_by_vanishing_poly(index.cs.domain.d1); - let r = &Evaluations::>::from_vec_and_domain(index.cs.gates.iter().map(|gate| witness[gate.wires.r.0]).collect(), index.cs.domain.d1).interpolate() - + &DensePolynomial::rand(1, &mut OsRng).mul_by_vanishing_poly(index.cs.domain.d1); - let o = &Evaluations::>::from_vec_and_domain(index.cs.gates.iter().map(|gate| witness[gate.wires.o.0]).collect(), index.cs.domain.d1).interpolate() - + &DensePolynomial::rand(1, &mut OsRng).mul_by_vanishing_poly(index.cs.domain.d1); - - // commit to the l, r, o wire values - let l_comm = index.urs.get_ref().commit(&l)?; - let r_comm = index.urs.get_ref().commit(&r)?; - let o_comm = index.urs.get_ref().commit(&o)?; - - // absorb the public input, l, r, o polycommitments into the argument - fq_sponge.absorb_fr(&public); - fq_sponge.absorb_g(&[l_comm, r_comm, o_comm]); - - // sample beta, gamma oracles - oracles.beta = fq_sponge.challenge(); - oracles.gamma = fq_sponge.challenge(); - - // compute permutation polynomial - - let mut z = vec![E::Fr::one(); n+1]; - z.iter_mut().skip(1).enumerate().for_each - ( - |(j, x)| *x = - (witness[j] + &(index.cs.sigmal1[0][j] * &oracles.beta) + &oracles.gamma) *& - (witness[j+n] + &(index.cs.sigmal1[1][j] * &oracles.beta) + &oracles.gamma) *& - (witness[j+2*n] + &(index.cs.sigmal1[2][j] * &oracles.beta) + &oracles.gamma) - ); - - algebra::fields::batch_inversion::(&mut z[1..=n]); - - (0..n).for_each - ( - |j| - { - let x = z[j]; - z[j+1] *= - &(x * &(witness[j] + &(index.cs.sid[j] * &oracles.beta) + &oracles.gamma) *& - (witness[j+n] + &(index.cs.sid[j] * &oracles.beta * &index.cs.r) + &oracles.gamma) *& - (witness[j+2*n] + &(index.cs.sid[j] * &oracles.beta * &index.cs.o) + &oracles.gamma)) - } - ); - - if z.pop().unwrap() != E::Fr::one() {return Err(ProofError::ProofCreation)}; - let z = Evaluations::>::from_vec_and_domain(z, index.cs.domain.d1).interpolate(); - - // evaluate witness polynomials over domains - let lagrange = index.cs.evaluate(&l, &r, &o, &z); - - // commit to z - let z_comm = index.urs.get_ref().commit(&z)?; - - // absorb the z commitment into the argument and query alpha - fq_sponge.absorb_g(&[z_comm]); - oracles.alpha = fq_sponge.challenge(); - let alpsq = oracles.alpha.square(); - - // compute quotient polynomial - - // generic constraints contribution - let (gen2, genp) = index.cs.gnrc_quot(&lagrange, &p); - - // permutation check contribution - let perm = index.cs.perm_quot(&lagrange, &oracles); - - // divide contributions with vanishing polynomial - let (mut t, res) = (&(&gen2.interpolate() + &perm.interpolate()) + &genp). - divide_by_vanishing_poly(index.cs.domain.d1).map_or(Err(ProofError::PolyDivision), |s| Ok(s))?; - if res.is_zero() == false {return Err(ProofError::PolyDivision)} - - // premutation boundary condition check contribution - let (bnd, res) = - DenseOrSparsePolynomial::divide_with_q_and_r(&(&z - &DensePolynomial::from_coefficients_slice(&[E::Fr::one()])).into(), - &DensePolynomial::from_coefficients_slice(&[-E::Fr::one(), E::Fr::one()]).into()). - map_or(Err(ProofError::PolyDivision), |s| Ok(s))?; - if res.is_zero() == false {return Err(ProofError::PolyDivision)} - - t += &bnd.scale(alpsq); - - // split t to fit to the commitment - let tlow: DensePolynomial; - let mut tmid = DensePolynomial::from_coefficients_slice(&[E::Fr::zero()]); - let mut thgh = DensePolynomial::from_coefficients_slice(&[E::Fr::zero()]); - if t.coeffs.len() <= n {tlow = t} - else if t.coeffs.len() <= 2*n - { - tlow = DensePolynomial::from_coefficients_slice(&t.coeffs[0..n]); - tmid = DensePolynomial::from_coefficients_slice(&t.coeffs[n..t.coeffs.len()]); - } - else - { - tlow = DensePolynomial::from_coefficients_slice(&t.coeffs[0..n]); - tmid = DensePolynomial::from_coefficients_slice(&t.coeffs[n..2*n]); - thgh = DensePolynomial::from_coefficients_slice(&t.coeffs[2*n..]); - } - - // commit to tlow, tmid, thgh - let tlow_comm = index.urs.get_ref().commit(&tlow)?; - let tmid_comm = index.urs.get_ref().commit(&tmid)?; - let thgh_comm = index.urs.get_ref().commit(&thgh)?; - - // absorb the polycommitments into the argument and sample zeta - - fq_sponge.absorb_g(&[tlow_comm, tmid_comm, thgh_comm]); - oracles.zeta = fq_sponge.challenge(); - let zeta2 = oracles.zeta.pow(&[n as u64]); - let zeta3 = zeta2.square(); - - // evaluate the polynomials - evals.l = l.evaluate(oracles.zeta); - evals.r = r.evaluate(oracles.zeta); - evals.o = o.evaluate(oracles.zeta); - evals.sigma1 = index.cs.sigmam[0].evaluate(oracles.zeta); - evals.sigma2 = index.cs.sigmam[1].evaluate(oracles.zeta); - evals.z = z.evaluate(oracles.zeta * &index.cs.domain.d1.group_gen); - - // compute linearization polynomial - - let bz = oracles.beta * &oracles.zeta; - let f1 = - &(&(&(&index.cs.qmm.scale(evals.l*&evals.r) + - &index.cs.qlm.scale(evals.l)) + - &index.cs.qrm.scale(evals.r)) + - &index.cs.qom.scale(evals.o)) + - &index.cs.qc; - let f2 = - z.scale - ( - (evals.l + &bz + &oracles.gamma) * - &(evals.r + &(bz * &index.cs.r) + &oracles.gamma) * - &(evals.o + &(bz * &index.cs.o) + &oracles.gamma) * - &oracles.alpha + - &(alpsq * &(zeta2 - &E::Fr::one()) / &(oracles.zeta - &E::Fr::one())) - ); - let f3 = - index.cs.sigmam[2].scale - ( - (evals.l + &(oracles.beta * &evals.sigma1) + &oracles.gamma) * - &(evals.r + &(oracles.beta * &evals.sigma2) + &oracles.gamma) * - &(oracles.beta * &evals.z * &oracles.alpha) - ); - let f = &(&f1 + &f2) - &f3; - evals.f = f.evaluate(oracles.zeta); - - // query opening scaler challenge - oracles.v = fq_sponge.challenge(); - - Ok(Self - { - l_comm, - r_comm, - o_comm, - z_comm, - tlow_comm, - tmid_comm, - thgh_comm, - proof1: index.urs.get_ref().open - ( - vec! - [ - &(&(&tlow + &tmid.scale(zeta2)) + &thgh.scale(zeta3)), - &f, - &l, - &r, - &o, - &index.cs.sigmam[0], - &index.cs.sigmam[1], - ], - oracles.v, - oracles.zeta - )?, - proof2: index.urs.get_ref().open(vec![&z], oracles.v, oracles.zeta * &index.cs.domain.d1.group_gen)?, - evals, - public - }) - } -} diff --git a/pairing/plonk/src/verifier.rs b/pairing/plonk/src/verifier.rs deleted file mode 100644 index dbb6f78feb..0000000000 --- a/pairing/plonk/src/verifier.rs +++ /dev/null @@ -1,147 +0,0 @@ -/******************************************************************************************** - -This source file implements zk-proof batch verifier functionality. - -*********************************************************************************************/ - -use rand_core::OsRng; -use oracle::rndoracle::ProofError; -pub use super::prover::ProverProof; -use crate::index::{VerifierIndex as Index}; -use plonk_circuits::scalars::RandomOracles; -use algebra::{Field, PrimeField, PairingEngine, ProjectiveCurve, VariableBaseMSM, Zero, One}; -use crate::plonk_sponge::FrSponge; -use oracle::sponge::FqSponge; -use ff_fft::EvaluationDomain; - -impl ProverProof -{ - // This function verifies the batch of zk-proofs - // proofs: vector of Plonk proofs - // index: Index - // RETURN: verification status - pub fn verify - , - EFrSponge: FrSponge, - > - ( - proofs: &Vec>, - index: &Index - ) -> Result - { - let mut batch = Vec::new(); - for proof in proofs.iter() - { - let oracles = proof.oracles::(index)?; - let zeta2 = oracles.zeta.pow(&[index.domain.size]); - let alpsq = oracles.alpha.square(); - let bz = oracles.beta * &oracles.zeta; - let ab = (proof.evals.l + &(oracles.beta * &proof.evals.sigma1) + &oracles.gamma) * - &(proof.evals.r + &(oracles.beta * &proof.evals.sigma2) + &oracles.gamma) * - &oracles.alpha * &proof.evals.z; - - // compute quotient polynomial commitment - let t_comm = VariableBaseMSM::multi_scalar_mul - ( - &[proof.tlow_comm, proof.tmid_comm, proof.thgh_comm], - &[E::Fr::one().into_repr(), zeta2.into_repr(), zeta2.square().into_repr()] - ).into_affine(); - - // evaluate lagrange polynoms - let mut lagrange = (0..if proof.public.len() > 0 {proof.public.len()} else {1}). - zip(index.domain.elements()).map(|(_,w)| oracles.zeta - &w).collect::>(); - algebra::fields::batch_inversion::(&mut lagrange); - lagrange.iter_mut().for_each(|l| *l *= &(zeta2 - &E::Fr::one())); - - // compute quotient polynomial evaluation - let t = - (proof.evals.f - &(ab * &(proof.evals.o + &oracles.gamma)) - - &(lagrange.iter().zip(proof.public.iter()).zip(index.domain.elements()). - map(|((l, p), w)| *l * p * &w).fold(E::Fr::zero(), |x, y| x + &y) * &index.domain.size_inv) - - &(lagrange[0] * &alpsq)) / &(zeta2 - &E::Fr::one()); - - // compute linearization polynomial commitment - let r_comm = VariableBaseMSM::multi_scalar_mul - ( - &[index.qm_comm, index.ql_comm, index.qr_comm, index.qo_comm, index.qc_comm, proof.z_comm, -index.sigma_comm[2]], - &[ - (proof.evals.l * &proof.evals.r).into_repr(), proof.evals.l.into_repr(), - proof.evals.r.into_repr(), proof.evals.o.into_repr(), E::Fr::one().into_repr(), - ( - (proof.evals.l + &bz + &oracles.gamma) * - &(proof.evals.r + &(bz * &index.r) + &oracles.gamma) * - &(proof.evals.o + &(bz * &index.o) + &oracles.gamma) * &oracles.alpha + - &(lagrange[0] * &alpsq) - ).into_repr(), - (ab * &oracles.beta).into_repr(), - ] - ).into_affine(); - - // prepare for the opening proof verification - batch.push - (( - oracles.zeta, - oracles.v, - vec! - [ - (t_comm, t, None), - (r_comm, proof.evals.f, None), - (proof.l_comm, proof.evals.l, None), - (proof.r_comm, proof.evals.r, None), - (proof.o_comm, proof.evals.o, None), - (index.sigma_comm[0], proof.evals.sigma1, None), - (index.sigma_comm[1], proof.evals.sigma2, None), - ], - proof.proof1 - )); - batch.push - (( - oracles.zeta * &index.domain.group_gen, - oracles.v, - vec![(proof.z_comm, proof.evals.z, None)], - proof.proof2 - )); - } - - // verify the opening proofs - match index.urs.verify(&batch, &mut OsRng) - { - false => Err(ProofError::OpenProof), - true => Ok(true) - } - } - - // This function queries random oracle values from non-interactive - // argument context by verifier - pub fn oracles - , - EFrSponge: FrSponge, - > - ( - &self, - index: &Index - ) -> Result, ProofError> - { - let mut oracles = RandomOracles::::zero(); - let mut fq_sponge = EFqSponge::new(index.fq_sponge_params.clone()); - - // absorb the public input, l, r, o polycommitments into the argument - fq_sponge.absorb_fr(&self.public); - fq_sponge.absorb_g(&[self.l_comm, self.r_comm, self.o_comm]); - // sample beta, gamma oracles - oracles.beta = fq_sponge.challenge(); - oracles.gamma = fq_sponge.challenge(); - - // absorb the z commitment into the argument and query alpha - fq_sponge.absorb_g(&[self.z_comm]); - oracles.alpha = fq_sponge.challenge(); - - // absorb the polycommitments into the argument and sample zeta - fq_sponge.absorb_g(&[self.tlow_comm, self.tmid_comm, self.thgh_comm]); - oracles.zeta = fq_sponge.challenge(); - // query opening scaler challenge - oracles.v = fq_sponge.challenge(); - - Ok(oracles) - } -} diff --git a/pairing/tests/batch.rs b/pairing/tests/batch.rs deleted file mode 100644 index 6f42313f55..0000000000 --- a/pairing/tests/batch.rs +++ /dev/null @@ -1,96 +0,0 @@ -/***************************************************************************************************************** - -This source file tests batch verificaion of batched polynomial commitment opening proofs - -*****************************************************************************************************************/ - -use commitment_pairing::urs::URS; -use algebra::{PairingEngine, bn_382::Bn_382, UniformRand}; -use std::time::{Instant, Duration}; -use ff_fft::DensePolynomial; -use rand_core::OsRng; -use colored::Colorize; -use rand::Rng; - -#[test] -fn batch_commitment_test() -{ - test::(); -} - -fn test() -{ - let rng = &mut OsRng; - let depth = 500; - - // generate sample URS - let urs = URS::::create - ( - depth, - vec![depth-1, depth-2, depth-3], - rng - ); - - let mut random = rand::thread_rng(); - - for i in 0..1 - { - println!("{}{:?}", "test # ".bright_cyan(), i); - - let mut proofs = Vec:: - <( - E::Fr, - E::Fr, - Vec<(E::G1Affine, E::Fr, Option<(E::G1Affine, usize)>)>, - E::G1Affine, - )>::new(); - - let mut commit = Duration::new(0, 0); - let mut open = Duration::new(0, 0); - - for _ in 0..7 - { - let size = (0..11).map - ( - |_| - { - let len: usize = random.gen(); - (len % (depth-2))+1 - } - ).collect::>(); - println!("{}{:?}", "sizes: ".bright_cyan(), size); - - let aa = size.iter().map(|s| DensePolynomial::::rand(s-1,rng)).collect::>(); - let a = aa.iter().map(|s| s).collect::>(); - let x = E::Fr::rand(rng); - - let mut start = Instant::now(); - let comm = a.iter().map(|a| urs.commit(&a.clone()).unwrap()).collect::>(); - commit += start.elapsed(); - - let mask = E::Fr::rand(rng); - start = Instant::now(); - let proof = urs.open(aa.iter().map(|s| s).collect::>(), mask, x).unwrap(); - open += start.elapsed(); - - proofs.push - (( - x, - mask, - (0..a.len()).map(|i| (comm[i], a[i].evaluate(x), None)).collect::>(), - proof, - )); - } - - println!("{}{:?}", "commitment time: ".yellow(), commit); - println!("{}{:?}", "open time: ".magenta(), open); - - let start = Instant::now(); - assert_eq!(urs.verify - ( - &proofs, - rng - ), true); - println!("{}{:?}", "verification time: ".green(), start.elapsed()); - } -} diff --git a/pairing/tests/marlin_group_addition.rs b/pairing/tests/marlin_group_addition.rs deleted file mode 100644 index 3fda027f7c..0000000000 --- a/pairing/tests/marlin_group_addition.rs +++ /dev/null @@ -1,262 +0,0 @@ -/********************************************************************************************************* - -This source file tests constraints for the Weierstrass curve y^2 = x^3 + 7 group addition -of non-special pairs of points - - (x2 - x1) * s = y2 - y1 - s * s = x1 + x2 + x3 - (x1 - x3) * s = y3 + y1 - - For the variable labeling - [1, x1, x2, x3, y1, y2, y3, s] - - the Index constraints are - - a=[[0,-1,1,0,0,0,0,0], [0,0,0,0,0,0,0,1], [0,1,0,-1,0,0,0,0]] - b=[[0,0,0, 0,0,0,0,1], [0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,1]] - c=[[0,0,0,0,-1,1,0,0], [0,1,1,1,0,0,0,0], [0,0,0,0,1,0,1,0]] - - The test verifies both positive and negative outcomes for satisfying and not satisfying witnesses - -**********************************************************************************************************/ - -use sprs::{CsMat, CsVecView}; -use oracle::{poseidon::{ArithmeticSpongeParams, MarlinSpongeConstants as SC}, sponge::{DefaultFqSponge, DefaultFrSponge}}; -use marlin_protocol_pairing::{prover::{ProverProof}, index::{Index, URSSpec}}; -use algebra::{bn_382::{Fp, Bn_382, g1::Bn_382G1Parameters}, One, Zero}; -use rand_core::{RngCore, OsRng}; -use std::{io, io::Write}; -use std::time::Instant; -use colored::Colorize; - -#[test] -fn pairing_marlin_group_addition() -{ - test(); -} - -fn test() -where ::Err : std::fmt::Debug -{ - let rng = &mut OsRng; - - // field unity element - let one = Fp::one(); - // field negative unit element - let neg1 = -one; - - // our circuit cinstraint system - - let mut a = CsMat::::zero((5, 8)); - let mut b = CsMat::::zero((5, 8)); - let mut c = CsMat::::zero((5, 8)); - - a = a - .append_outer_csvec(CsVecView::::new_view(8, &[1, 2], &[neg1, one]).unwrap()) - .append_outer_csvec(CsVecView::::new_view(8, &[7], &[one]).unwrap()) - .append_outer_csvec(CsVecView::::new_view(8, &[1, 3], &[one, neg1]).unwrap()); - - b = b - .append_outer_csvec(CsVecView::::new_view(8, &[7], &[one]).unwrap()) - .append_outer_csvec(CsVecView::::new_view(8, &[7], &[one]).unwrap()) - .append_outer_csvec(CsVecView::::new_view(8, &[7], &[one]).unwrap()); - - c = c - .append_outer_csvec(CsVecView::::new_view(8, &[4, 5], &[neg1, one]).unwrap()) - .append_outer_csvec(CsVecView::::new_view(8, &[1, 2, 3], &[one, one, one]).unwrap()) - .append_outer_csvec(CsVecView::::new_view(8, &[4, 6], &[one, one]).unwrap()); - - let index = Index::::create - ( - a, - b, - c, - 4, - oracle::bn_382::fp::params() as ArithmeticSpongeParams, - oracle::bn_382::fq::params(), - URSSpec::Generate(rng) - ).unwrap(); - - positive(&index, rng); - negative(&index); -} - -fn positive(index: &Index, rng: &mut dyn RngCore) -where ::Err : std::fmt::Debug -{ - // We have the Index. Choose examples of satisfying witness for Jubjub - let mut points = Vec::<(Fp, Fp, Fp, Fp, Fp, Fp)>::new(); - - points.push - (( - ::from_str("5172356774341916945486785014698808798139209652930291469942445827466617176873925086621674152688759641747407229992580").unwrap(), - ::from_str("5389835403017389419442092794364295847414750591777998334933723417842844526288891738232423481606681563583908752648585").unwrap(), - ::from_str("2546947049417344841111002212494667568252365848624282264487734777527422546757849528444366316986045677524512763495111").unwrap(), - ::from_str("1997638122333428225471467658615483900171126775340743769473169439761106892350780308959246670207945253590734533528364").unwrap(), - ::from_str("1674850877040352997414732903139735462343308610500259241884671999326597146560061364301738460545828640970450379452180").unwrap(), - ::from_str("3810650825927023273265535896307003193230881650215808774887308635589231174623309176102034870088533034962481600516076").unwrap(), - )); - points.push - (( - ::from_str("3879795264457994863044345731122127563968659155286939955243630259499486647511831537480701720885511597385884746982820").unwrap(), - ::from_str("4823171665573330555096743029931952635270457039608368692692935088741396345392788384518311296090867219414881059352340").unwrap(), - ::from_str("1692323036934184376735474571456321002006109633293195186678241855264713104686985522712202951967918089219148092028572").unwrap(), - ::from_str("2209464651087650164731996745113926648329961483466062736793777916964189183192011121604379002548567728567290657913223").unwrap(), - ::from_str("2348163941780191517995518495987651490622892886012727100525794693244638137192599324030217113440751606847920180713803").unwrap(), - ::from_str("4454706851138822876793194715545840379207531303175432600221231008853712012121251240963548916110604582992115955653270").unwrap(), - )); - points.push - (( - ::from_str("3400789538968233059173145658784600722588504237539048787023535803703264015099956088166134156568347966638071917915303").unwrap(), - ::from_str("621123523483818421378194114587761653395394010605097300573828630145594714262797932540228633935271287894833747678667").unwrap(), - ::from_str("1861078138229748651463580598306630340698695709298479313862504250753644022157264764048588857648999403515442211293648").unwrap(), - ::from_str("1402759138112536429766882866322191401455152786382634954470137274081091836807669830693235885007823455409845448532507").unwrap(), - ::from_str("2636112175785806489711342864806878604426303858096261709040701059465189456938740754404812820135345656228271794186839").unwrap(), - ::from_str("1256568754887691274941173078536147947138052455863623086244899444973367135605387356270847919765486881311208777164346").unwrap(), - )); - points.push - (( - ::from_str("2478567523807803044823498814493552676784005345112820479889159785702537553699213407926528335598560536333529678173515").unwrap(), - ::from_str("1429610824224105819022096794824833725671346669787509086262428112046017634195256096695085888088513480739414116355434").unwrap(), - ::from_str("3433825202284744924898740933255472924238475834098304603334531696173905093307025097179470211930412153594898991640392").unwrap(), - ::from_str("5529106429103107036773519209541737196328462244684980153333799250346789650918590566278885361943445666893827919992773").unwrap(), - ::from_str("5249333193239921862286692659605834037127141134737902165494537075455136421133863013829009853775102133434705561997135").unwrap(), - ::from_str("5211707708935794515800600299494960538336380325290025964615311319580355838061988483441778157486971788761832422047706").unwrap(), - )); - points.push - (( - ::from_str("147458112424376414621997978037198628281230983979066041123720454152322494857332053434681691878685856548608106856986").unwrap(), - ::from_str("632852117872999523570691722018024972892264322749710764059880290884632542786710748867063163428124193634651396659437").unwrap(), - ::from_str("5204093552607254614250701528632177968976746487946174226675406294342807100589579548450087150773804485277267337307130").unwrap(), - ::from_str("851406023642070633625219088663042661041353221500798086008906830050997727402745752304438325969120735726162271205108").unwrap(), - ::from_str("552295265751041791492069593853682243227582060223288941238331606487568169719678386470302944442375799241553902767182").unwrap(), - ::from_str("4336086719142104825567902974224061267890660930650361383496994062092647785535593948295151309544254618379516655470377").unwrap(), - )); - points.push - (( - ::from_str("3490207600741665366625509959868394397282525671450798904036007522509182472793447492084168928458090353484314376763227").unwrap(), - ::from_str("1380831856252180204898789305050851997442924411267225484611979722147678679544436926354771128773582198021483648567385").unwrap(), - ::from_str("2120354557629067932550134046677825128518143332393404083881997101503789120924159322303640623764593822268029585313376").unwrap(), - ::from_str("1092991618363041304858357775932541289572587223808071420756973545520423631209105063078084300055221872301002741920688").unwrap(), - ::from_str("1605290030348149658176172535833602819662245808434194279040860609205244165195983512100400484862256425647560767969440").unwrap(), - ::from_str("2386993496848148656322316757008809090731757879923470103791246538433262277529128310992656680922383766720368477625156").unwrap(), - )); - points.push - (( - ::from_str("1638374654853849195654124551691280460428083612823943462347619255956498862742720408888769748158996879556234032017620").unwrap(), - ::from_str("4696463046790812696644772536134730694383830429742760773846482828364760832740512122141679126896945492912370465987916").unwrap(), - ::from_str("3617243688932085408277715301069306617630380271027420929041113251867074342978965236280536563457836132453128954049534").unwrap(), - ::from_str("2710122816597306290503746828315039047582317305227168834547431135835634217761647011660061820624335511835127935174030").unwrap(), - ::from_str("921500447316892569376707206560342849122483342882261219690966701636629712782830468102915336061905457747788653057143").unwrap(), - ::from_str("5219418712123847153493507201307935981626191387915726486679485129683650510563888677270174906658570605360177547132711").unwrap(), - )); - points.push - (( - ::from_str("576144473696397097973782254663713612741693587507998585657939643441374119925443781099855821247569616352554627949614").unwrap(), - ::from_str("5352236591966276361890332086598227314030542240238478455688676970553337435889652186551973571009168613697178579611699").unwrap(), - ::from_str("2828754515664145684784985226357118541310611243025336022554902550604084587189082200943584927907046900755954787015229").unwrap(), - ::from_str("3161205806116323471708492597862587351781150204219415964573810028295284392216145624207550645494399092340022177165126").unwrap(), - ::from_str("3902930166191849795957267143655917594898902685051373575284018871959934672462836199412877161316375535512304818449138").unwrap(), - ::from_str("3439537491778852191662884877340565420556723254526595771226976438865274837523196848563824604575428228181375925112367").unwrap(), - )); - points.push - (( - ::from_str("3975857703851540404826772167355200868765839500201259530660426193330874994720636368264944650134867937994368133623424").unwrap(), - ::from_str("5404008797117176229768480661674266720465629504583055916114137135809171964682757270675407137380204829379800928806425").unwrap(), - ::from_str("5149775660547855706642619203137541130208039530617624930424186214694900226133029238205631813554575367645215651905718").unwrap(), - ::from_str("912560867533214342667610925727059581122160296223204528336760569329737606022773598716949469608418456841436717733650").unwrap(), - ::from_str("2361772560257806060391697637347795196697073007385082371009493637212597906287641517493257233187250924826177550515147").unwrap(), - ::from_str("1304527989810536849922023821350001495184930094181695710090607394133562298758385201023205221350985367173004379252620").unwrap(), - )); - points.push - (( - ::from_str("5502226838017077786426654731704772400845471875650491266565363420906771040750427824367287841412217114884691397809929").unwrap(), - ::from_str("3558210182254086348603204259628694223851158529696790509955564950434596266578621349330875065217679787287369448875015").unwrap(), - ::from_str("1321172652000590462919749014481227416957437277585347677751917393570871798430478578222556789479124360282597488862528").unwrap(), - ::from_str("1817964682602513729710432198132831699408829439216417056703680523866007606577303266376792163132424248003554474817101").unwrap(), - ::from_str("3116498715141724683149051461624569979663973751357290170267796754661152457577855966867446609811524433931603777277670").unwrap(), - ::from_str("2773782014032351532784325670003998192667953688555790212612755975320369406749808761658203420299756946851710956379722").unwrap(), - )); - - println!("{}", "Prover 1000 zk-proofs computation".green()); - let mut start = Instant::now(); - - let tests = 0..1000; - let mut batch = Vec::new(); - for test in tests.clone() - { - let (x1, y1, x2, y2, x3, y3) = points[test % 10]; - let s = (y2 - &y1) / &(x2 - &x1); - - let mut witness = vec![Fp::zero(); 8]; - witness[0] = Fp::one(); - witness[1] = x1; - witness[2] = x2; - witness[3] = x3; - witness[4] = y1; - witness[5] = y2; - witness[6] = y3; - witness[7] = s; - - // verify the circuit satisfiability by the computed witness - assert_eq!(index.verify(&witness), true); - - // add the proof to the batch - batch.push(ProverProof::create::, DefaultFrSponge>(&witness, &index).unwrap()); - - print!("{:?}\r", test); - io::stdout().flush().unwrap(); - } - println!("{}{:?}", "Execution time: ".yellow(), start.elapsed()); - - let verifier_index = index.verifier_index(); - // verify one proof serially - match ProverProof::verify::, DefaultFrSponge>(&vec![batch[0].clone()], &verifier_index, rng) - { - Ok(_) => {} - _ => {panic!("Failure verifying the prover's proof")} - } - - // verify the proofs in batch - println!("{}", "Verifier zk-proofs verification".green()); - start = Instant::now(); - match ProverProof::verify::, DefaultFrSponge>(&batch, &verifier_index, rng) - { - Err(error) => {panic!("Failure verifying the prover's proofs in batch: {}", error)}, - Ok(_) => {println!("{}{:?}", "Execution time: ".yellow(), start.elapsed());} - } -} - -fn negative(index: &Index) -where ::Err : std::fmt::Debug -{ - // build non-satisfying witness - let x1 = ::from_str("7502226838017077786426654731704772400845471875650491266565363420906771040750427824367287841412217114884691397809929").unwrap(); - let y1 = ::from_str("3558210182254086348603204259628694223851158529696790509955564950434596266578621349330875065217679787287369448875015").unwrap(); - let x2 = ::from_str("1321172652000590462919749014481227416957437277585347677751917393570871798430478578222556789479124360282597488862528").unwrap(); - let y2 = ::from_str("1817964682602513729710432198132831699408829439216417056703680523866007606577303266376792163132424248003554474817101").unwrap(); - let x3 = ::from_str("3116498715141724683149051461624569979663973751357290170267796754661152457577855966867446609811524433931603777277670").unwrap(); - let y3 = ::from_str("2773782014032351532784325670003998192667953688555790212612755975320369406749808761658203420299756946851710956379722").unwrap(); - - let s = (y2 - &y1) / &(x2 - &x1); - - let mut witness = vec![Fp::zero(); 8]; - witness[0] = Fp::one(); - witness[1] = x1; - witness[2] = x2; - witness[3] = x3; - witness[4] = y1; - witness[5] = y2; - witness[6] = y3; - witness[7] = s; - - // verify the circuit negative satisfiability by the computed witness - assert_eq!(index.verify(&witness), false); - - // create proof - match ProverProof::create::, DefaultFrSponge>(&witness, &index) - { - Ok(_) => {panic!("Failure invalidating the witness")} - _ => {} - } -} diff --git a/pairing/tests/urs.rs b/pairing/tests/urs.rs deleted file mode 100644 index 887c8fcd3c..0000000000 --- a/pairing/tests/urs.rs +++ /dev/null @@ -1,61 +0,0 @@ -/***************************************************************************************************************** - -This source file, for now, implements URS unit test suite driver. The following tests are implemented: - -1. urs_test - This unit test generates a Universal Reference String, computes its update and - proceeds to the verification of URS update consistency against its zk-proof with - the batched bilinear pairing map checks. - -*****************************************************************************************************************/ - -use algebra::{PairingEngine, bn_382::Bn_382}; -use commitment_pairing::urs::URS; -use colored::Colorize; -use std::time::{Instant}; -use rand_core::OsRng; - -// The following test verifies the consistency of the -// URS generation with the pairings of the URS exponents -#[test] -fn urs_test() -{ - test::(); -} - -fn test() -{ - let depth = 30; - let iterations = 1; - let mut rng = &mut OsRng; - - // generate sample URS string for circuit depth of up to 'depth' - println!("{}", "Generating the initial URS".green()); - let mut start = Instant::now(); - let mut urs = URS::::create - ( - depth, - vec![3,7], - &mut rng - ); - println!("{}{:?}", "Execution time: ".yellow(), start.elapsed()); - - for i in 0..iterations - { - println!("{}{:?}", "Iteration: ", i); - println!("{}", "Computing the update of the URS".green()); - - // save necessary URS elements to verify next update - let hx = urs.hx; - - start = Instant::now(); - // update sample URS string for circuit depth of up to 'depth' - urs.update(&mut rng); - println!("{}{:?}", "Execution time: ".yellow(), start.elapsed()); - - println!("{}", "Verifying the update against its zk-proof".green()); - start = Instant::now(); - assert_eq!(urs.check(hx, &mut rng), true); - println!("{}{:?}", "Execution time: ".yellow(), start.elapsed()); - } -}