ark_ec/models/short_weierstrass/
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::*,
One, Zero,
};
use ark_ff::{fields::Field, AdditiveGroup, PrimeField, ToConstraintField, UniformRand};
use educe::Educe;
use zeroize::Zeroize;
use super::{Projective, SWCurveConfig, SWFlags};
use crate::AffineRepr;
#[derive(Educe)]
#[educe(Copy, Clone, PartialEq, Eq, Hash)]
#[must_use]
pub struct Affine<P: SWCurveConfig> {
#[doc(hidden)]
pub x: P::BaseField,
#[doc(hidden)]
pub y: P::BaseField,
#[doc(hidden)]
pub infinity: bool,
}
impl<P: SWCurveConfig> PartialEq<Projective<P>> for Affine<P> {
fn eq(&self, other: &Projective<P>) -> bool {
self.into_group() == *other
}
}
impl<P: SWCurveConfig> Display for Affine<P> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self.infinity {
true => write!(f, "infinity"),
false => write!(f, "({}, {})", self.x, self.y),
}
}
}
impl<P: SWCurveConfig> Debug for Affine<P> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self.infinity {
true => write!(f, "infinity"),
false => write!(f, "({}, {})", self.x, self.y),
}
}
}
impl<P: SWCurveConfig> Affine<P> {
pub fn new(x: P::BaseField, y: P::BaseField) -> Self {
let point = Self {
x,
y,
infinity: false,
};
assert!(point.is_on_curve());
assert!(point.is_in_correct_subgroup_assuming_on_curve());
point
}
pub const fn new_unchecked(x: P::BaseField, y: P::BaseField) -> Self {
Self {
x,
y,
infinity: false,
}
}
pub const fn identity() -> Self {
Self {
x: P::BaseField::ZERO,
y: P::BaseField::ZERO,
infinity: true,
}
}
#[allow(dead_code)]
pub fn get_point_from_x_unchecked(x: P::BaseField, greatest: bool) -> Option<Self> {
Self::get_ys_from_x_unchecked(x).map(|(smaller, larger)| {
if greatest {
Self::new_unchecked(x, larger)
} else {
Self::new_unchecked(x, smaller)
}
})
}
pub fn get_ys_from_x_unchecked(x: P::BaseField) -> Option<(P::BaseField, P::BaseField)> {
let mut x3_plus_ax_plus_b = P::add_b(x.square() * x);
if !P::COEFF_A.is_zero() {
x3_plus_ax_plus_b += P::mul_by_a(x)
};
let y = x3_plus_ax_plus_b.sqrt()?;
let neg_y = -y;
match y < neg_y {
true => Some((y, neg_y)),
false => Some((neg_y, y)),
}
}
pub fn is_on_curve(&self) -> bool {
if !self.infinity {
let mut x3b = P::add_b(self.x.square() * self.x);
if !P::COEFF_A.is_zero() {
x3b += P::mul_by_a(self.x);
};
self.y.square() == x3b
} else {
true
}
}
pub fn to_flags(&self) -> SWFlags {
if self.infinity {
SWFlags::PointAtInfinity
} else if self.y <= -self.y {
SWFlags::YIsPositive
} else {
SWFlags::YIsNegative
}
}
}
impl<P: SWCurveConfig> Affine<P> {
pub fn is_in_correct_subgroup_assuming_on_curve(&self) -> bool {
P::is_in_correct_subgroup_assuming_on_curve(self)
}
}
impl<P: SWCurveConfig> Zeroize for Affine<P> {
fn zeroize(&mut self) {
self.x.zeroize();
self.y.zeroize();
self.infinity.zeroize();
}
}
impl<P: SWCurveConfig> Distribution<Affine<P>> for Standard {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Affine<P> {
loop {
let x = P::BaseField::rand(rng);
let greatest = rng.gen();
if let Some(p) = Affine::get_point_from_x_unchecked(x, greatest) {
return p.mul_by_cofactor();
}
}
}
}
impl<P: SWCurveConfig> 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.infinity).then(|| (self.x, self.y))
}
#[inline]
fn generator() -> Self {
P::GENERATOR
}
fn zero() -> Self {
Self {
x: P::BaseField::ZERO,
y: P::BaseField::ZERO,
infinity: true,
}
}
fn from_random_bytes(bytes: &[u8]) -> Option<Self> {
P::BaseField::from_random_bytes_with_flags::<SWFlags>(bytes).and_then(|(x, flags)| {
if x.is_zero() && flags.is_infinity() {
Some(Self::identity())
} else if let Some(y_is_positive) = flags.is_positive() {
Self::get_point_from_x_unchecked(x, y_is_positive)
} else {
None
}
})
}
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: SWCurveConfig> Neg for Affine<P> {
type Output = Self;
#[inline]
fn neg(mut self) -> Self {
self.y.neg_in_place();
self
}
}
impl<P: SWCurveConfig, T: Borrow<Self>> Add<T> for Affine<P> {
type Output = Projective<P>;
fn add(self, other: T) -> Projective<P> {
let mut copy = self.into_group();
copy += other.borrow();
copy
}
}
impl<P: SWCurveConfig> Add<Projective<P>> for Affine<P> {
type Output = Projective<P>;
fn add(self, other: Projective<P>) -> Projective<P> {
other + self
}
}
impl<'a, P: SWCurveConfig> Add<&'a Projective<P>> for Affine<P> {
type Output = Projective<P>;
fn add(self, other: &'a Projective<P>) -> Projective<P> {
*other + self
}
}
impl<P: SWCurveConfig, T: Borrow<Self>> Sub<T> for Affine<P> {
type Output = Projective<P>;
fn sub(self, other: T) -> Projective<P> {
let mut copy = self.into_group();
copy -= other.borrow();
copy
}
}
impl<P: SWCurveConfig> Sub<Projective<P>> for Affine<P> {
type Output = Projective<P>;
fn sub(self, other: Projective<P>) -> Projective<P> {
self + (-other)
}
}
impl<'a, P: SWCurveConfig> Sub<&'a Projective<P>> for Affine<P> {
type Output = Projective<P>;
fn sub(self, other: &'a Projective<P>) -> Projective<P> {
self + (-*other)
}
}
impl<P: SWCurveConfig> Default for Affine<P> {
#[inline]
fn default() -> Self {
Self::identity()
}
}
impl<P: SWCurveConfig, 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: SWCurveConfig> From<Projective<P>> for Affine<P> {
#[inline]
fn from(p: Projective<P>) -> Affine<P> {
if p.is_zero() {
Affine::identity()
} else if p.z.is_one() {
Affine::new_unchecked(p.x, p.y)
} else {
let zinv = p.z.inverse().unwrap();
let zinv_squared = zinv.square();
let x = p.x * &zinv_squared;
let y = p.y * &(zinv_squared * &zinv);
Affine::new_unchecked(x, y)
}
}
}
impl<P: SWCurveConfig> 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: SWCurveConfig> 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: SWCurveConfig> 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: SWCurveConfig, ConstraintF: Field> ToConstraintField<ConstraintF> for Affine<M>
where
M::BaseField: ToConstraintField<ConstraintF>,
{
#[inline]
fn to_field_elements(&self) -> Option<Vec<ConstraintF>> {
let mut x = self.x.to_field_elements()?;
let y = self.y.to_field_elements()?;
let infinity = self.infinity.to_field_elements()?;
x.extend_from_slice(&y);
x.extend_from_slice(&infinity);
Some(x)
}
}