-
Notifications
You must be signed in to change notification settings - Fork 17
BatchVerifier #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: batch-ring-proof
Are you sure you want to change the base?
BatchVerifier #66
Changes from 9 commits
06bbc1a
9af0789
3764010
237aa06
4472567
c771d38
0c3588f
75ecdce
ed6d7c4
29e47bc
c885dd7
2fbd0cb
5638cee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,12 +2,13 @@ use ark_ec::pairing::Pairing; | |
| use ark_ec::twisted_edwards::{Affine, TECurveConfig}; | ||
| use ark_ec::CurveGroup; | ||
| use ark_ff::PrimeField; | ||
| use ark_std::rand::RngCore; | ||
| use w3f_pcs::pcs::kzg::KZG; | ||
| use w3f_pcs::pcs::{RawVerifierKey, PCS}; | ||
| use w3f_plonk_common::kzg_acc::KzgAccumulator; | ||
| use w3f_plonk_common::piop::VerifierPiop; | ||
| use w3f_plonk_common::transcript::PlonkTranscript; | ||
| use w3f_plonk_common::verifier::PlonkVerifier; | ||
| use w3f_plonk_common::verifier::{Challenges, PlonkVerifier}; | ||
|
|
||
| use crate::piop::params::PiopParams; | ||
| use crate::piop::{FixedColumnsCommitted, PiopVerifier, VerifierKey}; | ||
|
|
@@ -89,40 +90,146 @@ where | |
| } | ||
| } | ||
|
|
||
| impl<E, Jubjub, T> RingVerifier<E::ScalarField, KZG<E>, Jubjub, T> | ||
| /// Accumulating batch verifier for ring proofs using KZG polynomial commitment scheme. | ||
| pub struct KzgBatchVerifier<E, J, T = ArkTranscript> | ||
| where | ||
| E: Pairing, | ||
| Jubjub: TECurveConfig<BaseField = E::ScalarField>, | ||
| J: TECurveConfig<BaseField = E::ScalarField>, | ||
| T: PlonkTranscript<E::ScalarField, KZG<E>>, | ||
| { | ||
| // Verifies a batch of proofs against the same ring. | ||
| pub fn verify_batch_kzg( | ||
| pub acc: KzgAccumulator<E>, | ||
| pub verifier: RingVerifier<E::ScalarField, KZG<E>, J, T>, | ||
| } | ||
|
|
||
| /// A ring proof that has been preprocessed for batch verification. | ||
| pub struct PreparedBatchItem<E, J> | ||
| where | ||
| E: Pairing, | ||
| J: TECurveConfig<BaseField = E::ScalarField>, | ||
| { | ||
| piop: PiopVerifier<E::ScalarField, <KZG<E> as PCS<E::ScalarField>>::C, Affine<J>>, | ||
| proof: RingProof<E::ScalarField, KZG<E>>, | ||
| challenges: Challenges<E::ScalarField>, | ||
| entropy: [u8; 32], | ||
| } | ||
|
|
||
| impl<E, J, T> KzgBatchVerifier<E, J, T> | ||
| where | ||
| E: Pairing, | ||
| J: TECurveConfig<BaseField = E::ScalarField>, | ||
| T: PlonkTranscript<E::ScalarField, KZG<E>>, | ||
| { | ||
| /// Prepare | ||
| pub fn prepare( | ||
| &self, | ||
| proof: RingProof<E::ScalarField, KZG<E>>, | ||
| result: Affine<J>, | ||
| ) -> PreparedBatchItem<E, J> { | ||
| let (challenges, mut rng) = self.verifier.plonk_verifier.restore_challenges( | ||
| &result, | ||
| &proof, | ||
| // '1' accounts for the quotient polynomial that is aggregated together with the columns | ||
| PiopVerifier::<E::ScalarField, <KZG<E> as PCS<_>>::C, Affine<J>>::N_COLUMNS + 1, | ||
| PiopVerifier::<E::ScalarField, <KZG<E> as PCS<_>>::C, Affine<J>>::N_CONSTRAINTS, | ||
| ); | ||
| let seed = self.verifier.piop_params.seed; | ||
| let seed_plus_result = (seed + result).into_affine(); | ||
| let domain_at_zeta = self.verifier.piop_params.domain.evaluate(challenges.zeta); | ||
| let piop = PiopVerifier::<_, _, Affine<J>>::init( | ||
| domain_at_zeta, | ||
| self.verifier.fixed_columns_committed.clone(), | ||
| proof.column_commitments.clone(), | ||
| proof.columns_at_zeta.clone(), | ||
| (seed.x, seed.y), | ||
| (seed_plus_result.x, seed_plus_result.y), | ||
| ); | ||
davxy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Pick some entropy from plonk verifier for later usage | ||
| let mut entropy = [0_u8; 32]; | ||
| rng.fill_bytes(&mut entropy); | ||
|
|
||
| PreparedBatchItem { | ||
| piop, | ||
| proof, | ||
| challenges, | ||
| entropy, | ||
| } | ||
| } | ||
|
Comment on lines
+154
to
+164
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @swasilyev @burdges @drskalman Need some extra attention here. |
||
|
|
||
| pub fn push_prepared(&mut self, item: PreparedBatchItem<E, J>) { | ||
| let mut ts = self.verifier.plonk_verifier.transcript_prelude.clone(); | ||
| ts._add_serializable(b"batch-entropy", &item.entropy); | ||
| self.acc | ||
| .accumulate(item.piop, item.proof, item.challenges, &mut ts.to_rng()); | ||
| } | ||
|
Comment on lines
+173
to
+178
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @swasilyev @burdges @drskalman here I pick the randomness back to:
|
||
|
|
||
| /// Adds a ring proof to the batch, preparing and accumulating it immediately. | ||
| /// | ||
| /// The proof's pairing equation is aggregated into the internal accumulator. | ||
| /// Call `verify` after pushing all proofs to perform the batched verification. | ||
| pub fn push(&mut self, proof: RingProof<E::ScalarField, KZG<E>>, result: Affine<J>) { | ||
| let item = self.prepare(proof, result); | ||
| self.push_prepared(item); | ||
| } | ||
|
|
||
| /// Batch verify | ||
| pub fn verify(&self) -> bool { | ||
| self.acc.verify() | ||
| } | ||
| } | ||
|
|
||
| impl<E, J, T> RingVerifier<E::ScalarField, KZG<E>, J, T> | ||
| where | ||
| E: Pairing, | ||
| J: TECurveConfig<BaseField = E::ScalarField>, | ||
| T: PlonkTranscript<E::ScalarField, KZG<E>>, | ||
| { | ||
| /// Build a new batch verifier. | ||
| pub fn kzg_batch_verifier(self) -> KzgBatchVerifier<E, J, T> { | ||
| KzgBatchVerifier { | ||
| acc: KzgAccumulator::<E>::new(self.plonk_verifier.pcs_vk.clone()), | ||
| verifier: self, | ||
| } | ||
| } | ||
|
|
||
| /// Verifies a batch of proofs against the same ring. | ||
| #[cfg(not(feature = "parallel"))] | ||
| pub fn verify_batch_kzg( | ||
| self, | ||
| proofs: Vec<RingProof<E::ScalarField, KZG<E>>>, | ||
| results: Vec<Affine<Jubjub>>, | ||
| results: Vec<Affine<J>>, | ||
| ) -> bool { | ||
| let mut acc = KzgAccumulator::<E>::new(self.plonk_verifier.pcs_vk.clone()); | ||
| let mut batch = self.kzg_batch_verifier(); | ||
| for (proof, result) in proofs.into_iter().zip(results) { | ||
| let (challenges, mut rng) = self.plonk_verifier.restore_challenges( | ||
| &result, | ||
| &proof, | ||
| // '1' accounts for the quotient polynomial that is aggregated together with the columns | ||
| PiopVerifier::<E::ScalarField, <KZG<E> as PCS<_>>::C, Affine<Jubjub>>::N_COLUMNS + 1, | ||
| PiopVerifier::<E::ScalarField, <KZG<E> as PCS<_>>::C, Affine<Jubjub>>::N_CONSTRAINTS, | ||
| ); | ||
| let seed = self.piop_params.seed; | ||
| let seed_plus_result = (seed + result).into_affine(); | ||
| let domain_at_zeta = self.piop_params.domain.evaluate(challenges.zeta); | ||
| let piop = PiopVerifier::<_, _, Affine<Jubjub>>::init( | ||
| domain_at_zeta, | ||
| self.fixed_columns_committed.clone(), | ||
| proof.column_commitments.clone(), | ||
| proof.columns_at_zeta.clone(), | ||
| (seed.x, seed.y), | ||
| (seed_plus_result.x, seed_plus_result.y), | ||
| ); | ||
| acc.accumulate(piop, proof, challenges, &mut rng); | ||
| batch.push(proof, result); | ||
| } | ||
| batch.verify() | ||
| } | ||
| } | ||
|
|
||
| #[cfg(feature = "parallel")] | ||
| impl<E, J, T> RingVerifier<E::ScalarField, KZG<E>, J, T> | ||
| where | ||
| E: Pairing, | ||
| J: TECurveConfig<BaseField = E::ScalarField>, | ||
| T: PlonkTranscript<E::ScalarField, KZG<E>> + Sync, | ||
| { | ||
| /// Verifies a batch of proofs against the same ring. | ||
| pub fn verify_batch_kzg( | ||
| self, | ||
| proofs: Vec<RingProof<E::ScalarField, KZG<E>>>, | ||
| results: Vec<Affine<J>>, | ||
| ) -> bool { | ||
| use rayon::prelude::*; | ||
| let mut batch = self.kzg_batch_verifier(); | ||
| let prepared: Vec<_> = proofs | ||
| .into_par_iter() | ||
| .zip(results) | ||
| .map(|(proof, result)| batch.prepare(proof, result)) | ||
| .collect(); | ||
| for item in prepared { | ||
| batch.push_prepared(item); | ||
| } | ||
| acc.verify() | ||
| batch.verify() | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.