diff --git a/pcs/Cargo.toml b/pcs/Cargo.toml index 30ce8aa..bf285be 100644 --- a/pcs/Cargo.toml +++ b/pcs/Cargo.toml @@ -24,8 +24,9 @@ path = "benches/bench.rs" harness = false [features] -default = [ "parallel", "print-trace" ] -# default = [ "parallel" ] +# by default we switch the groups +# default = [ "parallel", "print-trace", "group-switched" ] +default = [ "parallel", "group-switched" ] parallel = [ "ark-std/parallel", "ark-ff/parallel", @@ -34,4 +35,7 @@ parallel = [ ] print-trace = [ "ark-std/print-trace" - ] \ No newline at end of file + ] +# 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 diff --git a/pcs/readme.md b/pcs/readme.md index d72e8f7..4308c01 100644 --- a/pcs/readme.md +++ b/pcs/readme.md @@ -1,3 +1,7 @@ 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 diff --git a/pcs/src/commit.rs b/pcs/src/commit.rs index 150e4c1..8447819 100644 --- a/pcs/src/commit.rs +++ b/pcs/src/commit.rs @@ -18,14 +18,20 @@ 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, } impl MultilinearCommitmentScheme for KZGMultilinearPC { @@ -160,20 +166,28 @@ impl MultilinearCommitmentScheme for KZGMultilinearPC { window_size, verifier_param.g.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()); + #[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]; 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) @@ -181,11 +195,32 @@ impl MultilinearCommitmentScheme for KZGMultilinearPC { .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 + .into_iter() + .take(verifier_param.num_vars) + .map(E::G2Prepared::from), + ) + .collect(); + + #[cfg(not(feature = "group-switched"))] pairings.push(( E::G1Prepared::from(tmp), 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 316c2f8..1942cf1 100644 --- a/pcs/src/param.rs +++ b/pcs/src/param.rs @@ -19,7 +19,10 @@ 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, } /// Prover Parameters @@ -29,14 +32,26 @@ 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 @@ -44,12 +59,24 @@ pub struct ProverParam { pub struct VerifierParam { /// number of variables 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, } impl UniversalParams { @@ -116,8 +143,16 @@ impl UniversalParams { let total_timer = start_timer!(|| "SRS generation"); 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(); @@ -153,12 +188,22 @@ impl UniversalParams { 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); @@ -187,12 +232,17 @@ impl UniversalParams { let g_mask = { let window_size = FixedBaseMSM::get_mul_window_size(num_vars); let g_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, g); - E::G1Projective::batch_normalization_into_affine(&FixedBaseMSM::multi_scalar_mul( - scalar_bits, - window_size, - &g_table, - &t, - )) + + #[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 }; end_timer!(vp_generation_timer); end_timer!(total_timer); diff --git a/scripts/run_tests.sh b/scripts/run_tests.sh index a96e980..f654683 100755 --- a/scripts/run_tests.sh +++ b/scripts/run_tests.sh @@ -3,6 +3,7 @@ # We want the code to panic if there is an integer overflow export RUSTFLAGS="-C overflow-checks=on" +cargo test --release -p pcs --no-default-features --features=parallel -- -Zunstable-options --report-time cargo test --release -- -Zunstable-options --report-time cargo test --no-run --features=print-trace cargo test --no-run --no-default-features