Skip to content

Commit

Permalink
add bls12381
Browse files Browse the repository at this point in the history
  • Loading branch information
kilic committed May 30, 2024
1 parent 1301f0e commit 4576366
Show file tree
Hide file tree
Showing 10 changed files with 2,275 additions and 0 deletions.
126 changes: 126 additions & 0 deletions src/bls12381/engine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use super::fq12::Fq12;
use super::fq2::Fq2;
use super::{Fr, G1Affine, G2Affine, BLS_X, G1, G2};
use crate::ff_ext::quadratic::QuadSparseMul;
use crate::ff_ext::ExtField;
use core::borrow::Borrow;
use core::iter::Sum;
use core::ops::{Add, Mul, Neg, Sub};
use ff::Field;
use ff::PrimeField;
use group::prime::PrimeCurveAffine;
use group::Group;
use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
use rand::RngCore;
use std::ops::MulAssign;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};

crate::impl_gt!(Gt, Fq12, Fr);
crate::impl_miller_loop_components!(Bls12381, G1, G1Affine, G2, G2Affine, Fq12, Gt, Fr);

impl MillerLoopResult for Fq12 {
type Gt = Gt;

fn final_exponentiation(&self) -> Gt {
#[must_use]
fn exp_by_x(f: Fq12) -> Fq12 {
let mut acc = Fq12::one();
for (i, b) in BLS_X.into_iter().enumerate() {
(i != 0).then(|| acc.cyclotomic_square());
(b == 1).then(|| acc *= f);
}
acc.conjugate();
acc
}

let mut t0 = *self;
t0.frobenius_map(6);

Gt(self
.invert()
.map(|mut t1| {
let mut t2 = t0 * t1;
t1 = t2;
t2.frobenius_map(2);
t2 *= t1;
t1 = t2;
t1.cyclotomic_square();
t1.conjugate();
let mut t3 = exp_by_x(t2);
let mut t4 = t3;
t4.cyclotomic_square();
let mut t5 = t1 * t3;
t1 = exp_by_x(t5);
t0 = exp_by_x(t1);
let mut t6 = exp_by_x(t0) * t4;
t4 = exp_by_x(t6);
t5.conjugate();
t4 *= t5 * t2;
t1 *= t2;
t1.frobenius_map(3);
t2.conjugate();
t6 *= t2;
t6.frobenius_map(1);
t3 *= t0;
t3.frobenius_map(2);
t3 * t4 * t1 * t6
})
.unwrap())
}
}

pub fn multi_miller_loop(terms: &[(&G1Affine, &G2Affine)]) -> Fq12 {
let terms = terms
.iter()
.filter_map(|&(p, q)| {
if bool::from(p.is_identity()) || bool::from(q.is_identity()) {
None
} else {
Some((p, q))
}
})
.collect::<Vec<_>>();

let mut f = Fq12::one();
let mut r = terms.iter().map(|(_, q)| q.to_curve()).collect::<Vec<_>>();

for (i, x) in BLS_X.iter().map(|&b| b == 1).skip(1).enumerate() {
if i != 0 {
f.square_assign();
}

terms.iter().zip(r.iter_mut()).for_each(|((p, _), r)| {
double(&mut f, r, p);
});

if x {
for ((p, q), r) in terms.iter().zip(r.iter_mut()) {
add(&mut f, r, q, p);
}
}
}

f.conjugate();
f
}

fn ell(f: &mut Fq12, coeffs: &(Fq2, Fq2, Fq2), p: &G1Affine) {
let mut c0 = coeffs.0;
let mut c1 = coeffs.1;
c0.c0.mul_assign(&p.y);
c0.c1.mul_assign(&p.y);
c1.c0.mul_assign(&p.x);
c1.c1.mul_assign(&p.x);
Fq12::mul_by_014(f, &coeffs.2, &c1, &c0);
}

#[cfg(test)]
mod test {
use super::super::{Bls12381, Fr, G1, G2};
use super::{multi_miller_loop, Fq12, G1Affine, G2Affine, Gt};
use ff::Field;
use group::{prime::PrimeCurveAffine, Curve, Group};
use pairing::{Engine as _, MillerLoopResult, PairingCurveAffine};
use rand_core::OsRng;
crate::test_pairing!(Bls12381, G1, G1Affine, G2, G2Affine, Fq12, Gt, Fr);
}
56 changes: 56 additions & 0 deletions src/bls12381/fq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use core::convert::TryInto;
use halo2derive::impl_field;
use rand::RngCore;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

impl_field!(
bls12381_base,
Fq,
modulus = "1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
mul_gen = "2",
zeta = "1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac",
from_uniform = [64, 96],
endian = "big",
);

crate::extend_field_legendre!(Fq);
crate::impl_binops_calls!(Fq);
crate::impl_binops_additive!(Fq, Fq);
crate::impl_binops_multiplicative!(Fq, Fq);
crate::field_bits!(Fq);
crate::serialize_deserialize_primefield!(Fq);
crate::impl_from_u64!(Fq);

use ff::Field;

use crate::ff_ext::ExtField;
const NEGATIVE_ONE: Fq = Fq::ZERO.sub_const(&Fq::ONE);
impl ExtField for Fq {
const NON_RESIDUE: Self = NEGATIVE_ONE;
fn mul_by_nonresidue(&self) -> Self {
self.neg()
}
fn frobenius_map(&mut self, _: usize) {}
}

#[cfg(test)]
mod test {
use super::*;
crate::field_testing_suite!(Fq, "field_arithmetic");
crate::field_testing_suite!(Fq, "conversion");
crate::field_testing_suite!(Fq, "serialization");
crate::field_testing_suite!(Fq, "quadratic_residue");
crate::field_testing_suite!(Fq, "bits");
crate::field_testing_suite!(Fq, "serialization_check");
crate::field_testing_suite!(Fq, "constants");
crate::field_testing_suite!(Fq, "sqrt");
crate::field_testing_suite!(Fq, "zeta");
crate::field_testing_suite!(Fq, "from_uniform_bytes", 64, 96);
#[test]
fn test_fq_mul_nonresidue() {
let e = Fq::random(rand_core::OsRng);
let a0 = e.mul_by_nonresidue();
let a1 = e * Fq::NON_RESIDUE;
assert_eq!(a0, a1);
}
}
Loading

0 comments on commit 4576366

Please sign in to comment.