diff --git a/src/bls12_381/ec.rs b/src/bls12_381/ec.rs
index 973bdbfe7..a4eaa1a7f 100644
--- a/src/bls12_381/ec.rs
+++ b/src/bls12_381/ec.rs
@@ -7,7 +7,8 @@ macro_rules! curve_impl {
$basefield:ident,
$scalarfield:ident,
$uncompressed:ident,
- $compressed:ident
+ $compressed:ident,
+ $pairing:ident
) => {
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct $affine {
@@ -113,6 +114,8 @@ macro_rules! curve_impl {
type Projective = $projective;
type Uncompressed = $uncompressed;
type Compressed = $compressed;
+ type Pair = $pairing;
+ type PairingResult = Fq12;
fn zero() -> Self {
$affine {
@@ -155,6 +158,10 @@ macro_rules! curve_impl {
$prepared::from_affine(*self)
}
+ fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
+ self.perform_pairing(other)
+ }
+
fn into_projective(&self) -> $projective {
(*self).into()
}
@@ -574,10 +581,11 @@ macro_rules! curve_impl {
pub mod g1 {
use rand::{Rand, Rng};
- use super::super::{Fq, Fr, FrRepr, FqRepr};
- use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError};
+ use super::g2::G2Affine;
+ use super::super::{Fq, Fr, FrRepr, FqRepr, Fq12};
+ use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError, Engine};
- curve_impl!("G1", G1, G1Affine, G1Prepared, Fq, Fr, G1Uncompressed, G1Compressed);
+ curve_impl!("G1", G1, G1Affine, G1Prepared, Fq, Fr, G1Uncompressed, G1Compressed, G2Affine);
#[derive(Copy)]
pub struct G1Uncompressed([u8; 96]);
@@ -828,6 +836,10 @@ pub mod g1 {
fn get_coeff_b() -> Fq {
super::super::fq::B_COEFF
}
+
+ fn perform_pairing(&self, other: &G2Affine) -> Fq12 {
+ super::super::Bls12::pairing(*self, *other)
+ }
}
impl G1 {
@@ -1122,10 +1134,11 @@ pub mod g1 {
pub mod g2 {
use rand::{Rand, Rng};
- use super::super::{Fq2, Fr, Fq, FrRepr, FqRepr};
- use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError};
+ use super::super::{Fq2, Fr, Fq, FrRepr, FqRepr, Fq12};
+ use super::g1::G1Affine;
+ use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError, Engine};
- curve_impl!("G2", G2, G2Affine, G2Prepared, Fq2, Fr, G2Uncompressed, G2Compressed);
+ curve_impl!("G2", G2, G2Affine, G2Prepared, Fq2, Fr, G2Uncompressed, G2Compressed, G1Affine);
#[derive(Copy)]
pub struct G2Uncompressed([u8; 192]);
@@ -1403,6 +1416,10 @@ pub mod g2 {
c1: super::super::fq::B_COEFF
}
}
+
+ fn perform_pairing(&self, other: &G1Affine) -> Fq12 {
+ super::super::Bls12::pairing(*other, *self)
+ }
}
impl G2 {
diff --git a/src/lib.rs b/src/lib.rs
index ca3845127..6e98aa6ec 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -42,13 +42,13 @@ pub trait Engine {
type G1: CurveProjective + From;
/// The affine representation of an element in G1.
- type G1Affine: CurveAffine + From;
+ type G1Affine: CurveAffine + From;
/// The projective representation of an element in G2.
type G2: CurveProjective + From;
/// The affine representation of an element in G2.
- type G2Affine: CurveAffine + From;
+ type G2Affine: CurveAffine + From;
/// The base field that hosts G1.
type Fq: PrimeField + SqrtField;
@@ -172,6 +172,8 @@ pub trait CurveAffine: Copy +
type Prepared: Clone + Send + Sync + 'static;
type Uncompressed: EncodedPoint;
type Compressed: EncodedPoint;
+ type Pair: CurveAffine;
+ type PairingResult: Field;
/// Returns the additive identity.
fn zero() -> Self;
@@ -192,6 +194,9 @@ pub trait CurveAffine: Copy +
/// Prepares this element for pairing purposes.
fn prepare(&self) -> Self::Prepared;
+ /// Perform a pairing
+ fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
+
/// Converts this element into its affine representation.
fn into_projective(&self) -> Self::Projective;
diff --git a/src/tests/engine.rs b/src/tests/engine.rs
index b1bb754c4..03ffc6e62 100644
--- a/src/tests/engine.rs
+++ b/src/tests/engine.rs
@@ -6,6 +6,14 @@ pub fn engine_tests()
{
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
+ for _ in 0..10 {
+ let a = E::G1::rand(&mut rng).into_affine();
+ let b = E::G2::rand(&mut rng).into_affine();
+
+ assert!(a.pairing_with(&b) == b.pairing_with(&a));
+ assert!(a.pairing_with(&b) == E::pairing(a, b));
+ }
+
for _ in 0..1000 {
let z1 = E::G1Affine::zero().prepare();
let z2 = E::G2Affine::zero().prepare();