From 8c3092240d5c63cc9c1c347dda2a6d9c94eade01 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Mon, 13 Apr 2026 11:20:20 +0200 Subject: [PATCH 1/5] Simplify PreparedMultiRingItem --- w3f-ring-proof/Cargo.toml | 2 +- w3f-ring-proof/src/lib.rs | 5 +- .../src/multi_ring_batch_verifier.rs | 55 ++++++++++--------- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/w3f-ring-proof/Cargo.toml b/w3f-ring-proof/Cargo.toml index 6f1fef5..d189244 100644 --- a/w3f-ring-proof/Cargo.toml +++ b/w3f-ring-proof/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "w3f-ring-proof" -version = "0.0.6" +version = "0.0.7" edition = "2021" authors = ["Sergey Vasilyev "] license = "MIT/Apache-2.0" diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index 4c3ae5f..6c4815b 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -262,7 +262,10 @@ mod tests { // Multi-ring batch verification use crate::multi_ring_batch_verifier::MultiRingBatchVerifier; - let mut batch = MultiRingBatchVerifier::new(verifier_a.pcs_vk().clone()); + let mut batch = MultiRingBatchVerifier::new( + verifier_a.pcs_vk().clone(), + verifier_a.plonk_verifier.transcript_prelude.clone(), + ); for (result, proof) in claims_a { batch.push(&verifier_a, proof, result); } diff --git a/w3f-ring-proof/src/multi_ring_batch_verifier.rs b/w3f-ring-proof/src/multi_ring_batch_verifier.rs index 3d048f5..8aa5011 100644 --- a/w3f-ring-proof/src/multi_ring_batch_verifier.rs +++ b/w3f-ring-proof/src/multi_ring_batch_verifier.rs @@ -15,16 +15,11 @@ use crate::ring_verifier::RingVerifier; use crate::RingProof; /// A ring proof preprocessed for multi-ring batch verification. -/// -/// Holds a reference to the `RingVerifier` that was used during preparation, -/// so that `push_prepared` can access the correct ring's transcript prelude. -pub struct PreparedMultiRingItem<'a, E, J, T> +pub struct PreparedMultiRingItem where E: Pairing, J: TECurveConfig, - T: PlonkTranscript>, { - verifier: &'a RingVerifier, J, T>, piop: PiopVerifier as PCS>::C, Affine>, proof: RingProof>, challenges: Challenges, @@ -33,36 +28,47 @@ where /// Accumulating batch verifier for ring proofs across multiple rings. /// -/// Unlike `KzgBatchVerifier` which is tied to a single ring, -/// this verifier can accumulate proofs from different rings (keysets) -/// into a single batched pairing check. +/// Unlike `KzgBatchVerifier` which is tied to a single ring, this verifier +/// accumulates proofs from different rings (keysets) into a single batched +/// pairing check. All rings must share the same KZG SRS and the same +/// transcript type `T`. /// -/// All rings must share the same KZG SRS (same `KzgVerifierKey`). -pub struct MultiRingBatchVerifier { +/// Holds its own transcript instance, cloned on each `push_prepared` so the +/// per-proof entropy can be folded in without touching the originating +/// `RingVerifier`. The transcript's initial state is not load-bearing; any +/// valid `T` works (e.g. the prelude of any ring verifier being batched). +pub struct MultiRingBatchVerifier +where + T: PlonkTranscript>, +{ acc: KzgAccumulator, + transcript: T, } -impl MultiRingBatchVerifier { +impl MultiRingBatchVerifier +where + T: PlonkTranscript>, +{ /// Creates a new multi-ring batch verifier. - pub fn new(kzg_vk: KzgVerifierKey) -> Self { + pub fn new(kzg_vk: KzgVerifierKey, transcript: T) -> Self { Self { acc: KzgAccumulator::::new(kzg_vk), + transcript, } } /// Prepares a ring proof for batch verification without accumulating it. /// - /// The returned item holds a reference to the `verifier` and is independent - /// of the accumulator state, so multiple proofs (even from different rings) - /// can be prepared in parallel. - pub fn prepare<'a, J, T>( - verifier: &'a RingVerifier, J, T>, + /// The returned item is independent of both the accumulator state and + /// the originating `RingVerifier`, so multiple proofs (even from + /// different rings) can be prepared in parallel. + pub fn prepare( + verifier: &RingVerifier, J, T>, proof: RingProof>, result: Affine, - ) -> PreparedMultiRingItem<'a, E, J, T> + ) -> PreparedMultiRingItem where J: TECurveConfig, - T: PlonkTranscript>, { let (challenges, mut rng) = verifier.plonk_verifier.restore_challenges( &result, @@ -86,7 +92,6 @@ impl MultiRingBatchVerifier { rng.fill_bytes(&mut entropy); PreparedMultiRingItem { - verifier, piop, proof, challenges, @@ -99,26 +104,24 @@ impl MultiRingBatchVerifier { /// This is the second step of the two-phase batch verification workflow: /// 1. `prepare` - can be parallelized across multiple proofs /// 2. `push_prepared` - must be called sequentially (mutates the accumulator) - pub fn push_prepared(&mut self, item: PreparedMultiRingItem<'_, E, J, T>) + pub fn push_prepared(&mut self, item: PreparedMultiRingItem) where J: TECurveConfig, - T: PlonkTranscript>, { - let mut ts = item.verifier.plonk_verifier.transcript_prelude.clone(); + let mut ts = self.transcript.clone(); ts._add_serializable(b"batch-entropy", &item.entropy); self.acc .accumulate(item.piop, item.proof, item.challenges, &mut ts.to_rng()); } /// Adds a ring proof to the batch, preparing and accumulating it immediately. - pub fn push( + pub fn push( &mut self, verifier: &RingVerifier, J, T>, proof: RingProof>, result: Affine, ) where J: TECurveConfig, - T: PlonkTranscript>, { let item = Self::prepare(verifier, proof, result); self.push_prepared(item); From cc679eb5bdfbe5e190e5b2070f30ca9c5a41e48a Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Mon, 13 Apr 2026 11:52:41 +0200 Subject: [PATCH 2/5] Replace KzgBatchVerifier with a thing wrapper around MultiRingBatchVerifier --- w3f-ring-proof/benches/ring_proof.rs | 13 +- .../src/multi_ring_batch_verifier.rs | 8 +- w3f-ring-proof/src/ring_verifier.rs | 127 ++---------------- 3 files changed, 18 insertions(+), 130 deletions(-) diff --git a/w3f-ring-proof/benches/ring_proof.rs b/w3f-ring-proof/benches/ring_proof.rs index b0ab568..56f8158 100644 --- a/w3f-ring-proof/benches/ring_proof.rs +++ b/w3f-ring-proof/benches/ring_proof.rs @@ -195,6 +195,9 @@ fn bench_verify_batch_kzg(c: &mut Criterion) { .map(|_| generate_proof(&piop_params, &pcs_params, &pks, rng)) .collect(); + let (_, verifier_key) = index::<_, CS, _>(&pcs_params, &piop_params, &pks); + let verifier = RingVerifier::init(verifier_key, piop_params, make_transcript()); + for batch_size in [1, 4, 16, 32] { let (results, proofs): (Vec<_>, Vec<_>) = claims[..batch_size].iter().cloned().unzip(); @@ -202,15 +205,9 @@ fn bench_verify_batch_kzg(c: &mut Criterion) { BenchmarkId::new("kzg_accumulator", batch_size), &batch_size, |b, _| { - // Recreate verifier each iteration since verify_batch_kzg consumes self. b.iter_batched( - || { - let (_, vk) = index::<_, CS, _>(&pcs_params, &piop_params, &pks); - let verifier = - RingVerifier::init(vk, piop_params.clone(), make_transcript()); - (verifier, proofs.clone(), results.clone()) - }, - |(verifier, proofs, results)| verifier.verify_batch_kzg(proofs, results), + || (proofs.clone(), results.clone()), + |(proofs, results)| verifier.verify_batch_kzg(proofs, results), BatchSize::LargeInput, ); }, diff --git a/w3f-ring-proof/src/multi_ring_batch_verifier.rs b/w3f-ring-proof/src/multi_ring_batch_verifier.rs index 8aa5011..02f25a1 100644 --- a/w3f-ring-proof/src/multi_ring_batch_verifier.rs +++ b/w3f-ring-proof/src/multi_ring_batch_verifier.rs @@ -26,12 +26,10 @@ where entropy: [u8; 32], } -/// Accumulating batch verifier for ring proofs across multiple rings. +/// Accumulating batch verifier for ring proofs across one or more rings. /// -/// Unlike `KzgBatchVerifier` which is tied to a single ring, this verifier -/// accumulates proofs from different rings (keysets) into a single batched -/// pairing check. All rings must share the same KZG SRS and the same -/// transcript type `T`. +/// Accumulates proofs from one or more rings (keysets) into a single batched +/// pairing check. All rings must share the same KZG SRS. /// /// Holds its own transcript instance, cloned on each `push_prepared` so the /// per-proof entropy can be folded in without touching the originating diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index 9765b11..65484f4 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -2,14 +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::{Challenges, PlonkVerifier}; +use w3f_plonk_common::verifier::PlonkVerifier; +use crate::multi_ring_batch_verifier::MultiRingBatchVerifier; use crate::piop::params::PiopParams; use crate::piop::{FixedColumnsCommitted, PiopVerifier, VerifierKey}; use crate::{ArkTranscript, RingProof}; @@ -95,131 +94,25 @@ where } } -/// Accumulating batch verifier for ring proofs using KZG polynomial commitment scheme. -pub struct KzgBatchVerifier -where - E: Pairing, - J: TECurveConfig, - T: PlonkTranscript>, -{ - pub acc: KzgAccumulator, - pub verifier: RingVerifier, J, T>, -} - -/// A ring proof that has been preprocessed for batch verification. -pub struct PreparedBatchItem -where - E: Pairing, - J: TECurveConfig, -{ - piop: PiopVerifier as PCS>::C, Affine>, - proof: RingProof>, - challenges: Challenges, - entropy: [u8; 32], -} - -impl KzgBatchVerifier -where - E: Pairing, - J: TECurveConfig, - T: PlonkTranscript>, -{ - /// Prepares a ring proof for batch verification without accumulating it. - /// - /// Returns a `PreparedBatchItem` that can later be passed to `push_prepared`. - /// - /// This method is independent of the accumulator state, so multiple proofs can be - /// prepared in parallel (e.g., using `rayon`). Each prepared item is in the order - /// of a few KB, so for large batches you may want to prepare and push incrementally - /// rather than holding all prepared items in memory at once. - pub fn prepare( - &self, - proof: RingProof>, - result: Affine, - ) -> PreparedBatchItem { - 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:: as PCS<_>>::C, Affine>::N_COLUMNS + 1, - PiopVerifier:: as PCS<_>>::C, Affine>::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>::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), - ); - - // 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, - } - } - - /// Accumulates a previously prepared proof into the batch. - /// - /// This is the second step of the two-phase batch verification workflow: - /// 1. `prepare` - can be parallelized across multiple proofs - /// 2. `push_prepared` - must be called sequentially (mutates the accumulator) - /// - /// For simpler usage where parallelism isn't needed, use `push` instead. - pub fn push_prepared(&mut self, item: PreparedBatchItem) { - 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()); - } - - /// 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>, result: Affine) { - let item = self.prepare(proof, result); - self.push_prepared(item); - } - - /// Verifies all accumulated proofs in a single batched pairing check. - pub fn verify(&self) -> bool { - self.acc.verify() - } -} - impl RingVerifier, J, T> where E: Pairing, J: TECurveConfig, T: PlonkTranscript>, { - /// Build a new batch verifier. - pub fn kzg_batch_verifier(self) -> KzgBatchVerifier { - KzgBatchVerifier { - acc: KzgAccumulator::::new(self.plonk_verifier.pcs_vk.clone()), - verifier: self, - } - } - - /// Verifies a batch of proofs against the same ring. + /// Verifies a batch of proofs against this ring in a single batched + /// pairing check, using a `MultiRingBatchVerifier` under the hood. pub fn verify_batch_kzg( - self, + &self, proofs: Vec>>, results: Vec>, ) -> bool { - let mut batch = self.kzg_batch_verifier(); + let mut batch = MultiRingBatchVerifier::new( + self.plonk_verifier.pcs_vk.clone(), + self.plonk_verifier.transcript_prelude.clone(), + ); for (proof, result) in proofs.into_iter().zip(results) { - batch.push(proof, result); + batch.push(self, proof, result); } batch.verify() } From 8a2ca1c0d7acc6a0a0ef44d3abab10fde093fda7 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Mon, 13 Apr 2026 12:06:19 +0200 Subject: [PATCH 3/5] Refactory --- w3f-ring-proof/src/lib.rs | 4 +- .../src/multi_ring_batch_verifier.rs | 94 ++++++++++--------- w3f-ring-proof/src/ring_verifier.rs | 2 +- 3 files changed, 54 insertions(+), 46 deletions(-) diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index 6c4815b..cf62e00 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -267,10 +267,10 @@ mod tests { verifier_a.plonk_verifier.transcript_prelude.clone(), ); for (result, proof) in claims_a { - batch.push(&verifier_a, proof, result); + batch.push_raw(&verifier_a, proof, result); } for (result, proof) in claims_b { - batch.push(&verifier_b, proof, result); + batch.push_raw(&verifier_b, proof, result); } assert!(batch.verify()); } diff --git a/w3f-ring-proof/src/multi_ring_batch_verifier.rs b/w3f-ring-proof/src/multi_ring_batch_verifier.rs index 02f25a1..c16ebe3 100644 --- a/w3f-ring-proof/src/multi_ring_batch_verifier.rs +++ b/w3f-ring-proof/src/multi_ring_batch_verifier.rs @@ -15,7 +15,7 @@ use crate::ring_verifier::RingVerifier; use crate::RingProof; /// A ring proof preprocessed for multi-ring batch verification. -pub struct PreparedMultiRingItem +pub struct BatchItem where E: Pairing, J: TECurveConfig, @@ -26,47 +26,23 @@ where entropy: [u8; 32], } -/// Accumulating batch verifier for ring proofs across one or more rings. -/// -/// Accumulates proofs from one or more rings (keysets) into a single batched -/// pairing check. All rings must share the same KZG SRS. -/// -/// Holds its own transcript instance, cloned on each `push_prepared` so the -/// per-proof entropy can be folded in without touching the originating -/// `RingVerifier`. The transcript's initial state is not load-bearing; any -/// valid `T` works (e.g. the prelude of any ring verifier being batched). -pub struct MultiRingBatchVerifier -where - T: PlonkTranscript>, -{ - acc: KzgAccumulator, - transcript: T, -} - -impl MultiRingBatchVerifier +impl BatchItem where - T: PlonkTranscript>, + E: Pairing, + J: TECurveConfig, { - /// Creates a new multi-ring batch verifier. - pub fn new(kzg_vk: KzgVerifierKey, transcript: T) -> Self { - Self { - acc: KzgAccumulator::::new(kzg_vk), - transcript, - } - } - /// Prepares a ring proof for batch verification without accumulating it. /// - /// The returned item is independent of both the accumulator state and + /// The returned item is independent of both any accumulator state and /// the originating `RingVerifier`, so multiple proofs (even from /// different rings) can be prepared in parallel. - pub fn prepare( + pub fn new( verifier: &RingVerifier, J, T>, proof: RingProof>, result: Affine, - ) -> PreparedMultiRingItem + ) -> Self where - J: TECurveConfig, + T: PlonkTranscript>, { let (challenges, mut rng) = verifier.plonk_verifier.restore_challenges( &result, @@ -89,20 +65,46 @@ where let mut entropy = [0_u8; 32]; rng.fill_bytes(&mut entropy); - PreparedMultiRingItem { + Self { piop, proof, challenges, entropy, } } +} - /// Accumulates a previously prepared proof into the batch. - /// - /// This is the second step of the two-phase batch verification workflow: - /// 1. `prepare` - can be parallelized across multiple proofs - /// 2. `push_prepared` - must be called sequentially (mutates the accumulator) - pub fn push_prepared(&mut self, item: PreparedMultiRingItem) +/// Accumulating batch verifier for ring proofs across one or more rings. +/// +/// Accumulates proofs from one or more rings (keysets) into a single batched +/// pairing check. All rings must share the same KZG SRS. +/// +/// Holds its own transcript instance, cloned on each `push_prepared` so the +/// per-proof entropy can be folded in without touching the originating +/// `RingVerifier`. The transcript's initial state is not load-bearing; any +/// valid `T` works (e.g. the prelude of any ring verifier being batched). +pub struct MultiRingBatchVerifier +where + T: PlonkTranscript>, +{ + acc: KzgAccumulator, + transcript: T, +} + +impl MultiRingBatchVerifier +where + T: PlonkTranscript>, +{ + /// Creates a new multi-ring batch verifier. + pub fn new(kzg_vk: KzgVerifierKey, transcript: T) -> Self { + Self { + acc: KzgAccumulator::::new(kzg_vk), + transcript, + } + } + + /// Accumulates a prepared `BatchItem` into the batch. + pub fn push(&mut self, item: BatchItem) where J: TECurveConfig, { @@ -112,8 +114,15 @@ where .accumulate(item.piop, item.proof, item.challenges, &mut ts.to_rng()); } - /// Adds a ring proof to the batch, preparing and accumulating it immediately. - pub fn push( + /// Adds a raw ring proof to the batch. + /// + /// Equivalent to `self.push(BatchItem::new(verifier, proof, result))`: + /// preparation (transcript replay, challenge derivation, PIOP setup) and + /// accumulation happen internally. Use the two-step form directly when + /// preparation should be parallelized — `BatchItem::new` is independent + /// of the accumulator state, so multiple items can be built in parallel + /// and then pushed sequentially via [`push`](Self::push). + pub fn push_raw( &mut self, verifier: &RingVerifier, J, T>, proof: RingProof>, @@ -121,8 +130,7 @@ where ) where J: TECurveConfig, { - let item = Self::prepare(verifier, proof, result); - self.push_prepared(item); + self.push(BatchItem::new(verifier, proof, result)); } /// Verifies all accumulated proofs in a single batched pairing check. diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index 65484f4..feb09cd 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -112,7 +112,7 @@ where self.plonk_verifier.transcript_prelude.clone(), ); for (proof, result) in proofs.into_iter().zip(results) { - batch.push(self, proof, result); + batch.push_raw(self, proof, result); } batch.verify() } From baf2a122578179618b96302fbc27c4a1f15a610e Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Mon, 13 Apr 2026 12:08:04 +0200 Subject: [PATCH 4/5] Rename --- w3f-ring-proof/src/lib.rs | 4 ++-- w3f-ring-proof/src/multi_ring_batch_verifier.rs | 4 ++-- w3f-ring-proof/src/ring_verifier.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index cf62e00..367704a 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -261,8 +261,8 @@ mod tests { } // Multi-ring batch verification - use crate::multi_ring_batch_verifier::MultiRingBatchVerifier; - let mut batch = MultiRingBatchVerifier::new( + use crate::multi_ring_batch_verifier::BatchVerifier; + let mut batch = BatchVerifier::new( verifier_a.pcs_vk().clone(), verifier_a.plonk_verifier.transcript_prelude.clone(), ); diff --git a/w3f-ring-proof/src/multi_ring_batch_verifier.rs b/w3f-ring-proof/src/multi_ring_batch_verifier.rs index c16ebe3..9590802 100644 --- a/w3f-ring-proof/src/multi_ring_batch_verifier.rs +++ b/w3f-ring-proof/src/multi_ring_batch_verifier.rs @@ -83,7 +83,7 @@ where /// per-proof entropy can be folded in without touching the originating /// `RingVerifier`. The transcript's initial state is not load-bearing; any /// valid `T` works (e.g. the prelude of any ring verifier being batched). -pub struct MultiRingBatchVerifier +pub struct BatchVerifier where T: PlonkTranscript>, { @@ -91,7 +91,7 @@ where transcript: T, } -impl MultiRingBatchVerifier +impl BatchVerifier where T: PlonkTranscript>, { diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index feb09cd..64c32ec 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -8,7 +8,7 @@ use w3f_plonk_common::piop::VerifierPiop; use w3f_plonk_common::transcript::PlonkTranscript; use w3f_plonk_common::verifier::PlonkVerifier; -use crate::multi_ring_batch_verifier::MultiRingBatchVerifier; +use crate::multi_ring_batch_verifier::BatchVerifier; use crate::piop::params::PiopParams; use crate::piop::{FixedColumnsCommitted, PiopVerifier, VerifierKey}; use crate::{ArkTranscript, RingProof}; @@ -107,7 +107,7 @@ where proofs: Vec>>, results: Vec>, ) -> bool { - let mut batch = MultiRingBatchVerifier::new( + let mut batch = BatchVerifier::new( self.plonk_verifier.pcs_vk.clone(), self.plonk_verifier.transcript_prelude.clone(), ); From d44478964c927924cec9eabc9e4dbfce9e18f7bb Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Mon, 13 Apr 2026 12:54:22 +0200 Subject: [PATCH 5/5] Renaming --- w3f-ring-proof/src/lib.rs | 4 +- .../src/multi_ring_batch_verifier.rs | 46 +++++++++---------- w3f-ring-proof/src/ring_verifier.rs | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index 367704a..738a845 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -267,10 +267,10 @@ mod tests { verifier_a.plonk_verifier.transcript_prelude.clone(), ); for (result, proof) in claims_a { - batch.push_raw(&verifier_a, proof, result); + batch.push(&verifier_a, proof, result); } for (result, proof) in claims_b { - batch.push_raw(&verifier_b, proof, result); + batch.push(&verifier_b, proof, result); } assert!(batch.verify()); } diff --git a/w3f-ring-proof/src/multi_ring_batch_verifier.rs b/w3f-ring-proof/src/multi_ring_batch_verifier.rs index 9590802..dc19b33 100644 --- a/w3f-ring-proof/src/multi_ring_batch_verifier.rs +++ b/w3f-ring-proof/src/multi_ring_batch_verifier.rs @@ -79,8 +79,8 @@ where /// Accumulates proofs from one or more rings (keysets) into a single batched /// pairing check. All rings must share the same KZG SRS. /// -/// Holds its own transcript instance, cloned on each `push_prepared` so the -/// per-proof entropy can be folded in without touching the originating +/// Holds its own transcript instance, cloned on each `push_prepared` call so +/// the per-proof entropy can be folded in without touching the originating /// `RingVerifier`. The transcript's initial state is not load-bearing; any /// valid `T` works (e.g. the prelude of any ring verifier being batched). pub struct BatchVerifier @@ -103,26 +103,8 @@ where } } - /// Accumulates a prepared `BatchItem` into the batch. - pub fn push(&mut self, item: BatchItem) - where - J: TECurveConfig, - { - let mut ts = self.transcript.clone(); - ts._add_serializable(b"batch-entropy", &item.entropy); - self.acc - .accumulate(item.piop, item.proof, item.challenges, &mut ts.to_rng()); - } - - /// Adds a raw ring proof to the batch. - /// - /// Equivalent to `self.push(BatchItem::new(verifier, proof, result))`: - /// preparation (transcript replay, challenge derivation, PIOP setup) and - /// accumulation happen internally. Use the two-step form directly when - /// preparation should be parallelized — `BatchItem::new` is independent - /// of the accumulator state, so multiple items can be built in parallel - /// and then pushed sequentially via [`push`](Self::push). - pub fn push_raw( + /// Adds a ring proof to the batch. + pub fn push( &mut self, verifier: &RingVerifier, J, T>, proof: RingProof>, @@ -130,7 +112,25 @@ where ) where J: TECurveConfig, { - self.push(BatchItem::new(verifier, proof, result)); + self.push_prepared(BatchItem::new(verifier, proof, result)); + } + + /// Accumulates a prepared [`BatchItem`] into the batch. + /// + /// Equivalent to [`push`](Self::push), but splits the work: the caller + /// builds the [`BatchItem`] (transcript replay, challenge derivation, + /// PIOP setup) separately from accumulation. Useful when preparation + /// should be parallelized. `BatchItem::new` is independent of the + /// accumulator state, so multiple items can be built in parallel and + /// then pushed sequentially here. + pub fn push_prepared(&mut self, item: BatchItem) + where + J: TECurveConfig, + { + let mut ts = self.transcript.clone(); + ts._add_serializable(b"batch-entropy", &item.entropy); + self.acc + .accumulate(item.piop, item.proof, item.challenges, &mut ts.to_rng()); } /// Verifies all accumulated proofs in a single batched pairing check. diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index 64c32ec..39b6309 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -112,7 +112,7 @@ where self.plonk_verifier.transcript_prelude.clone(), ); for (proof, result) in proofs.into_iter().zip(results) { - batch.push_raw(self, proof, result); + batch.push(self, proof, result); } batch.verify() }