diff --git a/src/ipa_pc/mod.rs b/src/ipa_pc/mod.rs index 80e76663..ab97a5c4 100644 --- a/src/ipa_pc/mod.rs +++ b/src/ipa_pc/mod.rs @@ -4,7 +4,7 @@ use crate::{LabeledCommitment, LabeledPolynomial, LinearCombination}; use crate::{PCCommitterKey, PCRandomness, PCUniversalParams, Polynomial, PolynomialCommitment}; use algebra_core::{ - to_bytes, AffineCurve, Field, One, PrimeField, ProjectiveCurve, ToBytes, UniformRand, + to_bytes, AffineCurve, Field, One, PrimeField, ProjectiveCurve, UniformRand, VariableBaseMSM, Zero, }; use core::{convert::TryInto, marker::PhantomData}; @@ -340,6 +340,7 @@ impl PolynomialCommitment for InnerPr fn trim( pp: &Self::UniversalParams, supported_degree: usize, + _supported_hiding_bound: usize, _enforced_degree_bounds: Option<&[usize]>, ) -> Result<(Self::CommitterKey, Self::VerifierKey), Self::Error> { // Ensure that supported_degree + 1 is a power of two diff --git a/src/kzg10/data_structures.rs b/src/kzg10/data_structures.rs index 9f88c5f8..c46570c4 100644 --- a/src/kzg10/data_structures.rs +++ b/src/kzg10/data_structures.rs @@ -1,6 +1,7 @@ use crate::*; use algebra_core::{AffineCurve, PairingEngine, PrimeField, ProjectiveCurve, ToBytes, Zero}; use core::ops::{Add, AddAssign}; +use std::collections::BTreeMap; /// `UniversalParams` are the universal parameters for the KZG10 scheme. #[derive(Derivative)] @@ -9,13 +10,13 @@ pub struct UniversalParams { /// Group elements of the form `{ \beta^i G }`, where `i` ranges from 0 to `degree`. pub powers_of_g: Vec, /// Group elements of the form `{ \beta^i \gamma G }`, where `i` ranges from 0 to `degree`. - pub powers_of_gamma_g: Vec, + pub powers_of_gamma_g: BTreeMap, /// The generator of G2. pub h: E::G2Affine, /// \beta times the above generator of G2. pub beta_h: E::G2Affine, /// Group elements of the form `{ \beta^i G2 }`, where `i` ranges from `0` to `-degree`. - pub prepared_neg_powers_of_h: Option>, + pub prepared_neg_powers_of_h: BTreeMap, /// The generator of G2, prepared for use in pairings. #[derivative(Debug = "ignore")] pub prepared_h: E::G2Prepared, diff --git a/src/kzg10/mod.rs b/src/kzg10/mod.rs index 1fa2a8b8..41bc83d3 100644 --- a/src/kzg10/mod.rs +++ b/src/kzg10/mod.rs @@ -18,6 +18,7 @@ use core::marker::PhantomData; mod data_structures; pub use data_structures::*; +use std::collections::BTreeMap; /// `KZG10` is an implementation of the polynomial commitment scheme of /// [Kate, Zaverucha and Goldbgerg][kzg10] @@ -79,7 +80,10 @@ impl KZG10 { let powers_of_g = E::G1Projective::batch_normalization_into_affine(&powers_of_g); let powers_of_gamma_g = - E::G1Projective::batch_normalization_into_affine(&powers_of_gamma_g); + E::G1Projective::batch_normalization_into_affine(&powers_of_gamma_g) + .into_iter() + .enumerate() + .collect(); let prepared_neg_powers_of_h_time = start_timer!(|| "Generating negative powers of h in G2"); @@ -100,9 +104,17 @@ impl KZG10 { ); let affines = E::G2Projective::batch_normalization_into_affine(&neg_powers_of_h); - Some(affines.into_iter().map(|a| a.into()).collect()) + let mut affines_map = BTreeMap::new(); + affines + .into_iter() + .enumerate() + .map(|(i, a)| (i, a.into())) + .for_each(|(i, a)| { + affines_map.insert(i, a); + }); + affines_map } else { - None + BTreeMap::new() }; end_timer!(prepared_neg_powers_of_h_time); @@ -477,7 +489,9 @@ mod tests { supported_degree += 1; } let powers_of_g = pp.powers_of_g[..=supported_degree].to_vec(); - let powers_of_gamma_g = pp.powers_of_gamma_g[..=supported_degree].to_vec(); + let powers_of_gamma_g = (0..=supported_degree) + .map(|i| pp.powers_of_gamma_g[&i]) + .collect(); let powers = Powers { powers_of_g: Cow::Owned(powers_of_g), @@ -485,7 +499,7 @@ mod tests { }; let vk = VerifierKey { g: pp.powers_of_g[0], - gamma_g: pp.powers_of_gamma_g[0], + gamma_g: pp.powers_of_gamma_g[&0], h: pp.h, beta_h: pp.beta_h, prepared_h: pp.prepared_h.clone(), diff --git a/src/lib.rs b/src/lib.rs index 3fa9b38f..a266556b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,6 +145,7 @@ pub trait PolynomialCommitment: Sized { fn trim( pp: &Self::UniversalParams, supported_degree: usize, + supported_hiding_bound: usize, enforced_degree_bounds: Option<&[usize]>, ) -> Result<(Self::CommitterKey, Self::VerifierKey), Self::Error>; @@ -519,8 +520,22 @@ pub mod tests { )) } + let supported_hiding_bound = polynomials + .iter() + .map(|p| match p.hiding_bound() { + Some(b) => b, + None => 0, + }) + .max() + .unwrap_or(0); println!("supported degree: {:?}", supported_degree); - let (ck, vk) = PC::trim(&pp, supported_degree, Some(degree_bounds.as_slice()))?; + 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))?; @@ -628,11 +643,21 @@ pub mod tests { hiding_bound, )) } + let supported_hiding_bound = polynomials + .iter() + .map(|p| match p.hiding_bound() { + Some(b) => b, + None => 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"); @@ -769,6 +794,7 @@ pub mod tests { let (ck, vk) = PC::trim( &pp, supported_degree, + supported_degree, degree_bounds.as_ref().map(|s| s.as_slice()), )?; println!("Trimmed"); diff --git a/src/marlin_pc/mod.rs b/src/marlin_pc/mod.rs index c24332bd..18da2f74 100644 --- a/src/marlin_pc/mod.rs +++ b/src/marlin_pc/mod.rs @@ -168,12 +168,10 @@ impl PolynomialCommitment for MarlinKZG10 { kzg10::KZG10::setup(max_degree, false, rng).map_err(Into::into) } - // TODO: should trim also take in the hiding_bounds? That way we don't - // have to store many powers of gamma_g. - // TODO: add an optional hiding_bound. fn trim( pp: &Self::UniversalParams, supported_degree: usize, + supported_hiding_bound: usize, enforced_degree_bounds: Option<&[usize]>, ) -> Result<(Self::CommitterKey, Self::VerifierKey), Self::Error> { let max_degree = pp.max_degree(); @@ -187,15 +185,17 @@ impl PolynomialCommitment for MarlinKZG10 { supported_degree )); let powers = pp.powers_of_g[..=supported_degree].to_vec(); - // We want to support making up to supported_degree queries to committed + // We want to support making up to `supported_hiding_bound` queries to committed // polynomials. - let powers_of_gamma_g = pp.powers_of_gamma_g[..=(supported_degree + 1)].to_vec(); + let powers_of_gamma_g = (0..=supported_hiding_bound + 1) + .map(|i| pp.powers_of_gamma_g[&i]) + .collect::>(); end_timer!(ck_time); // Construct the core KZG10 verifier key. let vk = kzg10::VerifierKey { g: pp.powers_of_g[0], - gamma_g: pp.powers_of_gamma_g[0], + gamma_g: pp.powers_of_gamma_g[&0], h: pp.h, beta_h: pp.beta_h, prepared_h: pp.prepared_h.clone(), diff --git a/src/sonic_pc/data_structures.rs b/src/sonic_pc/data_structures.rs index 03d33298..a2d3e06c 100644 --- a/src/sonic_pc/data_structures.rs +++ b/src/sonic_pc/data_structures.rs @@ -1,6 +1,7 @@ use crate::kzg10; use crate::{PCCommitterKey, PCVerifierKey, Vec}; use algebra_core::PairingEngine; +use std::collections::BTreeMap; /// `UniversalParams` are the universal parameters for the KZG10 scheme. pub type UniversalParams = kzg10::UniversalParams; @@ -33,7 +34,7 @@ pub struct CommitterKey { /// The powers used to commit to shifted hiding polynomials. /// This is `None` if `self` does not support enforcing any degree bounds. - pub shifted_powers_of_gamma_g: Option>, + pub shifted_powers_of_gamma_g: Option>>, /// The degree bounds that are supported by `self`. /// Sorted in ascending order from smallest bound to largest bound. @@ -60,26 +61,26 @@ impl CommitterKey { ) -> Option> { match (&self.shifted_powers_of_g, &self.shifted_powers_of_gamma_g) { (Some(shifted_powers_of_g), Some(shifted_powers_of_gamma_g)) => { - let powers_range = if let Some(degree_bound) = degree_bound.into() { + let max_bound = self + .enforced_degree_bounds + .as_ref() + .unwrap() + .last() + .unwrap(); + let (bound, powers_range) = if let Some(degree_bound) = degree_bound.into() { assert!(self .enforced_degree_bounds .as_ref() .unwrap() .contains(°ree_bound)); - let max_bound = self - .enforced_degree_bounds - .as_ref() - .unwrap() - .last() - .unwrap(); - (max_bound - degree_bound).. + (degree_bound, (max_bound - degree_bound)..) } else { - 0.. + (*max_bound, 0..) }; let ck = kzg10::Powers { powers_of_g: shifted_powers_of_g[powers_range.clone()].into(), - powers_of_gamma_g: shifted_powers_of_gamma_g[powers_range].into(), + powers_of_gamma_g: shifted_powers_of_gamma_g[&bound].clone().into(), }; Some(ck) diff --git a/src/sonic_pc/mod.rs b/src/sonic_pc/mod.rs index 0ef9f2a2..8fdcad44 100644 --- a/src/sonic_pc/mod.rs +++ b/src/sonic_pc/mod.rs @@ -143,10 +143,11 @@ impl PolynomialCommitment for SonicKZG10 { fn trim( pp: &Self::UniversalParams, supported_degree: usize, + supported_hiding_bound: usize, enforced_degree_bounds: Option<&[usize]>, ) -> Result<(Self::CommitterKey, Self::VerifierKey), Self::Error> { let trim_time = start_timer!(|| "Trimming public parameters"); - let prepared_neg_powers_of_h = pp.prepared_neg_powers_of_h.as_ref().unwrap(); + let prepared_neg_powers_of_h = &pp.prepared_neg_powers_of_h; let max_degree = pp.max_degree(); if supported_degree > max_degree { return Err(Error::TrimmingDegreeTooLarge); @@ -180,8 +181,19 @@ impl PolynomialCommitment for SonicKZG10 { )); let shifted_powers_of_g = pp.powers_of_g[lowest_shift_degree..].to_vec(); - let shifted_powers_of_gamma_g = - pp.powers_of_gamma_g[lowest_shift_degree..].to_vec(); + let mut shifted_powers_of_gamma_g = BTreeMap::new(); + // Also add degree 0. + for degree_bound in enforced_degree_bounds { + let shift_degree = max_degree - degree_bound; + let mut powers_for_degree_bound = vec![]; + for i in 0..=supported_hiding_bound + 1 { + // We have an additional degree in `powers_of_gamma_g` beyond `powers_of_g`. + if shift_degree + i < max_degree + 2 { + powers_for_degree_bound.push(pp.powers_of_gamma_g[&(shift_degree + i)]); + } + } + shifted_powers_of_gamma_g.insert(*degree_bound, powers_for_degree_bound); + } end_timer!(shifted_ck_time); @@ -195,7 +207,7 @@ impl PolynomialCommitment for SonicKZG10 { .map(|bound| { ( *bound, - prepared_neg_powers_of_h[max_degree - *bound].clone(), + prepared_neg_powers_of_h[&(max_degree - *bound)].clone(), ) }) .collect(); @@ -213,7 +225,9 @@ impl PolynomialCommitment for SonicKZG10 { }; let powers_of_g = pp.powers_of_g[..=supported_degree].to_vec(); - let powers_of_gamma_g = pp.powers_of_gamma_g[..=(supported_degree + 1)].to_vec(); + let powers_of_gamma_g = (0..=supported_hiding_bound + 1) + .map(|i| pp.powers_of_gamma_g[&i]) + .collect(); let ck = CommitterKey { powers_of_g, @@ -227,7 +241,7 @@ impl PolynomialCommitment for SonicKZG10 { let g = pp.powers_of_g[0]; let h = pp.h; let beta_h = pp.beta_h; - let gamma_g = pp.powers_of_gamma_g[0]; + let gamma_g = pp.powers_of_gamma_g[&0]; let prepared_h = (&pp.prepared_h).clone(); let prepared_beta_h = (&pp.prepared_beta_h).clone();