Linearize the h(X) check.

This commit is contained in:
Sean Bowe 2021-02-26 17:12:38 -07:00
parent 93aabf26c6
commit f7ef626858
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
4 changed files with 58 additions and 73 deletions

View File

@ -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<Vec<permutation::prover::Evaluated<C>>> = permutations

View File

@ -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<C: CurveAffine> {
}
pub(in crate::plonk) struct Evaluated<C: CurveAffine> {
constructed: Constructed<C>,
h_poly: Polynomial<C::Scalar, Coeff>,
h_blind: Blind<C::Scalar>,
}
impl<C: CurveAffine> Argument<C> {
@ -69,25 +70,26 @@ impl<C: CurveAffine> Argument<C> {
}
impl<C: CurveAffine> Constructed<C> {
pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
pub(in crate::plonk) fn evaluate(
self,
x: ChallengeX<C>,
transcript: &mut T,
) -> Result<Evaluated<C>, Error> {
let h_evals: Vec<_> = self
xn: C::Scalar,
domain: &EvaluationDomain<C::Scalar>,
) -> Evaluated<C> {
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<C: CurveAffine> Evaluated<C> {
&self,
x: ChallengeX<C>,
) -> impl Iterator<Item = ProverQuery<'_, C>> + 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()
}
}

View File

@ -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<C: CurveAffine> {
}
pub struct Evaluated<C: CurveAffine> {
h_commitments: Vec<C>,
h_evals: Vec<C::Scalar>,
h_commitment: C,
expected_h_eval: C::Scalar,
}
impl<C: CurveAffine> Argument<C> {
@ -33,55 +34,41 @@ impl<C: CurveAffine> Argument<C> {
}
impl<C: CurveAffine> Committed<C> {
pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
pub(in crate::plonk) fn verify(
self,
transcript: &mut T,
expressions: impl Iterator<Item = C::Scalar>,
y: ChallengeY<C>,
xn: C::Scalar,
) -> Result<Evaluated<C>, 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<C: CurveAffine> Evaluated<C> {
pub(in crate::plonk) fn verify(
&self,
expressions: impl Iterator<Item = C::Scalar>,
y: ChallengeY<C>,
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<C>,
) -> impl Iterator<Item = VerifierQuery<'_, C>> + 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()
}
}

View File

@ -115,8 +115,6 @@ pub fn verify_proof<'a, C: CurveAffine, E: EncodedChallenge<C>, 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<Vec<_>, _> {
@ -140,7 +138,7 @@ pub fn verify_proof<'a, C: CurveAffine, E: EncodedChallenge<C>, 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<C>, T: TranscriptRea
},
);
vanishing.verify(expressions, y, xn)?;
}
vanishing.verify(expressions, y, xn)?
};
let queries = instance_commitments
.iter()