pairing: Move final_exponentiation into a MillerLoopResult trait
This commit is contained in:
parent
c8bf2e9fb7
commit
57bb18ca6f
|
@ -1,6 +1,6 @@
|
||||||
use ff::{Field, PrimeField, ScalarEngine};
|
use ff::{Field, PrimeField, ScalarEngine};
|
||||||
use group::{CurveAffine, CurveProjective, Group, PrimeGroup};
|
use group::{CurveAffine, CurveProjective, Group, PrimeGroup};
|
||||||
use pairing::{Engine, PairingCurveAffine};
|
use pairing::{Engine, MillerLoopResult, PairingCurveAffine};
|
||||||
|
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -357,10 +357,14 @@ impl Engine for DummyEngine {
|
||||||
|
|
||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MillerLoopResult for Fr {
|
||||||
|
type Gt = Fr;
|
||||||
|
|
||||||
/// Perform final exponentiation of the result of a miller loop.
|
/// Perform final exponentiation of the result of a miller loop.
|
||||||
fn final_exponentiation(this: &Self::MillerLoopResult) -> CtOption<Self::Gt> {
|
fn final_exponentiation(&self) -> Self::Gt {
|
||||||
CtOption::new(*this, Choice::from(1))
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use group::{CurveAffine, CurveProjective};
|
use group::{CurveAffine, CurveProjective};
|
||||||
use pairing::{Engine, PairingCurveAffine};
|
use pairing::{Engine, MillerLoopResult, PairingCurveAffine};
|
||||||
use std::ops::{AddAssign, Neg};
|
use std::ops::{AddAssign, Neg};
|
||||||
|
|
||||||
use super::{PreparedVerifyingKey, Proof, VerifyingKey};
|
use super::{PreparedVerifyingKey, Proof, VerifyingKey};
|
||||||
|
@ -41,14 +41,14 @@ 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::final_exponentiation(&E::miller_loop(
|
Ok(E::miller_loop(
|
||||||
[
|
[
|
||||||
(&proof.a.prepare(), &proof.b.prepare()),
|
(&proof.a.prepare(), &proof.b.prepare()),
|
||||||
(&acc.to_affine().prepare(), &pvk.neg_gamma_g2),
|
(&acc.to_affine().prepare(), &pvk.neg_gamma_g2),
|
||||||
(&proof.c.prepare(), &pvk.neg_delta_g2),
|
(&proof.c.prepare(), &pvk.neg_delta_g2),
|
||||||
]
|
]
|
||||||
.iter(),
|
.iter(),
|
||||||
))
|
)
|
||||||
.unwrap()
|
.final_exponentiation()
|
||||||
== pvk.alpha_g1_beta_g2)
|
== pvk.alpha_g1_beta_g2)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rand_xorshift::XorShiftRng;
|
||||||
|
|
||||||
use group::Group;
|
use group::Group;
|
||||||
use pairing::bls12_381::*;
|
use pairing::bls12_381::*;
|
||||||
use pairing::{Engine, PairingCurveAffine};
|
use pairing::{Engine, MillerLoopResult, PairingCurveAffine};
|
||||||
|
|
||||||
fn bench_pairing_g1_preparation(c: &mut Criterion) {
|
fn bench_pairing_g1_preparation(c: &mut Criterion) {
|
||||||
const SAMPLES: usize = 1000;
|
const SAMPLES: usize = 1000;
|
||||||
|
@ -100,7 +100,7 @@ fn bench_pairing_final_exponentiation(c: &mut Criterion) {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
c.bench_function("Final exponentiation", |b| {
|
c.bench_function("Final exponentiation", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let tmp = Bls12::final_exponentiation(&v[count]);
|
let tmp = v[count].final_exponentiation();
|
||||||
count = (count + 1) % SAMPLES;
|
count = (count + 1) % SAMPLES;
|
||||||
tmp
|
tmp
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,12 +21,11 @@ pub use self::fq2::Fq2;
|
||||||
pub use self::fq6::Fq6;
|
pub use self::fq6::Fq6;
|
||||||
pub use self::fr::{Fr, FrRepr};
|
pub use self::fr::{Fr, FrRepr};
|
||||||
|
|
||||||
use super::{Engine, PairingCurveAffine};
|
use super::{Engine, MillerLoopResult, PairingCurveAffine};
|
||||||
|
|
||||||
use ff::{BitIterator, Field, ScalarEngine};
|
use ff::{BitIterator, Field, ScalarEngine};
|
||||||
use group::CurveAffine;
|
use group::CurveAffine;
|
||||||
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||||
use subtle::CtOption;
|
|
||||||
|
|
||||||
// The BLS parameter x for BLS12-381 is -0xd201000000010000
|
// The BLS parameter x for BLS12-381 is -0xd201000000010000
|
||||||
const BLS_X: u64 = 0xd201000000010000;
|
const BLS_X: u64 = 0xd201000000010000;
|
||||||
|
@ -110,12 +109,17 @@ impl Engine for Bls12 {
|
||||||
|
|
||||||
f
|
f
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn final_exponentiation(r: &Fq12) -> CtOption<Fq12> {
|
impl MillerLoopResult for Fq12 {
|
||||||
let mut f1 = *r;
|
type Gt = Fq12;
|
||||||
|
|
||||||
|
fn final_exponentiation(&self) -> Fq12 {
|
||||||
|
let mut f1 = *self;
|
||||||
f1.conjugate();
|
f1.conjugate();
|
||||||
|
|
||||||
r.invert().map(|mut f2| {
|
self.invert()
|
||||||
|
.map(|mut f2| {
|
||||||
let mut r = f1;
|
let mut r = f1;
|
||||||
r.mul_assign(&f2);
|
r.mul_assign(&f2);
|
||||||
f2 = r;
|
f2 = r;
|
||||||
|
@ -163,6 +167,8 @@ impl Engine for Bls12 {
|
||||||
|
|
||||||
y1
|
y1
|
||||||
})
|
})
|
||||||
|
// self must be nonzero.
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ pub mod bls12_381;
|
||||||
use core::ops::Mul;
|
use core::ops::Mul;
|
||||||
use ff::{Field, PrimeField, ScalarEngine};
|
use ff::{Field, PrimeField, ScalarEngine};
|
||||||
use group::{CurveAffine, CurveProjective, GroupOps, GroupOpsOwned, ScalarMul, ScalarMulOwned};
|
use group::{CurveAffine, CurveProjective, GroupOps, GroupOpsOwned, ScalarMul, ScalarMulOwned};
|
||||||
use subtle::CtOption;
|
|
||||||
|
|
||||||
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
|
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
|
||||||
/// with well-defined relationships. In particular, the G1/G2 curve groups are
|
/// with well-defined relationships. In particular, the G1/G2 curve groups are
|
||||||
|
@ -66,7 +65,7 @@ pub trait Engine: ScalarEngine {
|
||||||
+ for<'a> Mul<&'a Self::Fr, Output = Self::G2>;
|
+ for<'a> Mul<&'a Self::Fr, Output = Self::G2>;
|
||||||
|
|
||||||
/// The type returned by `Engine::miller_loop`.
|
/// The type returned by `Engine::miller_loop`.
|
||||||
type MillerLoopResult;
|
type MillerLoopResult: MillerLoopResult<Gt = Self::Gt>;
|
||||||
|
|
||||||
/// The extension field that hosts the target group of the pairing.
|
/// The extension field that hosts the target group of the pairing.
|
||||||
type Gt: Field;
|
type Gt: Field;
|
||||||
|
@ -81,19 +80,14 @@ pub trait Engine: ScalarEngine {
|
||||||
),
|
),
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/// Perform final exponentiation of the result of a miller loop.
|
|
||||||
fn final_exponentiation(_: &Self::MillerLoopResult) -> CtOption<Self::Gt>;
|
|
||||||
|
|
||||||
/// Performs a complete pairing operation `(p, q)`.
|
/// Performs a complete pairing operation `(p, q)`.
|
||||||
fn pairing<G1, G2>(p: G1, q: G2) -> Self::Gt
|
fn pairing<G1, G2>(p: G1, q: G2) -> Self::Gt
|
||||||
where
|
where
|
||||||
G1: Into<Self::G1Affine>,
|
G1: Into<Self::G1Affine>,
|
||||||
G2: Into<Self::G2Affine>,
|
G2: Into<Self::G2Affine>,
|
||||||
{
|
{
|
||||||
Self::final_exponentiation(&Self::miller_loop(
|
Self::miller_loop([(&(p.into().prepare()), &(q.into().prepare()))].iter())
|
||||||
[(&(p.into().prepare()), &(q.into().prepare()))].iter(),
|
.final_exponentiation()
|
||||||
))
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,3 +104,18 @@ pub trait PairingCurveAffine: CurveAffine {
|
||||||
/// Perform a pairing
|
/// Perform a pairing
|
||||||
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
|
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents results of a Miller loop, one of the most expensive portions of the pairing
|
||||||
|
/// function.
|
||||||
|
///
|
||||||
|
/// `MillerLoopResult`s cannot be compared with each other until
|
||||||
|
/// [`MillerLoopResult::final_exponentiation`] is called, which is also expensive.
|
||||||
|
pub trait MillerLoopResult {
|
||||||
|
/// The extension field that hosts the target group of the pairing.
|
||||||
|
type Gt: Field;
|
||||||
|
|
||||||
|
/// This performs a "final exponentiation" routine to convert the result of a Miller
|
||||||
|
/// loop into an element of [`MillerLoopResult::Gt`], so that it can be compared with
|
||||||
|
/// other elements of `Gt`.
|
||||||
|
fn final_exponentiation(&self) -> Self::Gt;
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rand_core::SeedableRng;
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
use std::ops::MulAssign;
|
use std::ops::MulAssign;
|
||||||
|
|
||||||
use crate::{Engine, PairingCurveAffine};
|
use crate::{Engine, MillerLoopResult, PairingCurveAffine};
|
||||||
|
|
||||||
pub fn engine_tests<E: Engine>() {
|
pub fn engine_tests<E: Engine>() {
|
||||||
let mut rng = XorShiftRng::from_seed([
|
let mut rng = XorShiftRng::from_seed([
|
||||||
|
@ -31,22 +31,22 @@ pub fn engine_tests<E: Engine>() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
E::Gt::one(),
|
E::Gt::one(),
|
||||||
E::final_exponentiation(&E::miller_loop(&[(&z1, &b)])).unwrap()
|
E::miller_loop(&[(&z1, &b)]).final_exponentiation()
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
E::Gt::one(),
|
E::Gt::one(),
|
||||||
E::final_exponentiation(&E::miller_loop(&[(&a, &z2)])).unwrap()
|
E::miller_loop(&[(&a, &z2)]).final_exponentiation()
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
E::final_exponentiation(&E::miller_loop(&[(&z1, &b), (&c, &d)])).unwrap(),
|
E::miller_loop(&[(&z1, &b), (&c, &d)]).final_exponentiation(),
|
||||||
E::final_exponentiation(&E::miller_loop(&[(&a, &z2), (&c, &d)])).unwrap()
|
E::miller_loop(&[(&a, &z2), (&c, &d)]).final_exponentiation()
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
E::final_exponentiation(&E::miller_loop(&[(&a, &b), (&z1, &d)])).unwrap(),
|
E::miller_loop(&[(&a, &b), (&z1, &d)]).final_exponentiation(),
|
||||||
E::final_exponentiation(&E::miller_loop(&[(&a, &b), (&c, &z2)])).unwrap()
|
E::miller_loop(&[(&a, &b), (&c, &z2)]).final_exponentiation()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ fn random_miller_loop_tests<E: Engine>() {
|
||||||
let a = a.to_affine().prepare();
|
let a = a.to_affine().prepare();
|
||||||
let b = b.to_affine().prepare();
|
let b = b.to_affine().prepare();
|
||||||
|
|
||||||
let p1 = E::final_exponentiation(&E::miller_loop(&[(&a, &b)])).unwrap();
|
let p1 = E::miller_loop(&[(&a, &b)]).final_exponentiation();
|
||||||
|
|
||||||
assert_eq!(p1, p2);
|
assert_eq!(p1, p2);
|
||||||
}
|
}
|
||||||
|
@ -93,8 +93,7 @@ fn random_miller_loop_tests<E: Engine>() {
|
||||||
let c = c.to_affine().prepare();
|
let c = c.to_affine().prepare();
|
||||||
let d = d.to_affine().prepare();
|
let d = d.to_affine().prepare();
|
||||||
|
|
||||||
let abcd_with_double_loop =
|
let abcd_with_double_loop = E::miller_loop(&[(&a, &b), (&c, &d)]).final_exponentiation();
|
||||||
E::final_exponentiation(&E::miller_loop(&[(&a, &b), (&c, &d)])).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(abcd, abcd_with_double_loop);
|
assert_eq!(abcd, abcd_with_double_loop);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue