From c97da352ee1350ae42b0f8789eb177832f3b6cd2 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 29 Sep 2020 08:25:04 -0600 Subject: [PATCH] Remove SRS and replace with ProvingKey/VerifyingKey abstractions Co-authored-by: therealyingtong --- src/plonk.rs | 51 ++++++--- src/plonk/keygen.rs | 259 ++++++++++++++++++++++++++++++++++++++++++ src/plonk/prover.rs | 37 +++--- src/plonk/srs.rs | 257 ----------------------------------------- src/plonk/verifier.rs | 46 ++++---- 5 files changed, 337 insertions(+), 313 deletions(-) create mode 100644 src/plonk/keygen.rs delete mode 100644 src/plonk/srs.rs diff --git a/src/plonk.rs b/src/plonk.rs index 86be0de..fc89cc6 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -12,30 +12,37 @@ use crate::poly::{ use crate::transcript::Hasher; mod circuit; +mod keygen; mod prover; -mod srs; mod verifier; pub use circuit::*; +pub use keygen::*; pub use prover::*; -pub use srs::*; pub use verifier::*; -/// This is a structured reference string (SRS) that is (deterministically) -/// computed from a specific circuit and parameters for the polynomial -/// commitment scheme. +/// This is a verifying key which allows for the verification of proofs for a +/// particular circuit. #[derive(Debug)] -pub struct SRS { +pub struct VerifyingKey { domain: EvaluationDomain, - l0: Polynomial, fixed_commitments: Vec, + permutation_commitments: Vec>, + cs: ConstraintSystem, +} + +/// This is a proving key which allows for the creation of proofs for a +/// particular circuit. +#[derive(Debug)] +pub struct ProvingKey { + vk: VerifyingKey, + // TODO: get rid of this? + l0: Polynomial, fixed_polys: Vec>, fixed_cosets: Vec>, - permutation_commitments: Vec>, permutations: Vec>>, permutation_polys: Vec>>, permutation_cosets: Vec>>, - cs: ConstraintSystem, } /// This is an object which represents a (Turbo)PLONK proof. @@ -75,6 +82,20 @@ pub enum Error { OpeningError, } +impl ProvingKey { + /// Get the underlying `VerifyingKey` + pub fn get_vk(&self) -> &VerifyingKey { + &self.vk + } +} + +impl VerifyingKey { + /// Get the underlying `VerifyingKey` + pub fn get_domain(&self) -> &EvaluationDomain { + &self.domain + } +} + fn hash_point>( transcript: &mut H, point: &C, @@ -368,10 +389,10 @@ fn test_proving() { let empty_circuit: MyCircuit = MyCircuit { a: None }; - // Initialize the SRS - let srs = SRS::generate(¶ms, &empty_circuit).expect("SRS generation should not fail"); + // Initialize the proving key + let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail"); - let mut pubinputs = srs.domain.empty_lagrange(); + let mut pubinputs = pk.get_vk().get_domain().empty_lagrange(); pubinputs[0] = Fp::one(); pubinputs[0] += Fp::one(); let pubinput = params @@ -382,7 +403,7 @@ fn test_proving() { // Create a proof let proof = Proof::create::, DummyHash, _>( ¶ms, - &srs, + &pk, &circuit, &[pubinputs.clone()], ) @@ -390,7 +411,7 @@ fn test_proving() { let msm = params.empty_msm(); let guard = proof - .verify::, DummyHash>(¶ms, &srs, msm, &[pubinput]) + .verify::, DummyHash>(¶ms, pk.get_vk(), msm, &[pubinput]) .unwrap(); { let msm = guard.clone().use_challenges(); @@ -404,7 +425,7 @@ fn test_proving() { let msm = guard.clone().use_challenges(); assert!(msm.clone().eval()); let guard = proof - .verify::, DummyHash>(¶ms, &srs, msm, &[pubinput]) + .verify::, DummyHash>(¶ms, pk.get_vk(), msm, &[pubinput]) .unwrap(); { let msm = guard.clone().use_challenges(); diff --git a/src/plonk/keygen.rs b/src/plonk/keygen.rs new file mode 100644 index 0000000..d776920 --- /dev/null +++ b/src/plonk/keygen.rs @@ -0,0 +1,259 @@ +use super::{ + circuit::{AdviceWire, Assignment, Circuit, ConstraintSystem, FixedWire}, + Error, ProvingKey, VerifyingKey, +}; +use crate::arithmetic::{Curve, CurveAffine, Field}; +use crate::poly::{ + commitment::{Blind, Params}, + EvaluationDomain, LagrangeCoeff, Polynomial, Rotation, +}; + +/// Generate a `ProvingKey` from an instance of `Circuit`. +pub fn keygen( + params: &Params, + circuit: &ConcreteCircuit, +) -> Result, Error> +where + C: CurveAffine, + ConcreteCircuit: Circuit, +{ + struct Assembly { + fixed: Vec>, + mapping: Vec>>, + aux: Vec>>, + sizes: Vec>>, + _marker: std::marker::PhantomData, + } + + impl Assignment for Assembly { + fn assign_advice( + &mut self, + _: AdviceWire, + _: usize, + _: impl FnOnce() -> Result, + ) -> Result<(), Error> { + // We only care about fixed wires here + Ok(()) + } + + fn assign_fixed( + &mut self, + wire: FixedWire, + row: usize, + to: impl FnOnce() -> Result, + ) -> Result<(), Error> { + *self + .fixed + .get_mut(wire.0) + .and_then(|v| v.get_mut(row)) + .ok_or(Error::BoundsFailure)? = to()?; + + Ok(()) + } + + fn copy( + &mut self, + permutation: usize, + left_wire: usize, + left_row: usize, + right_wire: usize, + right_row: usize, + ) -> Result<(), Error> { + // Check bounds first + if permutation >= self.mapping.len() + || left_wire >= self.mapping[permutation].len() + || left_row >= self.mapping[permutation][left_wire].len() + || right_wire >= self.mapping[permutation].len() + || right_row >= self.mapping[permutation][right_wire].len() + { + return Err(Error::BoundsFailure); + } + + let mut left_cycle = self.aux[permutation][left_wire][left_row]; + let mut right_cycle = self.aux[permutation][right_wire][right_row]; + + if left_cycle == right_cycle { + return Ok(()); + } + + if self.sizes[permutation][left_cycle.0][left_cycle.1] + < self.sizes[permutation][right_cycle.0][right_cycle.1] + { + std::mem::swap(&mut left_cycle, &mut right_cycle); + } + + self.sizes[permutation][left_cycle.0][left_cycle.1] += + self.sizes[permutation][right_cycle.0][right_cycle.1]; + let mut i = right_cycle; + loop { + self.aux[permutation][i.0][i.1] = left_cycle; + i = self.mapping[permutation][i.0][i.1]; + if i == right_cycle { + break; + } + } + + let tmp = self.mapping[permutation][left_wire][left_row]; + self.mapping[permutation][left_wire][left_row] = + self.mapping[permutation][right_wire][right_row]; + self.mapping[permutation][right_wire][right_row] = tmp; + + Ok(()) + } + } + + let mut cs = ConstraintSystem::default(); + let config = ConcreteCircuit::configure(&mut cs); + + // Get the largest permutation argument length in terms of the number of + // advice wires involved. + let mut largest_permutation_length = 0; + for permutation in &cs.permutations { + largest_permutation_length = std::cmp::max(permutation.len(), largest_permutation_length); + } + + // The permutation argument will serve alongside the gates, so must be + // accounted for. + let mut degree = largest_permutation_length + 1; + + // Account for each gate to ensure our quotient polynomial is the + // correct degree and that our extended domain is the right size. + for poly in cs.gates.iter() { + degree = std::cmp::max(degree, poly.degree()); + } + + let domain = EvaluationDomain::new(degree as u32, params.k); + + // Compute [omega^0, omega^1, ..., omega^{params.n - 1}] + let mut omega_powers = Vec::with_capacity(params.n as usize); + { + let mut cur = C::Scalar::one(); + for _ in 0..params.n { + omega_powers.push(cur); + cur *= &domain.get_omega(); + } + } + + // Compute [omega_powers * \delta^0, omega_powers * \delta^1, ..., omega_powers * \delta^m] + let mut deltaomega = Vec::with_capacity(largest_permutation_length); + { + let mut cur = C::Scalar::one(); + for _ in 0..largest_permutation_length { + let mut omega_powers = omega_powers.clone(); + for o in &mut omega_powers { + *o *= &cur; + } + + deltaomega.push(omega_powers); + + cur *= &C::Scalar::DELTA; + } + } + + let mut assembly: Assembly = Assembly { + fixed: vec![domain.empty_lagrange(); cs.num_fixed_wires], + mapping: vec![], + aux: vec![], + sizes: vec![], + _marker: std::marker::PhantomData, + }; + + // Initialize the copy vector to keep track of copy constraints in all + // the permutation arguments. + for permutation in &cs.permutations { + let mut wires = vec![]; + for i in 0..permutation.len() { + // Computes [(i, 0), (i, 1), ..., (i, n - 1)] + wires.push((0..params.n).map(|j| (i, j as usize)).collect()); + } + assembly.mapping.push(wires.clone()); + assembly.aux.push(wires); + assembly + .sizes + .push(vec![vec![1usize; params.n as usize]; permutation.len()]); + } + + // Synthesize the circuit to obtain SRS + circuit.synthesize(&mut assembly, config)?; + + // Compute permutation polynomials, convert to coset form and + // pre-compute commitments for the SRS. + let mut permutation_commitments = vec![]; + let mut permutations = vec![]; + let mut permutation_polys = vec![]; + let mut permutation_cosets = vec![]; + for (permutation_index, permutation) in cs.permutations.iter().enumerate() { + let mut commitments = vec![]; + let mut inner_permutations = vec![]; + let mut polys = vec![]; + let mut cosets = vec![]; + for i in 0..permutation.len() { + // Computes the permutation polynomial based on the permutation + // description in the assembly. + let mut permutation_poly = domain.empty_lagrange(); + for (j, p) in permutation_poly.iter_mut().enumerate() { + let (permuted_i, permuted_j) = assembly.mapping[permutation_index][i][j]; + *p = deltaomega[permuted_i][permuted_j]; + } + + // Compute commitment to permutation polynomial + commitments.push( + params + .commit_lagrange(&permutation_poly, Blind::default()) + .to_affine(), + ); + // Store permutation polynomial and precompute its coset evaluation + inner_permutations.push(permutation_poly.clone()); + let poly = domain.lagrange_to_coeff(permutation_poly); + polys.push(poly.clone()); + cosets.push(domain.coeff_to_extended(poly, Rotation::default())); + } + permutation_commitments.push(commitments); + permutations.push(inner_permutations); + permutation_polys.push(polys); + permutation_cosets.push(cosets); + } + + let fixed_commitments = assembly + .fixed + .iter() + .map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine()) + .collect(); + + let fixed_polys: Vec<_> = assembly + .fixed + .into_iter() + .map(|poly| domain.lagrange_to_coeff(poly)) + .collect(); + + let fixed_cosets = cs + .fixed_queries + .iter() + .map(|&(wire, at)| { + let poly = fixed_polys[wire.0].clone(); + domain.coeff_to_extended(poly, at) + }) + .collect(); + + // Compute l_0(X) + // TODO: this can be done more efficiently + let mut l0 = domain.empty_lagrange(); + l0[0] = C::Scalar::one(); + let l0 = domain.lagrange_to_coeff(l0); + let l0 = domain.coeff_to_extended(l0, Rotation::default()); + + Ok(ProvingKey { + vk: VerifyingKey { + domain, + fixed_commitments, + permutation_commitments, + cs, + }, + l0, + fixed_polys, + fixed_cosets, + permutations, + permutation_polys, + permutation_cosets, + }) +} diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index f036b95..215094c 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -1,6 +1,6 @@ use super::{ circuit::{AdviceWire, Assignment, Circuit, ConstraintSystem, FixedWire}, - hash_point, Error, Proof, SRS, + hash_point, Error, Proof, ProvingKey, }; use crate::arithmetic::{ eval_polynomial, get_challenge_scalar, kate_division, parallelize, BatchInvert, Challenge, @@ -14,19 +14,19 @@ use crate::transcript::Hasher; impl Proof { /// This creates a proof for the provided `circuit` when given the public - /// parameters `params` and the structured reference string `srs` that was - /// previously computed for the same circuit. + /// parameters `params` and the proving key [`ProvingKey`] that was + /// generated previously for the same circuit. pub fn create< HBase: Hasher, HScalar: Hasher, ConcreteCircuit: Circuit, >( params: &Params, - srs: &SRS, + pk: &ProvingKey, circuit: &ConcreteCircuit, aux: &[Polynomial], ) -> Result { - if aux.len() != srs.cs.num_aux_wires { + if aux.len() != pk.vk.cs.num_aux_wires { return Err(Error::IncompatibleParams); } @@ -76,7 +76,7 @@ impl Proof { } } - let domain = &srs.domain; + let domain = &pk.vk.domain; let mut meta = ConstraintSystem::default(); let config = ConcreteCircuit::configure(&mut meta); @@ -176,7 +176,7 @@ impl Proof { // Iterate over each permutation let mut permutation_modified_advice = vec![]; - for (wires, permuted_values) in srs.cs.permutations.iter().zip(srs.permutations.iter()) { + for (wires, permuted_values) in pk.vk.cs.permutations.iter().zip(pk.permutations.iter()) { // Goal is to compute the products of fractions // // (p_j(\omega^i) + \delta^j \omega^i \beta + \gamma) / @@ -209,7 +209,8 @@ impl Proof { .flat_map(|v| v.iter_mut()) .batch_invert(); - for (wires, mut modified_advice) in srs + for (wires, mut modified_advice) in pk + .vk .cs .permutations .iter() @@ -287,7 +288,7 @@ impl Proof { h_poly = h_poly * x_2; let evaluation = poly.evaluate( - &|index| srs.fixed_cosets[index].clone(), + &|index| pk.fixed_cosets[index].clone(), &|index| advice_cosets[index].clone(), &|index| aux_cosets[index].clone(), &|a, b| a + &b, @@ -304,7 +305,7 @@ impl Proof { for ((h, c), l0) in h .iter_mut() .zip(coset[start..].iter()) - .zip(srs.l0[start..].iter()) + .zip(pk.l0[start..].iter()) { *h *= &x_2; *h += &(*l0 * &(C::Scalar::one() - c)); @@ -313,14 +314,14 @@ impl Proof { } // z(X) \prod (p(X) + \beta s_i(X) + \gamma) - z(omega^{-1} X) \prod (p(X) + \delta^i \beta X + \gamma) - for (permutation_index, wires) in srs.cs.permutations.iter().enumerate() { + for (permutation_index, wires) in pk.vk.cs.permutations.iter().enumerate() { h_poly = h_poly * x_2; let mut left = permutation_product_cosets[permutation_index].clone(); for (advice, permutation) in wires .iter() .map(|&(_, index)| &advice_cosets[index]) - .zip(srs.permutation_cosets[permutation_index].iter()) + .zip(pk.permutation_cosets[permutation_index].iter()) { parallelize(&mut left, |left, start| { for ((left, advice), permutation) in left @@ -402,7 +403,7 @@ impl Proof { .fixed_queries .iter() .map(|&(wire, at)| { - eval_polynomial(&srs.fixed_polys[wire.0], domain.rotate_omega(x_3, at)) + eval_polynomial(&pk.fixed_polys[wire.0], domain.rotate_omega(x_3, at)) }) .collect(); @@ -416,7 +417,7 @@ impl Proof { .map(|poly| eval_polynomial(poly, domain.rotate_omega(x_3, Rotation(-1)))) .collect(); - let permutation_evals: Vec> = srs + let permutation_evals: Vec> = pk .permutation_polys .iter() .map(|polys| { @@ -511,7 +512,7 @@ impl Proof { accumulate( point_index, - &srs.fixed_polys[wire.0], + &pk.fixed_polys[wire.0], Blind::default(), fixed_evals[query_index], ); @@ -528,7 +529,7 @@ impl Proof { } // Handle permutation arguments, if any exist - if !srs.cs.permutations.is_empty() { + if !pk.vk.cs.permutations.is_empty() { // Open permutation product commitments at x_3 for ((poly, blind), eval) in permutation_product_polys .iter() @@ -539,7 +540,7 @@ impl Proof { } // Open permutation polynomial commitments at x_3 - for (poly, eval) in srs + for (poly, eval) in pk .permutation_polys .iter() .zip(permutation_evals.iter()) @@ -548,7 +549,7 @@ impl Proof { accumulate(current_index, poly, Blind::default(), *eval); } - let current_index = (*srs.cs.rotations.get(&Rotation(-1)).unwrap()).0; + let current_index = (*pk.vk.cs.rotations.get(&Rotation(-1)).unwrap()).0; // Open permutation product commitments at \omega^{-1} x_3 for ((poly, blind), eval) in permutation_product_polys .iter() diff --git a/src/plonk/srs.rs b/src/plonk/srs.rs deleted file mode 100644 index 14a7be3..0000000 --- a/src/plonk/srs.rs +++ /dev/null @@ -1,257 +0,0 @@ -use super::{ - circuit::{AdviceWire, Assignment, Circuit, ConstraintSystem, FixedWire}, - Error, SRS, -}; -use crate::arithmetic::{Curve, CurveAffine, Field}; -use crate::poly::{ - commitment::{Blind, Params}, - EvaluationDomain, LagrangeCoeff, Polynomial, Rotation, -}; - -impl SRS { - /// This generates a structured reference string for the provided `circuit` - /// and `params`. - pub fn generate>( - params: &Params, - circuit: &ConcreteCircuit, - ) -> Result { - struct Assembly { - fixed: Vec>, - mapping: Vec>>, - aux: Vec>>, - sizes: Vec>>, - _marker: std::marker::PhantomData, - } - - impl Assignment for Assembly { - fn assign_advice( - &mut self, - _: AdviceWire, - _: usize, - _: impl FnOnce() -> Result, - ) -> Result<(), Error> { - // We only care about fixed wires here - Ok(()) - } - - fn assign_fixed( - &mut self, - wire: FixedWire, - row: usize, - to: impl FnOnce() -> Result, - ) -> Result<(), Error> { - *self - .fixed - .get_mut(wire.0) - .and_then(|v| v.get_mut(row)) - .ok_or(Error::BoundsFailure)? = to()?; - - Ok(()) - } - - fn copy( - &mut self, - permutation: usize, - left_wire: usize, - left_row: usize, - right_wire: usize, - right_row: usize, - ) -> Result<(), Error> { - // Check bounds first - if permutation >= self.mapping.len() - || left_wire >= self.mapping[permutation].len() - || left_row >= self.mapping[permutation][left_wire].len() - || right_wire >= self.mapping[permutation].len() - || right_row >= self.mapping[permutation][right_wire].len() - { - return Err(Error::BoundsFailure); - } - - let mut left_cycle = self.aux[permutation][left_wire][left_row]; - let mut right_cycle = self.aux[permutation][right_wire][right_row]; - - if left_cycle == right_cycle { - return Ok(()); - } - - if self.sizes[permutation][left_cycle.0][left_cycle.1] - < self.sizes[permutation][right_cycle.0][right_cycle.1] - { - std::mem::swap(&mut left_cycle, &mut right_cycle); - } - - self.sizes[permutation][left_cycle.0][left_cycle.1] += - self.sizes[permutation][right_cycle.0][right_cycle.1]; - let mut i = right_cycle; - loop { - self.aux[permutation][i.0][i.1] = left_cycle; - i = self.mapping[permutation][i.0][i.1]; - if i == right_cycle { - break; - } - } - - let tmp = self.mapping[permutation][left_wire][left_row]; - self.mapping[permutation][left_wire][left_row] = - self.mapping[permutation][right_wire][right_row]; - self.mapping[permutation][right_wire][right_row] = tmp; - - Ok(()) - } - } - - let mut cs = ConstraintSystem::default(); - let config = ConcreteCircuit::configure(&mut cs); - - // Get the largest permutation argument length in terms of the number of - // advice wires involved. - let mut largest_permutation_length = 0; - for permutation in &cs.permutations { - largest_permutation_length = - std::cmp::max(permutation.len(), largest_permutation_length); - } - - // The permutation argument will serve alongside the gates, so must be - // accounted for. - let mut degree = largest_permutation_length + 1; - - // Account for each gate to ensure our quotient polynomial is the - // correct degree and that our extended domain is the right size. - for poly in cs.gates.iter() { - degree = std::cmp::max(degree, poly.degree()); - } - - let domain = EvaluationDomain::new(degree as u32, params.k); - - // Compute [omega^0, omega^1, ..., omega^{params.n - 1}] - let mut omega_powers = Vec::with_capacity(params.n as usize); - { - let mut cur = C::Scalar::one(); - for _ in 0..params.n { - omega_powers.push(cur); - cur *= &domain.get_omega(); - } - } - - // Compute [omega_powers * \delta^0, omega_powers * \delta^1, ..., omega_powers * \delta^m] - let mut deltaomega = Vec::with_capacity(largest_permutation_length); - { - let mut cur = C::Scalar::one(); - for _ in 0..largest_permutation_length { - let mut omega_powers = omega_powers.clone(); - for o in &mut omega_powers { - *o *= &cur; - } - - deltaomega.push(omega_powers); - - cur *= &C::Scalar::DELTA; - } - } - - let mut assembly: Assembly = Assembly { - fixed: vec![domain.empty_lagrange(); cs.num_fixed_wires], - mapping: vec![], - aux: vec![], - sizes: vec![], - _marker: std::marker::PhantomData, - }; - - // Initialize the copy vector to keep track of copy constraints in all - // the permutation arguments. - for permutation in &cs.permutations { - let mut wires = vec![]; - for i in 0..permutation.len() { - // Computes [(i, 0), (i, 1), ..., (i, n - 1)] - wires.push((0..params.n).map(|j| (i, j as usize)).collect()); - } - assembly.mapping.push(wires.clone()); - assembly.aux.push(wires); - assembly - .sizes - .push(vec![vec![1usize; params.n as usize]; permutation.len()]); - } - - // Synthesize the circuit to obtain SRS - circuit.synthesize(&mut assembly, config)?; - - // Compute permutation polynomials, convert to coset form and - // pre-compute commitments for the SRS. - let mut permutation_commitments = vec![]; - let mut permutations = vec![]; - let mut permutation_polys = vec![]; - let mut permutation_cosets = vec![]; - for (permutation_index, permutation) in cs.permutations.iter().enumerate() { - let mut commitments = vec![]; - let mut inner_permutations = vec![]; - let mut polys = vec![]; - let mut cosets = vec![]; - for i in 0..permutation.len() { - // Computes the permutation polynomial based on the permutation - // description in the assembly. - let mut permutation_poly = domain.empty_lagrange(); - for (j, p) in permutation_poly.iter_mut().enumerate() { - let (permuted_i, permuted_j) = assembly.mapping[permutation_index][i][j]; - *p = deltaomega[permuted_i][permuted_j]; - } - - // Compute commitment to permutation polynomial - commitments.push( - params - .commit_lagrange(&permutation_poly, Blind::default()) - .to_affine(), - ); - // Store permutation polynomial and precompute its coset evaluation - inner_permutations.push(permutation_poly.clone()); - let poly = domain.lagrange_to_coeff(permutation_poly); - polys.push(poly.clone()); - cosets.push(domain.coeff_to_extended(poly, Rotation::default())); - } - permutation_commitments.push(commitments); - permutations.push(inner_permutations); - permutation_polys.push(polys); - permutation_cosets.push(cosets); - } - - let fixed_commitments = assembly - .fixed - .iter() - .map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine()) - .collect(); - - let fixed_polys: Vec<_> = assembly - .fixed - .into_iter() - .map(|poly| domain.lagrange_to_coeff(poly)) - .collect(); - - let fixed_cosets = cs - .fixed_queries - .iter() - .map(|&(wire, at)| { - let poly = fixed_polys[wire.0].clone(); - domain.coeff_to_extended(poly, at) - }) - .collect(); - - // Compute l_0(X) - // TODO: this can be done more efficiently - let mut l0 = domain.empty_lagrange(); - l0[0] = C::Scalar::one(); - let l0 = domain.lagrange_to_coeff(l0); - let l0 = domain.coeff_to_extended(l0, Rotation::default()); - - Ok(SRS { - domain, - l0, - fixed_commitments, - fixed_polys, - fixed_cosets, - permutation_commitments, - permutations, - permutation_polys, - permutation_cosets, - cs, - }) - } -} diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index 0200e93..642a00b 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -1,4 +1,4 @@ -use super::{hash_point, Error, Proof, SRS}; +use super::{hash_point, Error, Proof, VerifyingKey}; use crate::arithmetic::{get_challenge_scalar, Challenge, CurveAffine, Field}; use crate::poly::{ commitment::{Guard, Params, MSM}, @@ -11,14 +11,14 @@ impl<'a, C: CurveAffine> Proof { pub fn verify, HScalar: Hasher>( &self, params: &'a Params, - srs: &SRS, + vk: &VerifyingKey, mut msm: MSM<'a, C>, aux_commitments: &[C], ) -> Result, Error> { // Check that aux_commitments matches the expected number of aux_wires // and self.aux_evals - if aux_commitments.len() != srs.cs.num_aux_wires - || self.aux_evals.len() != srs.cs.num_aux_wires + if aux_commitments.len() != vk.cs.num_aux_wires + || self.aux_evals.len() != vk.cs.num_aux_wires { return Err(Error::IncompatibleParams); } @@ -88,7 +88,7 @@ impl<'a, C: CurveAffine> Proof { // Evaluate the circuit using the custom gates provided let mut h_eval = C::Scalar::zero(); - for poly in srs.cs.gates.iter() { + for poly in vk.cs.gates.iter() { h_eval *= &x_2; let evaluation: C::Scalar = poly.evaluate( @@ -114,7 +114,7 @@ impl<'a, C: CurveAffine> Proof { let mut tmp = denominator; // 1 / (x_3 - 1) tmp *= &(x_3n - &C::Scalar::one()); // (x_3^n - 1) / (x_3 - 1) - tmp *= &srs.domain.get_barycentric_weight(); // l_0(x_3) + tmp *= &vk.domain.get_barycentric_weight(); // l_0(x_3) tmp *= &(C::Scalar::one() - &eval); // l_0(X) * (1 - z(X)) h_eval += &tmp; @@ -122,7 +122,7 @@ impl<'a, C: CurveAffine> Proof { } // z(X) \prod (p(X) + \beta s_i(X) + \gamma) - z(omega^{-1} X) \prod (p(X) + \delta^i \beta X + \gamma) - for (permutation_index, wires) in srs.cs.permutations.iter().enumerate() { + for (permutation_index, wires) in vk.cs.permutations.iter().enumerate() { h_eval *= &x_2; let mut left = self.permutation_product_evals[permutation_index]; @@ -168,8 +168,8 @@ impl<'a, C: CurveAffine> Proof { // Compress the commitments and expected evaluations at x_3 together // using the challenge x_4 - let mut q_commitments: Vec<_> = vec![params.empty_msm(); srs.cs.rotations.len()]; - let mut q_evals: Vec<_> = vec![C::Scalar::zero(); srs.cs.rotations.len()]; + let mut q_commitments: Vec<_> = vec![params.empty_msm(); vk.cs.rotations.len()]; + let mut q_evals: Vec<_> = vec![C::Scalar::zero(); vk.cs.rotations.len()]; { let mut accumulate = |point_index: usize, new_commitment, eval| { q_commitments[point_index].scale(x_4); @@ -178,8 +178,8 @@ impl<'a, C: CurveAffine> Proof { q_evals[point_index] += &eval; }; - for (query_index, &(wire, ref at)) in srs.cs.advice_queries.iter().enumerate() { - let point_index = (*srs.cs.rotations.get(at).unwrap()).0; + for (query_index, &(wire, ref at)) in vk.cs.advice_queries.iter().enumerate() { + let point_index = (*vk.cs.rotations.get(at).unwrap()).0; accumulate( point_index, self.advice_commitments[wire.0], @@ -187,8 +187,8 @@ impl<'a, C: CurveAffine> Proof { ); } - for (query_index, &(wire, ref at)) in srs.cs.aux_queries.iter().enumerate() { - let point_index = (*srs.cs.rotations.get(at).unwrap()).0; + for (query_index, &(wire, ref at)) in vk.cs.aux_queries.iter().enumerate() { + let point_index = (*vk.cs.rotations.get(at).unwrap()).0; accumulate( point_index, aux_commitments[wire.0], @@ -196,22 +196,22 @@ impl<'a, C: CurveAffine> Proof { ); } - for (query_index, &(wire, ref at)) in srs.cs.fixed_queries.iter().enumerate() { - let point_index = (*srs.cs.rotations.get(at).unwrap()).0; + for (query_index, &(wire, ref at)) in vk.cs.fixed_queries.iter().enumerate() { + let point_index = (*vk.cs.rotations.get(at).unwrap()).0; accumulate( point_index, - srs.fixed_commitments[wire.0], + vk.fixed_commitments[wire.0], self.fixed_evals[query_index], ); } - let current_index = (*srs.cs.rotations.get(&Rotation::default()).unwrap()).0; + let current_index = (*vk.cs.rotations.get(&Rotation::default()).unwrap()).0; for (commitment, eval) in self.h_commitments.iter().zip(self.h_evals.iter()) { accumulate(current_index, *commitment, *eval); } // Handle permutation arguments, if any exist - if !srs.cs.permutations.is_empty() { + if !vk.cs.permutations.is_empty() { // Open permutation product commitments at x_3 for (commitment, eval) in self .permutation_product_commitments @@ -221,7 +221,7 @@ impl<'a, C: CurveAffine> Proof { accumulate(current_index, *commitment, *eval); } // Open permutation commitments for each permutation argument at x_3 - for (commitment, eval) in srs + for (commitment, eval) in vk .permutation_commitments .iter() .zip(self.permutation_evals.iter()) @@ -229,7 +229,7 @@ impl<'a, C: CurveAffine> Proof { { accumulate(current_index, *commitment, *eval); } - let current_index = (*srs.cs.rotations.get(&Rotation(-1)).unwrap()).0; + let current_index = (*vk.cs.rotations.get(&Rotation(-1)).unwrap()).0; // Open permutation product commitments at \omega^{-1} x_3 for (commitment, eval) in self .permutation_product_commitments @@ -263,10 +263,10 @@ impl<'a, C: CurveAffine> Proof { // We can compute the expected msm_eval at x_6 using the q_evals provided // by the prover and from x_5 let mut msm_eval = C::Scalar::zero(); - for (&row, point_index) in srs.cs.rotations.iter() { + for (&row, point_index) in vk.cs.rotations.iter() { let mut eval = self.q_evals[point_index.0]; - let point = srs.domain.rotate_omega(x_3, row); + let point = vk.domain.rotate_omega(x_3, row); eval = eval - &q_evals[point_index.0]; eval = eval * &(x_6 - &point).invert().unwrap(); @@ -281,7 +281,7 @@ impl<'a, C: CurveAffine> Proof { // Compute the final commitment that has to be opened let mut commitment_msm = params.empty_msm(); commitment_msm.add_term(C::Scalar::one(), self.f_commitment); - for (_, &point_index) in srs.cs.rotations.iter() { + for (_, &point_index) in vk.cs.rotations.iter() { commitment_msm.scale(x_7); commitment_msm.add_msm(&q_commitments[point_index.0]); msm_eval *= &x_7;