From 938a88464dbd88f7e879867699c6d9ba025b9f93 Mon Sep 17 00:00:00 2001 From: Hossein Moghaddas Date: Mon, 15 Jan 2024 13:22:31 +0100 Subject: [PATCH 1/6] Fix for KZG10 --- poly-commit/src/kzg10/mod.rs | 70 ++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/poly-commit/src/kzg10/mod.rs b/poly-commit/src/kzg10/mod.rs index a6ea5752..13ad826b 100644 --- a/poly-commit/src/kzg10/mod.rs +++ b/poly-commit/src/kzg10/mod.rs @@ -8,7 +8,7 @@ use crate::{BTreeMap, Error, LabeledPolynomial, PCRandomness, ToString, Vec}; use ark_ec::AffineRepr; use ark_ec::{pairing::Pairing, CurveGroup}; -use ark_ec::{scalar_mul::fixed_base::FixedBase, VariableBaseMSM}; +use ark_ec::{scalar_mul::ScalarMul, VariableBaseMSM}; use ark_ff::{One, PrimeField, UniformRand, Zero}; use ark_poly::DenseUVPolynomial; use ark_std::{format, marker::PhantomData, ops::Div, ops::Mul, vec}; @@ -69,33 +69,39 @@ where let mut powers_of_beta = vec![E::ScalarField::one()]; let mut cur = beta; - for _ in 0..max_degree { + for _ in 0..=max_degree { powers_of_beta.push(cur); cur *= β } - let window_size = FixedBase::get_mul_window_size(max_degree + 1); - - let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize; let g_time = start_timer!(|| "Generating powers of G"); - let g_table = FixedBase::get_window_table(scalar_bits, window_size, g); - let powers_of_g = - FixedBase::msm::(scalar_bits, window_size, &g_table, &powers_of_beta); + let powers_of_g = g.batch_mul(&powers_of_beta[0..max_degree]); + + // let window_size = FixedBase::get_mul_window_size(max_degree + 1); + + // let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize; + // let g_table = FixedBase::get_window_table(scalar_bits, window_size, g); + // let powers_of_g = + // FixedBase::msm::(scalar_bits, window_size, &g_table, &powers_of_beta); end_timer!(g_time); + let gamma_g_time = start_timer!(|| "Generating powers of gamma * G"); - let gamma_g_table = FixedBase::get_window_table(scalar_bits, window_size, gamma_g); - let mut powers_of_gamma_g = - FixedBase::msm::(scalar_bits, window_size, &gamma_g_table, &powers_of_beta); + let powers_of_gamma_g = gamma_g + .batch_mul(&powers_of_beta) + .into_iter() + .enumerate() + .collect(); + // let gamma_g_table = FixedBase::get_window_table(scalar_bits, window_size, gamma_g); + // let mut powers_of_gamma_g = + // FixedBase::msm::(scalar_bits, window_size, &gamma_g_table, &powers_of_beta); // Add an additional power of gamma_g, because we want to be able to support // up to D queries. - powers_of_gamma_g.push(powers_of_gamma_g.last().unwrap().mul(&beta)); + // let last_gamma_g = powers_of_gamma_g.last().unwrap().mul(&beta); + // powers_of_gamma_g.push(last_gamma_g.into_affine()); end_timer!(gamma_g_time); - let powers_of_g = E::G1::normalize_batch(&powers_of_g); - let powers_of_gamma_g = E::G1::normalize_batch(&powers_of_gamma_g) - .into_iter() - .enumerate() - .collect(); + // let powers_of_g = E::G1::normalize_batch(&powers_of_g); + // let powers_of_gamma_g = E::G1::normalize_batch(&powers_of_gamma_g) let neg_powers_of_h_time = start_timer!(|| "Generating negative powers of h in G2"); let neg_powers_of_h = if produce_g2_powers { @@ -106,20 +112,22 @@ where cur /= β } - let neg_h_table = FixedBase::get_window_table(scalar_bits, window_size, h); - let neg_powers_of_h = FixedBase::msm::( - scalar_bits, - window_size, - &neg_h_table, - &neg_powers_of_beta, - ); - - let affines = E::G2::normalize_batch(&neg_powers_of_h); - let mut affines_map = BTreeMap::new(); - affines.into_iter().enumerate().for_each(|(i, a)| { - affines_map.insert(i, a); - }); - affines_map + // let neg_h_table = FixedBase::get_window_table(scalar_bits, window_size, h); + h.batch_mul(&neg_powers_of_beta).into_iter().enumerate().collect() + // let neg_powers_of_h = FixedBase::msm::( + // scalar_bits, + // window_size, + // &neg_h_table, + // &neg_powers_of_beta, + // ); + + // let affines = E::G2::normalize_batch(&neg_powers_of_h); + // let mut affines_map = BTreeMap::new(); + // neg_powers_of_h.into_iter().enumerate().collect(); + // for_each(|(i, a)| { + // affines_map.insert(i, a); + // }); + // affines_map } else { BTreeMap::new() }; From 196a2153b08d015f34e5cdadcffeefd87ad78fd2 Mon Sep 17 00:00:00 2001 From: Hossein Moghaddas Date: Mon, 15 Jan 2024 15:13:30 +0100 Subject: [PATCH 2/6] Fix the breaking changes in `ark-ec` --- poly-commit/src/kzg10/mod.rs | 41 +++-------------- poly-commit/src/marlin/marlin_pst13_pc/mod.rs | 26 +++-------- poly-commit/src/multilinear_pc/mod.rs | 45 ++++--------------- poly-commit/src/streaming_kzg/time.rs | 10 ++--- 4 files changed, 23 insertions(+), 99 deletions(-) diff --git a/poly-commit/src/kzg10/mod.rs b/poly-commit/src/kzg10/mod.rs index 13ad826b..5bebdaeb 100644 --- a/poly-commit/src/kzg10/mod.rs +++ b/poly-commit/src/kzg10/mod.rs @@ -69,20 +69,13 @@ where let mut powers_of_beta = vec![E::ScalarField::one()]; let mut cur = beta; - for _ in 0..=max_degree { + for _ in 0..=max_degree + 1 { powers_of_beta.push(cur); cur *= β } let g_time = start_timer!(|| "Generating powers of G"); - let powers_of_g = g.batch_mul(&powers_of_beta[0..max_degree]); - - // let window_size = FixedBase::get_mul_window_size(max_degree + 1); - - // let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize; - // let g_table = FixedBase::get_window_table(scalar_bits, window_size, g); - // let powers_of_g = - // FixedBase::msm::(scalar_bits, window_size, &g_table, &powers_of_beta); + let powers_of_g = g.batch_mul(&powers_of_beta[0..max_degree + 1]); end_timer!(g_time); let gamma_g_time = start_timer!(|| "Generating powers of gamma * G"); @@ -91,18 +84,8 @@ where .into_iter() .enumerate() .collect(); - // let gamma_g_table = FixedBase::get_window_table(scalar_bits, window_size, gamma_g); - // let mut powers_of_gamma_g = - // FixedBase::msm::(scalar_bits, window_size, &gamma_g_table, &powers_of_beta); - // Add an additional power of gamma_g, because we want to be able to support - // up to D queries. - // let last_gamma_g = powers_of_gamma_g.last().unwrap().mul(&beta); - // powers_of_gamma_g.push(last_gamma_g.into_affine()); end_timer!(gamma_g_time); - // let powers_of_g = E::G1::normalize_batch(&powers_of_g); - // let powers_of_gamma_g = E::G1::normalize_batch(&powers_of_gamma_g) - let neg_powers_of_h_time = start_timer!(|| "Generating negative powers of h in G2"); let neg_powers_of_h = if produce_g2_powers { let mut neg_powers_of_beta = vec![E::ScalarField::one()]; @@ -112,22 +95,10 @@ where cur /= β } - // let neg_h_table = FixedBase::get_window_table(scalar_bits, window_size, h); - h.batch_mul(&neg_powers_of_beta).into_iter().enumerate().collect() - // let neg_powers_of_h = FixedBase::msm::( - // scalar_bits, - // window_size, - // &neg_h_table, - // &neg_powers_of_beta, - // ); - - // let affines = E::G2::normalize_batch(&neg_powers_of_h); - // let mut affines_map = BTreeMap::new(); - // neg_powers_of_h.into_iter().enumerate().collect(); - // for_each(|(i, a)| { - // affines_map.insert(i, a); - // }); - // affines_map + h.batch_mul(&neg_powers_of_beta) + .into_iter() + .enumerate() + .collect() } else { BTreeMap::new() }; diff --git a/poly-commit/src/marlin/marlin_pst13_pc/mod.rs b/poly-commit/src/marlin/marlin_pst13_pc/mod.rs index 14b48052..15fe6b63 100644 --- a/poly-commit/src/marlin/marlin_pst13_pc/mod.rs +++ b/poly-commit/src/marlin/marlin_pst13_pc/mod.rs @@ -8,7 +8,7 @@ use crate::{LabeledCommitment, LabeledPolynomial, LinearCombination}; use crate::{PCRandomness, PCUniversalParams, PolynomialCommitment}; use crate::{ToString, Vec}; use ark_ec::AffineRepr; -use ark_ec::{pairing::Pairing, scalar_mul::fixed_base::FixedBase, CurveGroup, VariableBaseMSM}; +use ark_ec::{pairing::Pairing, scalar_mul::ScalarMul, CurveGroup, VariableBaseMSM}; use ark_ff::{One, PrimeField, UniformRand, Zero}; use ark_poly::{multivariate::Term, DenseMVPolynomial}; use ark_std::rand::RngCore; @@ -210,19 +210,13 @@ where }) .unzip(); - let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize; let g_time = start_timer!(|| "Generating powers of G"); - let window_size = FixedBase::get_mul_window_size(max_degree + 1); - let g_table = FixedBase::get_window_table(scalar_bits, window_size, g); - let mut powers_of_g = - FixedBase::msm::(scalar_bits, window_size, &g_table, &powers_of_beta); - powers_of_g.push(g); + let mut powers_of_g = g.batch_mul(&powers_of_beta); + powers_of_g.push(g.into_affine()); powers_of_beta_terms.push(P::Term::new(vec![])); end_timer!(g_time); let gamma_g_time = start_timer!(|| "Generating powers of gamma * G"); - let window_size = FixedBase::get_mul_window_size(max_degree + 2); - let gamma_g_table = FixedBase::get_window_table(scalar_bits, window_size, gamma_g); // Each element `i` of `powers_of_gamma_g` is a vector of length `max_degree+1` // containing `betas[i]^j \gamma G` for `j` from 1 to `max_degree+1` to support // up to `max_degree` queries @@ -230,27 +224,17 @@ where ark_std::cfg_iter_mut!(powers_of_gamma_g) .enumerate() .for_each(|(i, v)| { - let mut powers_of_beta = Vec::with_capacity(max_degree); + let mut powers_of_beta = Vec::with_capacity(max_degree + 1); let mut cur = E::ScalarField::one(); for _ in 0..=max_degree { cur *= &betas[i]; powers_of_beta.push(cur); } - *v = FixedBase::msm::( - scalar_bits, - window_size, - &gamma_g_table, - &powers_of_beta, - ); + *v = gamma_g.batch_mul(&powers_of_beta); }); end_timer!(gamma_g_time); - let powers_of_g = E::G1::normalize_batch(&powers_of_g); let gamma_g = gamma_g.into_affine(); - let powers_of_gamma_g = powers_of_gamma_g - .into_iter() - .map(|v| E::G1::normalize_batch(&v)) - .collect(); let beta_h: Vec<_> = betas.iter().map(|b| h.mul(b).into_affine()).collect(); let h = h.into_affine(); let prepared_h = h.into(); diff --git a/poly-commit/src/multilinear_pc/mod.rs b/poly-commit/src/multilinear_pc/mod.rs index bd5d3e53..2cb954eb 100644 --- a/poly-commit/src/multilinear_pc/mod.rs +++ b/poly-commit/src/multilinear_pc/mod.rs @@ -3,7 +3,7 @@ use crate::multilinear_pc::data_structures::{ }; use ark_ec::AffineRepr; use ark_ec::{pairing::Pairing, CurveGroup}; -use ark_ec::{scalar_mul::fixed_base::FixedBase, VariableBaseMSM}; +use ark_ec::{scalar_mul::ScalarMul, VariableBaseMSM}; use ark_ff::{Field, PrimeField}; use ark_ff::{One, Zero}; use ark_poly::{DenseMultilinearExtension, MultilinearExtension}; @@ -27,14 +27,11 @@ impl MultilinearPC { /// setup pub fn setup(num_vars: usize, rng: &mut R) -> UniversalParams { assert!(num_vars > 0, "constant polynomial not supported"); - let g: E::G1 = E::G1::rand(rng); - let h: E::G2 = E::G2::rand(rng); - let g = g.into_affine(); - let h = h.into_affine(); + let g = E::G1::rand(rng); + let h = E::G2::rand(rng); let mut powers_of_g = Vec::new(); let mut powers_of_h = Vec::new(); let t: Vec<_> = (0..num_vars).map(|_| E::ScalarField::rand(rng)).collect(); - let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize; let mut eq: LinkedList> = LinkedList::from_iter(eq_extension(&t).into_iter()); @@ -54,29 +51,13 @@ impl MultilinearPC { } let mut pp_powers = Vec::new(); - let mut total_scalars = 0; for i in 0..num_vars { let eq = eq_arr.pop_front().unwrap(); let pp_k_powers = (0..(1 << (num_vars - i))).map(|x| eq[x]); pp_powers.extend(pp_k_powers); - total_scalars += 1 << (num_vars - i); } - let window_size = FixedBase::get_mul_window_size(total_scalars); - let g_table = FixedBase::get_window_table(scalar_bits, window_size, g.into_group()); - let h_table = FixedBase::get_window_table(scalar_bits, window_size, h.into_group()); - - let pp_g = E::G1::normalize_batch(&FixedBase::msm( - scalar_bits, - window_size, - &g_table, - &pp_powers, - )); - let pp_h = E::G2::normalize_batch(&FixedBase::msm( - scalar_bits, - window_size, - &h_table, - &pp_powers, - )); + let pp_g = g.batch_mul(&pp_powers); + let pp_h = h.batch_mul(&pp_powers); let mut start = 0; for i in 0..num_vars { let size = 1 << (num_vars - i); @@ -89,18 +70,14 @@ impl MultilinearPC { // uncomment to measure the time for calculating vp // let vp_generation_timer = start_timer!(|| "VP generation"); - let g_mask = { - let window_size = FixedBase::get_mul_window_size(num_vars); - let g_table = FixedBase::get_window_table(scalar_bits, window_size, g.into_group()); - E::G1::normalize_batch(&FixedBase::msm(scalar_bits, window_size, &g_table, &t)) - }; + let g_mask = g.batch_mul(&t); // end_timer!(vp_generation_timer); UniversalParams { num_vars, - g, + g: g.into_affine(), g_mask, - h, + h: h.into_affine(), powers_of_g, powers_of_h, } @@ -199,11 +176,7 @@ impl MultilinearPC { ) -> bool { let left = E::pairing(commitment.g_product.into_group() - &vk.g.mul(value), vk.h); - let scalar_size = E::ScalarField::MODULUS_BIT_SIZE as usize; - let window_size = FixedBase::get_mul_window_size(vk.nv); - - let g_table = FixedBase::get_window_table(scalar_size, window_size, vk.g.into_group()); - let g_mul: Vec = FixedBase::msm(scalar_size, window_size, &g_table, point); + let g_mul = vk.g.into_group().batch_mul(point); let pairing_lefts: Vec<_> = (0..vk.nv) .map(|i| vk.g_mask_random[i].into_group() - &g_mul[i]) diff --git a/poly-commit/src/streaming_kzg/time.rs b/poly-commit/src/streaming_kzg/time.rs index 8c7fa2f8..b8d52093 100644 --- a/poly-commit/src/streaming_kzg/time.rs +++ b/poly-commit/src/streaming_kzg/time.rs @@ -1,9 +1,9 @@ //! An impementation of a time-efficient version of Kate et al's polynomial commitment, //! with optimization from [\[BDFG20\]](https://eprint.iacr.org/2020/081.pdf). use ark_ec::pairing::Pairing; -use ark_ec::scalar_mul::fixed_base::FixedBase; +use ark_ec::scalar_mul::ScalarMul; use ark_ec::CurveGroup; -use ark_ff::{PrimeField, Zero}; +use ark_ff::Zero; use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial}; use ark_std::{borrow::Borrow, ops::Div, ops::Mul, rand::RngCore, vec::Vec, UniformRand}; @@ -50,11 +50,7 @@ impl CommitterKey { let powers_of_tau = powers(tau, max_degree + 1); let g = E::G1::rand(rng); - let window_size = FixedBase::get_mul_window_size(max_degree + 1); - let scalar_bits = E::ScalarField::MODULUS_BIT_SIZE as usize; - let g_table = FixedBase::get_window_table(scalar_bits, window_size, g); - let powers_of_g_proj = FixedBase::msm(scalar_bits, window_size, &g_table, &powers_of_tau); - let powers_of_g = E::G1::normalize_batch(&powers_of_g_proj); + let powers_of_g = g.batch_mul(&powers_of_tau); let g2 = E::G2::rand(rng).into_affine(); let powers_of_g2 = powers_of_tau From 4478505259c335c7707b5bf5f1f277888cc66b22 Mon Sep 17 00:00:00 2001 From: Hossein Moghaddas Date: Mon, 15 Jan 2024 15:15:44 +0100 Subject: [PATCH 3/6] Remove the extra loop --- poly-commit/src/lib.rs | 632 ++++++++++++++++++++--------------------- 1 file changed, 314 insertions(+), 318 deletions(-) diff --git a/poly-commit/src/lib.rs b/poly-commit/src/lib.rs index 23245476..599db692 100644 --- a/poly-commit/src/lib.rs +++ b/poly-commit/src/lib.rs @@ -656,83 +656,81 @@ pub mod tests { { let sponge = sponge(); - for __ in 0..1 { - let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap(); - let max_degree = 100; - let pp = PC::setup(max_degree, None, rng)?; - for _ in 0..10 { - let supported_degree = Uniform::from(1..=max_degree).sample(rng); - assert!( - max_degree >= supported_degree, - "max_degree < supported_degree" - ); - - let mut labels = Vec::new(); - let mut polynomials = Vec::new(); - let mut degree_bounds = Vec::new(); - - for i in 0..10 { - let label = format!("Test{}", i); - labels.push(label.clone()); - let degree_bound = 1usize; - let hiding_bound = Some(1); - degree_bounds.push(degree_bound); - - polynomials.push(LabeledPolynomial::new( - label, - rand_poly(supported_degree, None, rng), - Some(degree_bound), - hiding_bound, - )); - } + let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap(); + let max_degree = 100; + let pp = PC::setup(max_degree, None, rng)?; + for _ in 0..10 { + let supported_degree = Uniform::from(1..=max_degree).sample(rng); + assert!( + max_degree >= supported_degree, + "max_degree < supported_degree" + ); + + let mut labels = Vec::new(); + let mut polynomials = Vec::new(); + let mut degree_bounds = Vec::new(); + + for i in 0..10 { + let label = format!("Test{}", i); + labels.push(label.clone()); + let degree_bound = 1usize; + let hiding_bound = Some(1); + degree_bounds.push(degree_bound); + + polynomials.push(LabeledPolynomial::new( + label, + rand_poly(supported_degree, None, rng), + Some(degree_bound), + hiding_bound, + )); + } - let supported_hiding_bound = polynomials - .iter() - .map(|p| p.hiding_bound().unwrap_or(0)) - .max() - .unwrap_or(0); - println!("supported degree: {:?}", supported_degree); - println!("supported hiding bound: {:?}", supported_hiding_bound); - let (ck, vk) = PC::trim( - &pp, - supported_degree, - supported_hiding_bound, - Some(degree_bounds.as_slice()), - )?; - println!("Trimmed"); + let supported_hiding_bound = polynomials + .iter() + .map(|p| p.hiding_bound().unwrap_or(0)) + .max() + .unwrap_or(0); + println!("supported degree: {:?}", supported_degree); + println!("supported hiding bound: {:?}", supported_hiding_bound); + let (ck, vk) = PC::trim( + &pp, + supported_degree, + supported_hiding_bound, + Some(degree_bounds.as_slice()), + )?; + println!("Trimmed"); - let (comms, rands) = PC::commit(&ck, &polynomials, Some(rng))?; + let (comms, rands) = PC::commit(&ck, &polynomials, Some(rng))?; - let mut query_set = QuerySet::new(); - let mut values = Evaluations::new(); - let point = rand_point(None, rng); - for (i, label) in labels.iter().enumerate() { - query_set.insert((label.clone(), (format!("{}", i), point.clone()))); - let value = polynomials[i].evaluate(&point); - values.insert((label.clone(), point.clone()), value); - } - println!("Generated query set"); - - let proof = PC::batch_open( - &ck, - &polynomials, - &comms, - &query_set, - &mut (sponge.clone()), - &rands, - Some(rng), - )?; - let result = PC::batch_check( - &vk, - &comms, - &query_set, - &values, - &proof, - &mut (sponge.clone()), - rng, - )?; - assert!(result, "proof was incorrect, Query set: {:#?}", query_set); + let mut query_set = QuerySet::new(); + let mut values = Evaluations::new(); + let point = rand_point(None, rng); + for (i, label) in labels.iter().enumerate() { + query_set.insert((label.clone(), (format!("{}", i), point.clone()))); + let value = polynomials[i].evaluate(&point); + values.insert((label.clone(), point.clone()), value); } + println!("Generated query set"); + + let proof = PC::batch_open( + &ck, + &polynomials, + &comms, + &query_set, + &mut (sponge.clone()), + &rands, + Some(rng), + )?; + let result = PC::batch_check( + &vk, + &comms, + &query_set, + &values, + &proof, + &mut (sponge.clone()), + rng, + )?; + assert!(result, "proof was incorrect, Query set: {:#?}", query_set); } Ok(()) @@ -761,122 +759,121 @@ pub mod tests { let sponge = sponge(); - for _ in 0..1 { - let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap(); - // If testing multivariate polynomials, make the max degree lower - let max_degree = match num_vars { - Some(_) => max_degree.unwrap_or(Uniform::from(2..=10).sample(rng)), - None => max_degree.unwrap_or(Uniform::from(2..=64).sample(rng)), + let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap(); + // If testing multivariate polynomials, make the max degree lower + let max_degree = match num_vars { + Some(_) => max_degree.unwrap_or(Uniform::from(2..=10).sample(rng)), + None => max_degree.unwrap_or(Uniform::from(2..=64).sample(rng)), + }; + let pp = PC::setup(max_degree, num_vars, rng)?; + + for _ in 0..num_iters { + let supported_degree = + supported_degree.unwrap_or(Uniform::from(1..=max_degree).sample(rng)); + assert!( + max_degree >= supported_degree, + "max_degree < supported_degree" + ); + let mut polynomials: Vec> = Vec::new(); + let mut degree_bounds = if enforce_degree_bounds { + Some(Vec::new()) + } else { + None }; - let pp = PC::setup(max_degree, num_vars, rng)?; - - for __ in 0..num_iters { - let supported_degree = - supported_degree.unwrap_or(Uniform::from(1..=max_degree).sample(rng)); - assert!( - max_degree >= supported_degree, - "max_degree < supported_degree" - ); - let mut polynomials: Vec> = Vec::new(); - let mut degree_bounds = if enforce_degree_bounds { - Some(Vec::new()) + + let mut labels = Vec::new(); + println!("Sampled supported degree"); + + // Generate polynomials + let num_points_in_query_set = Uniform::from(1..=max_num_queries).sample(rng); + for i in 0..num_polynomials { + let label = format!("Test{}", i); + labels.push(label.clone()); + let degree = Uniform::from(1..=supported_degree).sample(rng); + let degree_bound = if let Some(degree_bounds) = &mut degree_bounds { + let range = Uniform::from(degree..=supported_degree); + let degree_bound = range.sample(rng); + degree_bounds.push(degree_bound); + Some(degree_bound) } else { None }; - let mut labels = Vec::new(); - println!("Sampled supported degree"); - - // Generate polynomials - let num_points_in_query_set = Uniform::from(1..=max_num_queries).sample(rng); - for i in 0..num_polynomials { - let label = format!("Test{}", i); - labels.push(label.clone()); - let degree = Uniform::from(1..=supported_degree).sample(rng); - let degree_bound = if let Some(degree_bounds) = &mut degree_bounds { - let range = Uniform::from(degree..=supported_degree); - let degree_bound = range.sample(rng); - degree_bounds.push(degree_bound); - Some(degree_bound) - } else { - None - }; - - let hiding_bound = if num_points_in_query_set >= degree { - Some(degree) - } else { - Some(num_points_in_query_set) - }; + let hiding_bound = if num_points_in_query_set >= degree { + Some(degree) + } else { + Some(num_points_in_query_set) + }; - polynomials.push(LabeledPolynomial::new( - label, - rand_poly(degree, num_vars, rng).into(), - degree_bound, - hiding_bound, - )) - } - let supported_hiding_bound = polynomials - .iter() - .map(|p| p.hiding_bound().unwrap_or(0)) - .max() - .unwrap_or(0); - println!("supported degree: {:?}", supported_degree); - println!("supported hiding bound: {:?}", supported_hiding_bound); - println!("num_points_in_query_set: {:?}", num_points_in_query_set); - let (ck, vk) = PC::trim( - &pp, - supported_degree, - supported_hiding_bound, - degree_bounds.as_ref().map(|s| s.as_slice()), - )?; - println!("Trimmed"); + polynomials.push(LabeledPolynomial::new( + label, + rand_poly(degree, num_vars, rng).into(), + degree_bound, + hiding_bound, + )) + } + let supported_hiding_bound = polynomials + .iter() + .map(|p| p.hiding_bound().unwrap_or(0)) + .max() + .unwrap_or(0); + println!("supported degree: {:?}", supported_degree); + println!("supported hiding bound: {:?}", supported_hiding_bound); + println!("num_points_in_query_set: {:?}", num_points_in_query_set); + let (ck, vk) = PC::trim( + &pp, + supported_degree, + supported_hiding_bound, + degree_bounds.as_ref().map(|s| s.as_slice()), + )?; + println!("Trimmed"); - let (comms, rands) = PC::commit(&ck, &polynomials, Some(rng))?; + let (comms, rands) = PC::commit(&ck, &polynomials, Some(rng))?; - // Construct query set - let mut query_set = QuerySet::new(); - let mut values = Evaluations::new(); - for _ in 0..num_points_in_query_set { - let point = rand_point(num_vars, rng); - for (i, label) in labels.iter().enumerate() { - query_set.insert((label.clone(), (format!("{}", i), point.clone()))); - let value = polynomials[i].evaluate(&point); - values.insert((label.clone(), point.clone()), value); - } + // Construct query set + let mut query_set = QuerySet::new(); + let mut values = Evaluations::new(); + for _ in 0..num_points_in_query_set { + let point = rand_point(num_vars, rng); + for (i, label) in labels.iter().enumerate() { + query_set.insert((label.clone(), (format!("{}", i), point.clone()))); + let value = polynomials[i].evaluate(&point); + values.insert((label.clone(), point.clone()), value); } - println!("Generated query set"); - - let proof = PC::batch_open( - &ck, - &polynomials, - &comms, - &query_set, - &mut (sponge.clone()), - &rands, - Some(rng), - )?; - let result = PC::batch_check( - &vk, - &comms, - &query_set, - &values, - &proof, - &mut (sponge.clone()), - rng, - )?; - if !result { - println!( - "Failed with {} polynomials, num_points_in_query_set: {:?}", - num_polynomials, num_points_in_query_set - ); - println!("Degree of polynomials:",); - for poly in polynomials { - println!("Degree: {:?}", poly.degree()); - } + } + println!("Generated query set"); + + let proof = PC::batch_open( + &ck, + &polynomials, + &comms, + &query_set, + &mut (sponge.clone()), + &rands, + Some(rng), + )?; + let result = PC::batch_check( + &vk, + &comms, + &query_set, + &values, + &proof, + &mut (sponge.clone()), + rng, + )?; + if !result { + println!( + "Failed with {} polynomials, num_points_in_query_set: {:?}", + num_polynomials, num_points_in_query_set + ); + println!("Degree of polynomials:",); + for poly in polynomials { + println!("Degree: {:?}", poly.degree()); } - assert!(result, "proof was incorrect, Query set: {:#?}", query_set); } + assert!(result, "proof was incorrect, Query set: {:#?}", query_set); } + Ok(()) } @@ -903,162 +900,161 @@ pub mod tests { let sponge = sponge(); - for __ in 0..1 { - let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap(); - // If testing multivariate polynomials, make the max degree lower - let max_degree = match num_vars { - Some(_) => max_degree.unwrap_or(Uniform::from(2..=10).sample(rng)), - None => max_degree.unwrap_or(Uniform::from(2..=64).sample(rng)), + let rng = &mut ChaCha20Rng::from_rng(test_rng()).unwrap(); + // If testing multivariate polynomials, make the max degree lower + let max_degree = match num_vars { + Some(_) => max_degree.unwrap_or(Uniform::from(2..=10).sample(rng)), + None => max_degree.unwrap_or(Uniform::from(2..=64).sample(rng)), + }; + let pp = PC::setup(max_degree, num_vars, rng)?; + + for _ in 0..num_iters { + let supported_degree = + supported_degree.unwrap_or(Uniform::from(1..=max_degree).sample(rng)); + assert!( + max_degree >= supported_degree, + "max_degree < supported_degree" + ); + let mut polynomials = Vec::new(); + let mut degree_bounds = if enforce_degree_bounds { + Some(Vec::new()) + } else { + None }; - let pp = PC::setup(max_degree, num_vars, rng)?; - - for _ in 0..num_iters { - let supported_degree = - supported_degree.unwrap_or(Uniform::from(1..=max_degree).sample(rng)); - assert!( - max_degree >= supported_degree, - "max_degree < supported_degree" - ); - let mut polynomials = Vec::new(); - let mut degree_bounds = if enforce_degree_bounds { - Some(Vec::new()) + + let mut labels = Vec::new(); + println!("Sampled supported degree"); + + // Generate polynomials + let num_points_in_query_set = Uniform::from(1..=max_num_queries).sample(rng); + for i in 0..num_polynomials { + let label = format!("Test{}", i); + labels.push(label.clone()); + let degree = Uniform::from(1..=supported_degree).sample(rng); + let degree_bound = if let Some(degree_bounds) = &mut degree_bounds { + if rng.gen() { + let range = Uniform::from(degree..=supported_degree); + let degree_bound = range.sample(rng); + degree_bounds.push(degree_bound); + Some(degree_bound) + } else { + None + } } else { None }; - let mut labels = Vec::new(); - println!("Sampled supported degree"); - - // Generate polynomials - let num_points_in_query_set = Uniform::from(1..=max_num_queries).sample(rng); - for i in 0..num_polynomials { - let label = format!("Test{}", i); - labels.push(label.clone()); - let degree = Uniform::from(1..=supported_degree).sample(rng); - let degree_bound = if let Some(degree_bounds) = &mut degree_bounds { - if rng.gen() { - let range = Uniform::from(degree..=supported_degree); - let degree_bound = range.sample(rng); - degree_bounds.push(degree_bound); - Some(degree_bound) + let hiding_bound = if num_points_in_query_set >= degree { + Some(degree) + } else { + Some(num_points_in_query_set) + }; + println!("Hiding bound: {:?}", hiding_bound); + + polynomials.push(LabeledPolynomial::new( + label, + rand_poly(degree, num_vars, rng), + degree_bound, + hiding_bound, + )) + } + println!("supported degree: {:?}", supported_degree); + println!("num_points_in_query_set: {:?}", num_points_in_query_set); + println!("{:?}", degree_bounds); + println!("{}", num_polynomials); + println!("{}", enforce_degree_bounds); + + let (ck, vk) = PC::trim( + &pp, + supported_degree, + supported_degree, + degree_bounds.as_ref().map(|s| s.as_slice()), + )?; + println!("Trimmed"); + + let (comms, rands) = PC::commit(&ck, &polynomials, Some(rng))?; + + // Let's construct our equations + let mut linear_combinations = Vec::new(); + let mut query_set = QuerySet::new(); + let mut values = Evaluations::new(); + for i in 0..num_points_in_query_set { + let point = rand_point(num_vars, rng); + for j in 0..num_equations.unwrap() { + let label = format!("query {} eqn {}", i, j); + let mut lc = LinearCombination::empty(label.clone()); + + let mut value = F::zero(); + let should_have_degree_bounds: bool = rng.gen(); + for (k, label) in labels.iter().enumerate() { + if should_have_degree_bounds { + value += &polynomials[k].evaluate(&point); + lc.push((F::one(), label.to_string().into())); + break; } else { - None - } - } else { - None - }; - - let hiding_bound = if num_points_in_query_set >= degree { - Some(degree) - } else { - Some(num_points_in_query_set) - }; - println!("Hiding bound: {:?}", hiding_bound); - - polynomials.push(LabeledPolynomial::new( - label, - rand_poly(degree, num_vars, rng), - degree_bound, - hiding_bound, - )) - } - println!("supported degree: {:?}", supported_degree); - println!("num_points_in_query_set: {:?}", num_points_in_query_set); - println!("{:?}", degree_bounds); - println!("{}", num_polynomials); - println!("{}", enforce_degree_bounds); - - let (ck, vk) = PC::trim( - &pp, - supported_degree, - supported_degree, - degree_bounds.as_ref().map(|s| s.as_slice()), - )?; - println!("Trimmed"); - - let (comms, rands) = PC::commit(&ck, &polynomials, Some(rng))?; - - // Let's construct our equations - let mut linear_combinations = Vec::new(); - let mut query_set = QuerySet::new(); - let mut values = Evaluations::new(); - for i in 0..num_points_in_query_set { - let point = rand_point(num_vars, rng); - for j in 0..num_equations.unwrap() { - let label = format!("query {} eqn {}", i, j); - let mut lc = LinearCombination::empty(label.clone()); - - let mut value = F::zero(); - let should_have_degree_bounds: bool = rng.gen(); - for (k, label) in labels.iter().enumerate() { - if should_have_degree_bounds { - value += &polynomials[k].evaluate(&point); - lc.push((F::one(), label.to_string().into())); - break; + let poly = &polynomials[k]; + if poly.degree_bound().is_some() { + continue; } else { - let poly = &polynomials[k]; - if poly.degree_bound().is_some() { - continue; - } else { - assert!(poly.degree_bound().is_none()); - let coeff = F::rand(rng); - value += &(coeff * poly.evaluate(&point)); - lc.push((coeff, label.to_string().into())); - } + assert!(poly.degree_bound().is_none()); + let coeff = F::rand(rng); + value += &(coeff * poly.evaluate(&point)); + lc.push((coeff, label.to_string().into())); } } - values.insert((label.clone(), point.clone()), value); - if !lc.is_empty() { - linear_combinations.push(lc); - // Insert query - query_set.insert((label.clone(), (format!("{}", i), point.clone()))); - } } - } - if linear_combinations.is_empty() { - continue; - } - println!("Generated query set"); - println!("Linear combinations: {:?}", linear_combinations); - - let proof = PC::open_combinations( - &ck, - &linear_combinations, - &polynomials, - &comms, - &query_set, - &mut (sponge.clone()), - &rands, - Some(rng), - )?; - println!("Generated proof"); - let result = PC::check_combinations( - &vk, - &linear_combinations, - &comms, - &query_set, - &values, - &proof, - &mut (sponge.clone()), - rng, - )?; - if !result { - println!( - "Failed with {} polynomials, num_points_in_query_set: {:?}", - num_polynomials, num_points_in_query_set - ); - println!("Degree of polynomials:",); - for poly in polynomials { - println!("Degree: {:?}", poly.degree()); + values.insert((label.clone(), point.clone()), value); + if !lc.is_empty() { + linear_combinations.push(lc); + // Insert query + query_set.insert((label.clone(), (format!("{}", i), point.clone()))); } } - assert!( - result, - "proof was incorrect, equations: {:#?}", - linear_combinations + } + if linear_combinations.is_empty() { + continue; + } + println!("Generated query set"); + println!("Linear combinations: {:?}", linear_combinations); + + let proof = PC::open_combinations( + &ck, + &linear_combinations, + &polynomials, + &comms, + &query_set, + &mut (sponge.clone()), + &rands, + Some(rng), + )?; + println!("Generated proof"); + let result = PC::check_combinations( + &vk, + &linear_combinations, + &comms, + &query_set, + &values, + &proof, + &mut (sponge.clone()), + rng, + )?; + if !result { + println!( + "Failed with {} polynomials, num_points_in_query_set: {:?}", + num_polynomials, num_points_in_query_set ); + println!("Degree of polynomials:",); + for poly in polynomials { + println!("Degree: {:?}", poly.degree()); + } } + assert!( + result, + "proof was incorrect, equations: {:#?}", + linear_combinations + ); } + Ok(()) } From 1a9400f4ae16a39ed01ff96a12f566ee98111469 Mon Sep 17 00:00:00 2001 From: Hossein Moghaddas Date: Mon, 15 Jan 2024 17:09:27 +0100 Subject: [PATCH 4/6] Fix the loop range --- poly-commit/src/kzg10/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/poly-commit/src/kzg10/mod.rs b/poly-commit/src/kzg10/mod.rs index 5bebdaeb..47089685 100644 --- a/poly-commit/src/kzg10/mod.rs +++ b/poly-commit/src/kzg10/mod.rs @@ -66,10 +66,10 @@ where let gamma_g = E::G1::rand(rng); let h = E::G2::rand(rng); + // powers_of_beta = [1, b, ..., b^(max_degree + 1)], len = max_degree + 2 let mut powers_of_beta = vec![E::ScalarField::one()]; - let mut cur = beta; - for _ in 0..=max_degree + 1 { + for _ in 0..=max_degree { powers_of_beta.push(cur); cur *= β } @@ -78,6 +78,8 @@ where let powers_of_g = g.batch_mul(&powers_of_beta[0..max_degree + 1]); end_timer!(g_time); + // Use the entire `powers_of_beta`, since we want to be able to support + // up to D queries. let gamma_g_time = start_timer!(|| "Generating powers of gamma * G"); let powers_of_gamma_g = gamma_g .batch_mul(&powers_of_beta) From a270950cb5e7ffa334955a2799f3b0094796b8a2 Mon Sep 17 00:00:00 2001 From: mmagician Date: Mon, 15 Jan 2024 19:39:19 +0100 Subject: [PATCH 5/6] re-use the preprocessing table --- poly-commit/src/marlin/marlin_pst13_pc/mod.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/poly-commit/src/marlin/marlin_pst13_pc/mod.rs b/poly-commit/src/marlin/marlin_pst13_pc/mod.rs index 15fe6b63..96855bd4 100644 --- a/poly-commit/src/marlin/marlin_pst13_pc/mod.rs +++ b/poly-commit/src/marlin/marlin_pst13_pc/mod.rs @@ -8,7 +8,11 @@ use crate::{LabeledCommitment, LabeledPolynomial, LinearCombination}; use crate::{PCRandomness, PCUniversalParams, PolynomialCommitment}; use crate::{ToString, Vec}; use ark_ec::AffineRepr; -use ark_ec::{pairing::Pairing, scalar_mul::ScalarMul, CurveGroup, VariableBaseMSM}; +use ark_ec::{ + pairing::Pairing, + scalar_mul::{BatchMulPreprocessing, ScalarMul}, + CurveGroup, VariableBaseMSM, +}; use ark_ff::{One, PrimeField, UniformRand, Zero}; use ark_poly::{multivariate::Term, DenseMVPolynomial}; use ark_std::rand::RngCore; @@ -221,6 +225,8 @@ where // containing `betas[i]^j \gamma G` for `j` from 1 to `max_degree+1` to support // up to `max_degree` queries let mut powers_of_gamma_g = vec![Vec::new(); num_vars]; + let gamma_g_table = BatchMulPreprocessing::new(gamma_g, max_degree + 1); + ark_std::cfg_iter_mut!(powers_of_gamma_g) .enumerate() .for_each(|(i, v)| { @@ -230,7 +236,7 @@ where cur *= &betas[i]; powers_of_beta.push(cur); } - *v = gamma_g.batch_mul(&powers_of_beta); + *v = gamma_g.batch_mul_with_preprocessing(&powers_of_beta, &gamma_g_table); }); end_timer!(gamma_g_time); From f23de5d9f84fc232e5bece831a085adb2471ec9a Mon Sep 17 00:00:00 2001 From: mmagician Date: Mon, 15 Jan 2024 19:48:12 +0100 Subject: [PATCH 6/6] also re-use the preprocessing table for multilinear_pc --- poly-commit/src/multilinear_pc/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/poly-commit/src/multilinear_pc/mod.rs b/poly-commit/src/multilinear_pc/mod.rs index 2cb954eb..94ea74cc 100644 --- a/poly-commit/src/multilinear_pc/mod.rs +++ b/poly-commit/src/multilinear_pc/mod.rs @@ -1,6 +1,7 @@ use crate::multilinear_pc::data_structures::{ Commitment, CommitterKey, Proof, UniversalParams, VerifierKey, }; +use ark_ec::scalar_mul::BatchMulPreprocessing; use ark_ec::AffineRepr; use ark_ec::{pairing::Pairing, CurveGroup}; use ark_ec::{scalar_mul::ScalarMul, VariableBaseMSM}; @@ -56,7 +57,9 @@ impl MultilinearPC { let pp_k_powers = (0..(1 << (num_vars - i))).map(|x| eq[x]); pp_powers.extend(pp_k_powers); } - let pp_g = g.batch_mul(&pp_powers); + + let g_table = BatchMulPreprocessing::new(g, num_vars); + let pp_g = g.batch_mul_with_preprocessing(&pp_powers, &g_table); let pp_h = h.batch_mul(&pp_powers); let mut start = 0; for i in 0..num_vars { @@ -70,7 +73,7 @@ impl MultilinearPC { // uncomment to measure the time for calculating vp // let vp_generation_timer = start_timer!(|| "VP generation"); - let g_mask = g.batch_mul(&t); + let g_mask = g.batch_mul_with_preprocessing(&t, &g_table); // end_timer!(vp_generation_timer); UniversalParams {