use crate::{
edwards_bls12::{Fq, Fr},
errors::GroupError,
templates::twisted_edwards_extended::{Affine, Projective},
traits::{AffineCurve, ModelParameters, MontgomeryParameters, TwistedEdwardsParameters},
};
use snarkvm_fields::field;
use snarkvm_utilities::biginteger::BigInteger256;
use std::str::FromStr;
pub type EdwardsAffine = Affine<EdwardsParameters>;
pub type EdwardsProjective = Projective<EdwardsParameters>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct EdwardsParameters;
impl ModelParameters for EdwardsParameters {
type BaseField = Fq;
type ScalarField = Fr;
}
impl TwistedEdwardsParameters for EdwardsParameters {
type MontgomeryParameters = EdwardsParameters;
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField) = (GENERATOR_X, GENERATOR_Y);
const COFACTOR: &'static [u64] = &[4];
const COFACTOR_INV: Fr = field!(
Fr,
BigInteger256([10836190823041854989, 14880086764632731920, 5023208332782666747, 239524813690824359,])
);
const EDWARDS_A: Fq =
field!(Fq, BigInteger256([0x8cf500000000000e, 0xe75281ef6000000e, 0x49dc37a90b0ba012, 0x55f8b2c6e710ab9,]));
const EDWARDS_D: Fq =
field!(Fq, BigInteger256([0xd047ffffffff5e30, 0xf0a91026ffff57d2, 0x9013f560d102582, 0x9fd242ca7be5700,]));
#[inline(always)]
fn mul_by_a(elem: &Self::BaseField) -> Self::BaseField {
-*elem
}
}
impl MontgomeryParameters for EdwardsParameters {
type TwistedEdwardsParameters = EdwardsParameters;
const MONTGOMERY_A: Fq = field!(
Fq,
BigInteger256([
13800168384327121454u64,
6841573379969807446u64,
12529593083398462246u64,
853978956621483129u64,
])
);
const MONTGOMERY_B: Fq = field!(
Fq,
BigInteger256([
7239382437352637935u64,
14509846070439283655u64,
5083066350480839936u64,
1265663645916442191u64,
])
);
}
impl FromStr for EdwardsAffine {
type Err = GroupError;
fn from_str(mut s: &str) -> Result<Self, Self::Err> {
s = s.trim();
if s.is_empty() {
return Err(GroupError::ParsingEmptyString);
}
if s.len() < 3 {
return Err(GroupError::InvalidString);
}
if !(s.starts_with('(') && s.ends_with(')')) {
return Err(GroupError::InvalidString);
}
let mut point = Vec::new();
for substr in s.split(|c| c == '(' || c == ')' || c == ',' || c == ' ') {
if !substr.is_empty() {
point.push(Fq::from_str(substr)?);
}
}
if point.len() != 2 {
return Err(GroupError::InvalidGroupElement);
}
let point = EdwardsAffine::new(point[0], point[1], point[0] * point[1]);
if !point.is_on_curve() { Err(GroupError::InvalidGroupElement) } else { Ok(point) }
}
}
const GENERATOR_X: Fq =
field!(Fq, BigInteger256([15976313411695170452, 17230178952810798400, 11626259175167078036, 678729006091608048]));
const GENERATOR_Y: Fq =
field!(Fq, BigInteger256([926786653590077393, 18147000980977651608, 13077459464847727671, 1231472949076376191]));