pairing: Extract Engine::miller_loop into a MultiMillerLoop trait

This enables MultiMillerLoop to be conditionally implemented, for
example in libraries where Engine::pairing supports no-std, but
MultiMillerLoop requires an allocator.
This commit is contained in:
Jack Grigg 2020-05-30 18:35:33 +12:00
parent ee6e00b0e7
commit 02dc1763a3
2 changed files with 24 additions and 22 deletions

View File

@ -1,6 +1,6 @@
use ff::{Field, PrimeField}; use ff::{Field, PrimeField};
use group::{CurveAffine, CurveProjective, Group, PrimeGroup}; use group::{CurveAffine, CurveProjective, Group, PrimeGroup};
use pairing::{Engine, MillerLoopResult, PairingCurveAffine}; use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
use rand_core::RngCore; use rand_core::RngCore;
use std::fmt; use std::fmt;
@ -332,21 +332,26 @@ impl Engine for DummyEngine {
type G2Affine = Fr; type G2Affine = Fr;
// TODO: This should be F_645131 or something. Doesn't matter for now. // TODO: This should be F_645131 or something. Doesn't matter for now.
type MillerLoopResult = Fr;
type Gt = Fr; type Gt = Fr;
fn miller_loop<'a, I>(i: I) -> Self::MillerLoopResult fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
where Self::multi_miller_loop(&[(p, &(q.prepare()))]).final_exponentiation()
I: IntoIterator< }
Item = &'a ( }
&'a <Self::G1Affine as PairingCurveAffine>::Prepared,
&'a <Self::G2Affine as PairingCurveAffine>::Prepared, impl MultiMillerLoop for DummyEngine {
), // TODO: This should be F_645131 or something. Doesn't matter for now.
>, type Result = Fr;
{
fn multi_miller_loop(
terms: &[(
&Self::G1Affine,
&<Self::G2Affine as PairingCurveAffine>::Prepared,
)],
) -> Self::Result {
let mut acc = <Fr as Field>::zero(); let mut acc = <Fr as Field>::zero();
for &(a, b) in i { for &(a, b) in terms {
let mut tmp = *a; let mut tmp = *a;
MulAssign::mul_assign(&mut tmp, b); MulAssign::mul_assign(&mut tmp, b);
AddAssign::add_assign(&mut acc, &tmp); AddAssign::add_assign(&mut acc, &tmp);

View File

@ -1,5 +1,5 @@
use group::{CurveAffine, CurveProjective}; use group::{CurveAffine, CurveProjective};
use pairing::{Engine, MillerLoopResult, PairingCurveAffine}; use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
use std::ops::{AddAssign, Neg}; use std::ops::{AddAssign, Neg};
use super::{PreparedVerifyingKey, Proof, VerifyingKey}; use super::{PreparedVerifyingKey, Proof, VerifyingKey};
@ -18,7 +18,7 @@ pub fn prepare_verifying_key<E: Engine>(vk: &VerifyingKey<E>) -> PreparedVerifyi
} }
} }
pub fn verify_proof<'a, E: Engine>( pub fn verify_proof<'a, E: MultiMillerLoop>(
pvk: &'a PreparedVerifyingKey<E>, pvk: &'a PreparedVerifyingKey<E>,
proof: &Proof<E>, proof: &Proof<E>,
public_inputs: &[E::Fr], public_inputs: &[E::Fr],
@ -41,14 +41,11 @@ pub fn verify_proof<'a, E: Engine>(
// A * B + inputs * (-gamma) + C * (-delta) = alpha * beta // A * B + inputs * (-gamma) + C * (-delta) = alpha * beta
// which allows us to do a single final exponentiation. // which allows us to do a single final exponentiation.
Ok(E::miller_loop( Ok(E::multi_miller_loop(&[
[ (&proof.a, &proof.b.prepare()),
(&proof.a.prepare(), &proof.b.prepare()), (&acc.to_affine(), &pvk.neg_gamma_g2),
(&acc.to_affine().prepare(), &pvk.neg_gamma_g2), (&proof.c, &pvk.neg_delta_g2),
(&proof.c.prepare(), &pvk.neg_delta_g2), ])
]
.iter(),
)
.final_exponentiation() .final_exponentiation()
== pvk.alpha_g1_beta_g2) == pvk.alpha_g1_beta_g2)
} }