Skip to content

Commit

Permalink
Merge branch 'main' into optimize_bls12_381_pairing
Browse files Browse the repository at this point in the history
  • Loading branch information
jotabulacios authored Oct 3, 2024
2 parents 8a53afb + 86b2789 commit 44f2e14
Show file tree
Hide file tree
Showing 15 changed files with 1,618 additions and 442 deletions.
4 changes: 2 additions & 2 deletions math/benches/criterion_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, Criterion};
use pprof::criterion::{Output, PProfProfiler};

mod fields;
use fields::mersenne31::mersenne31_ops_benchmarks;
use fields::mersenne31::{mersenne31_extension_ops_benchmarks, mersenne31_ops_benchmarks};
use fields::mersenne31_montgomery::mersenne31_mont_ops_benchmarks;
use fields::{
stark252::starkfield_ops_benchmarks, u64_goldilocks::u64_goldilocks_ops_benchmarks,
Expand All @@ -12,6 +12,6 @@ use fields::{
criterion_group!(
name = field_benches;
config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None)));
targets = starkfield_ops_benchmarks, mersenne31_ops_benchmarks, mersenne31_mont_ops_benchmarks, u64_goldilocks_ops_benchmarks, u64_goldilocks_montgomery_ops_benchmarks
targets = mersenne31_ops_benchmarks, mersenne31_extension_ops_benchmarks, mersenne31_mont_ops_benchmarks, starkfield_ops_benchmarks, u64_goldilocks_ops_benchmarks, u64_goldilocks_montgomery_ops_benchmarks
);
criterion_main!(field_benches);
64 changes: 63 additions & 1 deletion math/benches/fields/mersenne31.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
use std::hint::black_box;

use criterion::Criterion;
use lambdaworks_math::field::{element::FieldElement, fields::mersenne31::field::Mersenne31Field};
use lambdaworks_math::field::{
element::FieldElement,
fields::mersenne31::{
extensions::{Degree2ExtensionField, Degree4ExtensionField},
field::Mersenne31Field,
},
};
use rand::random;

pub type F = FieldElement<Mersenne31Field>;
pub type Fp2E = FieldElement<Degree2ExtensionField>;
pub type Fp4E = FieldElement<Degree4ExtensionField>;

#[inline(never)]
#[no_mangle]
Expand All @@ -17,6 +25,60 @@ pub fn rand_field_elements(num: usize) -> Vec<(F, F)> {
result
}

//TODO: Check if this is the correct way to bench.
pub fn rand_fp4e(num: usize) -> Vec<(Fp4E, Fp4E)> {
let mut result = Vec::with_capacity(num);
for _ in 0..result.capacity() {
result.push((
Fp4E::new([
Fp2E::new([F::new(random()), F::new(random())]),
Fp2E::new([F::new(random()), F::new(random())]),
]),
Fp4E::new([
Fp2E::new([F::new(random()), F::new(random())]),
Fp2E::new([F::new(random()), F::new(random())]),
]),
));
}
result
}

pub fn mersenne31_extension_ops_benchmarks(c: &mut Criterion) {
let input: Vec<Vec<(Fp4E, Fp4E)>> = [1000000].into_iter().map(rand_fp4e).collect::<Vec<_>>();

let mut group = c.benchmark_group("Mersenne31 Fp4 operations");

for i in input.clone().into_iter() {
group.bench_with_input(format!("Mul of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, y) in i {
black_box(black_box(x) * black_box(y));
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Square of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).square());
}
});
});
}

for i in input.clone().into_iter() {
group.bench_with_input(format!("Inv of Fp4 {:?}", &i.len()), &i, |bench, i| {
bench.iter(|| {
for (x, _) in i {
black_box(black_box(x).inv().unwrap());
}
});
});
}
}

