From 3cae0d5f19962f9693e58347dff215bae16db27c Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 15 Jul 2021 14:30:52 -0600 Subject: [PATCH] Merge the common pieces of the permutation argument into a separate proof component. --- src/plonk/permutation/prover.rs | 40 +++++++++++----------- src/plonk/permutation/verifier.rs | 57 +++++++++++++++++++------------ src/plonk/prover.rs | 10 +++--- src/plonk/verifier.rs | 8 +++-- 4 files changed, 66 insertions(+), 49 deletions(-) diff --git a/src/plonk/permutation/prover.rs b/src/plonk/permutation/prover.rs index b42d5d8e..648b3cd6 100644 --- a/src/plonk/permutation/prover.rs +++ b/src/plonk/permutation/prover.rs @@ -338,42 +338,43 @@ impl Committed { } impl super::ProvingKey { - fn evaluate(&self, x: ChallengeX) -> Vec { - self.polys - .iter() - .map(|poly| eval_polynomial(poly, *x)) - .collect() - } - - fn open(&self, x: ChallengeX) -> impl Iterator> + Clone { + pub(in crate::plonk) fn open( + &self, + x: ChallengeX, + ) -> impl Iterator> + Clone { self.polys.iter().map(move |poly| ProverQuery { point: *x, poly, blind: Blind::default(), }) } + + pub(in crate::plonk) fn evaluate, T: TranscriptWrite>( + &self, + x: ChallengeX, + 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 Constructed { pub(in crate::plonk) fn evaluate, T: TranscriptWrite>( self, pk: &plonk::ProvingKey, - pkey: &ProvingKey, x: ChallengeX, transcript: &mut T, ) -> Result, 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 Evaluated { pub(in crate::plonk) fn open<'a>( &'a self, pk: &'a plonk::ProvingKey, - pkey: &'a ProvingKey, x: ChallengeX, ) -> impl Iterator> + Clone { let blinding_factors = pk.vk.cs.blinding_factors(); @@ -461,7 +461,5 @@ impl Evaluated { }) }), ) - // Open permutation polynomial commitments at x - .chain(pkey.open(x)) } } diff --git a/src/plonk/permutation/verifier.rs b/src/plonk/permutation/verifier.rs index 31aef120..e3f9307a 100644 --- a/src/plonk/permutation/verifier.rs +++ b/src/plonk/permutation/verifier.rs @@ -10,6 +10,10 @@ use crate::{ transcript::{EncodedChallenge, TranscriptRead}, }; +pub struct CommonCommitted { + permutation_evals: Vec, +} + pub struct Committed { permutation_product_commitments: Vec, } @@ -23,7 +27,6 @@ pub struct EvaluatedSet { pub struct Evaluated { sets: Vec>, - permutation_evals: Vec, } impl Argument { @@ -50,18 +53,26 @@ impl Argument { } } -impl Committed { - pub(crate) fn evaluate, T: TranscriptRead>( - self, - vkey: &VerifyingKey, +impl VerifyingKey { + pub(in crate::plonk) fn evaluate, T: TranscriptRead>( + &self, transcript: &mut T, - ) -> Result, Error> { - let permutation_evals = vkey + ) -> Result, Error> { + let permutation_evals = self .commitments .iter() .map(|_| transcript.read_scalar().map_err(|_| Error::TranscriptError)) .collect::, _>>()?; + Ok(CommonCommitted { permutation_evals }) + } +} + +impl Committed { + pub(crate) fn evaluate, T: TranscriptRead>( + self, + transcript: &mut T, + ) -> Result, Error> { let mut sets = vec![]; let mut iter = self.permutation_product_commitments.into_iter(); @@ -91,10 +102,7 @@ impl Committed { }); } - Ok(Evaluated { - sets, - permutation_evals, - }) + Ok(Evaluated { sets }) } } @@ -103,6 +111,7 @@ impl Evaluated { &'a self, vk: &'a plonk::VerifyingKey, p: &'a Argument, + common: &'a CommonCommitted, advice_evals: &'a [C::Scalar], fixed_evals: &'a [C::Scalar], instance_evals: &'a [C::Scalar], @@ -152,7 +161,7 @@ impl Evaluated { 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 Evaluated { pub(in crate::plonk) fn queries<'r, 'params: 'r>( &'r self, vk: &'r plonk::VerifyingKey, - vkey: &'r VerifyingKey, x: ChallengeX, ) -> impl Iterator> + Clone { let blinding_factors = vk.cs.blinding_factors(); @@ -234,14 +242,19 @@ impl Evaluated { 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 CommonCommitted { + pub(in crate::plonk) fn queries<'r, 'params: 'r>( + &'r self, + vkey: &'r VerifyingKey, + x: ChallengeX, + ) -> impl Iterator> + 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)) } } diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index a4b2880a..79b016b2 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -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> = permutations .into_iter() - .map(|permutation| -> Result<_, _> { - permutation.evaluate(pk, &pk.permutation, x, transcript) - }) + .map(|permutation| -> Result<_, _> { permutation.evaluate(pk, x, transcript) }) .collect::, _>>()?; // 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)); diff --git a/src/plonk/verifier.rs b/src/plonk/verifier.rs index 8a910300..6124ba3e 100644 --- a/src/plonk/verifier.rs +++ b/src/plonk/verifier.rs @@ -136,9 +136,11 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge, 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::, _>>()?; let lookups_evaluated = lookups_committed @@ -194,6 +196,7 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge, 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, 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, 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