diff --git a/src/provider/non_hiding_kzg.rs b/src/provider/non_hiding_kzg.rs index f7384dac7..cd633fd51 100644 --- a/src/provider/non_hiding_kzg.rs +++ b/src/provider/non_hiding_kzg.rs @@ -3,16 +3,14 @@ use abomonation_derive::Abomonation; use ff::{Field, PrimeField, PrimeFieldBits}; use group::{prime::PrimeCurveAffine, Curve, Group as _}; use pairing::{Engine, MillerLoopResult, MultiMillerLoop}; -use rand::Rng; use rand_core::{CryptoRng, RngCore}; -use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; use std::{borrow::Borrow, marker::PhantomData, ops::Mul}; use crate::{ errors::{NovaError, PCSError}, - provider::util::fb_msm, provider::traits::DlogGroup, + provider::util::fb_msm, traits::{commitment::Len, Group, TranscriptReprTrait}, }; @@ -256,19 +254,6 @@ where Ok(UVKZGCommitment(C.to_affine())) } - /// Generate a commitment for a list of polynomials - pub fn batch_commit( - prover_param: impl Borrow>, - polys: &[UVKZGPoly], - ) -> Result>, NovaError> { - let prover_param = prover_param.borrow(); - - polys - .into_par_iter() - .map(|poly| Self::commit(prover_param, poly)) - .collect::>, NovaError>>() - } - /// On input a polynomial `p` and a point `point`, outputs a proof for the /// same. pub fn open( @@ -298,32 +283,9 @@ where )) } - /// Input a list of polynomials, and a same number of points, - /// compute a multi-opening for all the polynomials. - // This is a naive approach - // TODO: to implement a more efficient batch opening algorithm - // (e.g., the appendix C.4 in https://eprint.iacr.org/2020/1536.pdf) - pub fn batch_open( - prover_param: impl Borrow>, - polynomials: &[UVKZGPoly], - points: &[E::Fr], - ) -> Result<(Vec>, Vec>), NovaError> { - if polynomials.len() != points.len() { - return Err(NovaError::PCSError(PCSError::LengthError)); - } - let mut batch_proof = vec![]; - let mut evals = vec![]; - for (poly, point) in polynomials.iter().zip(points.iter()) { - let (proof, eval) = Self::open(prover_param.borrow(), poly, point)?; - batch_proof.push(proof); - evals.push(eval); - } - - Ok((batch_proof, evals)) - } - /// Verifies that `value` is the evaluation at `x` of the polynomial /// committed inside `comm`. + #[allow(dead_code)] pub fn verify( verifier_param: impl Borrow>, commitment: &UVKZGCommitment, @@ -348,69 +310,19 @@ where let pairing_result = E::multi_miller_loop(pairing_input_refs.as_slice()).final_exponentiation(); Ok(pairing_result.is_identity().into()) } - - /// Verifies that `value_i` is the evaluation at `x_i` of the polynomial - /// `poly_i` committed inside `comm`. - // This is a naive approach - // TODO: to implement the more efficient batch verification algorithm - // (e.g., the appendix C.4 in https://eprint.iacr.org/2020/1536.pdf) - pub fn batch_verify( - verifier_params: impl Borrow>, - multi_commitment: &[UVKZGCommitment], - points: &[E::Fr], - values: &[UVKZGEvaluation], - batch_proof: &[UVKZGProof], - rng: &mut R, - ) -> Result { - let verifier_params = verifier_params.borrow(); - - let mut total_c = ::identity(); - let mut total_w = ::identity(); - - let mut randomizer = E::Fr::ONE; - // Instead of multiplying g and gamma_g in each turn, we simply accumulate - // their coefficients and perform a final multiplication at the end. - let mut g_multiplier = E::Fr::ZERO; - for (((c, z), v), proof) in multi_commitment - .iter() - .zip(points) - .zip(values) - .zip(batch_proof) - { - let w = proof.proof; - let mut temp = w.mul(*z); - temp += &c.0; - let c = temp; - g_multiplier += &(randomizer * v.0); - total_c += &c.mul(randomizer); - total_w += &w.mul(randomizer); - // We don't need to sample randomizers from the full field, - // only from 128-bit strings. - randomizer = E::Fr::from_u128(rng.gen::()); - } - total_c -= &verifier_params.g.mul(g_multiplier); - - let mut affine_points = vec![E::G1Affine::identity(); 2]; - E::G1::batch_normalize(&[-total_w, total_c], &mut affine_points); - let (total_w, total_c) = (affine_points[0], affine_points[1]); - - let result = E::multi_miller_loop(&[ - (&total_w, &verifier_params.beta_h.into()), - (&total_c, &verifier_params.h.into()), - ]) - .final_exponentiation() - .is_identity() - .into(); - - Ok(result) - } } #[cfg(test)] mod tests { + use super::*; + use crate::spartan::polys::univariate::UniPoly; use rand::{thread_rng, Rng}; + use rand_core::{CryptoRng, RngCore}; - use super::*; + fn random(degree: usize, mut rng: &mut R) -> UVKZGPoly { + let coeffs = (0..=degree).map(|_| F::random(&mut rng)).collect(); + UniPoly::new(coeffs) + } fn end_to_end_test_template() -> Result<(), NovaError> where @@ -424,7 +336,7 @@ mod tests { let pp = UVUniversalKZGParam::::gen_srs_for_testing(&mut rng, degree); let (ck, vk) = pp.trim(degree); - let p = UVKZGPoly::random(degree, rng); + let p = random(degree, rng); let comm = UVKZGPCS::::commit(&ck, &p)?; let point = E::Fr::random(rng); let (proof, value) = UVKZGPCS::::open(&ck, &p, &point)?; @@ -438,51 +350,8 @@ mod tests { Ok(()) } - fn batch_check_test_template() -> Result<(), NovaError> - where - E: MultiMillerLoop, - E::G1: DlogGroup, - E::Fr: PrimeFieldBits, - { - for _ in 0..10 { - let mut rng = &mut thread_rng(); - - let degree = rng.gen_range(2..20); - - let pp = UVUniversalKZGParam::::gen_srs_for_testing(&mut rng, degree); - let (ck, vk) = pp.trim(degree); - - let mut comms = Vec::new(); - let mut values = Vec::new(); - let mut points = Vec::new(); - let mut proofs = Vec::new(); - for _ in 0..10 { - let mut rng = rng.clone(); - let p = UVKZGPoly::random(degree, &mut rng); - let comm = UVKZGPCS::::commit(&ck, &p)?; - let point = E::Fr::random(rng); - let (proof, value) = UVKZGPCS::::open(&ck, &p, &point)?; - - assert!(UVKZGPCS::::verify(&vk, &comm, &point, &proof, &value)?); - comms.push(comm); - values.push(value); - points.push(point); - proofs.push(proof); - } - assert!(UVKZGPCS::::batch_verify( - &vk, &comms, &points, &values, &proofs, &mut rng - )?); - } - Ok(()) - } - #[test] fn end_to_end_test() { end_to_end_test_template::().expect("test failed for Bn256"); } - - #[test] - fn batch_check_test() { - batch_check_test_template::().expect("test failed for Bn256"); - } } diff --git a/src/provider/non_hiding_zeromorph.rs b/src/provider/non_hiding_zeromorph.rs index 80b06a0e0..4e57eabf2 100644 --- a/src/provider/non_hiding_zeromorph.rs +++ b/src/provider/non_hiding_zeromorph.rs @@ -523,10 +523,9 @@ where mod test { use std::iter; - - use halo2curves::bn256::Fr as Scalar; use ff::{Field, PrimeField, PrimeFieldBits}; use halo2curves::bn256::Bn256; + use halo2curves::bn256::Fr as Scalar; use pairing::MultiMillerLoop; use rand::thread_rng; use rand_chacha::ChaCha20Rng; @@ -535,13 +534,13 @@ mod test { use super::quotients; use crate::{ provider::{ - Bn256Engine, keccak::Keccak256Transcript, non_hiding_kzg::{UVKZGPoly, UVUniversalKZGParam}, non_hiding_zeromorph::{ batched_lifted_degree_quotient, eval_and_quotient_scalars, trim, ZMEvaluation, ZMPCS, }, traits::DlogGroup, + Bn256Engine, }, spartan::polys::multilinear::MultilinearPolynomial, traits::{Engine as NovaEngine, Group, TranscriptEngineTrait, TranscriptReprTrait}, @@ -613,9 +612,7 @@ mod test { // Construct a random multilinear polynomial f, and u such that f(u) = v. let mut rng = ChaCha20Rng::from_seed([0u8; 32]); let poly = MultilinearPolynomial::random(num_vars, &mut rng); - let u_challenge: Vec<_> = (0..num_vars) - .map(|_| Scalar::random(&mut rng)) - .collect(); + let u_challenge: Vec<_> = (0..num_vars).map(|_| Scalar::random(&mut rng)).collect(); let v_evaluation = poly.evaluate(&u_challenge); // Compute the multilinear quotients q_k = q_k(X_0, ..., X_{k-1}) @@ -627,9 +624,7 @@ mod test { // Check that the identity holds for a random evaluation point z // poly - poly(z) = Σ (X_k - z_k) * q_k(X_0, ..., X_{k-1}) // except for our inversion of coefficient order in polynomials and points (see below) - let z_challenge: Vec<_> = (0..num_vars) - .map(|_| Scalar::random(&mut rng)) - .collect(); + let z_challenge: Vec<_> = (0..num_vars).map(|_| Scalar::random(&mut rng)).collect(); let mut result = poly.evaluate(&z_challenge); result -= v_evaluation; diff --git a/src/spartan/polys/multilinear.rs b/src/spartan/polys/multilinear.rs index d13132865..55af5bf63 100644 --- a/src/spartan/polys/multilinear.rs +++ b/src/spartan/polys/multilinear.rs @@ -197,8 +197,8 @@ mod tests { use super::*; use pasta_curves::Fp; -use rand_chacha::ChaCha20Rng; -use rand_core::SeedableRng; + use rand_chacha::ChaCha20Rng; + use rand_core::SeedableRng; fn make_mlp(len: usize, value: F) -> MultilinearPolynomial { MultilinearPolynomial { diff --git a/src/spartan/polys/univariate.rs b/src/spartan/polys/univariate.rs index 54c6f1013..4bc85e486 100644 --- a/src/spartan/polys/univariate.rs +++ b/src/spartan/polys/univariate.rs @@ -7,7 +7,6 @@ use std::{ }; use ff::PrimeField; -use rand_core::{CryptoRng, RngCore}; use rayon::prelude::{IntoParallelIterator, IntoParallelRefMutIterator, ParallelIterator}; use ref_cast::RefCast; use serde::{Deserialize, Serialize}; @@ -40,11 +39,6 @@ impl UniPoly { UniPoly::new(Vec::new()) } - pub fn random(degree: usize, mut rng: &mut R) -> Self { - let coeffs = (0..=degree).map(|_| Scalar::random(&mut rng)).collect(); - UniPoly::new(coeffs) - } - /// Divide self by another polynomial, and returns the /// quotient and remainder. pub fn divide_with_q_and_r(&self, divisor: &Self) -> Option<(UniPoly, UniPoly)> { @@ -235,9 +229,8 @@ impl AsRef> for UniPoly { #[cfg(test)] mod tests { - use crate::provider::{bn256_grumpkin, secp_secq::secp256k1}; - use super::*; + use crate::provider::{bn256_grumpkin, secp_secq::secp256k1}; fn test_from_evals_quad_with() { // polynomial is 2x^2 + 3x + 1