ark_ec/models/double_odd/
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::Vec,
14};
15
16use ark_ff::{fields::Field, AdditiveGroup, One, PrimeField, ToConstraintField, UniformRand};
17
18use educe::Educe;
19use zeroize::Zeroize;
20
21use super::{DOCurveConfig, Projective};
22use crate::{AffineRepr, CurveGroup};
23
24#[derive(Educe)]
37#[educe(Copy, Clone, Hash)]
38#[must_use]
39pub struct Affine<P: DOCurveConfig> {
40 #[doc(hidden)]
41 pub e: P::BaseField,
42 #[doc(hidden)]
43 pub u: P::BaseField,
44}
45
46impl<P: DOCurveConfig> Eq for Affine<P> {}
47impl<P: DOCurveConfig> PartialEq for Affine<P> {
48 fn eq(&self, other: &Self) -> bool {
49 if self.is_zero() {
50 return other.is_zero();
51 }
52 if other.is_zero() {
53 return false;
54 }
55 (self.e == other.e && self.u == other.u) || (self.e == -other.e && self.u == -other.u)
56 }
57}
58
59impl<P: DOCurveConfig> PartialEq<Projective<P>> for Affine<P> {
60 fn eq(&self, other: &Projective<P>) -> bool {
61 self.into_group() == *other
62 }
63}
64
65impl<P: DOCurveConfig> Display for Affine<P> {
66 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
67 write!(f, "({}, {})", self.e, self.u)
68 }
69}
70
71impl<P: DOCurveConfig> Debug for Affine<P> {
72 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
73 write!(f, "({}, {})", self.e, self.u)
74 }
75}
76
77impl<P: DOCurveConfig> Affine<P> {
78 pub fn new(e: P::BaseField, u: P::BaseField) -> Self {
79 let point = Self { e, u };
80 assert!(point.is_on_curve());
81 point
82 }
83
84 pub const fn new_unchecked(e: P::BaseField, u: P::BaseField) -> Self {
85 Self { e, u }
86 }
87
88 pub const fn identity() -> Self {
93 Self {
94 e: P::BaseField::ONE,
95 u: P::BaseField::ZERO,
96 }
97 }
98
99 #[allow(dead_code)]
100 pub fn get_point_from_u_unchecked(u: P::BaseField, greatest: bool) -> Option<Self> {
101 Self::get_es_from_u_unchecked(u).map(|(smaller, larger)| {
102 if greatest {
103 Self::new_unchecked(larger, u)
104 } else {
105 Self::new_unchecked(smaller, u)
106 }
107 })
108 }
109
110 pub fn get_e_from_u(u: P::BaseField) -> Option<P::BaseField> {
111 (P::get_c() * u.square().square() - (P::COEFF_A * u.square()).double() + P::BaseField::ONE)
113 .sqrt()
114 }
115
116 pub fn get_es_from_u_unchecked(u: P::BaseField) -> Option<(P::BaseField, P::BaseField)> {
117 let e = Self::get_e_from_u(u)?;
118 let neg_e = -e;
119 match e < neg_e {
120 true => Some((e, neg_e)),
121 false => Some((neg_e, e)),
122 }
123 }
124
125 pub fn is_on_curve(&self) -> bool {
128 let e_squared = P::get_c() * self.u.square().square()
129 - (P::COEFF_A * self.u.square()).double()
130 + P::BaseField::ONE;
131 self.e.square() == e_squared
132 }
133}
134
135impl<P: DOCurveConfig> Zeroize for Affine<P> {
136 fn zeroize(&mut self) {
137 self.e.zeroize();
138 self.u.zeroize();
139 }
140}
141
142impl<P: DOCurveConfig> Distribution<Affine<P>> for Standard {
143 #[inline]
145 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Affine<P> {
146 loop {
147 let u = P::BaseField::rand(rng);
148 let greatest = rng.gen();
149
150 if let Some(p) = Affine::get_point_from_u_unchecked(u, greatest) {
151 return p;
152 }
153 }
154 }
155}
156
157impl<P: DOCurveConfig> AffineRepr for Affine<P> {
158 type Config = P;
159 type BaseField = P::BaseField;
160 type ScalarField = P::ScalarField;
161 type Group = Projective<P>;
162
163 const GENERATOR: Self = P::GENERATOR;
164 const ZERO: Self = Self::identity();
165
166 fn xy(&self) -> Option<(Self::BaseField, Self::BaseField)> {
167 Some((self.e, self.u))
168 }
169
170 #[inline]
171 fn generator() -> Self {
172 Self::GENERATOR
173 }
174
175 fn zero() -> Self {
176 Self::ZERO
177 }
178
179 #[inline]
183 fn is_zero(&self) -> bool {
184 self.u == P::BaseField::ZERO
185 }
186
187 fn from_random_bytes(bytes: &[u8]) -> Option<Self> {
188 P::BaseField::from_random_bytes(bytes)
189 .and_then(|u| Self::get_point_from_u_unchecked(u, true))
190 }
191
192 fn mul_bigint(&self, by: impl AsRef<[u64]>) -> Self::Group {
193 P::mul_affine(self, by.as_ref())
194 }
195
196 fn mul_by_cofactor_to_group(&self) -> Self::Group {
199 P::mul_affine(self, Self::Config::COFACTOR)
200 }
201
202 fn clear_cofactor(&self) -> Self {
206 P::mul_affine(self, Self::Config::COFACTOR).into_affine()
207 }
208}
209
210impl<P: DOCurveConfig> Neg for Affine<P> {
211 type Output = Self;
212
213 #[inline]
214 fn neg(mut self) -> Self {
215 self.u.neg_in_place();
216 self
217 }
218}
219
220impl<P: DOCurveConfig, T: Borrow<Self>> Add<T> for Affine<P> {
221 type Output = Projective<P>;
222 fn add(self, other: T) -> Projective<P> {
226 let mut copy = self.into_group();
227 let other = other.borrow();
228 let othert = other.u.square();
229 let n1 = copy.e * other.e;
230 let n3 = copy.u * other.u;
231 let n4 = copy.t * othert;
232
233 let n5 = othert + copy.t;
234 let n6 = (copy.e + copy.u) * (other.e + other.u) - n1 - n3;
235 let cn4 = P::get_c() * n4;
236 let n7 = P::BaseField::ONE - cn4;
237
238 let n3d = n3.double();
239
240 copy.e = (P::BaseField::ONE + cn4) * (n1 - P::COEFF_A * n3d) + P::get_c() * n3d * n5;
241 copy.z = n7.square();
242 copy.t = n6.square();
243 copy.u = n7 * n6;
244
245 copy
246 }
247}
248
249impl<P: DOCurveConfig> Add<Projective<P>> for Affine<P> {
250 type Output = Projective<P>;
251 fn add(self, other: Projective<P>) -> Projective<P> {
252 other + self
253 }
254}
255
256impl<'a, P: DOCurveConfig> Add<&'a Projective<P>> for Affine<P> {
257 type Output = Projective<P>;
258 fn add(self, other: &'a Projective<P>) -> Projective<P> {
259 *other + self
260 }
261}
262
263impl<P: DOCurveConfig, T: Borrow<Self>> Sub<T> for Affine<P> {
264 type Output = Projective<P>;
265 fn sub(self, other: T) -> Projective<P> {
266 let mut copy = self.into_group();
267 copy -= other.borrow();
268 copy
269 }
270}
271
272impl<P: DOCurveConfig> Sub<Projective<P>> for Affine<P> {
273 type Output = Projective<P>;
274 fn sub(self, other: Projective<P>) -> Projective<P> {
275 self + (-other)
276 }
277}
278
279impl<'a, P: DOCurveConfig> Sub<&'a Projective<P>> for Affine<P> {
280 type Output = Projective<P>;
281 fn sub(self, other: &'a Projective<P>) -> Projective<P> {
282 self + (-*other)
283 }
284}
285
286impl<P: DOCurveConfig> Default for Affine<P> {
287 #[inline]
288 fn default() -> Self {
289 Self::identity()
290 }
291}
292
293impl<P: DOCurveConfig, T: Borrow<P::ScalarField>> Mul<T> for Affine<P> {
294 type Output = Projective<P>;
295
296 #[inline]
297 fn mul(self, other: T) -> Self::Output {
298 self.mul_bigint(other.borrow().into_bigint())
299 }
300}
301
302impl<P: DOCurveConfig> From<Projective<P>> for Affine<P> {
305 #[inline]
306 fn from(p: Projective<P>) -> Self {
307 use ark_std::Zero;
308
309 if p.is_zero() {
310 Self::identity()
311 } else if p.z.is_one() {
312 Self::new_unchecked(p.e, p.u)
313 } else {
314 let z_i = p.z.inverse().unwrap();
315
316 let u = p.u * &z_i;
317 let e = p.e * &z_i;
318
319 Self::new_unchecked(e, u)
320 }
321 }
322}
323
324impl<P: DOCurveConfig> CanonicalSerialize for Affine<P> {
325 #[inline]
326 fn serialize_with_mode<W: Write>(
327 &self,
328 writer: W,
329 compress: ark_serialize::Compress,
330 ) -> Result<(), SerializationError> {
331 P::serialize_with_mode(self, writer, compress)
332 }
333
334 #[inline]
335 fn serialized_size(&self, compress: Compress) -> usize {
336 P::serialized_size(compress)
337 }
338}
339
340impl<P: DOCurveConfig> Valid for Affine<P> {
341 fn check(&self) -> Result<(), SerializationError> {
342 if self.is_on_curve() {
343 Ok(())
344 } else {
345 Err(SerializationError::InvalidData)
346 }
347 }
348}
349
350impl<P: DOCurveConfig> CanonicalDeserialize for Affine<P> {
351 fn deserialize_with_mode<R: Read>(
352 reader: R,
353 compress: Compress,
354 validate: Validate,
355 ) -> Result<Self, SerializationError> {
356 P::deserialize_with_mode(reader, compress, validate)
357 }
358}
359
360impl<M: DOCurveConfig, ConstraintF: Field> ToConstraintField<ConstraintF> for Affine<M>
361where
362 M::BaseField: ToConstraintField<ConstraintF>,
363{
364 #[inline]
365 fn to_field_elements(&self) -> Option<Vec<ConstraintF>> {
366 let mut e = self.e.to_field_elements()?;
367 let u = self.u.to_field_elements()?;
368 e.extend_from_slice(&u);
369 Some(e)
370 }
371}