From f7ef626858528f2fe6babbbbae2cfdedc246cfb6 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Fri, 26 Feb 2021 17:12:38 -0700 Subject: [PATCH] Linearize the h(X) check. --- src/plonk/prover.rs | 3 +- src/plonk/vanishing/prover.rs | 53 +++++++++++++------------- src/plonk/vanishing/verifier.rs | 67 +++++++++++++-------------------- src/plonk/verifier.rs | 8 ++-- 4 files changed, 58 insertions(+), 73 deletions(-) diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 943aac0a..1af3ba0a 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -412,6 +412,7 @@ pub fn create_proof< let vanishing = vanishing::Argument::construct(params, domain, expressions, y, transcript)?; let x: ChallengeX<_> = transcript.squeeze_challenge_scalar(); + let xn = x.pow(&[params.n as u64, 0, 0, 0]); // Compute and hash instance evals for each circuit instance for instance in instance.iter() { @@ -473,7 +474,7 @@ pub fn create_proof< .map_err(|_| Error::TranscriptError)?; } - let vanishing = vanishing.evaluate(x, transcript)?; + let vanishing = vanishing.evaluate(xn, domain); // Evaluate the permutations, if any, at omega^i x. let permutations: Vec>> = permutations diff --git a/src/plonk/vanishing/prover.rs b/src/plonk/vanishing/prover.rs index 406b4d56..c2434609 100644 --- a/src/plonk/vanishing/prover.rs +++ b/src/plonk/vanishing/prover.rs @@ -1,10 +1,10 @@ +use ff::Field; use group::Curve; -use super::super::{ChallengeX, ChallengeY}; use super::Argument; use crate::{ - arithmetic::{eval_polynomial, CurveAffine, FieldExt}, - plonk::Error, + arithmetic::{CurveAffine, FieldExt}, + plonk::{ChallengeX, ChallengeY, Error}, poly::{ commitment::{Blind, Params}, multiopen::ProverQuery, @@ -19,7 +19,8 @@ pub(in crate::plonk) struct Constructed { } pub(in crate::plonk) struct Evaluated { - constructed: Constructed, + h_poly: Polynomial, + h_blind: Blind, } impl Argument { @@ -69,25 +70,26 @@ impl Argument { } impl Constructed { - pub(in crate::plonk) fn evaluate, T: TranscriptWrite>( + pub(in crate::plonk) fn evaluate( self, - x: ChallengeX, - transcript: &mut T, - ) -> Result, Error> { - let h_evals: Vec<_> = self + xn: C::Scalar, + domain: &EvaluationDomain, + ) -> Evaluated { + let h_poly = self .h_pieces .iter() - .map(|poly| eval_polynomial(poly, *x)) - .collect(); + .rev() + .fold(domain.empty_coeff(), |acc, eval| acc * xn + eval); - // Hash each advice evaluation - for eval in &h_evals { - transcript - .write_scalar(*eval) - .map_err(|_| Error::TranscriptError)?; - } + let h_blind = self + .h_blinds + .iter() + .rev() + .fold(Blind(C::Scalar::zero()), |acc, eval| { + acc * Blind(xn) + *eval + }); - Ok(Evaluated { constructed: self }) + Evaluated { h_poly, h_blind } } } @@ -96,14 +98,11 @@ impl Evaluated { &self, x: ChallengeX, ) -> impl Iterator> + Clone { - self.constructed - .h_pieces - .iter() - .zip(self.constructed.h_blinds.iter()) - .map(move |(h_poly, h_blind)| ProverQuery { - point: *x, - poly: h_poly, - blind: *h_blind, - }) + Some(ProverQuery { + point: *x, + poly: &self.h_poly, + blind: self.h_blind, + }) + .into_iter() } } diff --git a/src/plonk/vanishing/verifier.rs b/src/plonk/vanishing/verifier.rs index d9e68f31..997bac99 100644 --- a/src/plonk/vanishing/verifier.rs +++ b/src/plonk/vanishing/verifier.rs @@ -1,10 +1,11 @@ use ff::Field; +use group::{Curve, Group}; use crate::{ arithmetic::CurveAffine, plonk::{Error, VerifyingKey}, poly::multiopen::VerifierQuery, - transcript::{read_n_points, read_n_scalars, EncodedChallenge, TranscriptRead}, + transcript::{read_n_points, EncodedChallenge, TranscriptRead}, }; use super::super::{ChallengeX, ChallengeY}; @@ -15,8 +16,8 @@ pub struct Committed { } pub struct Evaluated { - h_commitments: Vec, - h_evals: Vec, + h_commitment: C, + expected_h_eval: C::Scalar, } impl Argument { @@ -33,55 +34,41 @@ impl Argument { } impl Committed { - pub(in crate::plonk) fn evaluate, T: TranscriptRead>( + pub(in crate::plonk) fn verify( self, - transcript: &mut T, + expressions: impl Iterator, + y: ChallengeY, + xn: C::Scalar, ) -> Result, Error> { - let h_evals = read_n_scalars(transcript, self.h_commitments.len()) - .map_err(|_| Error::TranscriptError)?; + let expected_h_eval = expressions.fold(C::Scalar::zero(), |h_eval, v| h_eval * &*y + &v); + let expected_h_eval = expected_h_eval * ((xn - C::Scalar::one()).invert().unwrap()); + + let h_commitment = self + .h_commitments + .iter() + .rev() + .fold(C::CurveExt::identity(), |acc, eval| { + acc * xn + eval.to_curve() + }) + .to_affine(); Ok(Evaluated { - h_commitments: self.h_commitments, - h_evals, + expected_h_eval, + h_commitment, }) } } impl Evaluated { - pub(in crate::plonk) fn verify( - &self, - expressions: impl Iterator, - y: ChallengeY, - xn: C::Scalar, - ) -> Result<(), Error> { - let expected_h_eval = expressions.fold(C::Scalar::zero(), |h_eval, v| h_eval * &*y + &v); - - // Compute h(x) from the prover - let h_eval = self - .h_evals - .iter() - .rev() - .fold(C::Scalar::zero(), |acc, eval| acc * &xn + eval); - - // Did the prover commit to the correct polynomial? - if expected_h_eval != (h_eval * &(xn - &C::Scalar::one())) { - return Err(Error::ConstraintSystemFailure); - } - - Ok(()) - } - pub(in crate::plonk) fn queries( &self, x: ChallengeX, ) -> impl Iterator> + Clone { - self.h_commitments - .iter() - .zip(self.h_evals.iter()) - .map(move |(commitment, &eval)| VerifierQuery { - point: *x, - commitment, - eval, - }) + Some(VerifierQuery { + point: *x, + commitment: &self.h_commitment, + eval: self.expected_h_eval, + }) + .into_iter() } } diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index 7e328ae3..3d95a6e3 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -115,8 +115,6 @@ pub fn verify_proof<'a, C: CurveAffine, E: EncodedChallenge, T: TranscriptRea let fixed_evals = read_n_scalars(transcript, vk.cs.fixed_queries.len()) .map_err(|_| Error::TranscriptError)?; - let vanishing = vanishing.evaluate(transcript)?; - let permutations_evaluated = permutations_committed .into_iter() .map(|permutations| -> Result, _> { @@ -140,7 +138,7 @@ pub fn verify_proof<'a, C: CurveAffine, E: EncodedChallenge, T: TranscriptRea // This check ensures the circuit is satisfied so long as the polynomial // commitments open to the correct values. - { + let vanishing = { // x^n let xn = x.pow(&[params.n as u64, 0, 0, 0]); @@ -219,8 +217,8 @@ pub fn verify_proof<'a, C: CurveAffine, E: EncodedChallenge, T: TranscriptRea }, ); - vanishing.verify(expressions, y, xn)?; - } + vanishing.verify(expressions, y, xn)? + }; let queries = instance_commitments .iter()