Merge the common pieces of the permutation argument into a separate proof component.

This commit is contained in:
Sean Bowe 2021-07-15 14:30:52 -06:00
parent 4a9e329ded
commit 3cae0d5f19
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
4 changed files with 66 additions and 49 deletions

View File

@ -338,42 +338,43 @@ impl<C: CurveAffine> Committed<C> {
}
impl<C: CurveAffine> super::ProvingKey<C> {
fn evaluate(&self, x: ChallengeX<C>) -> Vec<C::Scalar> {
self.polys
.iter()
.map(|poly| eval_polynomial(poly, *x))
.collect()
}
fn open(&self, x: ChallengeX<C>) -> impl Iterator<Item = ProverQuery<'_, C>> + Clone {
pub(in crate::plonk) fn open(
&self,
x: ChallengeX<C>,
) -> impl Iterator<Item = ProverQuery<'_, C>> + Clone {
self.polys.iter().map(move |poly| ProverQuery {
point: *x,
poly,
blind: Blind::default(),
})
}
pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
&self,
x: ChallengeX<C>,
transcript: &mut T,
) -> Result<(), Error> {
// Hash permutation evals
for eval in self.polys.iter().map(|poly| eval_polynomial(poly, *x)) {
transcript
.write_scalar(eval)
.map_err(|_| Error::TranscriptError)?;
}
Ok(())
}
}
impl<C: CurveAffine> Constructed<C> {
pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptWrite<C, E>>(
self,
pk: &plonk::ProvingKey<C>,
pkey: &ProvingKey<C>,
x: ChallengeX<C>,
transcript: &mut T,
) -> Result<Evaluated<C>, Error> {
let domain = &pk.vk.domain;
let blinding_factors = pk.vk.cs.blinding_factors();
// Hash permutation evals
// TODO: need to do this once for a single proof; as is this happens
// for every circuit instance in the proof.
for eval in pkey.evaluate(x).iter() {
transcript
.write_scalar(*eval)
.map_err(|_| Error::TranscriptError)?;
}
{
let mut sets = self.sets.iter();
@ -419,7 +420,6 @@ impl<C: CurveAffine> Evaluated<C> {
pub(in crate::plonk) fn open<'a>(
&'a self,
pk: &'a plonk::ProvingKey<C>,
pkey: &'a ProvingKey<C>,
x: ChallengeX<C>,
) -> impl Iterator<Item = ProverQuery<'a, C>> + Clone {
let blinding_factors = pk.vk.cs.blinding_factors();
@ -461,7 +461,5 @@ impl<C: CurveAffine> Evaluated<C> {
})
}),
)
// Open permutation polynomial commitments at x
.chain(pkey.open(x))
}
}

View File

