Skip to content
This repository was archived by the owner on Feb 7, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/multilinear_pc/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub struct UniversalParams<E: PairingEngine> {
pub h: E::G2Affine,
/// g^randomness
pub g_mask: Vec<E::G1Affine>,
/// h^randomness
pub h_mask: Vec<E::G2Affine>,
}

/// Public Parameter used by prover
Expand Down Expand Up @@ -51,20 +53,38 @@ pub struct VerifierKey<E: PairingEngine> {
pub h: E::G2Affine,
/// g^t1, g^t2, ...
pub g_mask_random: Vec<E::G1Affine>,
/// h^t1, h^t2,...
pub h_mask_random: Vec<E::G2Affine>,
}

#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
/// commitment
/// PST commitment on the G1 group
pub struct Commitment<E: PairingEngine> {
/// number of variables
pub nv: usize,
/// product of g as described by the vRAM paper
pub g_product: E::G1Affine,
}

#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
/// PST Commitment on the G2 group
pub struct Commitment_G2<E: PairingEngine> {
/// 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<E: PairingEngine> {
/// Evaluation of quotients
pub proofs: Vec<E::G2Affine>,
}

#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, PartialEq, Eq)]
/// PST Proof of opening on G1 (so commitment is on G2)
pub struct Proof_G1<E: PairingEngine> {
/// Evaluation of quotients
pub proofs: Vec<E::G1Affine>,
}
181 changes: 169 additions & 12 deletions src/multilinear_pc/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -96,15 +98,28 @@ impl<E: PairingEngine> MultilinearPC<E> {
&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,
}
}

Expand All @@ -129,6 +144,7 @@ impl<E: PairingEngine> MultilinearPC<E> {
g: params.g,
h: params.h,
g_mask_random: (&params.g_mask[to_reduce..]).to_vec(),
h_mask_random: (&params.h_mask[to_reduce..]).to_vec(),
};
(ck, vk)
}
Expand All @@ -141,14 +157,31 @@ impl<E: PairingEngine> MultilinearPC<E> {
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 =
VariableBaseMSM::multi_scalar_mul(&ck.powers_of_g[0], scalars.as_slice()).into_affine();
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<E>,
polynomial: &impl MultilinearExtension<E::Fr>,
) -> Commitment_G2<E> {
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<E>,
Expand All @@ -173,11 +206,11 @@ impl<E: PairingEngine> MultilinearPC<E> {
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)) {
Expand All @@ -186,7 +219,7 @@ impl<E: PairingEngine> MultilinearPC<E> {
+ &(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();
Expand All @@ -204,21 +237,117 @@ impl<E: PairingEngine> MultilinearPC<E> {
}

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::<Vec<_>>();
// print!("{:?}", res);
Proof { proofs: proofs }
}

/// Create PST opening proof in G1 (with a commitment on G2)
pub fn open_g1(
ck: &CommitterKey<E>,
polynomial: &impl MultilinearExtension<E::Fr>,
point: &[E::Fr],
) -> Proof_G1<E> {
assert_eq!(polynomial.num_vars(), ck.nv, "Invalid size of polynomial");
let nv = polynomial.num_vars();
let mut r: Vec<Vec<E::Fr>> = (0..nv + 1).map(|_| Vec::new()).collect();
let mut q: Vec<Vec<E::Fr>> = (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<E>,
commitment: &Commitment_G2<E>,
point: &[E::Fr],
value: E::Fr,
proof: &Proof_G1<E>,
) -> 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<E::G2Projective> =
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::G2Affine> =
E::G2Projective::batch_normalization_into_affine(&pairing_rights);
let pairing_rights: Vec<E::G2Prepared> = pairing_rights
.into_iter()
.map(|x| E::G2Prepared::from(x))
.collect();

let pairing_lefts: Vec<E::G1Prepared> = 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
}

/// Check a polynomial opening proof in G2 and commitment on G1
pub fn check<'a>(
vk: &VerifierKey<E>,
commitment: &Commitment<E>,
Expand All @@ -241,13 +370,13 @@ impl<E: PairingEngine> MultilinearPC<E> {
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::G1Affine> =
E::G1Projective::batch_normalization_into_affine(&pairing_lefts);
let pairing_lefts: Vec<E::G1Prepared> = pairing_lefts
.into_par_iter()
.into_iter()
.map(|x| E::G1Prepared::from(x))
.collect();

Expand All @@ -258,8 +387,8 @@ impl<E: PairingEngine> MultilinearPC<E> {
.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);
Expand Down Expand Up @@ -331,6 +460,34 @@ mod tests {
assert!(result);
}

fn test_polynomial_g2<R: RngCore>(
uni_params: &UniversalParams<E>,
poly: &impl MultilinearExtension<Fr>,
rng: &mut R,
) {
let nv = poly.num_vars();
assert_ne!(nv, 0);
let (ck, vk) = MultilinearPC::<E>::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();
Expand Down