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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//! # `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)]
#![allow(clippy::wrong_self_convention)]

#[cfg(not(target_endian = "little"))]
compile_error!("blstrs is only supported on little endian architectures");

#[macro_use]
mod macros;

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

pub use g1::{G1Affine, G1Compressed, G1Projective, G1Uncompressed};
pub use g2::{G2Affine, G2Compressed, G2Prepared, G2Projective, G2Uncompressed};
pub use gt::Gt;
pub use pairing::*;
pub use scalar::Scalar;
pub use traits::Compress;

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

#[cfg(test)]
mod tests;

// export for benchmarking only
#[cfg(feature = "__private_bench")]
pub use crate::{fp::Fp, fp12::Fp12, fp2::Fp2};

use ff::Field;
use group::prime::PrimeCurveAffine;
use pairing_lib::{Engine, MultiMillerLoop, PairingCurveAffine};

pub use elliptic_curve;
pub use ff;
pub use group;
pub use pairing_lib;

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

impl Engine for Bls12 {
    type Fr = Scalar;
    type G1 = G1Projective;
    type G1Affine = G1Affine;
    type G2 = G2Projective;
    type G2Affine = G2Affine;
    type Gt = Gt;

    fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
        pairing(p, q)
    }
}

impl MultiMillerLoop for Bls12 {
    type G2Prepared = G2Prepared;
    type Result = MillerLoopResult;

    /// Computes $$\sum_{i=1}^n \textbf{ML}(a_i, b_i)$$ given a series of terms
    /// $$(a_1, b_1), (a_2, b_2), ..., (a_n, b_n).$$
    fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result {
        let mut res = blst::blst_fp12::default();

        for (i, (p, q)) in terms.iter().enumerate() {
            let mut tmp = blst::blst_fp12::default();
            if (p.is_identity() | q.is_identity()).into() {
                // Define pairing with zero as one, matching what `pairing` does.
                tmp = crate::fp12::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);
                }
            }
        }

        MillerLoopResult(crate::fp12::Fp12(res))
    }
}

use elliptic_curve::{
    bigint::{ArrayEncoding, U384},
    consts::U48,
    point::PointCompression,
    Curve, FieldBytes, FieldBytesEncoding, PrimeCurve,
};

/// An engine for operations generic G1 operations
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
pub struct Bls12381G1;

unsafe impl Send for Bls12381G1 {}
unsafe impl Sync for Bls12381G1 {}

/// An engine for operations generic G2 operations
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
pub struct Bls12381G2;

impl Curve for Bls12381G1 {
    type FieldBytesSize = U48;
    type Uint = U384;
    const ORDER: U384 = U384::from_be_hex("0000000000000000000000000000000073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001");
}

impl PrimeCurve for Bls12381G1 {}

impl PointCompression for Bls12381G1 {
    const COMPRESS_POINTS: bool = true;
}

impl FieldBytesEncoding<Bls12381G1> for U384 {
    fn decode_field_bytes(field_bytes: &FieldBytes<Bls12381G1>) -> Self {
        U384::from_be_byte_array(*field_bytes)
    }

    fn encode_field_bytes(&self) -> FieldBytes<Bls12381G1> {
        self.to_be_byte_array()
    }
}

impl Curve for Bls12381G2 {
    type FieldBytesSize = U48;
    type Uint = U384;
    const ORDER: U384 = U384::from_be_hex("0000000000000000000000000000000073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001");
}

impl PrimeCurve for Bls12381G2 {}

impl PointCompression for Bls12381G2 {
    const COMPRESS_POINTS: bool = true;
}

impl FieldBytesEncoding<Bls12381G2> for U384 {
    fn decode_field_bytes(field_bytes: &FieldBytes<Bls12381G2>) -> Self {
        U384::from_be_byte_array(*field_bytes)
    }

    fn encode_field_bytes(&self) -> FieldBytes<Bls12381G2> {
        self.to_be_byte_array()
    }
}

#[cfg(feature = "gpu")]
fn u64_to_u32(limbs: &[u64]) -> Vec<u32> {
    limbs
        .iter()
        .flat_map(|limb| vec![(limb & 0xFFFF_FFFF) as u32, (limb >> 32) as u32])
        .collect()
}

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