Browse Source

feat: allow group switching, and switch group by default (#33)

main
zhenfei 2 years ago
committed by GitHub
parent
commit
3b58050b27
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 103 additions and 9 deletions
  1. +7
    -3
      pcs/Cargo.toml
  2. +4
    -0
      pcs/readme.md
  3. +35
    -0
      pcs/src/commit.rs
  4. +56
    -6
      pcs/src/param.rs
  5. +1
    -0
      scripts/run_tests.sh

+ 7
- 3
pcs/Cargo.toml

@ -24,8 +24,9 @@ path = "benches/bench.rs"
harness = false harness = false
[features] [features]
default = [ "parallel", "print-trace" ]
# default = [ "parallel" ]
# by default we switch the groups
# default = [ "parallel", "print-trace", "group-switched" ]
default = [ "parallel", "group-switched" ]
parallel = [ parallel = [
"ark-std/parallel", "ark-std/parallel",
"ark-ff/parallel", "ark-ff/parallel",
@ -34,4 +35,7 @@ parallel = [
] ]
print-trace = [ print-trace = [
"ark-std/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 = []

+ 4
- 0
pcs/readme.md

@ -1,3 +1,7 @@
KZG based multilinear polynomial commitment 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.

+ 35
- 0
pcs/src/commit.rs

@ -18,14 +18,20 @@ pub struct Commitment {
/// number of variables /// number of variables
pub nv: usize, pub nv: usize,
/// product of g as described by the vRAM paper /// product of g as described by the vRAM paper
#[cfg(not(feature = "group-switched"))]
pub g_product: E::G1Affine, pub g_product: E::G1Affine,
#[cfg(feature = "group-switched")]
pub g_product: E::G2Affine,
} }
#[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)] #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug)]
/// proof of opening /// proof of opening
pub struct Proof<E: PairingEngine> { pub struct Proof<E: PairingEngine> {
/// Evaluation of quotients /// Evaluation of quotients
#[cfg(not(feature = "group-switched"))]
pub proofs: Vec<E::G2Affine>, pub proofs: Vec<E::G2Affine>,
#[cfg(feature = "group-switched")]
pub proofs: Vec<E::G1Affine>,
} }
impl<E: PairingEngine> MultilinearCommitmentScheme<E> for KZGMultilinearPC<E> { impl<E: PairingEngine> MultilinearCommitmentScheme<E> for KZGMultilinearPC<E> {
@ -160,20 +166,28 @@ impl MultilinearCommitmentScheme for KZGMultilinearPC {
window_size, window_size,
verifier_param.g.into_projective(), verifier_param.g.into_projective(),
); );
#[cfg(not(feature = "group-switched"))]
let g_mul: Vec<E::G1Projective> = let g_mul: Vec<E::G1Projective> =
FixedBaseMSM::multi_scalar_mul(scalar_size, window_size, &g_table, point); FixedBaseMSM::multi_scalar_mul(scalar_size, window_size, &g_table, point);
#[cfg(feature = "group-switched")]
let g_mul: Vec<E::G2Projective> =
FixedBaseMSM::multi_scalar_mul(scalar_size, window_size, &g_table, point);
let mut g1_vec: Vec<_> = (0..verifier_param.num_vars) let mut g1_vec: Vec<_> = (0..verifier_param.num_vars)
.map(|i| verifier_param.g_mask[i].into_projective() - g_mul[i]) .map(|i| verifier_param.g_mask[i].into_projective() - g_mul[i])
.collect(); .collect();
g1_vec.push(verifier_param.g.mul(value) - commitment.g_product.into_projective()); g1_vec.push(verifier_param.g.mul(value) - commitment.g_product.into_projective());
#[cfg(not(feature = "group-switched"))]
let g1_vec: Vec<E::G1Affine> = E::G1Projective::batch_normalization_into_affine(&g1_vec); let g1_vec: Vec<E::G1Affine> = E::G1Projective::batch_normalization_into_affine(&g1_vec);
#[cfg(feature = "group-switched")]
let g1_vec: Vec<E::G2Affine> = E::G2Projective::batch_normalization_into_affine(&g1_vec);
let tmp = g1_vec[verifier_param.num_vars]; let tmp = g1_vec[verifier_param.num_vars];
end_timer!(prepare_inputs_timer); end_timer!(prepare_inputs_timer);
let pairing_product_timer = start_timer!(|| "pairing product"); let pairing_product_timer = start_timer!(|| "pairing product");
#[cfg(not(feature = "group-switched"))]
let mut pairings: Vec<_> = g1_vec let mut pairings: Vec<_> = g1_vec
.into_iter() .into_iter()
.take(verifier_param.num_vars) .take(verifier_param.num_vars)
@ -181,11 +195,32 @@ impl MultilinearCommitmentScheme for KZGMultilinearPC {
.zip(proof.proofs.iter().map(|&x| E::G2Prepared::from(x))) .zip(proof.proofs.iter().map(|&x| E::G2Prepared::from(x)))
.collect(); .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(( pairings.push((
E::G1Prepared::from(tmp), E::G1Prepared::from(tmp),
E::G2Prepared::from(verifier_param.h), 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(); let res = E::product_of_pairings(pairings.iter()) == E::Fqk::one();
end_timer!(pairing_product_timer); end_timer!(pairing_product_timer);

+ 56
- 6
pcs/src/param.rs

@ -19,7 +19,10 @@ pub struct UniversalParams {
/// prover parameters /// prover parameters
pub prover_param: ProverParam<E>, pub prover_param: ProverParam<E>,
/// g^randomness: g^t1, g^t2, ... /// g^randomness: g^t1, g^t2, ...
#[cfg(not(feature = "group-switched"))]
pub g_mask: Vec<E::G1Affine>, pub g_mask: Vec<E::G1Affine>,
#[cfg(feature = "group-switched")]
pub g_mask: Vec<E::G2Affine>,
} }
/// Prover Parameters /// Prover Parameters
@ -29,14 +32,26 @@ pub struct ProverParam {
pub num_vars: usize, pub num_vars: usize,
/// `pp_{num_vars}`, `pp_{num_vars - 1}`, `pp_{num_vars - 2}`, ..., defined /// `pp_{num_vars}`, `pp_{num_vars - 1}`, `pp_{num_vars - 2}`, ..., defined
/// by XZZPD19 /// by XZZPD19
#[cfg(not(feature = "group-switched"))]
pub powers_of_g: Vec<Evaluations<E::G1Affine>>, pub powers_of_g: Vec<Evaluations<E::G1Affine>>,
#[cfg(feature = "group-switched")]
pub powers_of_g: Vec<Evaluations<E::G2Affine>>,
/// `pp_{num_vars}`, `pp_{num_vars - 1}`, `pp_{num_vars - 2}`, ..., defined /// `pp_{num_vars}`, `pp_{num_vars - 1}`, `pp_{num_vars - 2}`, ..., defined
/// by XZZPD19 /// by XZZPD19
#[cfg(not(feature = "group-switched"))]
pub powers_of_h: Vec<Evaluations<E::G2Affine>>, pub powers_of_h: Vec<Evaluations<E::G2Affine>>,
#[cfg(feature = "group-switched")]
pub powers_of_h: Vec<Evaluations<E::G1Affine>>,
/// generator for G1 /// generator for G1
#[cfg(not(feature = "group-switched"))]
pub g: E::G1Affine, pub g: E::G1Affine,
#[cfg(feature = "group-switched")]
pub g: E::G2Affine,
/// generator for G2 /// generator for G2
#[cfg(not(feature = "group-switched"))]
pub h: E::G2Affine, pub h: E::G2Affine,
#[cfg(feature = "group-switched")]
pub h: E::G1Affine,
} }
/// Verifier Parameters /// Verifier Parameters
@ -44,12 +59,24 @@ pub struct ProverParam {
pub struct VerifierParam<E: PairingEngine> { pub struct VerifierParam<E: PairingEngine> {
/// number of variables /// number of variables
pub num_vars: usize, pub num_vars: usize,
/// generator of G1 /// generator of G1
#[cfg(not(feature = "group-switched"))]
pub g: E::G1Affine, pub g: E::G1Affine,
#[cfg(feature = "group-switched")]
pub g: E::G2Affine,
/// generator of G2 /// generator of G2
#[cfg(not(feature = "group-switched"))]
pub h: E::G2Affine, pub h: E::G2Affine,
#[cfg(feature = "group-switched")]
pub h: E::G1Affine,
/// g^t1, g^t2, ... /// g^t1, g^t2, ...
#[cfg(not(feature = "group-switched"))]
pub g_mask: Vec<E::G1Affine>, pub g_mask: Vec<E::G1Affine>,
#[cfg(feature = "group-switched")]
pub g_mask: Vec<E::G2Affine>,
} }
impl<E: PairingEngine> UniversalParams<E> { impl<E: PairingEngine> UniversalParams<E> {
@ -116,8 +143,16 @@ impl UniversalParams {
let total_timer = start_timer!(|| "SRS generation"); let total_timer = start_timer!(|| "SRS generation");
let pp_generation_timer = start_timer!(|| "Prover Param generation"); let pp_generation_timer = start_timer!(|| "Prover Param generation");
#[cfg(not(feature = "group-switched"))]
let g = E::G1Projective::rand(rng); 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); 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_g = Vec::new();
let mut powers_of_h = 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 g_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, g);
let h_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, h); 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( let pp_g = E::G1Projective::batch_normalization_into_affine(
&FixedBaseMSM::multi_scalar_mul(scalar_bits, window_size, &g_table, &pp_powers), &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( let pp_h = E::G2Projective::batch_normalization_into_affine(
&FixedBaseMSM::multi_scalar_mul(scalar_bits, window_size, &h_table, &pp_powers), &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; let mut start = 0;
for i in 0..num_vars { for i in 0..num_vars {
let size = 1 << (num_vars - i); let size = 1 << (num_vars - i);
@ -187,12 +232,17 @@ impl UniversalParams {
let g_mask = { let g_mask = {
let window_size = FixedBaseMSM::get_mul_window_size(num_vars); let window_size = FixedBaseMSM::get_mul_window_size(num_vars);
let g_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, g); 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!(vp_generation_timer);
end_timer!(total_timer); end_timer!(total_timer);

+ 1
- 0
scripts/run_tests.sh

@ -3,6 +3,7 @@
# We want the code to panic if there is an integer overflow # We want the code to panic if there is an integer overflow
export RUSTFLAGS="-C overflow-checks=on" 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 --release -- -Zunstable-options --report-time
cargo test --no-run --features=print-trace cargo test --no-run --features=print-trace
cargo test --no-run --no-default-features cargo test --no-run --no-default-features

Loading…
Cancel
Save