ark_ec/models/short_weierstrass/
affine.rs1use ark_serialize::{
2 CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate,
3};
4use ark_std::{
5 borrow::Borrow,
6 fmt::{Debug, Display, Formatter, Result as FmtResult},
7 io::{Read, Write},
8 ops::{Add, Mul, Neg, Sub},
9 rand::{
10 distributions::{Distribution, Standard},
11 Rng,
12 },
13 vec::*,
14 One, Zero,
15};
16
17use ark_ff::{fields::Field, AdditiveGroup, PrimeField, ToConstraintField, UniformRand};
18
19use educe::Educe;
20use zeroize::Zeroize;
21
22use super::{bucket::Bucket, Projective, SWCurveConfig, SWFlags, ZeroFlag};
23use crate::AffineRepr;
24
25#[derive(Educe)]
28#[educe(Copy, Clone, PartialEq, Eq, Hash)]
29#[must_use]
30pub struct Affine<P: SWCurveConfig> {
31 #[doc(hidden)]
32 pub x: P::BaseField,
33 #[doc(hidden)]
34 pub y: P::BaseField,
35 #[doc(hidden)]
36 pub(super) infinity: P::ZeroFlag,
37}
38
39impl<P: SWCurveConfig> PartialEq<Projective<P>> for Affine<P> {
40 fn eq(&self, other: &Projective<P>) -> bool {
41 self.into_group() == *other
42 }
43}
44
45impl<P: SWCurveConfig> Display for Affine<P> {
46 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
47 match self.is_zero() {
48 true => write!(f, "infinity"),
49 false => write!(f, "({}, {})", self.x, self.y),
50 }
51 }
52}
53
54impl<P: SWCurveConfig> Debug for Affine<P> {
55 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
56 match self.is_zero() {
57 true => write!(f, "infinity"),
58 false => write!(f, "({}, {})", self.x, self.y),
59 }
60 }
61}
62
63impl<P: SWCurveConfig> Affine<P> {
64 pub fn new(x: P::BaseField, y: P::BaseField) -> Self {
67 let point = Self {
68 x,
69 y,
70 infinity: P::ZeroFlag::IS_NOT_ZERO,
71 };
72 assert!(point.is_on_curve());
73 assert!(point.is_in_correct_subgroup_assuming_on_curve());
74 point
75 }
76
77 pub const fn new_unchecked(x: P::BaseField, y: P::BaseField) -> Self {
84 Self {
85 x,
86 y,
87 infinity: P::ZeroFlag::IS_NOT_ZERO,
88 }
89 }
90
91 pub const fn identity() -> Self {
92 Self {
100 x: P::BaseField::ZERO,
101 y: P::BaseField::ZERO,
102 infinity: P::ZeroFlag::IS_ZERO,
103 }
104 }
105
106 #[allow(dead_code)]
112 pub fn get_point_from_x_unchecked(x: P::BaseField, greatest: bool) -> Option<Self> {
113 Self::get_ys_from_x_unchecked(x).map(|(smaller, larger)| {
114 if greatest {
115 Self::new_unchecked(x, larger)
116 } else {
117 Self::new_unchecked(x, smaller)
118 }
119 })
120 }
121
122 pub fn get_ys_from_x_unchecked(x: P::BaseField) -> Option<(P::BaseField, P::BaseField)> {
130 let mut x3_plus_ax_plus_b = P::add_b(x.square() * x);
134 if !P::COEFF_A.is_zero() {
135 x3_plus_ax_plus_b += P::mul_by_a(x)
136 };
137 let y = x3_plus_ax_plus_b.sqrt()?;
138 let neg_y = -y;
139 match y < neg_y {
140 true => Some((y, neg_y)),
141 false => Some((neg_y, y)),
142 }
143 }
144
145 pub fn is_on_curve(&self) -> bool {
147 if self.is_zero() {
148 true
149 } else {
150 let mut x3b = P::add_b(self.x.square() * self.x);
152 if !P::COEFF_A.is_zero() {
153 x3b += P::mul_by_a(self.x);
154 };
155 self.y.square() == x3b
156 }
157 }
158
159 pub fn to_flags(&self) -> SWFlags {
160 if self.is_zero() {
161 SWFlags::PointAtInfinity
162 } else if self.y <= -self.y {
163 SWFlags::YIsPositive
164 } else {
165 SWFlags::YIsNegative
166 }
167 }
168
169 pub fn double_to_bucket(&self) -> Bucket<P> {
170 if self.is_zero() {
171 Bucket::ZERO
172 } else {
173 let u = self.y.double();
176 let v = u.square();
178 let w = u * &v;
180 let s = self.x * &v;
182 let mut m = self.x.square();
184 m += m.double();
185 if !P::COEFF_A.is_zero() {
186 m += P::COEFF_A;
187 }
188 let x = m.square() - s.double();
190 let y = m * (s - x) - w * self.y;
192 Bucket {
193 x,
194 y,
195 zz: v,
197 zzz: w,
199 }
200 }
201 }
202}
203
204impl<P: SWCurveConfig> Affine<P> {
205 pub fn is_in_correct_subgroup_assuming_on_curve(&self) -> bool {
209 P::is_in_correct_subgroup_assuming_on_curve(self)
210 }
211}
212
213impl<P: SWCurveConfig> Zeroize for Affine<P> {
214 fn zeroize(&mut self) {
217 self.x.zeroize();
218 self.y.zeroize();
219 self.infinity.zeroize();
220 }
221}
222
223impl<P: SWCurveConfig> Distribution<Affine<P>> for Standard {
224 #[inline]
226 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Affine<P> {
227 loop {
228 let x = P::BaseField::rand(rng);
229 let greatest = rng.gen();
230
231 if let Some(p) = Affine::get_point_from_x_unchecked(x, greatest) {
232 return p.mul_by_cofactor();
233 }
234 }
235 }
236}
237
238impl<P: SWCurveConfig> AffineRepr for Affine<P> {
239 type Config = P;
240 type BaseField = P::BaseField;
241 type ScalarField = P::ScalarField;
242 type Group = Projective<P>;
243
244 const GENERATOR: Self = P::GENERATOR;
245 const ZERO: Self = Self::identity();
246
247 fn xy(&self) -> Option<(Self::BaseField, Self::BaseField)> {
248 (!self.is_zero()).then(|| (self.x, self.y))
249 }
250
251 #[inline]
252 fn generator() -> Self {
253 Self::GENERATOR
254 }
255
256 fn zero() -> Self {
257 Self::ZERO
258 }
259
260 fn is_zero(&self) -> bool {
261 P::ZeroFlag::is_zero(self)
262 }
263
264 fn from_random_bytes(bytes: &[u8]) -> Option<Self> {
265 P::BaseField::from_random_bytes_with_flags::<SWFlags>(bytes).and_then(|(x, flags)| {
266 if x.is_zero() && flags.is_infinity() {
269 Some(Self::identity())
270 } else if let Some(y_is_positive) = flags.is_positive() {
271 Self::get_point_from_x_unchecked(x, y_is_positive)
272 } else {
274 None
275 }
276 })
277 }
278
279 fn mul_bigint(&self, by: impl AsRef<[u64]>) -> Self::Group {
280 P::mul_affine(self, by.as_ref())
281 }
282
283 fn mul_by_cofactor_to_group(&self) -> Self::Group {
286 P::mul_affine(self, Self::Config::COFACTOR)
287 }
288
289 fn clear_cofactor(&self) -> Self {
293 P::clear_cofactor(self)
294 }
295}
296
297impl<P: SWCurveConfig> Neg for Affine<P> {
298 type Output = Self;
299
300 #[inline]
303 fn neg(mut self) -> Self {
304 self.y.neg_in_place();
305 self
306 }
307}
308
309impl<P: SWCurveConfig, T: Borrow<Self>> Add<T> for Affine<P> {
310 type Output = Projective<P>;
311 fn add(self, other: T) -> Projective<P> {
312 let mut copy = self.into_group();
314 copy += other.borrow();
315 copy
316 }
317}
318
319impl<P: SWCurveConfig> Add<Projective<P>> for Affine<P> {
320 type Output = Projective<P>;
321 fn add(self, other: Projective<P>) -> Projective<P> {
322 other + self
323 }
324}
325
326impl<'a, P: SWCurveConfig> Add<&'a Projective<P>> for Affine<P> {
327 type Output = Projective<P>;
328 fn add(self, other: &'a Projective<P>) -> Projective<P> {
329 *other + self
330 }
331}
332
333impl<P: SWCurveConfig, T: Borrow<Self>> Sub<T> for Affine<P> {
334 type Output = Projective<P>;
335 fn sub(self, other: T) -> Projective<P> {
336 let mut copy = self.into_group();
337 copy -= other.borrow();
338 copy
339 }
340}
341
342impl<P: SWCurveConfig> Sub<Projective<P>> for Affine<P> {
343 type Output = Projective<P>;
344 fn sub(self, other: Projective<P>) -> Projective<P> {
345 self + (-other)
346 }
347}
348
349impl<'a, P: SWCurveConfig> Sub<&'a Projective<P>> for Affine<P> {
350 type Output = Projective<P>;
351 fn sub(self, other: &'a Projective<P>) -> Projective<P> {
352 self + (-*other)
353 }
354}
355
356impl<P: SWCurveConfig> Default for Affine<P> {
357 #[inline]
358 fn default() -> Self {
359 Self::identity()
360 }
361}
362
363impl<P: SWCurveConfig, T: Borrow<P::ScalarField>> Mul<T> for Affine<P> {
364 type Output = Projective<P>;
365
366 #[inline]
367 fn mul(self, other: T) -> Self::Output {
368 self.mul_bigint(other.borrow().into_bigint())
369 }
370}
371
372impl<P: SWCurveConfig> From<Projective<P>> for Affine<P> {
375 #[inline]
376 fn from(p: Projective<P>) -> Self {
377 if p.is_zero() {
378 Self::identity()
379 } else if p.z.is_one() {
380 Self::new_unchecked(p.x, p.y)
382 } else {
383 let zinv = p.z.inverse().unwrap();
385 let zinv_squared = zinv.square();
386
387 let x = p.x * &zinv_squared;
389
390 let y = p.y * &(zinv_squared * &zinv);
392
393 Self::new_unchecked(x, y)
394 }
395 }
396}
397
398impl<P: SWCurveConfig> CanonicalSerialize for Affine<P> {
399 #[inline]
400 fn serialize_with_mode<W: Write>(
401 &self,
402 writer: W,
403 compress: ark_serialize::Compress,
404 ) -> Result<(), SerializationError> {
405 P::serialize_with_mode(self, writer, compress)
406 }
407
408 #[inline]
409 fn serialized_size(&self, compress: Compress) -> usize {
410 P::serialized_size(compress)
411 }
412}
413
414impl<P: SWCurveConfig> Valid for Affine<P> {
415 fn check(&self) -> Result<(), SerializationError> {
416 if self.is_on_curve() && self.is_in_correct_subgroup_assuming_on_curve() {
417 Ok(())
418 } else {
419 Err(SerializationError::InvalidData)
420 }
421 }
422}
423
424impl<P: SWCurveConfig> CanonicalDeserialize for Affine<P> {
425 fn deserialize_with_mode<R: Read>(
426 reader: R,
427 compress: Compress,
428 validate: Validate,
429 ) -> Result<Self, SerializationError> {
430 P::deserialize_with_mode(reader, compress, validate)
431 }
432}
433
434impl<M: SWCurveConfig, ConstraintF: Field> ToConstraintField<ConstraintF> for Affine<M>
435where
436 M::BaseField: ToConstraintField<ConstraintF>,
437{
438 #[inline]
439 fn to_field_elements(&self) -> Option<Vec<ConstraintF>> {
440 let mut x = self.x.to_field_elements()?;
441 let y = self.y.to_field_elements()?;
442 let infinity = self.is_zero().to_field_elements()?;
443 x.extend_from_slice(&y);
444 x.extend_from_slice(&infinity);
445 Some(x)
446 }
447}