pub fn mersenne31_ops_benchmarks(c: &mut Criterion) {
let input: Vec<Vec<(F, F)>> = [1, 10, 100, 1000, 10000, 100000, 1000000]
.into_iter()
Expand Down
139 changes: 126 additions & 13 deletions math/src/elliptic_curve/short_weierstrass/curves/bls12_377/curve.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
use super::field_extension::BLS12377PrimeField;
use super::{
field_extension::{BLS12377PrimeField, Degree2ExtensionField},
twist::BLS12377TwistCurve,
};
use crate::cyclic_group::IsGroup;
use crate::elliptic_curve::short_weierstrass::point::ShortWeierstrassProjectivePoint;
use crate::elliptic_curve::traits::IsEllipticCurve;
use crate::unsigned_integer::element::U256;

use crate::{
elliptic_curve::short_weierstrass::traits::IsShortWeierstrass, field::element::FieldElement,
};

pub const SUBGROUP_ORDER: U256 =
U256::from_hex_unchecked("12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001");

pub const CURVE_COFACTOR: U256 =
U256::from_hex_unchecked("0x30631250834960419227450344600217059328");

pub type BLS12377FieldElement = FieldElement<BLS12377PrimeField>;
pub type BLS12377TwistCurveFieldElement = FieldElement<Degree2ExtensionField>;

/// The description of the curve.
#[derive(Clone, Debug)]
pub struct BLS12377Curve;
Expand Down Expand Up @@ -32,6 +47,71 @@ impl IsShortWeierstrass for BLS12377Curve {
}
}

/// This is equal to the frobenius trace of the BLS12 377 curve minus one or seed value z.
pub const MILLER_LOOP_CONSTANT: u64 = 0x8508c00000000001;

/// 𝛽 : primitive cube root of unity of 𝐹ₚ that §satisfies the minimal equation
/// 𝛽² + 𝛽 + 1 = 0 mod 𝑝
pub const CUBE_ROOT_OF_UNITY_G1: BLS12377FieldElement = FieldElement::from_hex_unchecked(
"0x1ae3a4617c510eabc8756ba8f8c524eb8882a75cc9bc8e359064ee822fb5bffd1e945779fffffffffffffffffffffff",
);

/// x-coordinate of 𝜁 ∘ 𝜋_q ∘ 𝜁⁻¹, where 𝜁 is the isomorphism u:E'(𝔽ₚ₆) −> E(𝔽ₚ₁₂) from the twist to E
pub const ENDO_U: BLS12377TwistCurveFieldElement =
BLS12377TwistCurveFieldElement::const_from_raw([
FieldElement::from_hex_unchecked(
"9B3AF05DD14F6EC619AAF7D34594AABC5ED1347970DEC00452217CC900000008508C00000000002",
),
FieldElement::from_hex_unchecked("0"),
]);

/// y-coordinate of 𝜁 ∘ 𝜋_q ∘ 𝜁⁻¹, where 𝜁 is the isomorphism u:E'(𝔽ₚ₆) −> E(𝔽ₚ₁₂) from the twist to E
pub const ENDO_V: BLS12377TwistCurveFieldElement =
BLS12377TwistCurveFieldElement::const_from_raw([
FieldElement::from_hex_unchecked("1680A40796537CAC0C534DB1A79BEB1400398F50AD1DEC1BCE649CF436B0F6299588459BFF27D8E6E76D5ECF1391C63"),
FieldElement::from_hex_unchecked("0"),
]);

impl ShortWeierstrassProjectivePoint<BLS12377Curve> {
/// Returns 𝜙(P) = (𝑥, 𝑦) ⇒ (𝛽𝑥, 𝑦), where 𝛽 is the Cube Root of Unity in the base prime field
/// https://eprint.iacr.org/2022/352.pdf 2 Preliminaries
fn phi(&self) -> Self {
let mut a = self.clone();
a.0.value[0] = a.x() * CUBE_ROOT_OF_UNITY_G1;
a
}

/// 𝜙(P) = −𝑢²P
/// https://eprint.iacr.org/2022/352.pdf 4.3 Prop. 4
pub fn is_in_subgroup(&self) -> bool {
self.operate_with_self(MILLER_LOOP_CONSTANT)
.operate_with_self(MILLER_LOOP_CONSTANT)
.neg()
== self.phi()
}
}

