Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impl Bandersnatch curve #513

Merged
merged 14 commits into from
Sep 5, 2023
129 changes: 129 additions & 0 deletions math/src/elliptic_curve/edwards/curves/bandersnatch/curve.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
pub use super::field::FqField;
use crate::elliptic_curve::edwards::point::EdwardsProjectivePoint;
use crate::elliptic_curve::traits::IsEllipticCurve;
use crate::{elliptic_curve::edwards::traits::IsEdwards, field::element::FieldElement};

pub type BaseBandersnatchFieldElement = FqField;

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

impl IsEllipticCurve for BandersnatchCurve {
type BaseField = BaseBandersnatchFieldElement;
type PointRepresentation = EdwardsProjectivePoint<Self>;

// Values are from https://github.com/arkworks-rs/curves/blob/5a41d7f27a703a7ea9c48512a4148443ec6c747e/ed_on_bls12_381_bandersnatch/src/curves/mod.rs#L120
// Converted to Hex
fn generator() -> Self::PointRepresentation {
Self::PointRepresentation::new([
FieldElement::<Self::BaseField>::new_base(
"29C132CC2C0B34C5743711777BBE42F32B79C022AD998465E1E71866A252AE18",
),
FieldElement::<Self::BaseField>::new_base(
"2A6C669EDA123E0F157D8B50BADCD586358CAD81EEE464605E3167B6CC974166",
),
FieldElement::one(),
])
}
MauroToscano marked this conversation as resolved.
Show resolved Hide resolved
}

impl IsEdwards for BandersnatchCurve {
fn a() -> FieldElement<Self::BaseField> {
FieldElement::<Self::BaseField>::new_base(
"73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFEFFFFFFFC",
)
}

fn d() -> FieldElement<Self::BaseField> {
FieldElement::<Self::BaseField>::new_base(
"6389C12633C267CBC66E3BF86BE3B6D8CB66677177E54F92B369F2F5188D58E7",
)
}
}

#[cfg(test)]
mod tests {

use super::*;
use crate::{
cyclic_group::IsGroup, elliptic_curve::traits::EllipticCurveError,
field::element::FieldElement, unsigned_integer::element::U256,
};

#[allow(clippy::upper_case_acronyms)]
type FEE = FieldElement<BaseBandersnatchFieldElement>;

fn point_1() -> EdwardsProjectivePoint<BandersnatchCurve> {
let x = FEE::new_base("29C132CC2C0B34C5743711777BBE42F32B79C022AD998465E1E71866A252AE18");
let y = FEE::new_base("2A6C669EDA123E0F157D8B50BADCD586358CAD81EEE464605E3167B6CC974166");

BandersnatchCurve::create_point_from_affine(x, y).unwrap()
}

#[test]
fn test_scalar_mul() {
let g = BandersnatchCurve::generator();
let result1 = g.operate_with_self(5u16);

assert_eq!(
result1.x().clone(),
FEE::new_base("68CBECE0B8FB55450410CBC058928A567EED293D168FAEF44BFDE25F943AABE0")
);

let scalar =
U256::from_hex("1CFB69D4CA675F520CCE760202687600FF8F87007419047174FD06B52876E7E6")
.unwrap();
let result2 = g.operate_with_self(scalar);

assert_eq!(
result2.x().clone(),
FEE::new_base("68CBECE0B8FB55450410CBC058928A567EED293D168FAEF44BFDE25F943AABE0")
);
}

#[test]
fn test_create_valid_point_works() {
let p = BandersnatchCurve::generator();

assert_eq!(p, p.clone());
}

#[test]
fn create_valid_point_works() {
let p = point_1();
assert_eq!(
*p.x(),
FEE::new_base("29C132CC2C0B34C5743711777BBE42F32B79C022AD998465E1E71866A252AE18")
);
assert_eq!(
*p.y(),
FEE::new_base("2A6C669EDA123E0F157D8B50BADCD586358CAD81EEE464605E3167B6CC974166")
);
assert_eq!(*p.z(), FEE::new_base("1"));
}

#[test]
fn create_invalid_points_panics() {
assert_eq!(
BandersnatchCurve::create_point_from_affine(FEE::from(1), FEE::from(1)).unwrap_err(),
EllipticCurveError::InvalidPoint
)
}

#[test]
fn equality_works() {
let g = BandersnatchCurve::generator();
let g2 = g.operate_with(&g);
assert_ne!(&g2, &g);
assert_eq!(&g, &g);
}

#[test]
fn operate_with_self_works_1() {
let g = BandersnatchCurve::generator();
assert_eq!(
g.operate_with(&g).operate_with(&g),
g.operate_with_self(3_u16)
);
}
}
28 changes: 28 additions & 0 deletions math/src/elliptic_curve/edwards/curves/bandersnatch/field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//! Base field of bandersantch -- which is also the scalar field of BLS12-381 curve.

use crate::{
field::{
element::FieldElement,
fields::montgomery_backed_prime_fields::{IsModulus, MontgomeryBackendPrimeField},
},
unsigned_integer::element::U256,
};

pub const BANDERSNATCH_PRIME_FIELD_ORDER: U256 =
U256::from_hex_unchecked("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001");

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

impl IsModulus<U256> for FqConfig {
const MODULUS: U256 = BANDERSNATCH_PRIME_FIELD_ORDER;
}

pub type FqField = MontgomeryBackendPrimeField<FqConfig, 4>;

impl FieldElement<FqField> {
pub fn new_base(a_hex: &str) -> Self {
Self::new(U256::from(a_hex))
}
}
pub type FqElement = FieldElement<FqField>;
2 changes: 2 additions & 0 deletions math/src/elliptic_curve/edwards/curves/bandersnatch/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod curve;
pub mod field;
1 change: 1 addition & 0 deletions math/src/elliptic_curve/edwards/curves/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod bandersnatch;
pub mod tiny_jub_jub;