From b354f028efc84934f4411b8b7200f27e4271a5f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= <4142+huitseeker@users.noreply.github.com> Date: Fri, 26 Jan 2024 07:20:36 -0500 Subject: [PATCH] Minor MLKZG adjustments (Nova forward ports) (#283) * refactor: move mlkzg -> hyperkzg * refactor: Refactor HyperKZG comments This is a port of the following upstream PRs: - https://github.com/microsoft/Nova/pull/299 - https://github.com/microsoft/Nova/pull/300 * refactor: Refactor engine and testing parameters in pcs.rs - in the IPA Evaluation Engine, transitioning from GrumpkinEngine to Bn256Engine, - avoids noise due to field arithmetic differences --- benches/pcs.rs | 9 +++++---- examples/and.rs | 2 +- examples/minroot.rs | 2 +- src/lib.rs | 2 +- src/provider/{mlkzg.rs => hyperkzg.rs} | 26 +++++++++++++++++--------- src/provider/mod.rs | 2 +- 6 files changed, 26 insertions(+), 17 deletions(-) rename src/provider/{mlkzg.rs => hyperkzg.rs} (92%) diff --git a/benches/pcs.rs b/benches/pcs.rs index f7946e71d..f8cf4b2e6 100644 --- a/benches/pcs.rs +++ b/benches/pcs.rs @@ -1,6 +1,7 @@ use arecibo::provider::{ - ipa_pc::EvaluationEngine as IPAEvaluationEngine, mlkzg::EvaluationEngine as MLEvaluationEngine, - non_hiding_zeromorph::ZMPCS, Bn256EngineKZG, Bn256EngineZM, GrumpkinEngine, + hyperkzg::EvaluationEngine as MLEvaluationEngine, + ipa_pc::EvaluationEngine as IPAEvaluationEngine, non_hiding_zeromorph::ZMPCS, Bn256Engine, + Bn256EngineKZG, Bn256EngineZM, }; use arecibo::spartan::polys::multilinear::MultilinearPolynomial; use arecibo::traits::{ @@ -154,8 +155,8 @@ fn bench_pcs(c: &mut Criterion) { NUM_VARS_TEST_VECTOR, bench_pcs_proving_internal, bench_pcs_verifying_internal, - (ipa_assets, IPAEvaluationEngine), - (mlkzg_assets, MLEvaluationEngine), + (ipa_assets, IPAEvaluationEngine), + (hyperkzg_assets, MLEvaluationEngine), (zm_assets, ZMPCS) ); } diff --git a/examples/and.rs b/examples/and.rs index 147f07d30..c0fb0ece4 100644 --- a/examples/and.rs +++ b/examples/and.rs @@ -23,7 +23,7 @@ use std::time::Instant; type E1 = Bn256EngineKZG; type E2 = GrumpkinEngine; -type EE1 = arecibo::provider::mlkzg::EvaluationEngine; +type EE1 = arecibo::provider::hyperkzg::EvaluationEngine; type EE2 = arecibo::provider::ipa_pc::EvaluationEngine; type S1 = arecibo::spartan::snark::RelaxedR1CSSNARK; // non-preprocessing SNARK type S2 = arecibo::spartan::snark::RelaxedR1CSSNARK; // non-preprocessing SNARK diff --git a/examples/minroot.rs b/examples/minroot.rs index c81397018..eba82fe8f 100644 --- a/examples/minroot.rs +++ b/examples/minroot.rs @@ -350,7 +350,7 @@ fn main() { let start = Instant::now(); type E1 = Bn256EngineKZG; type E2 = GrumpkinEngine; - type EE1 = arecibo::provider::mlkzg::EvaluationEngine; + type EE1 = arecibo::provider::hyperkzg::EvaluationEngine; type EE2 = arecibo::provider::ipa_pc::EvaluationEngine; type S1 = arecibo::spartan::snark::RelaxedR1CSSNARK; // non-preprocessing SNARK type S2 = arecibo::spartan::snark::RelaxedR1CSSNARK; // non-preprocessing SNARK diff --git a/src/lib.rs b/src/lib.rs index c28942c78..a0b367261 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1383,7 +1383,7 @@ mod tests { test_ivc_nontrivial_with_spark_compression_with::< Bn256EngineKZG, GrumpkinEngine, - provider::mlkzg::EvaluationEngine, + provider::hyperkzg::EvaluationEngine, EE<_>, >(); } diff --git a/src/provider/mlkzg.rs b/src/provider/hyperkzg.rs similarity index 92% rename from src/provider/mlkzg.rs rename to src/provider/hyperkzg.rs index 4e6b50ff3..5dbb5a6e2 100644 --- a/src/provider/mlkzg.rs +++ b/src/provider/hyperkzg.rs @@ -1,4 +1,10 @@ -//! This module implements Nova's evaluation engine using multilinear KZG +//! This module implements Nova's evaluation engine using `HyperKZG`, a KZG-based polynomial commitment for multilinear polynomials +//! HyperKZG is based on the transformation from univariate PCS to multilinear PCS in the Gemini paper (section 2.4.2 in https://eprint.iacr.org/2022/420.pdf). +//! However, there are some key differences: +//! (1) HyperKZG works with multilinear polynomials represented in evaluation form (rather than in coefficient form in Gemini's transformation). +//! This means that Spartan's polynomial IOP can use commit to its polynomials as-is without incurring any interpolations or FFTs. +//! (2) HyperKZG is specialized to use KZG as the univariate commitment scheme, so it includes several optimizations (both during the transformation of multilinear-to-univariate claims +//! and within the KZG commitment scheme implementation itself). #![allow(non_snake_case)] use crate::{ errors::NovaError, @@ -209,6 +215,8 @@ where assert_eq!(n, 1 << ell); // Below we assume that n is a power of two // Phase 1 -- create commitments com_1, ..., com_\ell + // We do not compute final Pi (and its commitment) as it is constant and equals to 'eval' + // also known to verifier, so can be derived on its side as well let mut polys: Vec> = Vec::new(); polys.push(hat_P.to_vec()); @@ -238,8 +246,8 @@ where .collect(); // Phase 2 - // We do not need to add x to the transcript, because in our context x was - // obtained from the transcript. + // We do not need to add x to the transcript, because in our context x was obtained from the transcript. + // We also do not need to absorb `C` and `eval` as they are already absorbed by the transcript by the caller let r = Self::compute_challenge(&comms, transcript); let u = vec![r, -r, r * r]; @@ -282,7 +290,7 @@ where assert!(t == 3); assert!(W.len() == 3); // We write a special case for t=3, since this what is required for - // mlkzg. Following the paper directly, we must compute: + // hyperkzg. Following the paper directly, we must compute: // let L0 = C_B - vk.G * B_u[0] + W[0] * u[0]; // let L1 = C_B - vk.G * B_u[1] + W[1] * u[1]; // let L2 = C_B - vk.G * B_u[2] + W[2] * u[2]; @@ -415,7 +423,7 @@ mod tests { type Fr = ::Scalar; #[test] - fn test_mlkzg_eval() { + fn test_hyperkzg_eval() { // Test with poly(X1, X2) = 1 + X1 + X2 + X1*X2 let n = 4; let ck: CommitmentKey = @@ -452,7 +460,7 @@ mod tests { } #[test] - fn test_mlkzg_alternative() { + fn test_hyperkzg_alternative() { fn test_inner(n: usize, poly: &[Fr], point: &[Fr], eval: Fr) -> Result<(), NovaError> { let ck: CommitmentKey = as CommitmentEngineTrait>::setup(b"test", n); @@ -500,7 +508,7 @@ mod tests { } #[test] - fn test_mlkzg() { + fn test_hyperkzg() { let n = 4; // poly = [1, 2, 1, 4] @@ -569,8 +577,8 @@ mod tests { } #[test] - fn test_mlkzg_more() { - // test the mlkzg prover and verifier with random instances (derived from a seed) + fn test_hyperkzg_more() { + // test the hyperkzg prover and verifier with random instances (derived from a seed) for num_vars in [4, 5, 6] { prove_verify_from_num_vars::<_, EvaluationEngine>(num_vars); } diff --git a/src/provider/mod.rs b/src/provider/mod.rs index aabdd8678..c52b517fd 100644 --- a/src/provider/mod.rs +++ b/src/provider/mod.rs @@ -1,8 +1,8 @@ //! This module implements Nova's traits using the following several different combinations // public modules to be used as an evaluation engine with Spartan +pub mod hyperkzg; pub mod ipa_pc; -pub mod mlkzg; pub mod non_hiding_zeromorph; // crate-public modules, made crate-public mostly for tests