Skip to content

Commit

Permalink
Add pairing BLS12 377 (#933)
Browse files Browse the repository at this point in the history
* save work

* save work

* cyclotomic square test pass

* save work

* save work

* fixed cyclotomic pow, now all tests pass

* remove not used functions

* update Readme

* add generator reference

* replace pow(2) for square()

* changed final_exp to avoid unwrap

* Revert "changed final_exp to avoid unwrap"

This reverts commit 2c3b0c6.

* removed . clone()s

* changed final_exp to avoid unwrap
  • Loading branch information
jotabulacios authored Nov 11, 2024
1 parent d35c96f commit e650e0f
Show file tree
Hide file tree
Showing 6 changed files with 538 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ List of symbols:
| Rescue Prime XLIX | :x: | :x: | :x: | :x: | :x: |
| **Elliptic Curves** | **Lambdaworks** | **Arkworks** | **Halo2** | **gnark** | **Constantine** |
| BLS12-381 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| BLS12-377 | 🏗️ | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: |
| BLS12-377 | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: |
| BN-254 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Pallas | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: |
| Vesta | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{
field_extension::{BLS12377PrimeField, Degree2ExtensionField},
pairing::{GAMMA_12, GAMMA_13},
twist::BLS12377TwistCurve,
};
use crate::cyclic_group::IsGroup;
Expand All @@ -12,10 +13,9 @@ use crate::{
};

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

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

pub type BLS12377FieldElement = FieldElement<BLS12377PrimeField>;
pub type BLS12377TwistCurveFieldElement = FieldElement<Degree2ExtensionField>;
Expand All @@ -28,6 +28,7 @@ impl IsEllipticCurve for BLS12377Curve {
type BaseField = BLS12377PrimeField;
type PointRepresentation = ShortWeierstrassProjectivePoint<Self>;

// generator values are taken from https://neuromancer.sk/std/bls/BLS12-377
fn generator() -> Self::PointRepresentation {
Self::PointRepresentation::new([
FieldElement::<Self::BaseField>::new_base("8848defe740a67c8fc6225bf87ff5485951e2caa9d41bb188282c8bd37cb5cd5481512ffcd394eeab9b16eb21be9ef"),
Expand Down Expand Up @@ -99,8 +100,8 @@ impl ShortWeierstrassProjectivePoint<BLS12377TwistCurve> {
fn psi(&self) -> Self {
let [x, y, z] = self.coordinates();
Self::new([
x.conjugate() * ENDO_U,
y.conjugate() * ENDO_V,
x.conjugate() * GAMMA_12,
y.conjugate() * GAMMA_13,
z.conjugate(),
])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ impl IsModulus<U384> for BLS12377FieldModulus {
}

pub type BLS12377PrimeField = MontgomeryBackendPrimeField<BLS12377FieldModulus, 6>;
type Fp2E = FieldElement<Degree2ExtensionField>;

#[derive(Clone, Debug)]
pub struct Degree2ExtensionField;

impl IsField for Degree2ExtensionField {
type BaseType = [FieldElement<BLS12377PrimeField>; 2];
/// Returns the component wise addition of `a` and `b`
/// Returns the component wise addition of `a` and `b`
fn add(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
[&a[0] + &b[0], &a[1] + &b[1]]
}
Expand All @@ -41,14 +41,13 @@ impl IsField for Degree2ExtensionField {
fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
let a0b0 = &a[0] * &b[0];
let a1b1 = &a[1] * &b[1];
let z = (&a[0] + &a[1]) * (&b[0] + &b[1]);
[&a0b0 + &a1b1 * FP2_RESIDUE, z - a0b0 - a1b1]
[&a0b0 + &a1b1 * &FP2_RESIDUE, &a[0] * &b[1] + &a[1] * &b[0]]
}

fn square(a: &Self::BaseType) -> Self::BaseType {
let [a0, a1] = a;
let v0 = a0 * a1;
let c0 = (a0 + a1) * (a0 + &FP2_RESIDUE * a1) - &v0 - FP2_RESIDUE * &v0;
let c0 = (a0 + a1) * (a0 + &FP2_RESIDUE * a1) - &v0 - &FP2_RESIDUE * &v0;
let c1 = &v0 + &v0;
[c0, c1]
}
Expand All @@ -65,8 +64,7 @@ impl IsField for Degree2ExtensionField {
/// Returns the multiplicative inverse of `a`
/// This uses the equality `(a0 + a1 * t) * (a0 - a1 * t) = a0.pow(2) - a1.pow(2) * Q::residue()`
fn inv(a: &Self::BaseType) -> Result<Self::BaseType, FieldError> {
let q: FieldElement<BLS12377PrimeField> = -FieldElement::from(5);
let inv_norm = (a[0].pow(2_u64) - q * a[1].pow(2_u64)).inv()?;
let inv_norm = (a[0].square() - FP2_RESIDUE * a[1].square()).inv()?;
Ok([&a[0] * &inv_norm, -&a[1] * inv_norm])
}

Expand Down Expand Up @@ -214,12 +212,12 @@ impl HasCubicNonResidue<Degree2ExtensionField> for LevelTwoResidue {
fn residue() -> FieldElement<Degree2ExtensionField> {
FieldElement::new([
FieldElement::new(U384::from("0")),
-FieldElement::new(U384::from("1")),
FieldElement::new(U384::from("1")),
])
}
}

pub type Degree6ExtensionField = CubicExtensionField<Degree2ExtensionField, LevelTwoResidue>;
type Fp6E = FieldElement<Degree6ExtensionField>;

#[derive(Debug, Clone)]
pub struct LevelThreeResidue;
Expand All @@ -235,6 +233,7 @@ impl HasQuadraticNonResidue<Degree6ExtensionField> for LevelThreeResidue {

/// We define Fp12 = Fp6 [w] / (w^2 - v)
pub type Degree12ExtensionField = QuadraticExtensionField<Degree6ExtensionField, LevelThreeResidue>;
pub type Fp12E = FieldElement<Degree12ExtensionField>;

impl FieldElement<Degree6ExtensionField> {
pub fn new_base(a_hex: &str) -> Self {
Expand All @@ -251,6 +250,13 @@ impl FieldElement<BLS12377PrimeField> {
Self::new(U384::from(a_hex))
}
}

impl FieldElement<Degree4ExtensionField> {
pub fn new_base(a_hex: &str) -> Self {
Self::new([Fp2E::new_base(a_hex), Fp2E::zero()])
}
}

impl FieldElement<Degree12ExtensionField> {
pub fn new_base(a_hex: &str) -> Self {
Self::new([
Expand Down Expand Up @@ -292,6 +298,51 @@ impl FieldElement<Degree12ExtensionField> {
])
}
}
impl HasQuadraticNonResidue<Degree2ExtensionField> for LevelTwoResidue {
fn residue() -> FieldElement<Degree2ExtensionField> {
FieldElement::new([
FieldElement::new(U384::from("0")),
FieldElement::new(U384::from("1")),
])
}
}
pub type Degree4ExtensionField = QuadraticExtensionField<Degree2ExtensionField, LevelTwoResidue>;

/// Computes the multiplication of an element of fp2 by the level two non-residue (0+u).
pub fn mul_fp2_by_nonresidue(a: &Fp2E) -> Fp2E {
let c0 = FP2_RESIDUE * &a.value()[1]; // c0 = -5 * a1
let c1 = a.value()[0].clone(); // c1 = a0
Fp2E::new([c0, c1])
}
/// Computes the multiplication of an element of fp6 by the level three non-residue v.
pub fn mul_fp6_by_nonresidue(a: &Fp6E) -> Fp6E {
let [a0, a1, a2] = a.value();

let c0 = mul_fp2_by_nonresidue(a2);
let c1 = a0.clone();
let c2 = a1.clone();

Fp6E::new([c0, c1, c2])
}

///Multiplication between a = a0 + a1 * w and b = b0 + b1 * w with
/// b1 = b10 + b11 * v + 0 * v^2 which is the case of the line used
/// in the miller loop.
pub fn sparse_fp12_mul(a: &Fp12E, b: &Fp12E) -> Fp12E {
let [a0, a1] = a.value();
let [b0, b1] = b.value();
let b00 = &b0.value()[0];
let [b10, b11, _] = b1.value();

let t0 = a0 * b0;
let t1 = a1 * b1;
let c0 = &t0 + mul_fp6_by_nonresidue(&t1);
let t2 = Fp6E::new([b10 + b00, b11.clone(), Fp2E::zero()]);
let mut c1 = (a0 + a1) * t2;
c1 = c1 - t0 - t1;

Fp12E::new([c0, c1])
}

#[cfg(test)]
mod tests {
Expand Down Expand Up @@ -359,4 +410,12 @@ mod tests {
let a = FpE::from(3);
assert_eq!(a.square(), a.clone() * a);
}
#[test]
fn test_mul_fp2_by_nonresidue() {
// Element in Fp2: a = 3 + 5u
let a = Fp2E::new([FpE::from(3), FpE::from(5)]);
// Expected result: (-25) + 3u
let expected = Fp2E::new([-FpE::from(25), FpE::from(3)]);
assert_eq!(mul_fp2_by_nonresidue(&a), expected);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod curve;
pub mod field_extension;
pub mod pairing;
pub mod twist;
Loading

0 comments on commit e650e0f

Please sign in to comment.