openzeppelin_crypto/curve/sw/
affine.rs1use core::{
7 borrow::Borrow,
8 fmt::{Debug, Display, Formatter},
9 ops::{Add, Mul, Neg, Sub},
10};
11
12use educe::Educe;
13use num_traits::{One, Zero};
14use zeroize::Zeroize;
15
16use super::{Projective, SWCurveConfig};
17use crate::{
18 bits::BitIteratorBE,
19 curve::AffineRepr,
20 field::{group::AdditiveGroup, prime::PrimeField, Field},
21};
22
23#[derive(Educe)]
26#[educe(Copy, Clone, PartialEq, Eq, Hash)]
27#[must_use]
28pub struct Affine<P: SWCurveConfig> {
29 #[doc(hidden)]
30 pub x: P::BaseField,
31 #[doc(hidden)]
32 pub y: P::BaseField,
33 #[doc(hidden)]
34 pub infinity: bool,
35}
36
37impl<P: SWCurveConfig> PartialEq<Projective<P>> for Affine<P> {
38 fn eq(&self, other: &Projective<P>) -> bool {
39 self.into_group() == *other
40 }
41}
42
43impl<P: SWCurveConfig> Display for Affine<P> {
44 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
45 if self.infinity {
46 write!(f, "infinity")
47 } else {
48 write!(f, "({}, {})", self.x, self.y)
49 }
50 }
51}
52
53impl<P: SWCurveConfig> Debug for Affine<P> {
54 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
55 if self.infinity {
56 write!(f, "infinity")
57 } else {
58 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 {
73 let point = Self { x, y, infinity: false };
74 assert!(point.is_on_curve());
75 assert!(point.is_in_prime_order_subgroup());
76 point
77 }
78
79 pub const fn new_unchecked(x: P::BaseField, y: P::BaseField) -> Self {
86 Self { x, y, infinity: false }
87 }
88
89 pub const fn identity() -> Self {
91 Self { x: P::BaseField::ZERO, y: P::BaseField::ZERO, infinity: true }
92 }
93
94 pub fn is_on_curve(&self) -> bool {
96 if self.infinity {
97 return true;
98 }
99
100 let mut x3b = P::add_b(self.x.square() * self.x);
101 if !P::COEFF_A.is_zero() {
103 x3b += P::mul_by_a(self.x);
104 }
105 self.y.square() == x3b
106 }
107}
108
109impl<P: SWCurveConfig> Affine<P> {
110 pub fn is_in_prime_order_subgroup(&self) -> bool {
114 P::is_in_prime_order_subgroup(self)
115 }
116}
117
118impl<P: SWCurveConfig> Zeroize for Affine<P> {
119 fn zeroize(&mut self) {
120 self.x.zeroize();
121 self.y.zeroize();
122 self.infinity.zeroize();
123 }
124}
125
126impl<P: SWCurveConfig> AffineRepr for Affine<P> {
127 type BaseField = P::BaseField;
128 type Config = P;
129 type Group = Projective<P>;
130 type ScalarField = P::ScalarField;
131
132 fn xy(&self) -> Option<(Self::BaseField, Self::BaseField)> {
133 (!self.infinity).then_some((self.x, self.y))
134 }
135
136 #[inline]
137 fn generator() -> Self {
138 P::GENERATOR
139 }
140
141 fn zero() -> Self {
142 Self { x: P::BaseField::ZERO, y: P::BaseField::ZERO, infinity: true }
143 }
144
145 fn mul_bigint(&self, by: impl BitIteratorBE) -> Self::Group {
146 P::mul_affine(self, by)
147 }
148
149 fn mul_by_cofactor_to_group(&self) -> Self::Group {
152 P::mul_affine(self, Self::Config::COFACTOR)
153 }
154
155 fn clear_cofactor(&self) -> Self {
159 P::clear_cofactor(self)
160 }
161}
162
163impl<P: SWCurveConfig> Neg for Affine<P> {
164 type Output = Self;
165
166 #[inline]
169 fn neg(mut self) -> Self {
170 self.y.neg_in_place();
171 self
172 }
173}
174
175impl<P: SWCurveConfig, T: Borrow<Self>> Add<T> for Affine<P> {
176 type Output = Projective<P>;
177
178 fn add(self, other: T) -> Projective<P> {
179 let mut copy = self.into_group();
180 copy += other.borrow();
181 copy
182 }
183}
184
185impl<P: SWCurveConfig> Add<Projective<P>> for Affine<P> {
186 type Output = Projective<P>;
187
188 fn add(self, other: Projective<P>) -> Projective<P> {
189 other + self
190 }
191}
192
193impl<'a, P: SWCurveConfig> Add<&'a Projective<P>> for Affine<P> {
194 type Output = Projective<P>;
195
196 fn add(self, other: &'a Projective<P>) -> Projective<P> {
197 *other + self
198 }
199}
200
201impl<P: SWCurveConfig, T: Borrow<Self>> Sub<T> for Affine<P> {
202 type Output = Projective<P>;
203
204 fn sub(self, other: T) -> Projective<P> {
205 let mut copy = self.into_group();
206 copy -= other.borrow();
207 copy
208 }
209}
210
211impl<P: SWCurveConfig> Sub<Projective<P>> for Affine<P> {
212 type Output = Projective<P>;
213
214 fn sub(self, other: Projective<P>) -> Projective<P> {
215 self + (-other)
216 }
217}
218
219impl<'a, P: SWCurveConfig> Sub<&'a Projective<P>> for Affine<P> {
220 type Output = Projective<P>;
221
222 fn sub(self, other: &'a Projective<P>) -> Projective<P> {
223 self + (-*other)
224 }
225}
226
227impl<P: SWCurveConfig> Default for Affine<P> {
228 #[inline]
229 fn default() -> Self {
230 Self::identity()
231 }
232}
233
234impl<P: SWCurveConfig, T: Borrow<P::ScalarField>> Mul<T> for Affine<P> {
235 type Output = Projective<P>;
236
237 #[inline]
238 fn mul(self, other: T) -> Self::Output {
239 self.mul_bigint(other.borrow().into_bigint())
240 }
241}
242
243impl<P: SWCurveConfig> From<Projective<P>> for Affine<P> {
246 #[inline]
247 fn from(p: Projective<P>) -> Affine<P> {
248 if p.is_zero() {
249 Affine::identity()
250 } else if p.z.is_one() {
251 Affine::new_unchecked(p.x, p.y)
253 } else {
254 let zinv = p.z.inverse().unwrap();
256 let zinv_squared = zinv.square();
257
258 let x = p.x * zinv_squared;
260
261 let y = p.y * zinv_squared * zinv;
263
264 Affine::new_unchecked(x, y)
265 }
266 }
267}