ark_ec/models/twisted_edwards/
affine.rsuse ark_serialize::{
CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate,
};
use ark_std::{
borrow::Borrow,
fmt::{Debug, Display, Formatter, Result as FmtResult},
io::{Read, Write},
ops::{Add, Mul, Neg, Sub},
rand::{
distributions::{Distribution, Standard},
Rng,
},
vec::*,
};
use educe::Educe;
use num_traits::{One, Zero};
use zeroize::Zeroize;
use ark_ff::{fields::Field, AdditiveGroup, PrimeField, ToConstraintField, UniformRand};
use super::{Projective, TECurveConfig, TEFlags};
use crate::AffineRepr;
#[derive(Educe)]
#[educe(Copy, Clone, PartialEq, Eq, Hash)]
#[must_use]
pub struct Affine<P: TECurveConfig> {
pub x: P::BaseField,
pub y: P::BaseField,
}
impl<P: TECurveConfig> Display for Affine<P> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self.is_zero() {
true => write!(f, "infinity"),
false => write!(f, "({}, {})", self.x, self.y),
}
}
}
impl<P: TECurveConfig> Debug for Affine<P> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self.is_zero() {
true => write!(f, "infinity"),
false => write!(f, "({}, {})", self.x, self.y),
}
}
}
impl<P: TECurveConfig> PartialEq<Projective<P>> for Affine<P> {
fn eq(&self, other: &Projective<P>) -> bool {
self.into_group() == *other
}
}
impl<P: TECurveConfig> Affine<P> {
pub const fn new_unchecked(x: P::BaseField, y: P::BaseField) -> Self {
Self { x, y }
}
pub fn new(x: P::BaseField, y: P::BaseField) -> Self {
let p = Self::new_unchecked(x, y);
assert!(p.is_on_curve());
assert!(p.is_in_correct_subgroup_assuming_on_curve());
p
}
pub const fn zero() -> Self {
Self::new_unchecked(P::BaseField::ZERO, P::BaseField::ONE)
}
pub fn is_zero(&self) -> bool {
self.x.is_zero() && self.y.is_one()
}
#[allow(dead_code)]
pub fn get_point_from_y_unchecked(y: P::BaseField, greatest: bool) -> Option<Self> {
Self::get_xs_from_y_unchecked(y).map(|(x, neg_x)| {
if greatest {
Self::new_unchecked(neg_x, y)
} else {
Self::new_unchecked(x, y)
}
})
}
#[allow(dead_code)]
pub fn get_xs_from_y_unchecked(y: P::BaseField) -> Option<(P::BaseField, P::BaseField)> {
let y2 = y.square();
let numerator = P::BaseField::one() - y2;
let denominator = P::COEFF_A - (y2 * P::COEFF_D);
denominator
.inverse()
.map(|denom| denom * &numerator)
.and_then(|x2| x2.sqrt())
.map(|x| {
let neg_x = -x;
if x <= neg_x {
(x, neg_x)
} else {
(neg_x, x)
}
})
}
pub fn is_on_curve(&self) -> bool {
let x2 = self.x.square();
let y2 = self.y.square();
let lhs = y2 + P::mul_by_a(x2);
let rhs = P::BaseField::one() + &(P::COEFF_D * &(x2 * &y2));
lhs == rhs
}
}
impl<P: TECurveConfig> Affine<P> {
pub fn is_in_correct_subgroup_assuming_on_curve(&self) -> bool {
P::is_in_correct_subgroup_assuming_on_curve(self)
}
}
impl<P: TECurveConfig> AffineRepr for Affine<P> {
type Config = P;
type BaseField = P::BaseField;
type ScalarField = P::ScalarField;
type Group = Projective<P>;
fn xy(&self) -> Option<(Self::BaseField, Self::BaseField)> {
(!self.is_zero()).then(|| (self.x, self.y))
}
fn generator() -> Self {
P::GENERATOR
}
fn zero() -> Self {
Self::new_unchecked(P::BaseField::ZERO, P::BaseField::ONE)
}
fn from_random_bytes(bytes: &[u8]) -> Option<Self> {
P::BaseField::from_random_bytes_with_flags::<TEFlags>(bytes)
.and_then(|(y, flags)| Self::get_point_from_y_unchecked(y, flags.is_negative()))
}
fn mul_bigint(&self, by: impl AsRef<[u64]>) -> Self::Group {
P::mul_affine(self, by.as_ref())
}
#[must_use]
fn mul_by_cofactor_to_group(&self) -> Self::Group {
P::mul_affine(self, Self::Config::COFACTOR)
}
fn clear_cofactor(&self) -> Self {
P::clear_cofactor(self)
}
}
impl<P: TECurveConfig> Zeroize for Affine<P> {
fn zeroize(&mut self) {
self.x.zeroize();
self.y.zeroize();
}
}
impl<P: TECurveConfig> Neg for Affine<P> {
type Output = Self;
fn neg(self) -> Self {
Self::new_unchecked(-self.x, self.y)
}
}
impl<P: TECurveConfig, T: Borrow<Self>> Add<T> for Affine<P> {
type Output = Projective<P>;
fn add(self, other: T) -> Self::Output {
let mut copy = self.into_group();
copy += other.borrow();
copy
}
}
impl<P: TECurveConfig> Add<Projective<P>> for Affine<P> {
type Output = Projective<P>;
fn add(self, other: Projective<P>) -> Projective<P> {
other + self
}
}
impl<'a, P: TECurveConfig> Add<&'a Projective<P>> for Affine<P> {
type Output = Projective<P>;
fn add(self, other: &'a Projective<P>) -> Projective<P> {
*other + self
}
}
impl<P: TECurveConfig, T: Borrow<Self>> Sub<T> for Affine<P> {
type Output = Projective<P>;
fn sub(self, other: T) -> Self::Output {
let mut copy = self.into_group();
copy -= other.borrow();
copy
}
}
impl<P: TECurveConfig> Sub<Projective<P>> for Affine<P> {
type Output = Projective<P>;
fn sub(self, other: Projective<P>) -> Projective<P> {
self + (-other)
}
}
impl<'a, P: TECurveConfig> Sub<&'a Projective<P>> for Affine<P> {
type Output = Projective<P>;
fn sub(self, other: &'a Projective<P>) -> Projective<P> {
self + (-*other)
}
}
impl<P: TECurveConfig> Default for Affine<P> {
#[inline]
fn default() -> Self {
Self::zero()
}
}
impl<P: TECurveConfig> Distribution<Affine<P>> for Standard {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Affine<P> {
loop {
let y = P::BaseField::rand(rng);
let greatest = rng.gen();
if let Some(p) = Affine::get_point_from_y_unchecked(y, greatest) {
return p.mul_by_cofactor();
}
}
}
}
impl<P: TECurveConfig, T: Borrow<P::ScalarField>> Mul<T> for Affine<P> {
type Output = Projective<P>;
#[inline]
fn mul(self, other: T) -> Self::Output {
self.mul_bigint(other.borrow().into_bigint())
}
}
impl<P: TECurveConfig> From<Projective<P>> for Affine<P> {
fn from(p: Projective<P>) -> Affine<P> {
if p.is_zero() {
Affine::zero()
} else if p.z.is_one() {
Affine::new_unchecked(p.x, p.y)
} else {
let z_inv = p.z.inverse().unwrap();
let x = p.x * &z_inv;
let y = p.y * &z_inv;
Affine::new_unchecked(x, y)
}
}
}
impl<P: TECurveConfig> CanonicalSerialize for Affine<P> {
#[inline]
fn serialize_with_mode<W: Write>(
&self,
writer: W,
compress: ark_serialize::Compress,
) -> Result<(), SerializationError> {
P::serialize_with_mode(self, writer, compress)
}
#[inline]
fn serialized_size(&self, compress: Compress) -> usize {
P::serialized_size(compress)
}
}
impl<P: TECurveConfig> Valid for Affine<P> {
fn check(&self) -> Result<(), SerializationError> {
if self.is_on_curve() && self.is_in_correct_subgroup_assuming_on_curve() {
Ok(())
} else {
Err(SerializationError::InvalidData)
}
}
}
impl<P: TECurveConfig> CanonicalDeserialize for Affine<P> {
fn deserialize_with_mode<R: Read>(
reader: R,
compress: Compress,
validate: Validate,
) -> Result<Self, SerializationError> {
P::deserialize_with_mode(reader, compress, validate)
}
}
impl<M: TECurveConfig, ConstraintF: Field> ToConstraintField<ConstraintF> for Affine<M>
where
M::BaseField: ToConstraintField<ConstraintF>,
{
#[inline]
fn to_field_elements(&self) -> Option<Vec<ConstraintF>> {
let mut x_fe = self.x.to_field_elements()?;
let y_fe = self.y.to_field_elements()?;
x_fe.extend_from_slice(&y_fe);
Some(x_fe)
}
}