Skip to main content

nam_blstrs/
lib.rs

1//! # `blstrs`
2//!
3//! An implementation of the BLS12-381 pairing-friendly elliptic curve construction.
4
5#![deny(clippy::all, clippy::perf, clippy::correctness)]
6#![allow(clippy::many_single_char_names)]
7#![allow(clippy::wrong_self_convention)]
8
9#[cfg(not(target_endian = "little"))]
10compile_error!("blstrs is only supported on little endian architectures");
11
12#[macro_use]
13mod macros;
14
15mod fp;
16mod fp12;
17mod fp2;
18mod fp6;
19mod g1;
20mod g2;
21mod gt;
22mod pairing;
23mod scalar;
24mod traits;
25
26pub use g1::{G1Affine, G1Compressed, G1Projective, G1Uncompressed};
27pub use g2::{G2Affine, G2Compressed, G2Prepared, G2Projective, G2Uncompressed};
28pub use gt::{Gt, GtCompressed};
29pub use pairing::*;
30pub use scalar::Scalar;
31pub use traits::Compress;
32
33#[cfg(feature = "serde")]
34mod serde_impl;
35
36#[cfg(test)]
37mod tests;
38
39// export for benchmarking only
40#[cfg(feature = "__private_bench")]
41pub use crate::{fp::Fp, fp2::Fp2, fp12::Fp12};
42
43use ff::Field;
44use group::prime::PrimeCurveAffine;
45use pairing_lib::{Engine, MultiMillerLoop, PairingCurveAffine};
46
47/// Bls12-381 engine
48#[derive(Debug, Copy, Clone)]
49pub struct Bls12;
50
51impl Engine for Bls12 {
52    type Fr = Scalar;
53    type G1 = G1Projective;
54    type G1Affine = G1Affine;
55    type G2 = G2Projective;
56    type G2Affine = G2Affine;
57    type Gt = Gt;
58
59    fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
60        pairing(p, q)
61    }
62}
63
64impl MultiMillerLoop for Bls12 {
65    type G2Prepared = G2Prepared;
66    type Result = MillerLoopResult;
67
68    /// Computes $$\sum_{i=1}^n \textbf{ML}(a_i, b_i)$$ given a series of terms
69    /// $$(a_1, b_1), (a_2, b_2), ..., (a_n, b_n).$$
70    fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result {
71        let mut res = blst::blst_fp12::default();
72
73        for (i, (p, q)) in terms.iter().enumerate() {
74            let mut tmp = blst::blst_fp12::default();
75            if (p.is_identity() | q.is_identity()).into() {
76                // Define pairing with zero as one, matching what `pairing` does.
77                tmp = crate::fp12::Fp12::ONE.0;
78            } else {
79                unsafe {
80                    blst::blst_miller_loop_lines(&mut tmp, q.lines.as_ptr(), &p.0);
81                }
82            }
83            if i == 0 {
84                res = tmp;
85            } else {
86                unsafe {
87                    blst::blst_fp12_mul(&mut res, &res, &tmp);
88                }
89            }
90        }
91
92        MillerLoopResult(crate::fp12::Fp12(res))
93    }
94}
95
96#[cfg(feature = "gpu")]
97fn u64_to_u32(limbs: &[u64]) -> Vec<u32> {
98    limbs
99        .iter()
100        .flat_map(|limb| vec![(limb & 0xFFFF_FFFF) as u32, (limb >> 32) as u32])
101        .collect()
102}
103
104#[test]
105fn bls12_engine_tests() {
106    crate::tests::engine::engine_tests::<Bls12>();
107}