From b0fd1b616cb0681ff59a531163b2e91542aef378 Mon Sep 17 00:00:00 2001 From: Jose Maldonado Date: Wed, 21 Jan 2026 00:33:18 -0500 Subject: [PATCH] Fix soundness bug: HyperKZG verify ignored pairing check --- poly_commit/src/kzg/uni_kzg/hyper_kzg.rs | 4 +- poly_commit/tests/test_uni_kzg.rs | 47 +++++++++++++++++++++++- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/poly_commit/src/kzg/uni_kzg/hyper_kzg.rs b/poly_commit/src/kzg/uni_kzg/hyper_kzg.rs index a3da52d0f..8f3afd7ae 100644 --- a/poly_commit/src/kzg/uni_kzg/hyper_kzg.rs +++ b/poly_commit/src/kzg/uni_kzg/hyper_kzg.rs @@ -252,9 +252,7 @@ where tau, lagrange_eval, opening.quotient_delta_x_commitment, - ); - - true + ) } pub fn multiple_points_batch_open_impl( diff --git a/poly_commit/tests/test_uni_kzg.rs b/poly_commit/tests/test_uni_kzg.rs index fbc2d8114..f402a26b4 100644 --- a/poly_commit/tests/test_uni_kzg.rs +++ b/poly_commit/tests/test_uni_kzg.rs @@ -3,7 +3,10 @@ mod common; use arith::{Field, Fr}; use ark_std::test_rng; use gkr_engine::ExpanderPCS; -use gkr_engine::{BN254Config, ExpanderSingleVarChallenge, MPIConfig, MPIEngine, Transcript}; +use gkr_engine::{BN254Config, ExpanderSingleVarChallenge, MPIConfig, MPIEngine, StructuredReferenceString, Transcript}; +use halo2curves::group::prime::PrimeCurveAffine; +use halo2curves::group::Curve; +use poly_commit::PolynomialCommitmentScheme; use gkr_hashers::Keccak256hasher; use halo2curves::bn256::Bn256; use poly_commit::HyperUniKZGPCS; @@ -99,3 +102,45 @@ fn test_uni_kzg_batch_open() { HyperUniKZGPCS, >(true); } + +#[test] +fn test_hyperkzg_rejects_corrupted_proof() { + let mut rng = test_rng(); + let num_vars = 4; + + let (srs, _) = + as PolynomialCommitmentScheme>::gen_srs_for_testing( + &num_vars, &mut rng, + ); + let (proving_key, verification_key) = srs.into_keys(); + + let poly = MultiLinearPoly::::random(num_vars, &mut rng); + let x: Vec = (0..num_vars).map(|_| Fr::random_unsafe(&mut rng)).collect(); + + let mut scratch_pad = (); + let commitment = + as PolynomialCommitmentScheme>::commit( + &num_vars, &proving_key, &poly, &mut scratch_pad, + ); + + let mut transcript = BytesHashTranscript::::new(); + let (eval, opening) = as PolynomialCommitmentScheme>::open( + &num_vars, &proving_key, &poly, &x, &scratch_pad, &mut transcript, + ); + + // Valid proof should pass + let mut transcript_v = BytesHashTranscript::::new(); + assert!( as PolynomialCommitmentScheme>::verify( + &num_vars, &verification_key, &commitment, &x, eval, &opening, &mut transcript_v, + )); + + // Corrupted proof should fail + let mut corrupted = opening.clone(); + corrupted.quotient_delta_x_commitment = + (corrupted.quotient_delta_x_commitment.to_curve() * Fr::from(2u64)).to_affine(); + + let mut transcript_c = BytesHashTranscript::::new(); + assert!(! as PolynomialCommitmentScheme>::verify( + &num_vars, &verification_key, &commitment, &x, eval, &corrupted, &mut transcript_c, + )); +}