From a81d1cc5d3bb63589f2d4fe7dc4746e82fb8af30 Mon Sep 17 00:00:00 2001 From: Mara Mihali Date: Thu, 26 Jan 2023 10:34:46 +0000 Subject: [PATCH 1/3] add support for commitment in g2 --- src/lib.rs | 6 +- src/multilinear_pc/data_structures.rs | 18 +++ src/multilinear_pc/mod.rs | 155 +++++++++++++++++++++++++- 3 files changed, 174 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8458395..64327fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,10 +4,8 @@ #![deny(trivial_numeric_casts, private_in_public, variant_size_differences)] #![deny(stable_features, non_shorthand_field_patterns)] #![deny(unused_attributes, unused_mut)] -#![deny(missing_docs)] -#![deny(unused_imports)] -#![deny(renamed_and_removed_lints, stable_features, unused_allocation)] -#![deny(unused_comparisons, bare_trait_objects, unused_must_use, const_err)] +#![deny(stable_features, unused_allocation)] +#![deny(unused_comparisons, bare_trait_objects, unused_must_use)] #![forbid(unsafe_code)] #[macro_use] diff --git a/src/multilinear_pc/data_structures.rs b/src/multilinear_pc/data_structures.rs index fc287b9..f3ebfc5 100644 --- a/src/multilinear_pc/data_structures.rs +++ b/src/multilinear_pc/data_structures.rs @@ -23,6 +23,8 @@ pub struct UniversalParams { pub h: E::G2Affine, /// g^randomness pub g_mask: Vec, + //h^randomness + pub h_mask: Vec, } /// Public Parameter used by prover @@ -51,6 +53,8 @@ pub struct VerifierKey { pub h: E::G2Affine, /// g^t1, g^t2, ... pub g_mask_random: Vec, + // h^t1, h^t2,... + pub h_mask_random: Vec, } #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] @@ -62,9 +66,23 @@ pub struct Commitment { pub g_product: E::G1Affine, } +#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] +pub struct Commitment_G2 { + /// number of variables + pub nv: usize, + /// product of g as described by the vRAM paper + pub h_product: E::G2Affine, +} + #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq, Eq)] /// proof of opening pub struct Proof { /// Evaluation of quotients pub proofs: Vec, } + +#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq, Eq)] +pub struct Proof_G1 { + /// Evaluation of quotients + pub proofs: Vec, +} diff --git a/src/multilinear_pc/mod.rs b/src/multilinear_pc/mod.rs index b10ffec..98cdd55 100644 --- a/src/multilinear_pc/mod.rs +++ b/src/multilinear_pc/mod.rs @@ -1,3 +1,5 @@ +use self::data_structures::{Commitment_G2, Proof_G1}; + use super::timer::Timer; use crate::multilinear_pc::data_structures::{ Commitment, CommitterKey, Proof, UniversalParams, VerifierKey, @@ -95,15 +97,28 @@ impl MultilinearPC { &t, )) }; + + let h_mask = { + let window_size = FixedBaseMSM::get_mul_window_size(num_vars); + let h_table = + FixedBaseMSM::get_window_table(scalar_bits, window_size, h.into_projective()); + E::G2Projective::batch_normalization_into_affine(&FixedBaseMSM::multi_scalar_mul( + scalar_bits, + window_size, + &h_table, + &t, + )) + }; // end_timer!(vp_generation_timer); UniversalParams { num_vars, g, - g_mask, h, powers_of_g, powers_of_h, + g_mask, + h_mask, } } @@ -128,6 +143,7 @@ impl MultilinearPC { g: params.g, h: params.h, g_mask_random: (¶ms.g_mask[to_reduce..]).to_vec(), + h_mask_random: (¶ms.h_mask[to_reduce..]).to_vec(), }; (ck, vk) } @@ -148,6 +164,21 @@ impl MultilinearPC { Commitment { nv, g_product } } + pub fn commit_g2( + ck: &CommitterKey, + polynomial: &impl MultilinearExtension, + ) -> Commitment_G2 { + let nv = polynomial.num_vars(); + let scalars: Vec<_> = polynomial + .to_evaluations() + .into_iter() + .map(|x| x.into_repr()) + .collect(); + let h_product = + VariableBaseMSM::multi_scalar_mul(&ck.powers_of_h[0], scalars.as_slice()).into_affine(); + Commitment_G2 { nv, h_product } + } + /// On input a polynomial `p` and a point `point`, outputs a proof for the same. pub fn open( ck: &CommitterKey, @@ -209,8 +240,102 @@ impl MultilinearPC { Proof { proofs: proofs } } + pub fn open_g1( + ck: &CommitterKey, + polynomial: &impl MultilinearExtension, + point: &[E::Fr], + ) -> Proof_G1 { + assert_eq!(polynomial.num_vars(), ck.nv, "Invalid size of polynomial"); + let nv = polynomial.num_vars(); + let mut r: Vec> = (0..nv + 1).map(|_| Vec::new()).collect(); + let mut q: Vec> = (0..nv + 1).map(|_| Vec::new()).collect(); + + r[nv] = polynomial.to_evaluations(); + + let mut thread_handles = vec![]; + let proofs: Vec<_> = vec![E::G1Affine::zero(); nv]; + + let mut i = 0; + for mut p in proofs { + let k = nv - i; + let point_at_k = point[i]; + q[k] = (0..(1 << (k - 1))).map(|_| E::Fr::zero()).collect(); + r[k - 1] = (0..(1 << (k - 1))).map(|_| E::Fr::zero()).collect(); + for b in 0..(1 << (k - 1)) { + q[k][b] = r[k][(b << 1) + 1] - &r[k][b << 1]; + r[k - 1][b] = r[k][b << 1] * &(E::Fr::one() - &point_at_k) + + &(r[k][(b << 1) + 1] * &point_at_k); + } + let scalars: Vec<_> = (0..(1 << k)) + .map(|x| q[k][x >> 1].into_repr()) // fine + .collect(); + let pg = ck.powers_of_g[i].clone(); + thread_handles.push(thread::spawn(move || { + p = VariableBaseMSM::multi_scalar_mul(&pg, &scalars).into_affine(); + p + })); + + i = i + 1; + } + + let proofs = thread_handles + .into_iter() + .map(|g| g.join().unwrap()) + .collect(); + + Proof_G1 { proofs: proofs } + } + /// Verifies that `value` is the evaluation at `x` of the polynomial /// committed inside `comm`. + pub fn check_2<'a>( + vk: &VerifierKey, + commitment: &Commitment_G2, + point: &[E::Fr], + value: E::Fr, + proof: &Proof_G1, + ) -> bool { + let left = E::pairing( + vk.g, + commitment.h_product.into_projective() - &vk.h.mul(value), + ); + // println!("left is {:?}", left); + + let scalar_size = E::Fr::size_in_bits(); + let window_size = FixedBaseMSM::get_mul_window_size(vk.nv); + + let h_table = + FixedBaseMSM::get_window_table(scalar_size, window_size, vk.h.into_projective()); + let h_mul: Vec = + FixedBaseMSM::multi_scalar_mul(scalar_size, window_size, &h_table, point); + + let pairing_rights: Vec<_> = (0..vk.nv) + .into_iter() + .map(|i| vk.h_mask_random[i].into_projective() - &h_mul[i]) + .collect(); + let pairing_rights: Vec = + E::G2Projective::batch_normalization_into_affine(&pairing_rights); + let pairing_rights: Vec = pairing_rights + .into_iter() + .map(|x| E::G2Prepared::from(x)) + .collect(); + + let pairing_lefts: Vec = proof + .proofs + .iter() + .map(|x| E::G1Prepared::from(*x)) + .collect(); + + let pairings: Vec<_> = pairing_lefts + .into_iter() + .zip(pairing_rights.into_iter()) + .collect(); + let right = E::product_of_pairings(pairings.iter()); + // println!("right is {:?}", right); + + left == right + } + pub fn check<'a>( vk: &VerifierKey, commitment: &Commitment, @@ -322,6 +447,34 @@ mod tests { assert!(result); } + fn test_polynomial_g2( + uni_params: &UniversalParams, + poly: &impl MultilinearExtension, + rng: &mut R, + ) { + let nv = poly.num_vars(); + assert_ne!(nv, 0); + let (ck, vk) = MultilinearPC::::trim(&uni_params, nv); + let point: Vec<_> = (0..nv).map(|_| Fr::rand(rng)).collect(); + let com = MultilinearPC::commit_g2(&ck, poly); + let proof = MultilinearPC::open_g1(&ck, poly, &point); + + let value = poly.evaluate(&point).unwrap(); + let result = MultilinearPC::check_2(&vk, &com, &point, value, &proof); + assert!(result); + } + + #[test] + fn test() { + let mut rng = test_rng(); + + // normal polynomials + let uni_params = MultilinearPC::setup(2, &mut rng); + + let poly1 = DenseMultilinearExtension::rand(2, &mut rng); + test_polynomial_g2(&uni_params, &poly1, &mut rng); + } + #[test] fn setup_commit_verify_correct_polynomials() { let mut rng = test_rng(); From a3a44b486074f4fb96655ec657644b65811abb8e Mon Sep 17 00:00:00 2001 From: nikkolasg Date: Fri, 3 Feb 2023 13:36:51 +0100 Subject: [PATCH 2/3] adding documentation --- src/multilinear_pc/data_structures.rs | 8 +++++--- src/multilinear_pc/mod.rs | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/multilinear_pc/data_structures.rs b/src/multilinear_pc/data_structures.rs index f3ebfc5..104c5ed 100644 --- a/src/multilinear_pc/data_structures.rs +++ b/src/multilinear_pc/data_structures.rs @@ -23,7 +23,7 @@ pub struct UniversalParams { pub h: E::G2Affine, /// g^randomness pub g_mask: Vec, - //h^randomness + /// h^randomness pub h_mask: Vec, } @@ -53,12 +53,12 @@ pub struct VerifierKey { pub h: E::G2Affine, /// g^t1, g^t2, ... pub g_mask_random: Vec, - // h^t1, h^t2,... + /// h^t1, h^t2,... pub h_mask_random: Vec, } #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] -/// commitment +/// PST commitment on the G1 group pub struct Commitment { /// number of variables pub nv: usize, @@ -67,6 +67,7 @@ pub struct Commitment { } #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] +/// PST Commitment on the G2 group pub struct Commitment_G2 { /// number of variables pub nv: usize, @@ -82,6 +83,7 @@ pub struct Proof { } #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq, Eq)] +/// PST Proof of opening on G1 (so commitment is on G2) pub struct Proof_G1 { /// Evaluation of quotients pub proofs: Vec, diff --git a/src/multilinear_pc/mod.rs b/src/multilinear_pc/mod.rs index df23d75..2f63c59 100644 --- a/src/multilinear_pc/mod.rs +++ b/src/multilinear_pc/mod.rs @@ -165,6 +165,8 @@ impl MultilinearPC { Commitment { nv, g_product } } + /// commit the given polynomial using the G2 group as a basis + /// That means the opening will be in G1. pub fn commit_g2( ck: &CommitterKey, polynomial: &impl MultilinearExtension, @@ -248,6 +250,7 @@ impl MultilinearPC { Proof { proofs: proofs } } + /// Create PST opening proof in G1 (with a commitment on G2) pub fn open_g1( ck: &CommitterKey, polynomial: &impl MultilinearExtension, @@ -344,6 +347,7 @@ impl MultilinearPC { left == right } + /// Check a polynomial opening proof in G2 and commitment on G1 pub fn check<'a>( vk: &VerifierKey, commitment: &Commitment, From 7d1deae2de8c5c488ecf91fbe3ea1e2001a1f984 Mon Sep 17 00:00:00 2001 From: Mara Mihali Date: Mon, 6 Feb 2023 17:20:24 +0000 Subject: [PATCH 3/3] remove unnecessry parallel iterators --- src/multilinear_pc/mod.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/multilinear_pc/mod.rs b/src/multilinear_pc/mod.rs index 2f63c59..61b35ba 100644 --- a/src/multilinear_pc/mod.rs +++ b/src/multilinear_pc/mod.rs @@ -157,7 +157,7 @@ impl MultilinearPC { let nv = polynomial.num_vars(); let scalars: Vec<_> = polynomial .to_evaluations() - .into_par_iter() + .into_iter() .map(|x| x.into_repr()) .collect(); let g_product = @@ -206,11 +206,11 @@ impl MultilinearPC { let k = nv - i; let point_at_k = point[i]; q[k] = (0..(1 << (k - 1))) - .into_par_iter() + .into_iter() .map(|_| E::Fr::zero()) .collect(); r[k - 1] = (0..(1 << (k - 1))) - .into_par_iter() + .into_iter() .map(|_| E::Fr::zero()) .collect(); for b in 0..(1 << (k - 1)) { @@ -219,7 +219,7 @@ impl MultilinearPC { + &(r[k][(b << 1) + 1] * &point_at_k); } let scalars: Vec<_> = (0..(1 << k)) - .into_par_iter() + .into_iter() .map(|x| q[k][x >> 1].into_repr()) // fine .collect(); let ph = ck.powers_of_h[i].clone(); @@ -237,13 +237,13 @@ impl MultilinearPC { } let proofs = thread_handles - .into_par_iter() + .into_iter() .map(|h| h.join().unwrap()) .collect(); // let res = s - // .into_par_iter() - // .zip(ck.powers_of_h.clone().into_par_iter()) + // .into_iter() + // .zip(ck.powers_of_h.clone().into_iter()) // .map(|(si, hi)| VariableBaseMSM::multi_scalar_mul(&hi, &si).into_affine()) // .collect::>(); // print!("{:?}", res); @@ -370,13 +370,13 @@ impl MultilinearPC { FixedBaseMSM::multi_scalar_mul(scalar_size, window_size, &g_table, point); let pairing_lefts: Vec<_> = (0..vk.nv) - .into_par_iter() + .into_iter() .map(|i| vk.g_mask_random[i].into_projective() - &g_mul[i]) .collect(); let pairing_lefts: Vec = E::G1Projective::batch_normalization_into_affine(&pairing_lefts); let pairing_lefts: Vec = pairing_lefts - .into_par_iter() + .into_iter() .map(|x| E::G1Prepared::from(x)) .collect(); @@ -387,8 +387,8 @@ impl MultilinearPC { .collect(); let pairings: Vec<_> = pairing_lefts - .into_par_iter() - .zip(pairing_rights.into_par_iter()) + .into_iter() + .zip(pairing_rights.into_iter()) .collect(); let right = E::product_of_pairings(pairings.iter()); // println!("right is {:?}", right);