1#[macro_export]
2macro_rules! endo {
3 ($name:ident, $field:ident, $params:expr) => {
4 impl CurveEndo for $name {
5 fn decompose_scalar(k: &$field) -> (u128, bool, u128, bool) {
6 let to_limbs = |e: &$field| {
7 let repr = e.to_repr();
8 let repr = repr.as_ref();
9 let tmp0 = u64::from_le_bytes(repr[0..8].try_into().unwrap());
10 let tmp1 = u64::from_le_bytes(repr[8..16].try_into().unwrap());
11 let tmp2 = u64::from_le_bytes(repr[16..24].try_into().unwrap());
12 let tmp3 = u64::from_le_bytes(repr[24..32].try_into().unwrap());
13 [tmp0, tmp1, tmp2, tmp3]
14 };
15
16 let get_lower_128 = |e: &$field| {
17 let e = to_limbs(e);
18 u128::from(e[0]) | (u128::from(e[1]) << 64)
19 };
20
21 let is_neg = |e: &$field| {
22 let e = to_limbs(e);
23 let (_, borrow) = sbb(0xffffffffffffffff, e[0], 0);
24 let (_, borrow) = sbb(0xffffffffffffffff, e[1], borrow);
25 let (_, borrow) = sbb(0xffffffffffffffff, e[2], borrow);
26 let (_, borrow) = sbb(0x00, e[3], borrow);
27 borrow & 1 != 0
28 };
29
30 let input = to_limbs(&k);
31 let c1 = mul_512($params.gamma2, input);
32 let c2 = mul_512($params.gamma1, input);
33 let c1 = [c1[4], c1[5], c1[6], c1[7]];
34 let c2 = [c2[4], c2[5], c2[6], c2[7]];
35 let q1 = mul_512(c1, $params.b1);
36 let q2 = mul_512(c2, $params.b2);
37 let q1 = $field::from_raw([q1[0], q1[1], q1[2], q1[3]]);
38 let q2 = $field::from_raw([q2[0], q2[1], q2[2], q2[3]]);
39 let k2 = q2 - q1;
40 let k1 = k + k2 * $field::ZETA;
41 let k1_neg = is_neg(&k1);
42 let k2_neg = is_neg(&k2);
43 let k1 = if k1_neg { -k1 } else { k1 };
44 let k2 = if k2_neg { -k2 } else { k2 };
45
46 (get_lower_128(&k1), k1_neg, get_lower_128(&k2), k2_neg)
47 }
48 }
49 };
50}
51
52#[macro_export]
53macro_rules! new_curve_impl {
54 (($($privacy:tt)*),
55 $name:ident,
56 $name_affine:ident,
57 $base:ident,
58 $scalar:ident,
59 $generator:expr,
60 $constant_a:expr,
61 $constant_b:expr,
62 $curve_id:literal,
63 $hash_to_curve:expr,
64 $flag_config:expr,
65 standard_sign
66 ) => {
67
68 paste::paste! {
69 impl $crate::serde::Compressed<$name_affine> for [<$name:upper Compressed >] {
70 const CONFIG: $crate::serde::CompressedFlagConfig = $flag_config;
71 fn sign(c: &$name_affine) -> subtle::Choice {
72 Choice::from(c.y.to_repr()[0] as u8 & 1) & !c.is_identity()
73 }
74 fn resolve(x: $base, sign_set: Choice) -> CtOption<$name_affine> {
75 $name_affine::y2(x).sqrt().map(|y| {
76 let y = $base::conditional_select(&y, &-y, sign_set ^ Choice::from(y.to_repr()[0] as u8 & 1));
77 $name_affine { x, y }
78 })
79 }
80 }
81 }
82
83
84 new_curve_impl!(($($privacy)*), $name, $name_affine, $base, $scalar, $generator, $constant_a, $constant_b, $curve_id, $hash_to_curve, $flag_config);
85 };
86
87 (($($privacy:tt)*),
88 $name:ident,
89 $name_affine:ident,
90 $base:ident,
91 $scalar:ident,
92 $generator:expr,
93 $constant_a:expr,
94 $constant_b:expr,
95 $curve_id:literal,
96 $hash_to_curve:expr,
97 $flag_config:expr
98 ) => {
99
100
101 paste::paste! {
102 const [< $name:upper _COMPRESSED_SIZE >]: usize = $base::SIZE + if $flag_config.has_extra_byte() { 1 } else { 0 };
103
104 pub type [<$name:upper Compressed >] = $crate::serde::Repr<[< $name:upper _COMPRESSED_SIZE >]>;
105 pub type [<$name Uncompressed >] = $crate::serde::Repr<{ 2*$base::SIZE }>;
106
107 impl GroupEncoding for $name_affine {
108 type Repr = [<$name:upper Compressed >];
109
110 fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
111 <Self::Repr as $crate::serde::Compressed<$name_affine>>::decode(bytes.clone())
112 }
113
114 fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
115 <Self::Repr as $crate::serde::Compressed<$name_affine>>::decode(bytes.clone())
116 }
117
118 fn to_bytes(&self) -> Self::Repr {
119 <Self::Repr as $crate::serde::Compressed<$name_affine>>::encode(&self)
120 }
121 }
122
123 impl GroupEncoding for $name {
124 type Repr = [<$name:upper Compressed >];
125
126 fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
127 <Self::Repr as $crate::serde::Compressed<$name_affine>>::decode(bytes.clone()).map(Self::from)
128 }
129
130 fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
131 <Self::Repr as $crate::serde::Compressed<$name_affine>>::decode(bytes.clone()).map(Self::from)
132 }
133
134 fn to_bytes(&self) -> Self::Repr {
135 <Self::Repr as $crate::serde::Compressed<$name_affine>>::encode(&self.to_affine())
136 }
137 }
138
139 impl group::UncompressedEncoding for $name_affine {
140 type Uncompressed = [<$name Uncompressed >];
141
142 fn from_uncompressed(bytes: &Self::Uncompressed) -> CtOption<Self> {
143 Self::from_uncompressed_unchecked(bytes).and_then(|p| CtOption::new(p, p.is_on_curve()))
144 }
145
146 fn from_uncompressed_unchecked(bytes: &Self::Uncompressed) -> CtOption<Self> {
147 let mut repr = [0u8; $base::SIZE];
148
149 let x = {
150 repr.copy_from_slice(&bytes[0..$base::SIZE]);
151 $base::from_bytes(&repr)
152 };
153
154 let y = {
155 repr.copy_from_slice(&bytes[$base::SIZE..2*$base::SIZE]);
156 $base::from_bytes(&repr)
157 };
158
159 x.and_then(|x| {
160 y.and_then(|y| {
161 let is_identity = x.is_zero() & y.is_zero();
162 let unchecked = Self { x, y };
163 subtle::CtOption::new($name_affine::identity(), is_identity)
164 .or_else(|| subtle::CtOption::new(unchecked, Choice::from(1u8)))
165 })
166 })
167 }
168
169 fn to_uncompressed(&self) -> Self::Uncompressed {
170 let mut res = Self::Uncompressed::default();
171
172 res[0..$base::SIZE].copy_from_slice(
173 &$base::conditional_select(&self.x, &$base::zero(), self.is_identity()).to_bytes()[..],
174 );
175
176 res[$base::SIZE.. 2*$base::SIZE].copy_from_slice(
177 &$base::conditional_select(&self.y, &$base::zero(), self.is_identity()).to_bytes()[..],
178 );
179
180 res
181 }
182 }
183 }
184
185 #[cfg(feature = "derive_serde")]
188 macro_rules! serialize_deserialize_to_from_bytes {
189 () => {
190 impl ::serde::Serialize for $name {
191 fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
192 let bytes = &self.to_bytes();
193 if serializer.is_human_readable() {
194 ::hex::serde::serialize(&bytes, serializer)
195 } else {
196 ::serde_arrays::serialize(bytes.inner(), serializer)
197 }
198 }
199 }
200
201 paste::paste! {
202 impl<'de> ::serde::Deserialize<'de> for $name {
203 fn deserialize<D: ::serde::Deserializer<'de>>(
204 deserializer: D,
205 ) -> Result<Self, D::Error> {
206 use ::serde::de::Error as _;
207 let bytes = if deserializer.is_human_readable() {
208 ::hex::serde::deserialize(deserializer)?
209 } else {
210 ::serde_arrays::deserialize::<_, u8, [< $name:upper _COMPRESSED_SIZE >]>(deserializer)?
211 };
212 Option::from(Self::from_bytes(&bytes.into())).ok_or_else(|| {
213 D::Error::custom("deserialized bytes don't encode a valid field element")
214 })
215 }
216 }
217 }
218
219 impl ::serde::Serialize for $name_affine {
220 fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
221 let bytes = &self.to_bytes();
222 if serializer.is_human_readable() {
223 ::hex::serde::serialize(&bytes, serializer)
224 } else {
225 ::serde_arrays::serialize(bytes.inner(), serializer)
226 }
227 }
228 }
229
230 paste::paste! {
231 impl<'de> ::serde::Deserialize<'de> for $name_affine {
232 fn deserialize<D: ::serde::Deserializer<'de>>(
233 deserializer: D,
234 ) -> Result<Self, D::Error> {
235 use ::serde::de::Error as _;
236 let bytes = if deserializer.is_human_readable() {
237 ::hex::serde::deserialize(deserializer)?
238 } else {
239 ::serde_arrays::deserialize::<_, u8, [< $name:upper _COMPRESSED_SIZE >]>(deserializer)?
240 };
241 Option::from(Self::from_bytes(&bytes.into())).ok_or_else(|| {
242 D::Error::custom("deserialized bytes don't encode a valid field element")
243 })
244 }
245 }
246 }
247 };
248 }
249
250 #[derive(Copy, Clone, Debug)]
251 $($privacy)* struct $name {
252 pub x: $base,
253 pub y: $base,
254 pub z: $base,
255 }
256
257 #[derive(Copy, Clone, PartialEq)]
258 $($privacy)* struct $name_affine {
259 pub x: $base,
260 pub y: $base,
261 }
262
263 #[cfg(feature = "derive_serde")]
264 serialize_deserialize_to_from_bytes!();
265
266
267
268 impl $name {
269 pub fn generator() -> Self {
270 let generator = $name_affine::generator();
271 Self {
272 x: generator.x,
273 y: generator.y,
274 z: $base::one(),
275 }
276 }
277
278 #[inline]
279 fn curve_constant_3b() -> $base {
280 lazy_static::lazy_static! {
281 static ref CONST_3B: $base = $constant_b + $constant_b + $constant_b;
282 }
283 *CONST_3B
284 }
285
286 fn mul_by_3b(input: &$base) -> $base {
287 if $name::CURVE_ID == "bn256_g1"{
288 input.double().double().double() + input
289 } else {
290 input * $name::curve_constant_3b()
291 }
292 }
293 }
294
295 impl $name_affine {
296 pub fn generator() -> Self {
297 Self {
298 x: $generator.0,
299 y: $generator.1,
300 }
301 }
302
303 #[inline(always)]
304 fn y2(x: $base) -> $base {
305 if $constant_a == $base::ZERO {
306 let x3 = x.square() * x;
307 (x3 + $constant_b)
308 } else {
309 let x2 = x.square();
310 ((x2 + $constant_a) * x + $constant_b)
311 }
312 }
313
314 pub fn random(mut rng: impl RngCore) -> Self {
315 loop {
316 let x = $base::random(&mut rng);
317 let ysign = (rng.next_u32() % 2) as u8;
318
319 let y2 = $name_affine::y2(x);
320 if let Some(y) = Option::<$base>::from(y2.sqrt()) {
321 let sign = y.to_repr()[0] & 1;
322 let y = if ysign ^ sign == 0 { y } else { -y };
323
324 let p = $name_affine {
325 x,
326 y,
327 };
328
329
330 use $crate::group::cofactor::CofactorGroup;
331 let p = p.to_curve();
332 return p.clear_cofactor().to_affine()
333 }
334 }
335 }
336 }
337
338
339
340 impl<'a> From<&'a $name_affine> for $name {
343 fn from(p: &'a $name_affine) -> $name {
344 p.to_curve()
345 }
346 }
347
348 impl From<$name_affine> for $name {
349 fn from(p: $name_affine) -> $name {
350 p.to_curve()
351 }
352 }
353
354 impl Default for $name {
355 fn default() -> $name {
356 $name::identity()
357 }
358 }
359
360 impl subtle::ConstantTimeEq for $name {
361 fn ct_eq(&self, other: &Self) -> Choice {
362 let x1 = self.x * other.z;
367 let y1 = self.y * other.z;
368
369 let x2 = other.x * self.z;
370 let y2 = other.y * self.z;
371
372 let self_is_zero = self.is_identity();
373 let other_is_zero = other.is_identity();
374
375 (self_is_zero & other_is_zero) | ((!self_is_zero) & (!other_is_zero) & x1.ct_eq(&x2) & y1.ct_eq(&y2))
377 }
379
380 }
381
382 impl subtle::ConditionallySelectable for $name {
383 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
384 $name {
385 x: $base::conditional_select(&a.x, &b.x, choice),
386 y: $base::conditional_select(&a.y, &b.y, choice),
387 z: $base::conditional_select(&a.z, &b.z, choice),
388 }
389 }
390 }
391
392 impl PartialEq for $name {
393 fn eq(&self, other: &Self) -> bool {
394 self.ct_eq(other).into()
395 }
396 }
397
398 impl cmp::Eq for $name {}
399
400 impl CurveExt for $name {
401
402 type ScalarExt = $scalar;
403 type Base = $base;
404 type AffineExt = $name_affine;
405
406 const CURVE_ID: &'static str = $curve_id;
407
408 fn endo(&self) -> Self {
409 Self {
410 x: self.x * Self::Base::ZETA,
411 y: self.y,
412 z: self.z,
413 }
414 }
415
416 fn jacobian_coordinates(&self) -> ($base, $base, $base) {
417 let x = self.x * self.z;
419 let y = self.y * self.z.square();
420 (x, y, self.z)
421 }
422
423
424 #[allow(clippy::redundant_closure_call)]
425 fn hash_to_curve<'a>(domain_prefix: &'a str) -> Box<dyn Fn(&[u8]) -> Self + 'a> {
426 $hash_to_curve(domain_prefix)
427 }
428
429 fn is_on_curve(&self) -> Choice {
430 if $constant_a == $base::ZERO {
431 (self.z * self.y.square() - self.x.square() * self.x)
435 .ct_eq(&(self.z.square() * self.z * $constant_b))
436 | self.z.is_zero()
437 } else {
438 let z2 = self.z.square();
442 (self.z * self.y.square() - (self.x.square() + $constant_a * z2) * self.x)
443 .ct_eq(&(z2 * self.z * $constant_b))
444 | self.z.is_zero()
445 }
446 }
447
448 fn b() -> Self::Base {
449 $constant_b
450 }
451
452 fn a() -> Self::Base {
453 $constant_a
454 }
455
456 fn new_jacobian(x: Self::Base, y: Self::Base, z: Self::Base) -> CtOption<Self> {
457 let z_inv = z.invert().unwrap_or($base::zero());
459 let p_x = x * z_inv;
460 let p_y = y * z_inv.square();
461 let p = $name {
462 x:p_x,
463 y:$base::conditional_select(&p_y, &$base::one(), z.is_zero()),
464 z
465 };
466 CtOption::new(p, p.is_on_curve())
467 }
468 }
469
470 impl group::Curve for $name {
471
472 type AffineRepr = $name_affine;
473
474 fn batch_normalize(p: &[Self], q: &mut [Self::AffineRepr]) {
475 assert_eq!(p.len(), q.len());
476
477 let mut acc = $base::one();
478 for (p, q) in p.iter().zip(q.iter_mut()) {
479 q.x = acc;
482
483 acc = $base::conditional_select(&(acc * p.z), &acc, p.is_identity());
485 }
486
487 acc = acc.invert().unwrap();
490
491 for (p, q) in p.iter().rev().zip(q.iter_mut().rev()) {
492 let skip = p.is_identity();
493
494 let tmp = q.x * acc;
496
497 acc = $base::conditional_select(&(acc * p.z), &acc, skip);
499
500 q.x = p.x * tmp;
501 q.y = p.y * tmp;
502
503 *q = $name_affine::conditional_select(&q, &$name_affine::identity(), skip);
504 }
505 }
506
507 fn to_affine(&self) -> Self::AffineRepr {
508 let zinv = self.z.invert().unwrap_or($base::zero());
509 let x = self.x * zinv;
510 let y = self.y * zinv;
511 let tmp = $name_affine {
512 x,
513 y,
514 };
515 $name_affine::conditional_select(&tmp, &$name_affine::identity(), zinv.is_zero())
516 }
517 }
518
519 impl group::Group for $name {
520 type Scalar = $scalar;
521
522 fn random(mut rng: impl RngCore) -> Self {
523 $name_affine::random(&mut rng).to_curve()
524 }
525
526 fn double(&self) -> Self {
527 if $constant_a == $base::ZERO {
528 let t0 = self.y.square();
530 let z3 = t0 + t0;
531 let z3 = z3 + z3;
532 let z3 = z3 + z3;
533 let t1 = self.y * self.z;
534 let t2 = self.z.square();
535 let t2 = $name::mul_by_3b(&t2);
536 let x3 = t2 * z3;
537 let y3 = t0 + t2;
538 let z3 = t1 * z3;
539 let t1 = t2 + t2;
540 let t2 = t1 + t2;
541 let t0 = t0 - t2;
542 let y3 = t0 * y3;
543 let y3 = x3 + y3;
544 let t1 = self.x * self.y;
545 let x3 = t0 * t1;
546 let x3 = x3 + x3;
547
548 let tmp = $name {
549 x: x3,
550 y: y3,
551 z: z3,
552 };
553
554 $name::conditional_select(&tmp, &$name::identity(), self.is_identity())
555 } else {
556 let t0 = self.x.square();
558 let t1 = self.y.square();
559 let t2 = self.z.square();
560 let t3 = self.x * self.y;
561 let t3 = t3 + t3;
562 let z3 = self.x * self.z;
563 let z3 = z3 + z3;
564 let x3 = $constant_a * z3;
565 let y3 = $name::mul_by_3b(&t2);
566 let y3 = x3 + y3;
567 let x3 = t1 - y3;
568 let y3 = t1 + y3;
569 let y3 = x3 * y3;
570 let x3 = t3 * x3;
571 let z3 = $name::mul_by_3b(&z3);
572 let t2 = $constant_a * t2;
573 let t3 = t0 - t2;
574 let t3 = $constant_a * t3;
575 let t3 = t3 + z3;
576 let z3 = t0 + t0;
577 let t0 = z3 + t0;
578 let t0 = t0 + t2;
579 let t0 = t0 * t3;
580 let y3 = y3 + t0;
581 let t2 = self.y * self.z;
582 let t2 = t2 + t2;
583 let t0 = t2 * t3;
584 let x3 = x3 - t0;
585 let z3 = t2 * t1;
586 let z3 = z3 + z3;
587 let z3 = z3 + z3;
588
589 let tmp = $name {
590 x: x3,
591 y: y3,
592 z: z3,
593 };
594
595 $name::conditional_select(&tmp, &$name::identity(), self.is_identity())
596 }
597 }
598
599 fn generator() -> Self {
600 $name::generator()
601 }
602
603 fn identity() -> Self {
604 Self {
605 x: $base::zero(),
606 y: $base::one(),
607 z: $base::zero(),
608 }
609 }
610
611 fn is_identity(&self) -> Choice {
612 self.z.is_zero()
613 }
614 }
615
616 impl $crate::serde::SerdeObject for $name {
617 fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self {
618 debug_assert_eq!(bytes.len(), 3 * $base::SIZE);
619 let [x, y, z] = [0, 1, 2]
620 .map(|i| $base::from_raw_bytes_unchecked(&bytes[i * $base::SIZE..(i + 1) * $base::SIZE]));
621 Self { x, y, z }
622 }
623 fn from_raw_bytes(bytes: &[u8]) -> Option<Self> {
624 if bytes.len() != 3 * $base::SIZE {
625 return None;
626 }
627 let [x, y, z] =
628 [0, 1, 2].map(|i| $base::from_raw_bytes(&bytes[i * $base::SIZE..(i + 1) * $base::SIZE]));
629 x.zip(y).zip(z).and_then(|((x, y), z)| {
630 let res = Self { x, y, z };
631 bool::from(res.is_on_curve()).then(|| res)
633 })
634 }
635 fn to_raw_bytes(&self) -> Vec<u8> {
636 let mut res = Vec::with_capacity(3 * $base::SIZE);
637 Self::write_raw(self, &mut res).unwrap();
638 res
639 }
640 fn read_raw_unchecked<R: std::io::Read>(reader: &mut R) -> Self {
641 let [x, y, z] = [(); 3].map(|_| $base::read_raw_unchecked(reader));
642 Self { x, y, z }
643 }
644 fn read_raw<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
645 let x = $base::read_raw(reader)?;
646 let y = $base::read_raw(reader)?;
647 let z = $base::read_raw(reader)?;
648 Ok(Self { x, y, z })
649 }
650 fn write_raw<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
651 self.x.write_raw(writer)?;
652 self.y.write_raw(writer)?;
653 self.z.write_raw(writer)
654 }
655 }
656
657 impl group::prime::PrimeGroup for $name {}
658
659 impl group::prime::PrimeCurve for $name {
660 type Affine = $name_affine;
661 }
662
663 impl group::cofactor::CofactorCurve for $name {
664 type Affine = $name_affine;
665 }
666
667 impl std::fmt::Debug for $name_affine {
670 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
671 if self.is_identity().into() {
672 write!(f, "Infinity")
673 } else {
674 write!(f, "({:?}, {:?})", self.x, self.y)
675 }
676 }
677 }
678
679 impl<'a> From<&'a $name> for $name_affine {
680 fn from(p: &'a $name) -> $name_affine {
681 p.to_affine()
682 }
683 }
684
685 impl From<$name> for $name_affine {
686 fn from(p: $name) -> $name_affine {
687 p.to_affine()
688 }
689 }
690
691 impl Default for $name_affine {
692 fn default() -> $name_affine {
693 $name_affine::identity()
694 }
695 }
696
697 impl subtle::ConstantTimeEq for $name_affine {
698 fn ct_eq(&self, other: &Self) -> Choice {
699 let z1 = self.is_identity();
700 let z2 = other.is_identity();
701
702 (z1 & z2) | ((!z1) & (!z2) & (self.x.ct_eq(&other.x)) & (self.y.ct_eq(&other.y)))
703 }
704 }
705
706 impl subtle::ConditionallySelectable for $name_affine {
707 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
708 $name_affine {
709 x: $base::conditional_select(&a.x, &b.x, choice),
710 y: $base::conditional_select(&a.y, &b.y, choice),
711 }
712 }
713 }
714
715 impl cmp::Eq for $name_affine {}
716
717
718 impl $crate::serde::SerdeObject for $name_affine {
719 fn from_raw_bytes_unchecked(bytes: &[u8]) -> Self {
720 debug_assert_eq!(bytes.len(), 2 * $base::SIZE);
721 let [x, y] =
722 [0, $base::SIZE].map(|i| $base::from_raw_bytes_unchecked(&bytes[i..i + $base::SIZE]));
723 Self { x, y }
724 }
725 fn from_raw_bytes(bytes: &[u8]) -> Option<Self> {
726 if bytes.len() != 2 * $base::SIZE {
727 return None;
728 }
729 let [x, y] = [0, $base::SIZE].map(|i| $base::from_raw_bytes(&bytes[i..i + $base::SIZE]));
730 x.zip(y).and_then(|(x, y)| {
731 let res = Self { x, y };
732 bool::from(res.is_on_curve()).then(|| res)
734 })
735 }
736 fn to_raw_bytes(&self) -> Vec<u8> {
737 let mut res = Vec::with_capacity(2 * $base::SIZE);
738 Self::write_raw(self, &mut res).unwrap();
739 res
740 }
741 fn read_raw_unchecked<R: std::io::Read>(reader: &mut R) -> Self {
742 let [x, y] = [(); 2].map(|_| $base::read_raw_unchecked(reader));
743 Self { x, y }
744 }
745 fn read_raw<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
746 let x = $base::read_raw(reader)?;
747 let y = $base::read_raw(reader)?;
748 Ok(Self { x, y })
749 }
750 fn write_raw<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
751 self.x.write_raw(writer)?;
752 self.y.write_raw(writer)
753 }
754 }
755
756 impl group::prime::PrimeCurveAffine for $name_affine {
757 type Curve = $name;
758 type Scalar = $scalar;
759
760
761 fn generator() -> Self {
762 $name_affine::generator()
763 }
764
765 fn identity() -> Self {
766 Self {
767 x: $base::zero(),
768 y: $base::zero(),
769 }
770 }
771
772 fn is_identity(&self) -> Choice {
773 self.x.is_zero() & self.y.is_zero()
774 }
775
776 fn to_curve(&self) -> Self::Curve {
777 let tmp = $name {
778 x: self.x,
779 y: self.y,
780 z: $base::one(),
781 };
782 $name::conditional_select(&tmp, &$name::identity(), self.is_identity())
783 }
784 }
785
786 impl group::cofactor::CofactorCurveAffine for $name_affine {
787 type Curve = $name;
788 type Scalar = $scalar;
789
790 fn identity() -> Self {
791 <Self as group::prime::PrimeCurveAffine>::identity()
792 }
793
794 fn generator() -> Self {
795 <Self as group::prime::PrimeCurveAffine>::generator()
796 }
797
798 fn is_identity(&self) -> Choice {
799 <Self as group::prime::PrimeCurveAffine>::is_identity(self)
800 }
801
802 fn to_curve(&self) -> Self::Curve {
803 <Self as group::prime::PrimeCurveAffine>::to_curve(self)
804 }
805 }
806
807
808 impl CurveAffine for $name_affine {
809 type ScalarExt = $scalar;
810 type Base = $base;
811 type CurveExt = $name;
812
813 fn is_on_curve(&self) -> Choice {
814 if $constant_a == $base::ZERO {
815 (self.y.square() - self.x.square() * self.x).ct_eq(&$constant_b)
817 | self.is_identity()
818 } else {
819 (self.y.square() - (self.x.square() + $constant_a) * self.x).ct_eq(&$constant_b)
821 | self.is_identity()
822 }
823 }
824
825 fn coordinates(&self) -> CtOption<Coordinates<Self>> {
826 Coordinates::from_xy( self.x, self.y )
827 }
828
829 fn from_xy(x: Self::Base, y: Self::Base) -> CtOption<Self> {
830 let p = $name_affine {
831 x, y
832 };
833 CtOption::new(p, p.is_on_curve())
834 }
835
836 fn a() -> Self::Base {
837 $constant_a
838 }
839
840 fn b() -> Self::Base {
841 $constant_b
842 }
843 }
844
845
846 impl_binops_additive!($name, $name);
847 impl_binops_additive!($name, $name_affine);
848 impl_binops_additive_specify_output!($name_affine, $name_affine, $name);
849 impl_binops_additive_specify_output!($name_affine, $name, $name);
850 impl_binops_multiplicative!($name, $scalar);
851 impl_binops_multiplicative_mixed!($name_affine, $scalar, $name);
852
853 impl<'a> Neg for &'a $name {
854 type Output = $name;
855
856 fn neg(self) -> $name {
857 $name {
858 x: self.x,
859 y: -self.y,
860 z: self.z,
861 }
862 }
863 }
864
865 impl Neg for $name {
866 type Output = $name;
867
868 fn neg(self) -> $name {
869 -&self
870 }
871 }
872
873 impl<T> Sum<T> for $name
874 where
875 T: core::borrow::Borrow<$name>,
876 {
877 fn sum<I>(iter: I) -> Self
878 where
879 I: Iterator<Item = T>,
880 {
881 iter.fold(Self::identity(), |acc, item| acc + item.borrow())
882 }
883 }
884
885 impl<'a, 'b> Add<&'a $name> for &'b $name {
886 type Output = $name;
887
888 fn add(self, rhs: &'a $name) -> $name {
889 if $constant_a == $base::ZERO {
890 let t0 = self.x * rhs.x;
892 let t1 = self.y * rhs.y;
893 let t2 = self.z * rhs.z;
894 let t3 = self.x + self.y;
895 let t4 = rhs.x + rhs.y;
896 let t3 = t3 * t4;
897 let t4 = t0 + t1;
898 let t3 = t3 - t4;
899 let t4 = self.y + self.z;
900 let x3 = rhs.y + rhs.z;
901 let t4 = t4 * x3;
902 let x3 = t1 + t2;
903 let t4 = t4 - x3;
904 let x3 = self.x + self.z;
905 let y3 = rhs.x + rhs.z;
906 let x3 = x3 * y3;
907 let y3 = t0 + t2;
908 let y3 = x3 - y3;
909 let x3 = t0 + t0;
910 let t0 = x3 + t0;
911 let t2 = $name::mul_by_3b(&t2);
912 let z3 = t1 + t2;
913 let t1 = t1 - t2;
914 let y3 = $name::mul_by_3b(&y3);
915 let x3 = t4 * y3;
916 let t2 = t3 * t1;
917 let x3 = t2 - x3;
918 let y3 = y3 * t0;
919 let t1 = t1 * z3;
920 let y3 = t1 + y3;
921 let t0 = t0 * t3;
922 let z3 = z3 * t4;
923 let z3 = z3 + t0;
924
925 $name {
926 x: x3,
927 y: y3,
928 z: z3,
929 }
930 } else {
931 let t0 = self.x * rhs.x;
933 let t1 = self.y * rhs.y;
934 let t2 = self.z * rhs.z;
935 let t3 = self.x + self.y;
936 let t4 = rhs.x + rhs.y;
937 let t3 = t3 * t4;
938 let t4 = t0 + t1;
939 let t3 = t3 - t4;
940 let t4 = self.x + self.z;
941 let t5 = rhs.x + rhs.z;
942 let t4 = t4 * t5;
943 let t5 = t0 + t2;
944 let t4 = t4 - t5;
945 let t5 = self.y + self.z;
946 let x3 = rhs.y + rhs.z;
947 let t5 = t5 * x3;
948 let x3 = t1 + t2;
949 let t5 = t5 - x3;
950 let z3 = $constant_a * t4;
951 let x3 = $name::mul_by_3b(&t2);
952 let z3 = x3 + z3;
953 let x3 = t1 - z3;
954 let z3 = t1 + z3;
955 let y3 = x3 * z3;
956 let t1 = t0 + t0;
957 let t1 = t1 + t0;
958 let t2 = $constant_a * t2;
959 let t4 = $name::mul_by_3b(&t4);
960 let t1 = t1 + t2;
961 let t2 = t0 - t2;
962 let t2 = $constant_a * t2;
963 let t4 = t4 + t2;
964 let t0 = t1 * t4;
965 let y3 = y3 + t0;
966 let t0 = t5 * t4;
967 let x3 = t3 * x3;
968 let x3 = x3 - t0;
969 let t0 = t3 * t1;
970 let z3 = t5 * z3;
971 let z3 = z3 + t0;
972
973 $name {
974 x: x3,
975 y: y3,
976 z: z3,
977 }
978 }
979 }
980 }
981
982 impl<'a, 'b> Add<&'a $name_affine> for &'b $name {
983 type Output = $name;
984
985 fn add(self, rhs: &'a $name_affine) -> $name {
987 if $constant_a == $base::ZERO {
988 let t0 = self.x * rhs.x;
990 let t1 = self.y * rhs.y;
991 let t3 = rhs.x + rhs.y;
992 let t4 = self.x + self.y;
993 let t3 = t3 * t4;
994 let t4 = t0 + t1;
995 let t3 = t3 - t4;
996 let t4 = rhs.y * self.z;
997 let t4 = t4 + self.y;
998 let y3 = rhs.x * self.z;
999 let y3 = y3 + self.x;
1000 let x3 = t0 + t0;
1001 let t0 = x3 + t0;
1002 let t2 = $name::mul_by_3b(&self.z);
1003 let z3 = t1 + t2;
1004 let t1 = t1 - t2;
1005 let y3 = $name::mul_by_3b(&y3);
1006 let x3 = t4 * y3;
1007 let t2 = t3 * t1;
1008 let x3 = t2 - x3;
1009 let y3 = y3 * t0;
1010 let t1 = t1 * z3;
1011 let y3 = t1 + y3;
1012 let t0 = t0 * t3;
1013 let z3 = z3 * t4;
1014 let z3 = z3 + t0;
1015
1016 let tmp = $name{
1017 x: x3,
1018 y: y3,
1019 z: z3,
1020 };
1021
1022 $name::conditional_select(&tmp, self, rhs.is_identity())
1023 } else {
1024 let t0 = self.x * rhs.x;
1026 let t1 = self.y * rhs.y;
1027 let t3 = rhs.x + rhs.y;
1028 let t4 = self.x + self.y;
1029 let t3 = t3 * t4;
1030 let t4 = t0 + t1;
1031 let t3 = t3 - t4;
1032 let t4 = rhs.x * self.z;
1033 let t4 = t4 + self.x;
1034 let t5 = rhs.y * self.z;
1035 let t5 = t5 + self.y;
1036 let z3 = $constant_a * t4;
1037 let x3 = $name::mul_by_3b(&self.z);
1038 let z3 = x3 + z3;
1039 let x3 = t1 - z3;
1040 let z3 = t1 + z3;
1041 let y3 = x3 * z3;
1042 let t1 = t0 + t0;
1043 let t1 = t1 + t0;
1044 let t2 = $constant_a * self.z;
1045 let t4 = $name::mul_by_3b(&t4);
1046 let t1 = t1 + t2;
1047 let t2 = t0 - t2;
1048 let t2 = $constant_a * t2;
1049 let t4 = t4 + t2;
1050 let t0 = t1 * t4;
1051 let y3 = y3 + t0;
1052 let t0 = t5 * t4;
1053 let x3 = t3 * x3;
1054 let x3 = x3 - t0;
1055 let t0 = t3 * t1;
1056 let z3 = t5 * z3;
1057 let z3 = z3 + t0;
1058
1059 let tmp = $name{
1060 x: x3,
1061 y: y3,
1062 z: z3,
1063 };
1064
1065 $name::conditional_select(&tmp, self, rhs.is_identity())
1066 }
1067 }
1068 }
1069
1070 impl<'a, 'b> Sub<&'a $name> for &'b $name {
1071 type Output = $name;
1072
1073 fn sub(self, other: &'a $name) -> $name {
1074 self + (-other)
1075 }
1076 }
1077
1078 impl<'a, 'b> Sub<&'a $name_affine> for &'b $name {
1079 type Output = $name;
1080
1081 fn sub(self, other: &'a $name_affine) -> $name {
1082 self + (-other)
1083 }
1084 }
1085
1086
1087
1088 #[allow(clippy::suspicious_arithmetic_impl)]
1089 impl<'a, 'b> Mul<&'b $scalar> for &'a $name {
1090 type Output = $name;
1091
1092 fn mul(self, other: &'b $scalar) -> Self::Output {
1097 let mut acc = $name::identity();
1098 for bit in other
1099 .to_repr()
1100 .as_ref()
1101 .iter()
1102 .rev()
1103 .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
1104 {
1105 acc = acc.double();
1106 acc = $name::conditional_select(&acc, &(acc + self), bit);
1107 }
1108
1109 acc
1110 }
1111 }
1112
1113 impl<'a> Neg for &'a $name_affine {
1114 type Output = $name_affine;
1115
1116 fn neg(self) -> $name_affine {
1117 $name_affine {
1118 x: self.x,
1119 y: -self.y,
1120 }
1121 }
1122 }
1123
1124 impl Neg for $name_affine {
1125 type Output = $name_affine;
1126
1127 fn neg(self) -> $name_affine {
1128 -&self
1129 }
1130 }
1131
1132 impl<'a, 'b> Add<&'a $name> for &'b $name_affine {
1133 type Output = $name;
1134
1135 fn add(self, rhs: &'a $name) -> $name {
1136 rhs + self
1137 }
1138 }
1139
1140 impl<'a, 'b> Add<&'a $name_affine> for &'b $name_affine {
1141 type Output = $name;
1142
1143 fn add(self, rhs: &'a $name_affine) -> $name {
1144 rhs.to_curve() + self.to_curve()
1145 }
1146 }
1147
1148 impl<'a, 'b> Sub<&'a $name_affine> for &'b $name_affine {
1149 type Output = $name;
1150
1151 fn sub(self, other: &'a $name_affine) -> $name {
1152 self + (-other)
1153 }
1154 }
1155
1156 impl<'a, 'b> Sub<&'a $name> for &'b $name_affine {
1157 type Output = $name;
1158
1159 fn sub(self, other: &'a $name) -> $name {
1160 self + (-other)
1161 }
1162 }
1163
1164 #[allow(clippy::suspicious_arithmetic_impl)]
1165 impl<'a, 'b> Mul<&'b $scalar> for &'a $name_affine {
1166 type Output = $name;
1167
1168 fn mul(self, other: &'b $scalar) -> Self::Output {
1169 let mut acc = $name::identity();
1170
1171 for bit in other
1176 .to_repr()
1177 .as_ref()
1178 .iter()
1179 .rev()
1180 .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
1181 {
1182 acc = acc.double();
1183 acc = $name::conditional_select(&acc, &(acc + self), bit);
1184 }
1185
1186 acc
1187 }
1188 }
1189 };
1190}