From 488904a40215716c5453cd415eb22e44bcb91201 Mon Sep 17 00:00:00 2001 From: Srinath Setty Date: Thu, 18 Jun 2026 17:51:56 -0700 Subject: [PATCH 1/3] uniform handling of hyperkzg and mercury --- src/provider/hyperkzg.rs | 45 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/provider/hyperkzg.rs b/src/provider/hyperkzg.rs index 8a2517b8..cb4c4868 100644 --- a/src/provider/hyperkzg.rs +++ b/src/provider/hyperkzg.rs @@ -813,10 +813,8 @@ pub struct EvaluationArgument where E::GE: PairingGroup, { - #[serde_as(as = "Vec")] - com: Vec>, - #[serde_as(as = "[EvmCompatSerde; 3]")] - w: [G1Affine; 3], + com: Vec>, + w: [Commitment; 3], #[serde_as(as = "Vec<[EvmCompatSerde; 3]>")] v: Vec<[E::Scalar; 3]>, } @@ -826,15 +824,15 @@ where E::GE: PairingGroup, { /// Create a new evaluation argument - pub fn new(com: Vec>, w: [G1Affine; 3], v: Vec<[E::Scalar; 3]>) -> Self { + pub fn new(com: Vec>, w: [Commitment; 3], v: Vec<[E::Scalar; 3]>) -> Self { Self { com, w, v } } /// The KZG commitments to intermediate polynomials - pub fn com(&self) -> &[G1Affine] { + pub fn com(&self) -> &[Commitment] { &self.com } /// The KZG witnesses for batch openings - pub fn w(&self) -> &[G1Affine] { + pub fn w(&self) -> &[Commitment] { &self.w } /// The evaluations of the polynomials at challenge points @@ -855,7 +853,7 @@ where { // This impl block defines helper functions that are not a part of // EvaluationEngineTrait, but that we will use to implement the trait methods. - fn compute_challenge(com: &[G1Affine], transcript: &mut ::TE) -> E::Scalar { + fn compute_challenge(com: &[Commitment], transcript: &mut ::TE) -> E::Scalar { transcript.absorb(b"c", &com.to_vec().as_slice()); transcript.squeeze(b"c").unwrap() @@ -885,7 +883,10 @@ where q_powers } - fn verifier_second_challenge(W: &[G1Affine], transcript: &mut ::TE) -> E::Scalar { + fn verifier_second_challenge( + W: &[Commitment], + transcript: &mut ::TE, + ) -> E::Scalar { transcript.absorb(b"W", &W.to_vec().as_slice()); transcript.squeeze(b"d").unwrap() @@ -929,7 +930,7 @@ where let x: Vec = point.to_vec(); //////////////// begin helper closures ////////// - let kzg_open = |f: &[E::Scalar], u: E::Scalar| -> G1Affine { + let kzg_open = |f: &[E::Scalar], u: E::Scalar| -> Commitment { // Divides polynomial f(x) by (x - u) to obtain the witness polynomial h(x) = f(x)/(x - u) // for KZG opening. // @@ -995,13 +996,13 @@ where let target_chunks = DEFAULT_TARGET_CHUNKS; let h = &div_by_monomial(f, u, target_chunks); - E::CE::commit(ck, h, &E::Scalar::ZERO).comm.affine() + E::CE::commit(ck, h, &E::Scalar::ZERO) }; let kzg_open_batch = |f: &[Vec], u: &[E::Scalar; 3], transcript: &mut ::TE| - -> (Vec>, Vec<[E::Scalar; 3]>) { + -> (Vec>, Vec<[E::Scalar; 3]>) { let poly_eval = |f: &[E::Scalar], u: E::Scalar| -> E::Scalar { // Horner's method let mut acc = E::Scalar::ZERO; @@ -1056,7 +1057,7 @@ where let w = u .into_par_iter() .map(|ui| kzg_open(&B, *ui)) - .collect::>>(); + .collect::>>(); // The prover computes the challenge to keep the transcript in the same // state as that of the verifier @@ -1091,10 +1092,7 @@ where // We do not need to commit to the first polynomial as it is already committed. // Compute commitments in parallel let r = vec![E::Scalar::ZERO; ell - 1]; - let com: Vec> = E::CE::batch_commit(ck, &polys[1..], r.as_slice()) - .par_iter() - .map(|i| i.comm.affine()) - .collect(); + let com: Vec> = E::CE::batch_commit(ck, &polys[1..], r.as_slice()); // Phase 2 // We do not need to add x to the transcript, because in our context x was obtained from the transcript. @@ -1198,6 +1196,9 @@ where }) .collect::>(); + let com_affine: Vec> = pi.com.iter().map(|c| c.into_inner().affine()).collect(); + let w_affine: Vec> = pi.w.iter().map(|c| c.into_inner().affine()).collect(); + let L = E::GE::vartime_multiscalar_mul( &[ &q_powers_multiplied[..], @@ -1211,16 +1212,16 @@ where .concat(), &[ &[C.comm.affine()][..], - &pi.com, - &pi.w, + &com_affine, + &w_affine, slice::from_ref(&vk.G), ] .concat(), ); - let R0 = E::GE::group(&pi.w[0]); - let R1 = E::GE::group(&pi.w[1]); - let R2 = E::GE::group(&pi.w[2]); + let R0 = pi.w[0].into_inner(); + let R1 = pi.w[1].into_inner(); + let R2 = pi.w[2].into_inner(); let R = R0 + R1 * d_0 + R2 * d_1; // Check that e(L, vk.H) == e(R, vk.tau_H) From d7fa23d76496701bce4a465c725ba5cb1408441b Mon Sep 17 00:00:00 2001 From: Srinath Setty Date: Thu, 18 Jun 2026 17:55:49 -0700 Subject: [PATCH 2/3] update version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e6cafed4..e07a9b89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nova-snark" -version = "0.72.0" +version = "0.73.0" authors = ["Srinath Setty "] edition = "2021" description = "High-speed recursive arguments from folding schemes" From 19d9aeba83c77685e2794311cbd98f8b28329e01 Mon Sep 17 00:00:00 2001 From: Srinath Setty Date: Thu, 18 Jun 2026 18:30:57 -0700 Subject: [PATCH 3/3] =?UTF-8?q?flip=20the=20transcript=20encoding=20to=20?= =?UTF-8?q?=C2=A01=20=3D=20infinity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/provider/hyperkzg.rs | 3 ++- src/provider/pedersen.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/provider/hyperkzg.rs b/src/provider/hyperkzg.rs index cb4c4868..406ab58d 100644 --- a/src/provider/hyperkzg.rs +++ b/src/provider/hyperkzg.rs @@ -236,7 +236,8 @@ where { fn to_transcript_bytes(&self) -> Vec { let (x, y, is_infinity) = self.comm.to_coordinates(); - let is_infinity_byte = (!is_infinity).into(); + // Encode the infinity flag as 1 = infinity, matching the RO and in-circuit conventions. + let is_infinity_byte = is_infinity.into(); [ x.to_transcript_bytes(), y.to_transcript_bytes(), diff --git a/src/provider/pedersen.rs b/src/provider/pedersen.rs index 45ebda97..9eba020a 100644 --- a/src/provider/pedersen.rs +++ b/src/provider/pedersen.rs @@ -106,7 +106,8 @@ where { fn to_transcript_bytes(&self) -> Vec { let (x, y, is_infinity) = self.comm.to_coordinates(); - let is_infinity_byte = (!is_infinity).into(); + // Encode the infinity flag as 1 = infinity, matching the RO and in-circuit conventions. + let is_infinity_byte = is_infinity.into(); [ x.to_transcript_bytes(), y.to_transcript_bytes(),