mirror of https://github.com/zcash/halo2.git
Linearize the h(X) check.
This commit is contained in:
parent
93aabf26c6
commit
f7ef626858
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
Some(ProverQuery {
|
||||
point: *x,
|
||||
poly: h_poly,
|
||||
blind: *h_blind,
|
||||
poly: &self.h_poly,
|
||||
blind: self.h_blind,
|
||||
})
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
Some(VerifierQuery {
|
||||
point: *x,
|
||||
commitment,
|
||||
eval,
|
||||
commitment: &self.h_commitment,
|
||||
eval: self.expected_h_eval,
|
||||
})
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue