From 0caf1d20878f82dbe5ba9b47533759248c6f9404 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Fri, 18 Sep 2020 00:33:42 +0800 Subject: [PATCH] Provide aux_commitments to verifier and aux_lagrange_polys to prover --- src/plonk.rs | 1 + src/plonk/circuit.rs | 21 +++++++++++++----- src/plonk/prover.rs | 50 +++++++++++++++++++++++++++++++++++++++++++ src/plonk/verifier.rs | 18 ++++++++++++++++ 4 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/plonk.rs b/src/plonk.rs index ac5ac13..4559c0f 100644 --- a/src/plonk.rs +++ b/src/plonk.rs @@ -50,6 +50,7 @@ pub struct Proof { permutation_product_inv_evals: Vec, permutation_evals: Vec>, advice_evals: Vec, + aux_evals: Vec, fixed_evals: Vec, h_evals: Vec, f_commitment: C, diff --git a/src/plonk/circuit.rs b/src/plonk/circuit.rs index 8ec8e3d..301eff8 100644 --- a/src/plonk/circuit.rs +++ b/src/plonk/circuit.rs @@ -14,6 +14,10 @@ pub struct FixedWire(pub usize); #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct AdviceWire(pub usize); +/// This represents a wire which has an externally assigned value +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct AuxWire(pub usize); + /// This trait allows a [`Circuit`] to direct some backend to assign a witness /// for a constraint system. pub trait Assignment { @@ -68,6 +72,8 @@ pub enum Expression { Fixed(usize), /// This is an advice (witness) wire queried at a certain relative location Advice(usize), + /// This is an auxiliary (external) wire queried at a certain relative location + Aux(usize), /// This is the sum of two polynomials Sum(Box>, Box>), /// This is the product of two polynomials @@ -83,6 +89,7 @@ impl Expression { &self, fixed_wire: &impl Fn(usize) -> T, advice_wire: &impl Fn(usize) -> T, + aux_wire: &impl Fn(usize) -> T, sum: &impl Fn(T, T) -> T, product: &impl Fn(T, T) -> T, scaled: &impl Fn(T, F) -> T, @@ -90,18 +97,19 @@ impl Expression { match self { Expression::Fixed(index) => fixed_wire(*index), Expression::Advice(index) => advice_wire(*index), + Expression::Aux(index) => aux_wire(*index), Expression::Sum(a, b) => { - let a = a.evaluate(fixed_wire, advice_wire, sum, product, scaled); - let b = b.evaluate(fixed_wire, advice_wire, sum, product, scaled); + let a = a.evaluate(fixed_wire, advice_wire, aux_wire, sum, product, scaled); + let b = b.evaluate(fixed_wire, advice_wire, aux_wire, sum, product, scaled); sum(a, b) } Expression::Product(a, b) => { - let a = a.evaluate(fixed_wire, advice_wire, sum, product, scaled); - let b = b.evaluate(fixed_wire, advice_wire, sum, product, scaled); + let a = a.evaluate(fixed_wire, advice_wire, aux_wire, sum, product, scaled); + let b = b.evaluate(fixed_wire, advice_wire, aux_wire, sum, product, scaled); product(a, b) } Expression::Scaled(a, f) => { - let a = a.evaluate(fixed_wire, advice_wire, sum, product, scaled); + let a = a.evaluate(fixed_wire, advice_wire, aux_wire, sum, product, scaled); scaled(a, *f) } } @@ -112,6 +120,7 @@ impl Expression { match self { Expression::Fixed(_) => 1, Expression::Advice(_) => 1, + Expression::Aux(_) => 1, Expression::Sum(a, b) => max(a.degree(), b.degree()), Expression::Product(a, b) => a.degree() + b.degree(), Expression::Scaled(poly, _) => poly.degree(), @@ -153,6 +162,7 @@ pub struct ConstraintSystem { pub(crate) num_advice_wires: usize, pub(crate) gates: Vec>, pub(crate) advice_queries: Vec<(AdviceWire, Rotation)>, + pub(crate) aux_queries: Vec<(AuxWire, Rotation)>, pub(crate) fixed_queries: Vec<(FixedWire, Rotation)>, // Mapping from a witness vector rotation to the index in the point vector. @@ -179,6 +189,7 @@ impl Default for ConstraintSystem { gates: vec![], fixed_queries: Vec::new(), advice_queries: Vec::new(), + aux_queries: Vec::new(), rotations, permutations: Vec::new(), } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 93c6942..999a82f 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -24,6 +24,7 @@ impl Proof { params: &Params, srs: &SRS, circuit: &ConcreteCircuit, + aux_lagrange_polys: Vec>, ) -> Result { struct WitnessCollection { advice: Vec>, @@ -125,6 +126,35 @@ impl Proof { }) .collect(); + // Compute commitments to auxiliary wire polynomials + let aux_commitments_projective: Vec<_> = aux_lagrange_polys + .iter() + .map(|poly| params.commit_lagrange(poly, Blind::default())) + .collect(); + let mut aux_commitments = vec![C::zero(); aux_commitments_projective.len()]; + C::Projective::batch_to_affine(&aux_commitments_projective, &mut aux_commitments); + let aux_commitments = aux_commitments; + drop(aux_commitments_projective); + + for commitment in &aux_commitments { + hash_point(&mut transcript, commitment)?; + } + + let aux_polys: Vec<_> = aux_lagrange_polys + .clone() + .into_iter() + .map(|poly| domain.lagrange_to_coeff(poly)) + .collect(); + + let aux_cosets: Vec<_> = meta + .aux_queries + .iter() + .map(|&(wire, at)| { + let poly = aux_polys[wire.0].clone(); + domain.coeff_to_extended(poly, at) + }) + .collect(); + // Sample x_0 challenge let x_0: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128())); @@ -253,6 +283,7 @@ impl Proof { let evaluation = poly.evaluate( &|index| srs.fixed_cosets[index].clone(), &|index| advice_cosets[index].clone(), + &|index| aux_cosets[index].clone(), &|a, b| a + &b, &|a, b| a * &b, &|a, scalar| a * scalar, @@ -355,6 +386,12 @@ impl Proof { .map(|&(wire, at)| eval_polynomial(&advice_polys[wire.0], domain.rotate_omega(x_3, at))) .collect(); + let aux_evals: Vec<_> = meta + .aux_queries + .iter() + .map(|&(wire, at)| eval_polynomial(&aux_polys[wire.0], domain.rotate_omega(x_3, at))) + .collect(); + let fixed_evals: Vec<_> = meta .fixed_queries .iter() @@ -396,6 +433,7 @@ impl Proof { // Hash each advice evaluation for eval in advice_evals .iter() + .chain(aux_evals.iter()) .chain(fixed_evals.iter()) .chain(h_evals.iter()) .chain(permutation_product_evals.iter()) @@ -451,6 +489,17 @@ impl Proof { ); } + for (query_index, &(wire, ref at)) in meta.aux_queries.iter().enumerate() { + let point_index = (*meta.rotations.get(at).unwrap()).0; + + accumulate( + point_index, + &aux_polys[wire.0], + Blind::default(), + aux_evals[query_index], + ); + } + for (query_index, &(wire, ref at)) in meta.fixed_queries.iter().enumerate() { let point_index = (*meta.rotations.get(at).unwrap()).0; @@ -595,6 +644,7 @@ impl Proof { permutation_evals, advice_evals, fixed_evals, + aux_evals, h_evals, f_commitment, q_evals, diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index a9ae739..6c2cf75 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -13,6 +13,7 @@ impl<'a, C: CurveAffine> Proof { params: &'a Params, srs: &SRS, mut msm: MSM<'a, C>, + aux_commitments: Vec, ) -> Result, Error> { // Scale the MSM by a random factor to ensure that if the existing MSM // has is_zero() == false then this argument won't be able to interfere @@ -28,6 +29,12 @@ impl<'a, C: CurveAffine> Proof { .expect("proof cannot contain points at infinity"); } + // Hash the external auxiliary commitments into the transcript + for commitment in &aux_commitments { + hash_point(&mut transcript, commitment) + .expect("proof cannot contain points at infinity"); + } + // Sample x_0 challenge let x_0: C::Scalar = get_challenge_scalar(Challenge(transcript.squeeze().get_lower_128())); @@ -59,6 +66,7 @@ impl<'a, C: CurveAffine> Proof { for eval in self .advice_evals .iter() + .chain(self.aux_evals.iter()) .chain(self.fixed_evals.iter()) .chain(self.h_evals.iter()) .chain(self.permutation_product_evals.iter()) @@ -80,6 +88,7 @@ impl<'a, C: CurveAffine> Proof { let evaluation: C::Scalar = poly.evaluate( &|index| self.fixed_evals[index], &|index| self.advice_evals[index], + &|index| self.aux_evals[index], &|a, b| a + &b, &|a, b| a * &b, &|a, scalar| a * &scalar, @@ -172,6 +181,15 @@ 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; + accumulate( + point_index, + aux_commitments[wire.0], + self.aux_evals[query_index], + ); + } + for (query_index, &(wire, ref at)) in srs.cs.fixed_queries.iter().enumerate() { let point_index = (*srs.cs.rotations.get(at).unwrap()).0; accumulate(