From 06bbc1a5a3996e1fd1949cece36256daece61879 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 28 Jan 2026 16:56:39 +0100 Subject: [PATCH 01/12] Reference davxy fflonk --- Cargo.toml | 5 ++++- w3f-plonk-common/src/kzg_acc.rs | 3 +-- w3f-ring-proof/src/lib.rs | 24 +++++++++++++++++++++--- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bc402de..ddd1cb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,8 @@ ark-ff = { version = "0.5", default-features = false } ark-ec = { version = "0.5", default-features = false } ark-poly = { version = "0.5", default-features = false } ark-serialize = { version = "0.5", default-features = false, features = ["derive"] } -w3f-pcs = { git = "https://github.com/w3f/fflonk", default-features = false } +w3f-pcs = { git = "https://github.com/davxy/fflonk", default-features = false } rayon = { version = "1", default-features = false } + +# [patch."https://github.com/w3f/fflonk"] +# w3f-pcs = { path = "/mnt/ssd/develop/w3f/fflonk" } diff --git a/w3f-plonk-common/src/kzg_acc.rs b/w3f-plonk-common/src/kzg_acc.rs index d49af79..8b487e7 100644 --- a/w3f-plonk-common/src/kzg_acc.rs +++ b/w3f-plonk-common/src/kzg_acc.rs @@ -4,11 +4,10 @@ use crate::{ColumnsCommited, ColumnsEvaluated, Proof}; use ark_ec::pairing::Pairing; use ark_ec::{CurveGroup, VariableBaseMSM}; use ark_ff::{PrimeField, Zero}; -use ark_std::iterable::Iterable; use ark_std::rand::Rng; use w3f_pcs::pcs::kzg::params::KzgVerifierKey; use w3f_pcs::pcs::kzg::{AccumulatedOpening, KZG}; -use w3f_pcs::pcs::{Commitment, PCS}; +use w3f_pcs::pcs::PCS; // Aggregates opennings for KZG commitments. // Somewhat similar to https://eprint.iacr.org/2020/499.pdf, section 8. diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index 239d20c..f44f898 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -153,11 +153,29 @@ mod tests { (pcs_params, piop_params) } - #[test] // cargo test test_ring_proof_kzg --release --features="print-trace" -- --show-output + // + // Batch vs sequential verification times (ms): + // + // | proofs | batch | sequential | speedup | + // |--------|--------|------------|---------| + // | 1 | 2.790 | 3.032 | 1.09x | + // | 2 | 3.218 | 6.425 | 2.00x | + // | 4 | 5.122 | 11.968 | 2.34x | + // | 8 | 6.487 | 23.922 | 3.69x | + // | 16 | 10.002 | 47.773 | 4.78x | + // | 32 | 16.601 | 95.570 | 5.76x | + // | 64 | 29.484 | 210.959 | 7.15x | + // | 128 | 52.170 | 422.217 | 8.09x | + // | 256 | 85.164 | 762.874 | 8.96x | + // + // Sequential verification scales linearly with proof count. Batch verification + // scales sub-linearly. + #[test] fn test_ring_proof_kzg() { - let (verifier, claims) = _test_ring_proof::>(2usize.pow(10), 10); - let t_verify_batch = start_timer!(|| "Verify Batch KZG"); + let batch_size: usize = 16; + let (verifier, claims) = _test_ring_proof::>(2usize.pow(10), batch_size); + let t_verify_batch = start_timer!(|| format!("Verify Batch KZG (batch={batch_size})")); let (blinded_pks, proofs) = claims.into_iter().unzip(); assert!(verifier.verify_batch_kzg(proofs, blinded_pks)); end_timer!(t_verify_batch); From 9af0789c1ced3b3149b9655710dc1ecfa979f9f0 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 28 Jan 2026 17:50:40 +0100 Subject: [PATCH 02/12] Batch verifier struct --- w3f-ring-proof/src/ring_verifier.rs | 86 ++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index 4f38cac..b48f366 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -89,40 +89,76 @@ where } } -impl RingVerifier, Jubjub, T> +/// Batch verifier for KZG PCS +pub struct KzgBatchVerifier where E: Pairing, - Jubjub: TECurveConfig, + J: TECurveConfig, T: PlonkTranscript>, { + acc: KzgAccumulator, + pub verifier: RingVerifier, J, T>, +} + +impl KzgBatchVerifier +where + E: Pairing, + J: TECurveConfig, + T: PlonkTranscript>, +{ + /// Push a proof in the batch + pub fn push(&mut self, proof: RingProof>, result: Affine) { + 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), + ); + self.acc.accumulate(piop, proof, challenges, &mut rng); + } + + /// Batch verify + 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. pub fn verify_batch_kzg( - &self, + self, proofs: Vec>>, - results: Vec>, + results: Vec>, ) -> bool { - let mut acc = KzgAccumulator::::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:: as PCS<_>>::C, Affine>::N_COLUMNS + 1, - PiopVerifier:: as PCS<_>>::C, Affine>::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>::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); } - acc.verify() + batch.verify() } } From 3764010fe38d12b662e6d20c3e881c7452e3dd34 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 28 Jan 2026 17:56:27 +0100 Subject: [PATCH 03/12] Remove cruft --- Cargo.toml | 5 +---- w3f-ring-proof/src/ring_verifier.rs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ddd1cb2..bc402de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,8 +13,5 @@ ark-ff = { version = "0.5", default-features = false } ark-ec = { version = "0.5", default-features = false } ark-poly = { version = "0.5", default-features = false } ark-serialize = { version = "0.5", default-features = false, features = ["derive"] } -w3f-pcs = { git = "https://github.com/davxy/fflonk", default-features = false } +w3f-pcs = { git = "https://github.com/w3f/fflonk", default-features = false } rayon = { version = "1", default-features = false } - -# [patch."https://github.com/w3f/fflonk"] -# w3f-pcs = { path = "/mnt/ssd/develop/w3f/fflonk" } diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index b48f366..5f9aa2b 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -96,7 +96,7 @@ where J: TECurveConfig, T: PlonkTranscript>, { - acc: KzgAccumulator, + pub acc: KzgAccumulator, pub verifier: RingVerifier, J, T>, } From 237aa063acb0fb50dcbde7a68750094ac6b5fb7b Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 28 Jan 2026 18:17:43 +0100 Subject: [PATCH 04/12] Default to ArkTranscript --- w3f-ring-proof/src/ring_verifier.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index b48f366..dd55724 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -90,7 +90,7 @@ where } /// Batch verifier for KZG PCS -pub struct KzgBatchVerifier +pub struct KzgBatchVerifier where E: Pairing, J: TECurveConfig, From 44725672c5120ae9e8d958d3860898ce9238b159 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 28 Jan 2026 18:43:52 +0100 Subject: [PATCH 05/12] Default to ArkTranscript --- w3f-ring-proof/src/ring_verifier.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index 5f9aa2b..c48b728 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -90,7 +90,7 @@ where } /// Batch verifier for KZG PCS -pub struct KzgBatchVerifier +pub struct KzgBatchVerifier where E: Pairing, J: TECurveConfig, From c771d3810f546b678e20da500884158d65190a1d Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Thu, 29 Jan 2026 18:39:09 +0100 Subject: [PATCH 06/12] Clone verifier transcript --- w3f-plonk-common/src/verifier.rs | 2 +- w3f-ring-proof/src/ring_verifier.rs | 52 ++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/w3f-plonk-common/src/verifier.rs b/w3f-plonk-common/src/verifier.rs index 7df1928..ec5de7b 100644 --- a/w3f-plonk-common/src/verifier.rs +++ b/w3f-plonk-common/src/verifier.rs @@ -14,7 +14,7 @@ pub struct PlonkVerifier, T: PlonkTranscript> { pub pcs_vk: CS::VK, // Transcript, // initialized with the public parameters and the commitments to the precommitted columns. - transcript_prelude: T, + pub transcript_prelude: T, } impl, T: PlonkTranscript> PlonkVerifier { diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index dd55724..61cb02a 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -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,7 +90,7 @@ where } } -/// Batch verifier for KZG PCS +/// Accumulating batch verifier for ring proofs using KZG polynomial commitment scheme. pub struct KzgBatchVerifier where E: Pairing, @@ -100,14 +101,30 @@ where 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>, { - /// Push a proof in the batch - pub fn push(&mut self, proof: RingProof>, result: Affine) { + /// Prepare + pub fn prepare( + &self, + proof: RingProof>, + result: Affine, + ) -> PreparedBatchItem { let (challenges, mut rng) = self.verifier.plonk_verifier.restore_challenges( &result, &proof, @@ -126,7 +143,32 @@ where (seed.x, seed.y), (seed_plus_result.x, seed_plus_result.y), ); - self.acc.accumulate(piop, proof, challenges, &mut rng); + + let mut entropy = [0_u8; 32]; + rng.fill_bytes(&mut entropy); + + PreparedBatchItem { + piop, + proof, + challenges, + entropy, + } + } + + 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); } /// Batch verify From 75ecdce589c49dbb3e500389d8196fd62a953447 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Thu, 29 Jan 2026 19:34:54 +0100 Subject: [PATCH 07/12] Parallel benches --- w3f-ring-proof/src/lib.rs | 42 ++++++++++++++++++++--------- w3f-ring-proof/src/ring_verifier.rs | 30 ++++++++++++++++++++- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index f44f898..ce64356 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -155,22 +155,38 @@ mod tests { // cargo test test_ring_proof_kzg --release --features="print-trace" -- --show-output // + // ## Parallel feature off + // // Batch vs sequential verification times (ms): // - // | proofs | batch | sequential | speedup | - // |--------|--------|------------|---------| - // | 1 | 2.790 | 3.032 | 1.09x | - // | 2 | 3.218 | 6.425 | 2.00x | - // | 4 | 5.122 | 11.968 | 2.34x | - // | 8 | 6.487 | 23.922 | 3.69x | - // | 16 | 10.002 | 47.773 | 4.78x | - // | 32 | 16.601 | 95.570 | 5.76x | - // | 64 | 29.484 | 210.959 | 7.15x | - // | 128 | 52.170 | 422.217 | 8.09x | - // | 256 | 85.164 | 762.874 | 8.96x | + // | proofs | sequential | batch | speedup | + // |--------|------------|--------|---------| + // | 1 | 3.032 | 2.790 | 1.09x | + // | 2 | 6.425 | 3.218 | 2.00x | + // | 4 | 11.968 | 5.122 | 2.34x | + // | 8 | 23.922 | 6.487 | 3.69x | + // | 16 | 47.773 | 10.002 | 4.78x | + // | 32 | 95.570 | 16.601 | 5.76x | + // | 64 | 210.959 | 29.484 | 7.15x | + // | 128 | 422.217 | 52.170 | 8.09x | + // | 256 | 762.874 | 85.164 | 8.96x | + // + // Sequential verification scales linearly with proof count. + // Batch verification scales sub-linearly. + // + // ## Parallel feature on // - // Sequential verification scales linearly with proof count. Batch verification - // scales sub-linearly. + // | proofs | sequential | batch | speedup | + // |--------|------------|--------|---------| + // | 1 | 3.548 | 2.678 | 1.32x | + // | 2 | 7.160 | 3.108 | 2.30x | + // | 4 | 14.323 | 3.115 | 4.60x | + // | 8 | 28.528 | 3.189 | 8.95x | + // | 16 | 57.961 | 3.818 | 15.18x | + // | 32 | 108.132 | 4.741 | 22.81x | + // | 64 | 218.614 | 6.042 | 36.18x | + // | 128 | 466.069 | 8.324 | 55.99x | + // | 256 | 895.605 | 11.869 | 75.46x | #[test] fn test_ring_proof_kzg() { let batch_size: usize = 16; diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index 63c54aa..4bf69e1 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -192,7 +192,8 @@ where } } - // Verifies a batch of proofs against the same ring. + /// Verifies a batch of proofs against the same ring. + #[cfg(not(feature = "parallel"))] pub fn verify_batch_kzg( self, proofs: Vec>>, @@ -205,3 +206,30 @@ where batch.verify() } } + +#[cfg(feature = "parallel")] +impl RingVerifier, J, T> +where + E: Pairing, + J: TECurveConfig, + T: PlonkTranscript> + Sync, +{ + /// Verifies a batch of proofs against the same ring. + pub fn verify_batch_kzg( + self, + proofs: Vec>>, + results: Vec>, + ) -> 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); + } + batch.verify() + } +} From ed6d7c42558386c2cf98869aa2903e0441a2a41e Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Thu, 29 Jan 2026 20:07:30 +0100 Subject: [PATCH 08/12] Fix --- w3f-ring-proof/src/lib.rs | 23 +++++++++++++++++++++-- w3f-ring-proof/src/piop/mod.rs | 3 +-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index ce64356..d0d675e 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -51,7 +51,7 @@ impl ArkTranscript { #[cfg(test)] mod tests { use ark_bls12_381::Bls12_381; - use ark_ec::CurveGroup; + use ark_ec::{AffineRepr, CurveGroup}; use ark_ed_on_bls12_381_bandersnatch::{BandersnatchConfig, EdwardsAffine, Fq, Fr}; use ark_std::ops::Mul; use ark_std::rand::Rng; @@ -67,7 +67,26 @@ mod tests { use super::*; - fn _test_ring_proof>( + impl> Clone for VerifierKey { + fn clone(&self) -> Self { + Self { + pcs_raw_vk: self.pcs_raw_vk.clone(), + fixed_columns_committed: self.fixed_columns_committed.clone(), + } + } + } + + impl, G: AffineRepr> Clone for ProverKey { + fn clone(&self) -> Self { + Self { + pcs_ck: self.pcs_ck.clone(), + fixed_columns: self.fixed_columns.clone(), + verifier_key: self.verifier_key.clone(), + } + } + } + + fn _test_ring_proof + Clone>( domain_size: usize, batch_size: usize, ) -> ( diff --git a/w3f-ring-proof/src/piop/mod.rs b/w3f-ring-proof/src/piop/mod.rs index 29cd41a..c1e02d0 100644 --- a/w3f-ring-proof/src/piop/mod.rs +++ b/w3f-ring-proof/src/piop/mod.rs @@ -127,14 +127,13 @@ impl> FixedColumns { } // #[derive(CanonicalSerialize, CanonicalDeserialize)] -#[derive(Clone)] pub struct ProverKey, G: AffineRepr> { pub(crate) pcs_ck: CS::CK, pub(crate) fixed_columns: FixedColumns, pub(crate) verifier_key: VerifierKey, // used in the Fiat-Shamir transform } -#[derive(Clone, Debug, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)] +#[derive(Debug, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize)] pub struct VerifierKey> { pub(crate) pcs_raw_vk: ::RVK, pub(crate) fixed_columns_committed: FixedColumnsCommitted, From 29e47bcdfc7921b88cf57589ae9f0e65c5846a67 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Fri, 30 Jan 2026 11:13:48 +0100 Subject: [PATCH 09/12] Revert built-in parallel accumulation for prepared proofs --- w3f-ring-proof/src/ring_verifier.rs | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index 4bf69e1..37b3e7b 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -193,7 +193,6 @@ where } /// Verifies a batch of proofs against the same ring. - #[cfg(not(feature = "parallel"))] pub fn verify_batch_kzg( self, proofs: Vec>>, @@ -206,30 +205,3 @@ where batch.verify() } } - -#[cfg(feature = "parallel")] -impl RingVerifier, J, T> -where - E: Pairing, - J: TECurveConfig, - T: PlonkTranscript> + Sync, -{ - /// Verifies a batch of proofs against the same ring. - pub fn verify_batch_kzg( - self, - proofs: Vec>>, - results: Vec>, - ) -> 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); - } - batch.verify() - } -} From c885dd7bb843760d62827435269d76337e7b491b Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Fri, 30 Jan 2026 11:32:02 +0100 Subject: [PATCH 10/12] Docs --- w3f-ring-proof/src/ring_verifier.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index 37b3e7b..0098259 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -119,7 +119,14 @@ where J: TECurveConfig, T: PlonkTranscript>, { - /// Prepare + /// 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>, @@ -156,6 +163,13 @@ where } } + /// 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); @@ -172,7 +186,7 @@ where self.push_prepared(item); } - /// Batch verify + /// Verifies all accumulated proofs in a single batched pairing check. pub fn verify(&self) -> bool { self.acc.verify() } From 2fbd0cbbc5a9889d46c4189b1724d1f3a9cf8312 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Fri, 30 Jan 2026 11:33:54 +0100 Subject: [PATCH 11/12] Remove cruft --- w3f-ring-proof/src/lib.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index d0d675e..de24e5a 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -174,8 +174,6 @@ mod tests { // cargo test test_ring_proof_kzg --release --features="print-trace" -- --show-output // - // ## Parallel feature off - // // Batch vs sequential verification times (ms): // // | proofs | sequential | batch | speedup | @@ -192,20 +190,6 @@ mod tests { // // Sequential verification scales linearly with proof count. // Batch verification scales sub-linearly. - // - // ## Parallel feature on - // - // | proofs | sequential | batch | speedup | - // |--------|------------|--------|---------| - // | 1 | 3.548 | 2.678 | 1.32x | - // | 2 | 7.160 | 3.108 | 2.30x | - // | 4 | 14.323 | 3.115 | 4.60x | - // | 8 | 28.528 | 3.189 | 8.95x | - // | 16 | 57.961 | 3.818 | 15.18x | - // | 32 | 108.132 | 4.741 | 22.81x | - // | 64 | 218.614 | 6.042 | 36.18x | - // | 128 | 466.069 | 8.324 | 55.99x | - // | 256 | 895.605 | 11.869 | 75.46x | #[test] fn test_ring_proof_kzg() { let batch_size: usize = 16; From 5638ceebda8db21d167ae059187e4ccc28f48c77 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Wed, 4 Feb 2026 11:14:35 +0100 Subject: [PATCH 12/12] Restore w3f fflonk --- Cargo.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e84d0b5..bc402de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,5 @@ ark-ff = { version = "0.5", default-features = false } ark-ec = { version = "0.5", default-features = false } ark-poly = { version = "0.5", default-features = false } ark-serialize = { version = "0.5", default-features = false, features = ["derive"] } -# TODO: restore w3f once https://github.com/w3f/fflonk/pull/46 gets merged -# w3f-pcs = { git = "https://github.com/w3f/fflonk", default-features = false } -w3f-pcs = { git = "https://github.com/davxy/fflonk", default-features = false } +w3f-pcs = { git = "https://github.com/w3f/fflonk", default-features = false } rayon = { version = "1", default-features = false }