use crate::curves::{Field, Group, PrimeField, SquareRootField};
use snarkvm_utilities::{
biginteger::BigInteger,
bytes::{FromBytes, ToBytes},
rand::UniformRand,
serialize::*,
};
use std::{
fmt::{Debug, Display},
hash::Hash,
iter,
ops::{Add, AddAssign, Neg, Sub, SubAssign},
};
use crate::curves::Zero;
pub trait PairingEngine: Sized + 'static + Copy + Debug + Sync + Send {
type Fr: PrimeField + SquareRootField + Into<<Self::Fr as PrimeField>::BigInteger>;
type G1Projective: ProjectiveCurve<BaseField = Self::Fq, ScalarField = Self::Fr, Affine = Self::G1Affine>
+ From<Self::G1Affine>;
type G1Affine: AffineCurve<BaseField = Self::Fq, ScalarField = Self::Fr, Projective = Self::G1Projective>
+ PairingCurve<PairWith = Self::G2Affine, PairingResult = Self::Fqk>
+ From<Self::G1Projective>;
type G2Projective: ProjectiveCurve<BaseField = Self::Fqe, ScalarField = Self::Fr, Affine = Self::G2Affine>
+ From<Self::G2Affine>;
type G2Affine: AffineCurve<BaseField = Self::Fqe, ScalarField = Self::Fr, Projective = Self::G2Projective>
+ PairingCurve<PairWith = Self::G1Affine, PairingResult = Self::Fqk>
+ From<Self::G2Projective>;
type Fq: PrimeField + SquareRootField;
type Fqe: SquareRootField;
type Fqk: Field;
#[must_use]
fn miller_loop<'a, I>(i: I) -> Self::Fqk
where
I: Iterator<
Item = (
&'a <Self::G1Affine as PairingCurve>::Prepared,
&'a <Self::G2Affine as PairingCurve>::Prepared,
),
>;
#[must_use]
fn final_exponentiation(_: &Self::Fqk) -> Option<Self::Fqk>;
#[must_use]
fn product_of_pairings<'a, I>(i: I) -> Self::Fqk
where
I: Iterator<
Item = (
&'a <Self::G1Affine as PairingCurve>::Prepared,
&'a <Self::G2Affine as PairingCurve>::Prepared,
),
>,
{
Self::final_exponentiation(&Self::miller_loop(i)).unwrap()
}
#[must_use]
fn pairing<G1, G2>(p: G1, q: G2) -> Self::Fqk
where
G1: Into<Self::G1Affine>,
G2: Into<Self::G2Affine>,
{
Self::final_exponentiation(&Self::miller_loop(iter::once((
&p.into().prepare(),
&q.into().prepare(),
))))
.unwrap()
}
}
pub trait ProjectiveCurve:
Eq
+ Sized
+ ToBytes
+ FromBytes
+ CanonicalSerialize
+ ConstantSerializedSize
+ CanonicalDeserialize
+ Copy
+ Clone
+ Default
+ Send
+ Sync
+ Hash
+ Debug
+ Display
+ UniformRand
+ Zero
+ 'static
+ Neg<Output = Self>
+ for<'a> Add<&'a Self, Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
+ for<'a> AddAssign<&'a Self>
+ for<'a> SubAssign<&'a Self>
+ From<<Self as ProjectiveCurve>::Affine>
{
type ScalarField: PrimeField + SquareRootField + Into<<Self::ScalarField as PrimeField>::BigInteger>;
type BaseField: Field;
type Affine: AffineCurve<Projective = Self, ScalarField = Self::ScalarField> + From<Self> + Into<Self>;
#[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;
#[must_use]
fn double(&self) -> Self {
let mut copy = *self;
copy.double_in_place();
copy
}
fn double_in_place(&mut self) -> &mut Self;
fn add_assign_mixed(&mut self, other: &Self::Affine);
fn mul_assign<S: Into<<Self::ScalarField as PrimeField>::BigInteger>>(&mut self, other: S);
#[must_use]
fn into_affine(&self) -> Self::Affine;
#[must_use]
fn recommended_wnaf_for_scalar(scalar: <Self::ScalarField as PrimeField>::BigInteger) -> usize;
#[must_use]
fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize;
}
pub trait AffineCurve:
Eq
+ Sized
+ ToBytes
+ FromBytes
+ CanonicalSerialize
+ ConstantSerializedSize
+ CanonicalDeserialize
+ Copy
+ Clone
+ Default
+ Send
+ Sync
+ Hash
+ Debug
+ Display
+ Neg<Output = Self>
+ Zero
+ 'static
+ From<<Self as AffineCurve>::Projective>
{
type ScalarField: PrimeField + SquareRootField + Into<<Self::ScalarField as PrimeField>::BigInteger>;
type BaseField: Field;
type Projective: ProjectiveCurve<Affine = Self, ScalarField = Self::ScalarField> + From<Self> + Into<Self>;
#[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>;
fn add(self, other: &Self) -> Self;
#[must_use]
fn mul<S: Into<<Self::ScalarField as PrimeField>::BigInteger>>(&self, other: S) -> Self::Projective;
#[must_use]
fn mul_by_cofactor_to_projective(&self) -> Self::Projective;
#[must_use]
fn into_projective(&self) -> Self::Projective;
fn from_random_bytes(bytes: &[u8]) -> Option<Self>;
#[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;
}
pub trait PairingCurve: AffineCurve {
type Engine: PairingEngine<Fr = Self::ScalarField>;
type Prepared: CanonicalSerialize + CanonicalDeserialize + ToBytes + 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;
}
impl<C: ProjectiveCurve> Group for C {
type ScalarField = C::ScalarField;
#[inline]
#[must_use]
fn double(&self) -> Self {
let mut tmp = *self;
tmp += self;
tmp
}
#[inline]
fn double_in_place(&mut self) -> &mut Self {
<C as ProjectiveCurve>::double_in_place(self)
}
}
pub trait ModelParameters: Send + Sync + 'static {
type BaseField: Field + SquareRootField;
type ScalarField: PrimeField + SquareRootField + Into<<Self::ScalarField as PrimeField>::BigInteger>;
}
pub trait SWModelParameters: ModelParameters {
const COEFF_A: Self::BaseField;
const COEFF_B: Self::BaseField;
const COFACTOR: &'static [u64];
const COFACTOR_INV: Self::ScalarField;
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField);
#[inline(always)]
fn mul_by_a(elem: &Self::BaseField) -> Self::BaseField {
let mut copy = *elem;
copy *= &Self::COEFF_A;
copy
}
#[inline(always)]
fn add_b(elem: &Self::BaseField) -> Self::BaseField {
let mut copy = *elem;
copy += &Self::COEFF_B;
copy
}
#[inline(always)]
fn empirical_recommended_wnaf_for_scalar(scalar: <Self::ScalarField as PrimeField>::BigInteger) -> usize {
let num_bits = scalar.num_bits() as usize;
if num_bits >= 103 {
4
} else if num_bits >= 37 {
3
} else {
2
}
}
#[inline(always)]
fn empirical_recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize {
const RECOMMENDATIONS: [usize; 11] = [1, 3, 8, 20, 47, 126, 260, 826, 1501, 4555, 84071];
let mut result = 4;
for r in &RECOMMENDATIONS {
match num_scalars > *r {
true => result += 1,
false => break,
}
}
result
}
}
pub trait TEModelParameters: ModelParameters {
const COEFF_A: Self::BaseField;
const COEFF_D: Self::BaseField;
const COFACTOR: &'static [u64];
const COFACTOR_INV: Self::ScalarField;
const AFFINE_GENERATOR_COEFFS: (Self::BaseField, Self::BaseField);
type MontgomeryModelParameters: MontgomeryModelParameters<BaseField = Self::BaseField>;
#[inline(always)]
fn mul_by_a(elem: &Self::BaseField) -> Self::BaseField {
let mut copy = *elem;
copy *= &Self::COEFF_A;
copy
}
#[inline(always)]
fn empirical_recommended_wnaf_for_scalar(scalar: <Self::ScalarField as PrimeField>::BigInteger) -> usize {
let num_bits = scalar.num_bits() as usize;
if num_bits >= 130 {
4
} else if num_bits >= 34 {
3
} else {
2
}
}
#[inline(always)]
fn empirical_recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize {
const RECOMMENDATIONS: [usize; 12] = [1, 3, 7, 20, 43, 120, 273, 563, 1630, 3128, 7933, 62569];
let mut ret = 4;
for r in &RECOMMENDATIONS {
if num_scalars > *r {
ret += 1;
} else {
break;
}
}
ret
}
}
pub trait MontgomeryModelParameters: ModelParameters {
const COEFF_A: Self::BaseField;
const COEFF_B: Self::BaseField;
type TEModelParameters: TEModelParameters<BaseField = Self::BaseField>;
}