diff --git a/CHANGELOG.md b/CHANGELOG.md index 9203dcd4..89bae257 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Pending +- [\#98](https://github.com/arkworks-rs/poly-commit/pull/98) Use pairing-product to accelerate `KZG` and `multilinear_pc` verifications. + ### Breaking changes - [\#82](https://github.com/arkworks-rs/poly-commit/pull/82) Function parameter `opening_challenge: F` for `open`, @@ -13,6 +15,8 @@ ### Improvements +- [\#98](https://github.com/arkworks-rs/poly-commit/pull/98) Improve KZG10 verification speed. + ### Bug fixes ## v0.3.0 diff --git a/src/kzg10/mod.rs b/src/kzg10/mod.rs index fd1bcd71..11ed944e 100644 --- a/src/kzg10/mod.rs +++ b/src/kzg10/mod.rs @@ -291,13 +291,15 @@ where if let Some(random_v) = proof.random_v { inner -= &vk.gamma_g.mul(random_v); } - let lhs = E::pairing(inner, vk.h); - - let inner = vk.beta_h.into_projective() - &vk.h.mul(point); - let rhs = E::pairing(proof.w, inner); - - end_timer!(check_time, || format!("Result: {}", lhs == rhs)); - Ok(lhs == rhs) + let inner2 = vk.beta_h.into_projective() - &vk.h.mul(point); + + let pairing_prod_inputs: [(E::G1Prepared, E::G2Prepared); 2] = [ + ((-inner).into_affine().into(), vk.h.into()), + (proof.w.into(), inner2.into_affine().into()), + ]; + let res = E::product_of_pairings(pairing_prod_inputs.iter()).is_one(); + end_timer!(check_time, || format!("Result: {}", res)); + Ok(res) } /// Check that each `proof_i` in `proofs` is a valid proof of evaluation for diff --git a/src/multilinear_pc/mod.rs b/src/multilinear_pc/mod.rs index 8473a7b9..5618eaa1 100644 --- a/src/multilinear_pc/mod.rs +++ b/src/multilinear_pc/mod.rs @@ -194,39 +194,30 @@ impl MultilinearPC { value: E::Fr, proof: &Proof, ) -> bool { - let left = E::pairing( - commitment.g_product.into_projective() - &vk.g.mul(value), - vk.h, - ); - let scalar_size = E::Fr::MODULUS_BIT_SIZE as usize; let window_size = FixedBase::get_mul_window_size(vk.nv); let g_table = FixedBase::get_window_table(scalar_size, window_size, vk.g.into_projective()); let g_mul: Vec = FixedBase::msm(scalar_size, window_size, &g_table, point); - let pairing_lefts: Vec<_> = (0..vk.nv) - .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_iter() - .map(|x| E::G1Prepared::from(x)) + let mut g1_vec: Vec<_> = (0..vk.nv) + .map(|i| vk.g_mask_random[i].into_projective() - g_mul[i]) .collect(); + g1_vec.push(vk.g.mul(value) - commitment.g_product.into_projective()); - let pairing_rights: Vec = proof - .proofs - .iter() - .map(|x| E::G2Prepared::from(*x)) - .collect(); + let g1_vec: Vec = E::G1Projective::batch_normalization_into_affine(&g1_vec); + let tmp = g1_vec[vk.nv]; - let pairings: Vec<_> = pairing_lefts + let mut pairings: Vec<_> = g1_vec .into_iter() - .zip(pairing_rights.into_iter()) + .take(vk.nv) + .map(E::G1Prepared::from) + .zip(proof.proofs.iter().map(|&x| E::G2Prepared::from(x))) .collect(); - let right = E::product_of_pairings(pairings.iter()); - left == right + + pairings.push((E::G1Prepared::from(tmp), E::G2Prepared::from(vk.h))); + + E::product_of_pairings(pairings.iter()).is_one() } }