impl ShortWeierstrassProjectivePoint<BLS12377TwistCurve> {
/// 𝜓(P) = 𝜁 ∘ 𝜋ₚ ∘ 𝜁⁻¹, where 𝜁 is the isomorphism u:E'(𝔽ₚ₆) −> E(𝔽ₚ₁₂) from the twist to E,, 𝜋ₚ is the p-power frobenius endomorphism
/// and 𝜓 satisifies minmal equation 𝑋² + 𝑡𝑋 + 𝑞 = 𝑂
/// https://eprint.iacr.org/2022/352.pdf 4.2 (7)
/// ψ(P) = (ψ_x * conjugate(x), ψ_y * conjugate(y), conjugate(z))
fn psi(&self) -> Self {
let [x, y, z] = self.coordinates();
Self::new([
x.conjugate() * ENDO_U,
y.conjugate() * ENDO_V,
z.conjugate(),
])
}

/// 𝜓(P) = 𝑢P, where 𝑢 = SEED of the curve
/// https://eprint.iacr.org/2022/352.pdf 4.2
pub fn is_in_subgroup(&self) -> bool {
self.psi() == self.operate_with_self(MILLER_LOOP_CONSTANT)
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -43,17 +123,18 @@ mod tests {
use super::BLS12377Curve;

#[allow(clippy::upper_case_acronyms)]
type FEE = FieldElement<BLS12377PrimeField>;
type FpE = FieldElement<BLS12377PrimeField>;
type Fp2 = FieldElement<Degree2ExtensionField>;

fn point_1() -> ShortWeierstrassProjectivePoint<BLS12377Curve> {
let x = FEE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea");
let y = FEE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2");
let x = FpE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea");
let y = FpE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2");
BLS12377Curve::create_point_from_affine(x, y).unwrap()
}

fn point_1_times_5() -> ShortWeierstrassProjectivePoint<BLS12377Curve> {
let x = FEE::new_base("3c852d5aab73fbb51e57fbf5a0a8b5d6513ec922b2611b7547bfed74cba0dcdfc3ad2eac2733a4f55d198ec82b9964");
let y = FEE::new_base("a71425e68e55299c64d7eada9ae9c3fb87a9626b941d17128b64685fc07d0e635f3c3a512903b4e0a43e464045967b");
let x = FpE::new_base("3c852d5aab73fbb51e57fbf5a0a8b5d6513ec922b2611b7547bfed74cba0dcdfc3ad2eac2733a4f55d198ec82b9964");
let y = FpE::new_base("a71425e68e55299c64d7eada9ae9c3fb87a9626b941d17128b64685fc07d0e635f3c3a512903b4e0a43e464045967b");
BLS12377Curve::create_point_from_affine(x, y).unwrap()
}

Expand Down Expand Up @@ -101,9 +182,9 @@ mod tests {
let point_1 = point_1().to_affine();

// Create point 2
let x = FEE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea") * FEE::from(2);
let y = FEE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2") * FEE::from(2);
let z = FEE::from(2);
let x = FpE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea") * FpE::from(2);
let y = FpE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2") * FpE::from(2);
let z = FpE::from(2);
let point_2 = ShortWeierstrassProjectivePoint::<BLS12377Curve>::new([x, y, z]);

let first_algorithm_result = point_2.operate_with(&point_1).to_affine();
Expand All @@ -115,15 +196,15 @@ mod tests {
#[test]
fn create_valid_point_works() {
let p = point_1();
assert_eq!(*p.x(), FEE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea"));
assert_eq!(*p.y(), FEE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2"));
assert_eq!(*p.z(), FEE::new_base("1"));
assert_eq!(*p.x(), FpE::new_base("134e4cc122cb62a06767fb98e86f2d5f77e2a12fefe23bb0c4c31d1bd5348b88d6f5e5dee2b54db4a2146cc9f249eea"));
assert_eq!(*p.y(), FpE::new_base("17949c29effee7a9f13f69b1c28eccd78c1ed12b47068836473481ff818856594fd9c1935e3d9e621901a2d500257a2"));
assert_eq!(*p.z(), FpE::new_base("1"));
}

#[test]
fn create_invalid_points_panics() {
assert_eq!(
BLS12377Curve::create_point_from_affine(FEE::from(1), FEE::from(1)).unwrap_err(),
BLS12377Curve::create_point_from_affine(FpE::from(1), FpE::from(1)).unwrap_err(),
EllipticCurveError::InvalidPoint
)
}
Expand All @@ -144,4 +225,36 @@ mod tests {
g.operate_with_self(3_u16)
);
}

#[test]
fn generator_g1_is_in_subgroup() {
let g = BLS12377Curve::generator();
assert!(g.is_in_subgroup())
}

#[test]
fn point1_is_in_subgroup() {
let p = point_1();
assert!(p.is_in_subgroup())
}

#[test]
fn arbitrary_g1_point_is_in_subgroup() {
let g = BLS12377Curve::generator().operate_with_self(32u64);
assert!(g.is_in_subgroup())
}
#[test]
fn generator_g2_is_in_subgroup() {
let g = BLS12377TwistCurve::generator();
assert!(g.is_in_subgroup())
}

#[test]
fn g2_conjugate_works() {
let a = Fp2::zero();
let mut expected = a.conjugate();
expected = expected.conjugate();

assert_eq!(a, expected);
}
}
Loading

0 comments on commit 44f2e14

Please sign in to comment.