@ -10,6 +10,10 @@ use crate::{
transcript::{EncodedChallenge, TranscriptRead},
};
pub struct CommonCommitted<C: CurveAffine> {
permutation_evals: Vec<C::Scalar>,
}
pub struct Committed<C: CurveAffine> {
permutation_product_commitments: Vec<C>,
}
@ -23,7 +27,6 @@ pub struct EvaluatedSet<C: CurveAffine> {
pub struct Evaluated<C: CurveAffine> {
sets: Vec<EvaluatedSet<C>>,
permutation_evals: Vec<C::Scalar>,
}
impl Argument {
@ -50,18 +53,26 @@ impl Argument {
}
}
impl<C: CurveAffine> Committed<C> {
pub(crate) fn evaluate<E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
self,
vkey: &VerifyingKey<C>,
impl<C: CurveAffine> VerifyingKey<C> {
pub(in crate::plonk) fn evaluate<E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
&self,
transcript: &mut T,
) -> Result<Evaluated<C>, Error> {
let permutation_evals = vkey
) -> Result<CommonCommitted<C>, Error> {
let permutation_evals = self
.commitments
.iter()
.map(|_| transcript.read_scalar().map_err(|_| Error::TranscriptError))
.collect::<Result<Vec<_>, _>>()?;
Ok(CommonCommitted { permutation_evals })
}
}
impl<C: CurveAffine> Committed<C> {
pub(crate) fn evaluate<E: EncodedChallenge<C>, T: TranscriptRead<C, E>>(
self,
transcript: &mut T,
) -> Result<Evaluated<C>, Error> {
let mut sets = vec![];
let mut iter = self.permutation_product_commitments.into_iter();
@ -91,10 +102,7 @@ impl<C: CurveAffine> Committed<C> {
});
}
Ok(Evaluated {
sets,
permutation_evals,
})
Ok(Evaluated { sets })
}
}
@ -103,6 +111,7 @@ impl<C: CurveAffine> Evaluated<C> {
&'a self,
vk: &'a plonk::VerifyingKey<C>,
p: &'a Argument,
common: &'a CommonCommitted<C>,
advice_evals: &'a [C::Scalar],
fixed_evals: &'a [C::Scalar],
instance_evals: &'a [C::Scalar],
@ -152,7 +161,7 @@ impl<C: CurveAffine> Evaluated<C> {
self.sets
.iter()
.zip(p.columns.chunks(chunk_len))
.zip(self.permutation_evals.chunks(chunk_len))
.zip(common.permutation_evals.chunks(chunk_len))
.enumerate()
.map(move |(chunk_index, ((set, columns), permutation_evals))| {
let mut left = set.permutation_product_next_eval;
@ -201,7 +210,6 @@ impl<C: CurveAffine> Evaluated<C> {
pub(in crate::plonk) fn queries<'r, 'params: 'r>(
&'r self,
vk: &'r plonk::VerifyingKey<C>,
vkey: &'r VerifyingKey<C>,
x: ChallengeX<C>,
) -> impl Iterator<Item = VerifierQuery<'r, 'params, C>> + Clone {
let blinding_factors = vk.cs.blinding_factors();
@ -234,14 +242,19 @@ impl<C: CurveAffine> Evaluated<C> {
set.permutation_product_last_eval.unwrap(),
))
}))
// Open permutation commitments for each permutation argument at x
.chain(
vkey.commitments
.iter()
.zip(self.permutation_evals.iter())
.map(move |(commitment, &eval)| {
VerifierQuery::new_commitment(commitment, *x, eval)
}),
)
}
}
impl<C: CurveAffine> CommonCommitted<C> {
pub(in crate::plonk) fn queries<'r, 'params: 'r>(
&'r self,
vkey: &'r VerifyingKey<C>,
x: ChallengeX<C>,
) -> impl Iterator<Item = VerifierQuery<'r, 'params, C>> + Clone {
// Open permutation commitments for each permutation argument at x
vkey.commitments
.iter()
.zip(self.permutation_evals.iter())
.map(move |(commitment, &eval)| VerifierQuery::new_commitment(commitment, *x, eval))
}
}

View File

@ -518,12 +518,13 @@ pub fn create_proof<
let vanishing = vanishing.evaluate(x, xn, domain, transcript)?;
// Evaluate common permutation data
pk.permutation.evaluate(x, transcript)?;
// Evaluate the permutations, if any, at omega^i x.
let permutations: Vec<permutation::prover::Evaluated<C>> = permutations
.into_iter()
.map(|permutation| -> Result<_, _> {
permutation.evaluate(pk, &pk.permutation, x, transcript)
})
.map(|permutation| -> Result<_, _> { permutation.evaluate(pk, x, transcript) })
.collect::<Result<Vec<_>, _>>()?;
// Evaluate the lookups, if any, at omega^i x.
@ -566,7 +567,7 @@ pub fn create_proof<
blind: advice.advice_blinds[column.index()],
}),
)
.chain(permutation.open(pk, &pk.permutation, x))
.chain(permutation.open(pk, x))
.chain(lookups.iter().flat_map(move |p| p.open(pk, x)).into_iter())
})
.chain(
@ -580,6 +581,7 @@ pub fn create_proof<
blind: Blind::default(),
}),
)
.chain(pk.permutation.open(x))
// We query the h(X) polynomial at x
.chain(vanishing.open(x));

View File

@ -136,9 +136,11 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge<C>, T: Transcri
let vanishing = vanishing.evaluate_after_x(transcript)?;
let permutations_common = vk.permutation.evaluate(transcript)?;
let permutations_evaluated = permutations_committed
.into_iter()
.map(|permutation| permutation.evaluate(&vk.permutation, transcript))
.map(|permutation| permutation.evaluate(transcript))
.collect::<Result<Vec<_>, _>>()?;
let lookups_evaluated = lookups_committed
@ -194,6 +196,7 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge<C>, T: Transcri
.chain(permutation.expressions(
vk,
&vk.cs.permutation,
&permutations_common,
advice_evals,
fixed_evals,
instance_evals,
@ -263,7 +266,7 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge<C>, T: Transcri
)
},
))
.chain(permutation.queries(vk, &vk.permutation, x))
.chain(permutation.queries(vk, x))
.chain(
lookups
.iter()
@ -285,6 +288,7 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge<C>, T: Transcri
)
}),
)
.chain(permutations_common.queries(&vk.permutation, x))
.chain(vanishing.queries(x));
// We are now convinced the circuit is satisfied so long as the