diff --git a/pcs/Cargo.toml b/pcs/Cargo.toml index bf285be..669ba65 100644 --- a/pcs/Cargo.toml +++ b/pcs/Cargo.toml @@ -24,9 +24,8 @@ path = "benches/bench.rs" harness = false [features] -# by default we switch the groups -# default = [ "parallel", "print-trace", "group-switched" ] -default = [ "parallel", "group-switched" ] +# default = [ "parallel", "print-trace" ] +default = [ "parallel" ] parallel = [ "ark-std/parallel", "ark-ff/parallel", @@ -35,7 +34,4 @@ parallel = [ ] print-trace = [ "ark-std/print-trace" - ] -# With the flag, we switch the groups of G1 and G2 as in a normal KZG. -# i.e., commitments are over G2 and openings are over G1 when this feature is turned on. -group-switched = [] \ No newline at end of file + ] \ No newline at end of file diff --git a/pcs/readme.md b/pcs/readme.md index 4308c01..8b461e7 100644 --- a/pcs/readme.md +++ b/pcs/readme.md @@ -3,5 +3,4 @@ KZG based multilinear polynomial commitment # Compiling features: - `parallel`: use multi-threading when possible. -- `print-trace`: print out user friendly information about the running time for each micro component. -- `group-switched`: witch the groups of G1 and G2 as in a normal KZG. i.e., commitments are over G2 and openings are over G1 when this feature is turned on. \ No newline at end of file +- `print-trace`: print out user friendly information about the running time for each micro component. \ No newline at end of file diff --git a/pcs/src/commit.rs b/pcs/src/commit.rs index 8447819..7ad2ef6 100644 --- a/pcs/src/commit.rs +++ b/pcs/src/commit.rs @@ -18,19 +18,13 @@ pub struct Commitment { /// number of variables pub nv: usize, /// product of g as described by the vRAM paper - #[cfg(not(feature = "group-switched"))] pub g_product: E::G1Affine, - #[cfg(feature = "group-switched")] - pub g_product: E::G2Affine, } #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] /// proof of opening pub struct Proof { /// Evaluation of quotients - #[cfg(not(feature = "group-switched"))] - pub proofs: Vec, - #[cfg(feature = "group-switched")] pub proofs: Vec, } @@ -106,9 +100,9 @@ impl MultilinearCommitmentScheme for KZGMultilinearPC { let mut proofs = Vec::new(); - for (i, (&point_at_k, hi)) in point + for (i, (&point_at_k, gi)) in point .iter() - .zip(prover_param.powers_of_h.iter()) + .zip(prover_param.powers_of_g.iter()) .take(nv) .enumerate() { @@ -133,8 +127,8 @@ impl MultilinearCommitmentScheme for KZGMultilinearPC { q[k] = cur_q; r[k - 1] = cur_r; - // this is a MSM over G2 and is likely to be the bottleneck - proofs.push(VariableBaseMSM::multi_scalar_mul(&hi.evals, &scalars).into_affine()); + // this is a MSM over G1 and is likely to be the bottleneck + proofs.push(VariableBaseMSM::multi_scalar_mul(&gi.evals, &scalars).into_affine()); end_timer!(ith_round); } @@ -161,66 +155,42 @@ impl MultilinearCommitmentScheme for KZGMultilinearPC { let scalar_size = E::Fr::size_in_bits(); let window_size = FixedBaseMSM::get_mul_window_size(verifier_param.num_vars); - let g_table = FixedBaseMSM::get_window_table( + let h_table = FixedBaseMSM::get_window_table( scalar_size, window_size, - verifier_param.g.into_projective(), + verifier_param.h.into_projective(), ); - #[cfg(not(feature = "group-switched"))] - let g_mul: Vec = - FixedBaseMSM::multi_scalar_mul(scalar_size, window_size, &g_table, point); - #[cfg(feature = "group-switched")] - let g_mul: Vec = - FixedBaseMSM::multi_scalar_mul(scalar_size, window_size, &g_table, point); - - let mut g1_vec: Vec<_> = (0..verifier_param.num_vars) - .map(|i| verifier_param.g_mask[i].into_projective() - g_mul[i]) - .collect(); - g1_vec.push(verifier_param.g.mul(value) - commitment.g_product.into_projective()); + let h_mul: Vec = + FixedBaseMSM::multi_scalar_mul(scalar_size, window_size, &h_table, point); - #[cfg(not(feature = "group-switched"))] - let g1_vec: Vec = E::G1Projective::batch_normalization_into_affine(&g1_vec); - #[cfg(feature = "group-switched")] - let g1_vec: Vec = E::G2Projective::batch_normalization_into_affine(&g1_vec); - let tmp = g1_vec[verifier_param.num_vars]; + let h_vec: Vec<_> = (0..verifier_param.num_vars) + .map(|i| verifier_param.h_mask[i].into_projective() - h_mul[i]) + .collect(); + let h_vec: Vec = E::G2Projective::batch_normalization_into_affine(&h_vec); end_timer!(prepare_inputs_timer); let pairing_product_timer = start_timer!(|| "pairing product"); - #[cfg(not(feature = "group-switched"))] - let mut pairings: Vec<_> = g1_vec - .into_iter() - .take(verifier_param.num_vars) - .map(E::G1Prepared::from) - .zip(proof.proofs.iter().map(|&x| E::G2Prepared::from(x))) - .collect(); - - #[cfg(feature = "group-switched")] let mut pairings: Vec<_> = proof .proofs .iter() - .take(verifier_param.num_vars) .map(|&x| E::G1Prepared::from(x)) .zip( - g1_vec + h_vec .into_iter() .take(verifier_param.num_vars) .map(E::G2Prepared::from), ) .collect(); - #[cfg(not(feature = "group-switched"))] pairings.push(( - E::G1Prepared::from(tmp), + E::G1Prepared::from( + (verifier_param.g.mul(value) - commitment.g_product.into_projective()) + .into_affine(), + ), E::G2Prepared::from(verifier_param.h), )); - #[cfg(feature = "group-switched")] - pairings.push(( - E::G1Prepared::from(verifier_param.h), - E::G2Prepared::from(tmp), - )); - let res = E::product_of_pairings(pairings.iter()) == E::Fqk::one(); end_timer!(pairing_product_timer); diff --git a/pcs/src/param.rs b/pcs/src/param.rs index 1942cf1..c70beb1 100644 --- a/pcs/src/param.rs +++ b/pcs/src/param.rs @@ -18,11 +18,8 @@ pub struct Evaluations { pub struct UniversalParams { /// prover parameters pub prover_param: ProverParam, - /// g^randomness: g^t1, g^t2, ... - #[cfg(not(feature = "group-switched"))] - pub g_mask: Vec, - #[cfg(feature = "group-switched")] - pub g_mask: Vec, + /// h^randomness: h^t1, h^t2, ..., **h^{t_nv}** + pub h_mask: Vec, } /// Prover Parameters @@ -32,26 +29,11 @@ pub struct ProverParam { pub num_vars: usize, /// `pp_{num_vars}`, `pp_{num_vars - 1}`, `pp_{num_vars - 2}`, ..., defined /// by XZZPD19 - #[cfg(not(feature = "group-switched"))] pub powers_of_g: Vec>, - #[cfg(feature = "group-switched")] - pub powers_of_g: Vec>, - /// `pp_{num_vars}`, `pp_{num_vars - 1}`, `pp_{num_vars - 2}`, ..., defined - /// by XZZPD19 - #[cfg(not(feature = "group-switched"))] - pub powers_of_h: Vec>, - #[cfg(feature = "group-switched")] - pub powers_of_h: Vec>, /// generator for G1 - #[cfg(not(feature = "group-switched"))] pub g: E::G1Affine, - #[cfg(feature = "group-switched")] - pub g: E::G2Affine, /// generator for G2 - #[cfg(not(feature = "group-switched"))] pub h: E::G2Affine, - #[cfg(feature = "group-switched")] - pub h: E::G1Affine, } /// Verifier Parameters @@ -61,22 +43,13 @@ pub struct VerifierParam { pub num_vars: usize, /// generator of G1 - #[cfg(not(feature = "group-switched"))] pub g: E::G1Affine, - #[cfg(feature = "group-switched")] - pub g: E::G2Affine, /// generator of G2 - #[cfg(not(feature = "group-switched"))] pub h: E::G2Affine, - #[cfg(feature = "group-switched")] - pub h: E::G1Affine, - - /// g^t1, g^t2, ... - #[cfg(not(feature = "group-switched"))] - pub g_mask: Vec, - #[cfg(feature = "group-switched")] - pub g_mask: Vec, + + /// h^randomness: h^t1, h^t2, ..., **h^{t_nv}** + pub h_mask: Vec, } impl UniversalParams { @@ -91,7 +64,7 @@ impl UniversalParams { num_vars: self.prover_param.num_vars, g: self.prover_param.g, h: self.prover_param.h, - g_mask: self.g_mask.clone(), + h_mask: self.h_mask.clone(), } } @@ -112,7 +85,6 @@ impl UniversalParams { let to_reduce = self.prover_param.num_vars - supported_num_vars; let ck = ProverParam { - powers_of_h: self.prover_param.powers_of_h[to_reduce..].to_vec(), powers_of_g: self.prover_param.powers_of_g[to_reduce..].to_vec(), g: self.prover_param.g, h: self.prover_param.h, @@ -122,7 +94,7 @@ impl UniversalParams { num_vars: supported_num_vars, g: self.prover_param.g, h: self.prover_param.h, - g_mask: self.g_mask[to_reduce..].to_vec(), + h_mask: self.h_mask[to_reduce..].to_vec(), }; Ok((ck, vk)) } @@ -144,18 +116,11 @@ impl UniversalParams { let pp_generation_timer = start_timer!(|| "Prover Param generation"); - #[cfg(not(feature = "group-switched"))] let g = E::G1Projective::rand(rng); - #[cfg(feature = "group-switched")] - let g = E::G2Projective::rand(rng); - - #[cfg(not(feature = "group-switched"))] let h = E::G2Projective::rand(rng); - #[cfg(feature = "group-switched")] - let h = E::G1Projective::rand(rng); let mut powers_of_g = Vec::new(); - let mut powers_of_h = Vec::new(); + let t: Vec<_> = (0..num_vars).map(|_| E::Fr::rand(rng)).collect(); let scalar_bits = E::Fr::size_in_bits(); @@ -186,35 +151,18 @@ impl UniversalParams { } let window_size = FixedBaseMSM::get_mul_window_size(total_scalars); let g_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, g); - let h_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, h); - #[cfg(not(feature = "group-switched"))] let pp_g = E::G1Projective::batch_normalization_into_affine( &FixedBaseMSM::multi_scalar_mul(scalar_bits, window_size, &g_table, &pp_powers), ); - #[cfg(feature = "group-switched")] - let pp_g = E::G2Projective::batch_normalization_into_affine( - &FixedBaseMSM::multi_scalar_mul(scalar_bits, window_size, &g_table, &pp_powers), - ); - #[cfg(not(feature = "group-switched"))] - let pp_h = E::G2Projective::batch_normalization_into_affine( - &FixedBaseMSM::multi_scalar_mul(scalar_bits, window_size, &h_table, &pp_powers), - ); - #[cfg(feature = "group-switched")] - let pp_h = E::G1Projective::batch_normalization_into_affine( - &FixedBaseMSM::multi_scalar_mul(scalar_bits, window_size, &h_table, &pp_powers), - ); + let mut start = 0; for i in 0..num_vars { let size = 1 << (num_vars - i); let pp_k_g = Evaluations { evals: pp_g[start..(start + size)].to_vec(), }; - let pp_k_h = Evaluations { - evals: pp_h[start..(start + size)].to_vec(), - }; powers_of_g.push(pp_k_g); - powers_of_h.push(pp_k_h); start += size; } @@ -223,32 +171,26 @@ impl UniversalParams { g: g.into_affine(), h: h.into_affine(), powers_of_g, - powers_of_h, }; end_timer!(pp_generation_timer); let vp_generation_timer = start_timer!(|| "VP generation"); - let g_mask = { + let h_mask = { let window_size = FixedBaseMSM::get_mul_window_size(num_vars); - let g_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, g); - - #[cfg(not(feature = "group-switched"))] - let res = E::G1Projective::batch_normalization_into_affine( - &FixedBaseMSM::multi_scalar_mul(scalar_bits, window_size, &g_table, &t), - ); - - #[cfg(feature = "group-switched")] - let res = E::G2Projective::batch_normalization_into_affine( - &FixedBaseMSM::multi_scalar_mul(scalar_bits, window_size, &g_table, &t), - ); - res + let h_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, h); + E::G2Projective::batch_normalization_into_affine(&FixedBaseMSM::multi_scalar_mul( + scalar_bits, + window_size, + &h_table, + &t, + )) }; end_timer!(vp_generation_timer); end_timer!(total_timer); Ok(Self { prover_param: pp, - g_mask, + h_mask, }) } }