1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
//! # `blstrs`
//!
//! An implementation of the BLS12-381 pairing-friendly elliptic curve construction.

#![deny(clippy::all, clippy::perf, clippy::correctness)]
#![allow(clippy::many_single_char_names)]

#[macro_use]
mod macros;

mod fp;
mod fp12;
mod fp2;
mod fp6;
mod g1;
mod g2;
mod pairing;
mod scalar;
mod traits;

pub use fff::*;
pub use fp::{Fp, FpRepr};
pub use fp12::Fp12;
pub use fp2::Fp2;
pub use fp6::Fp6;
pub use g1::*;
pub use g2::*;
pub use pairing::*;
pub use scalar::{Scalar, ScalarRepr, S as SCALAR_S};
pub use traits::*;

#[cfg(feature = "serde")]
mod serde_impl;

#[cfg(test)]
mod tests;

/// Bls12-381 engine
#[derive(Debug, Copy, Clone)]
pub struct Bls12;

impl fff::ScalarEngine for Bls12 {
    type Fr = Scalar;
}

impl Engine for Bls12 {
    type G1 = G1Projective;
    type G1Affine = G1Affine;
    type G2 = G2Projective;
    type G2Affine = G2Affine;
    type Fq = Fp;
    type Fqe = Fp2;
    type Fqk = Fp12;

    fn miller_loop<'a, I>(i: I) -> Self::Fqk
    where
        I: IntoIterator<
            Item = &'a (
                &'a <Self::G1Affine as PairingCurveAffine>::Prepared,
                &'a <Self::G2Affine as PairingCurveAffine>::Prepared,
            ),
        >,
    {
        use groupy::CurveAffine;

        let mut res = blst::blst_fp12::default();

        for (i, (p, q)) in i.into_iter().enumerate() {
            let mut tmp = blst::blst_fp12::default();
            if q.is_zero() || p.is_zero() {
                // Define pairing with zero as one, matching what `pairing` does.
                tmp = Fp12::one().0;
            } else {
                unsafe {
                    blst::blst_miller_loop_lines(&mut tmp, q.lines.as_ptr(), &p.0);
                }
            }
            if i == 0 {
                res = tmp;
            } else {
                unsafe {
                    blst::blst_fp12_mul(&mut res, &res, &tmp);
                }
            }
        }

        Fp12(res)
    }

    fn final_exponentiation(r: &Fp12) -> Option<Fp12> {
        let mut out = blst::blst_fp12::default();
        unsafe { blst::blst_final_exp(&mut out, &r.0) };

        // TODO: What about the None case?
        Some(out.into())
    }
}

#[test]
fn bls12_engine_tests() {
    crate::tests::engine::engine_tests::<Bls12>();
}