use ff::PrimeField;
use group::{Curve, Group};
#[cfg(feature = "dev-curves")]
use midnight_curves::bn256;
use midnight_curves::{
secp256k1::{Secp256k1, Secp256k1Affine},
CurveAffine, Fq as BlsScalar, JubjubAffine, JubjubExtended, JubjubSubgroup,
};
pub trait CircuitCurve: Curve + Default {
type Base: PrimeField;
type CryptographicGroup: Group<Scalar = Self::Scalar> + Into<Self>;
const COFACTOR: u128 = 1;
const NUM_BITS_SUBGROUP: u32;
fn coordinates(&self) -> Option<(Self::Base, Self::Base)>;
fn from_xy(x: Self::Base, y: Self::Base) -> Option<Self>;
fn into_subgroup(self) -> Self::CryptographicGroup;
}
pub trait WeierstrassCurve: CircuitCurve {
const A: Self::Base;
const B: Self::Base;
const BASE_ZETA: Self::Base;
const SCALAR_ZETA: Self::Scalar;
}
pub trait EdwardsCurve: CircuitCurve {
const A: Self::Base;
const D: Self::Base;
}
impl CircuitCurve for JubjubExtended {
type Base = BlsScalar;
type CryptographicGroup = JubjubSubgroup;
const COFACTOR: u128 = 8;
const NUM_BITS_SUBGROUP: u32 = 252;
fn coordinates(&self) -> Option<(Self::Base, Self::Base)> {
Some((self.to_affine().get_u(), self.to_affine().get_v()))
}
fn from_xy(x: Self::Base, y: Self::Base) -> Option<Self> {
let mut bytes = y.to_bytes_le();
let x_sign = x.to_bytes_le()[0] << 7;
bytes[31] |= x_sign;
let point = JubjubAffine::from_bytes(bytes).into_option().expect("Failed here");
if point.get_v() == y {
Some(point.into())
} else {
None
}
}
fn into_subgroup(self) -> Self::CryptographicGroup {
<JubjubExtended as CofactorGroup>::into_subgroup(self)
.expect("Point should be part of the subgroup")
}
}
impl EdwardsCurve for JubjubExtended {
const A: Self::Base = Self::Base::from_raw([
0xffff_ffff_0000_0000,
0x53bd_a402_fffe_5bfe,
0x3339_d808_09a1_d805,
0x73ed_a753_299d_7d48,
]);
const D: Self::Base = Self::Base::from_raw([
0x0106_5fd6_d634_3eb1,
0x292d_7f6d_3757_9d26,
0xf5fd_9207_e6bd_7fd4,
0x2a93_18e7_4bfa_2b48,
]);
}
use midnight_curves::secp256k1::{Fp, Fq};
impl CircuitCurve for Secp256k1 {
type Base = Fp;
type CryptographicGroup = Secp256k1;
const NUM_BITS_SUBGROUP: u32 = 256;
fn coordinates(&self) -> Option<(Self::Base, Self::Base)> {
Some((self.to_affine().x, self.to_affine().y))
}
fn from_xy(x: Self::Base, y: Self::Base) -> Option<Self> {
<Secp256k1Affine as CurveAffine>::from_xy(x, y).into_option().map(|p| p.into())
}
fn into_subgroup(self) -> Self::CryptographicGroup {
self
}
}
impl WeierstrassCurve for Secp256k1 {
const A: Self::Base = Fp::from_raw([0, 0, 0, 0]);
const B: Self::Base = Fp::from_raw([7, 0, 0, 0]);
const BASE_ZETA: Self::Base = <Fp as ff::WithSmallOrderMulGroup<3>>::ZETA;
const SCALAR_ZETA: Self::Scalar = <Fq as ff::WithSmallOrderMulGroup<3>>::ZETA;
}
use group::cofactor::CofactorGroup;
use midnight_curves::{Fp as BlsBase, G1Affine, G1Projective};
impl CircuitCurve for G1Projective {
type Base = BlsBase;
type CryptographicGroup = G1Projective;
const NUM_BITS_SUBGROUP: u32 = 255;
fn coordinates(&self) -> Option<(Self::Base, Self::Base)> {
Some((self.to_affine().x(), self.to_affine().y()))
}
fn from_xy(x: Self::Base, y: Self::Base) -> Option<Self> {
<G1Affine as CurveAffine>::from_xy(x, y).into_option().map(|p| p.into())
}
fn into_subgroup(self) -> Self::CryptographicGroup {
self
}
}
impl WeierstrassCurve for G1Projective {
const A: Self::Base = midnight_curves::A;
const B: Self::Base = midnight_curves::B;
const BASE_ZETA: Self::Base = <BlsBase as ff::WithSmallOrderMulGroup<3>>::ZETA;
const SCALAR_ZETA: Self::Scalar = <BlsScalar as ff::WithSmallOrderMulGroup<3>>::ZETA;
}
#[cfg(feature = "dev-curves")]
impl CircuitCurve for bn256::G1 {
type Base = bn256::Fq;
type CryptographicGroup = bn256::G1;
const NUM_BITS_SUBGROUP: u32 = 254;
fn coordinates(&self) -> Option<(Self::Base, Self::Base)> {
Some((self.to_affine().x, self.to_affine().y))
}
fn from_xy(x: Self::Base, y: Self::Base) -> Option<Self> {
<bn256::G1Affine as CurveAffine>::from_xy(x, y).into_option().map(|p| p.into())
}
fn into_subgroup(self) -> Self::CryptographicGroup {
self
}
}
#[cfg(feature = "dev-curves")]
impl WeierstrassCurve for bn256::G1 {
const A: Self::Base = bn256::Fq::from_raw([0, 0, 0, 0]);
const B: Self::Base = bn256::Fq::from_raw([3, 0, 0, 0]);
const BASE_ZETA: Self::Base = <bn256::Fq as ff::WithSmallOrderMulGroup<3>>::ZETA;
const SCALAR_ZETA: Self::Scalar = <bn256::Fr as ff::WithSmallOrderMulGroup<3>>::ZETA;
}