From a035e2345498f0eb6e6ed81fd6929aa244842992 Mon Sep 17 00:00:00 2001 From: Davide Galassi Date: Tue, 4 Aug 2026 13:24:01 +0200 Subject: [PATCH] Batch verifiers reject proofs/results length mismatch --- w3f-ring-proof/src/lib.rs | 14 ++++++++++++++ w3f-ring-proof/src/ring_verifier.rs | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/w3f-ring-proof/src/lib.rs b/w3f-ring-proof/src/lib.rs index 77cee5b..72865c8 100644 --- a/w3f-ring-proof/src/lib.rs +++ b/w3f-ring-proof/src/lib.rs @@ -125,6 +125,20 @@ mod tests { _test_ring_proof::(2usize.pow(10), 1); } + // `zip` would silently drop unmatched elements, reporting success for + // inputs that received no verification at all (srlabs_findings#713). + #[test] + fn test_batch_length_mismatch_rejected() { + let (verifier, mut claims) = _test_ring_proof::>(2usize.pow(9), 1); + let (result, proof) = claims.pop().unwrap(); + assert!(verifier.verify(proof.clone(), result)); + + assert!(!verifier.verify_batch(Vec::new(), vec![result])); + assert!(!verifier.verify_batch(vec![proof.clone()], Vec::new())); + assert!(!verifier.verify_batch_kzg(Vec::new(), vec![result])); + assert!(!verifier.verify_batch_kzg(vec![proof], Vec::new())); + } + #[test] fn test_lagrangian_commitment() { let rng = &mut test_rng(); diff --git a/w3f-ring-proof/src/ring_verifier.rs b/w3f-ring-proof/src/ring_verifier.rs index 07cae81..49db50a 100644 --- a/w3f-ring-proof/src/ring_verifier.rs +++ b/w3f-ring-proof/src/ring_verifier.rs @@ -74,11 +74,16 @@ where &self.plonk_verifier.pcs_vk } + /// Verifies the proofs sequentially, pairing them with the results + /// positionally. Fails if the two vectors differ in length. pub fn verify_batch( &self, proofs: Vec>, results: Vec>, ) -> bool { + if proofs.len() != results.len() { + return false; + } for (proof, result) in proofs.into_iter().zip(results) { let res = self.verify(proof, result); if !res { @@ -97,11 +102,16 @@ where { /// Verifies a batch of proofs against this ring in a single batched /// pairing check, using a [`BatchVerifier`] under the hood. + /// Proofs are paired with the results positionally. Fails if the two + /// vectors differ in length. pub fn verify_batch_kzg( &self, proofs: Vec>>, results: Vec>, ) -> bool { + if proofs.len() != results.len() { + return false; + } let mut batch = BatchVerifier::new( self.plonk_verifier.pcs_vk.clone(), self.plonk_verifier.transcript_prelude.clone(),