use crate::{templates::short_weierstrass_jacobian, PairingEngine};
use snarkvm_fields::{Field, PrimeField, SquareRootField, Zero};
use snarkvm_utilities::{rand::Uniform, serialize::*, FromBytes, ToBytes, ToMinimalBits};
use core::{
fmt::{Debug, Display},
hash::Hash,
iter,
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use serde::{de::DeserializeOwned, Serialize};
pub trait ProjectiveCurve:
CanonicalSerialize
+ CanonicalDeserialize
+ Copy
+ Clone
+ Debug
+ Display
+ Default
+ FromBytes
+ Send
+ Sync
+ 'static
+ Eq
+ Hash
+ Neg<Output = Self>
+ Uniform
+ Zero
+ Add<Self, Output = Self>
+ Sub<Self, Output = Self>
+ Mul<Self::ScalarField, Output = Self>
+ AddAssign<Self>
+ SubAssign<Self>
+ MulAssign<Self::ScalarField>
+ for<'a> Add<&'a Self, Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
+ for<'a> AddAssign<&'a Self>
+ for<'a> SubAssign<&'a Self>
+ PartialEq<Self::Affine>
+ Sized
+ ToBytes
+ iter::Sum
+ From<<Self as ProjectiveCurve>::Affine>
{
type Affine: AffineCurve<Projective = Self, ScalarField = Self::ScalarField> + From<Self> + Into<Self>;
type BaseField: Field;
type ScalarField: PrimeField + SquareRootField + Into<<Self::ScalarField as PrimeField>::BigInteger>;
#[must_use]
fn prime_subgroup_generator() -> Self;
fn batch_normalization(v: &mut [Self]);
fn batch_normalization_into_affine(mut v: Vec<Self>) -> Vec<Self::Affine> {
Self::batch_normalization(&mut v);
v.into_iter().map(|v| v.into()).collect()
}
#[must_use]
fn is_normalized(&self) -> bool;
fn add_assign_mixed(&mut self, other: &Self::Affine);
fn add_mixed(&self, other: &Self::Affine) -> Self {
let mut copy = *self;
copy.add_assign_mixed(other);
copy
}
fn sub_assign_mixed(&mut self, other: &Self::Affine) {
self.add_assign_mixed(&-*other);
}
#[must_use]
fn double(&self) -> Self;
fn double_in_place(&mut self);
#[must_use]
#[allow(clippy::wrong_self_convention)]
fn to_affine(&self) -> Self::Affine;
}
#[allow(clippy::wrong_self_convention)]
pub trait AffineCurve:
CanonicalSerialize
+ CanonicalDeserialize
+ Copy
+ Clone
+ Debug
+ Display
+ Default
+ FromBytes
+ Send
+ Sync
+ 'static
+ Eq
+ Hash
+ Neg<Output = Self>
+ Uniform
+ PartialEq<Self::Projective>
+ Mul<Self::ScalarField, Output = Self::Projective>
+ Sized
+ Serialize
+ DeserializeOwned
+ ToBytes
+ From<<Self as AffineCurve>::Projective>
+ ToMinimalBits
+ Zero
{
type Projective: ProjectiveCurve<Affine = Self, ScalarField = Self::ScalarField> + From<Self> + Into<Self>;
type BaseField: Field + SquareRootField;
type ScalarField: PrimeField + SquareRootField + Into<<Self::ScalarField as PrimeField>::BigInteger>;
type Coordinates;
fn from_coordinates(coordinates: Self::Coordinates) -> Option<Self>;
fn from_coordinates_unchecked(coordinates: Self::Coordinates) -> Self;
fn cofactor() -> &'static [u64];
#[must_use]
fn prime_subgroup_generator() -> Self;
fn from_x_coordinate(x: Self::BaseField, greatest: bool) -> Option<Self>;
fn from_y_coordinate(y: Self::BaseField, greatest: bool) -> Option<Self>;
#[must_use]
fn mul_by_cofactor_to_projective(&self) -> Self::Projective;
#[must_use]
fn to_projective(&self) -> Self::Projective;
fn from_random_bytes(bytes: &[u8]) -> Option<Self>;
fn mul_bits(&self, bits: impl Iterator<Item = bool>) -> Self::Projective;
#[must_use]
fn mul_by_cofactor(&self) -> Self {
self.mul_by_cofactor_to_projective().into()
}
#[must_use]
fn mul_by_cofactor_inv(&self) -> Self;
#[must_use]
fn is_in_correct_subgroup_assuming_on_curve(&self) -> bool;
#[must_use]
fn to_x_coordinate(&self) -> Self::BaseField;
#[must_use]
fn to_y_coordinate(&self) -> Self::BaseField;
fn is_on_curve(&self) -> bool;
fn batch_add_loop_1(
a: &mut Self,
b: &mut Self,
half: &Self::BaseField, inversion_tmp: &mut Self::BaseField,
);
fn batch_add_loop_2(a: &mut Self, b: Self, inversion_tmp: &mut Self::BaseField);
}
pub trait PairingCurve: AffineCurve {
type Engine: PairingEngine<Fr = Self::ScalarField>;
type Prepared: CanonicalSerialize
+ CanonicalDeserialize
+ ToBytes
+ FromBytes
+ PartialEq
+ Eq
+ Default
+ Clone
+ Send
+ Sync
+ Debug
+ 'static;
type PairWith: PairingCurve<PairWith = Self>;
type PairingResult: Field;
#[must_use]
fn prepare(&self) -> Self::Prepared;
#[must_use]
fn pairing_with(&self, other: &Self::PairWith) -> Self::PairingResult;
}
pub trait ModelParameters: 'static + Copy + Clone + Debug + PartialEq + Eq + Hash + Send + Sync + Sized {
type BaseField: Field + SquareRootField;
type ScalarField: PrimeField + SquareRootField + Into<<Self::ScalarField as PrimeField>::BigInteger>;
}
pub trait ShortWeierstrassParameters: ModelParameters {
const WEIERSTRASS_A: Self::BaseField;
const WEIERSTRASS_B: Self::BaseField;
const COFACTOR: &'static [u64];
const COFACTOR_INV: Self::ScalarField;
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField);
const PHI: Self::BaseField;
const Q1: [u64; 4] = [9183663392111466540, 12968021215939883360, 3, 0];
const Q2: [u64; 4] = [13, 0, 0, 0];
const B1: Self::ScalarField;
const B2: Self::ScalarField;
const R128: Self::ScalarField;
const HALF_R: [u64; 8] = [0, 0, 0, 0x8000000000000000, 0, 0, 0, 0];
#[inline(always)]
fn mul_by_a(elem: &Self::BaseField) -> Self::BaseField {
let mut copy = *elem;
copy *= &Self::WEIERSTRASS_A;
copy
}
#[inline(always)]
fn add_b(elem: &Self::BaseField) -> Self::BaseField {
let mut copy = *elem;
copy += &Self::WEIERSTRASS_B;
copy
}
fn is_in_correct_subgroup_assuming_on_curve(p: &short_weierstrass_jacobian::Affine<Self>) -> bool;
fn glv_endomorphism(p: short_weierstrass_jacobian::Affine<Self>) -> short_weierstrass_jacobian::Affine<Self>;
fn mul_projective(
p: short_weierstrass_jacobian::Projective<Self>,
by: Self::ScalarField,
) -> short_weierstrass_jacobian::Projective<Self>;
}
pub trait TwistedEdwardsParameters: ModelParameters {
const EDWARDS_A: Self::BaseField;
const EDWARDS_D: Self::BaseField;
const COFACTOR: &'static [u64];
const COFACTOR_INV: Self::ScalarField;
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField);
type MontgomeryParameters: MontgomeryParameters<BaseField = Self::BaseField>;
#[inline(always)]
fn mul_by_a(elem: &Self::BaseField) -> Self::BaseField {
let mut copy = *elem;
copy *= &Self::EDWARDS_A;
copy
}
}
pub trait MontgomeryParameters: ModelParameters {
const MONTGOMERY_A: Self::BaseField;
const MONTGOMERY_B: Self::BaseField;
type TwistedEdwardsParameters: TwistedEdwardsParameters<BaseField = Self::BaseField>;
}