1use crate::fp::Fp;
4use crate::fp2::Fp2;
5use crate::BlsScalar;
6
7use core::borrow::Borrow;
8use core::iter::Sum;
9use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
10use dusk_bytes::{Error as BytesError, HexDebug, Serializable};
11use parity_scale_codec::{Decode, Encode};
12use subtle;
13use serde::{Deserialize, Serialize};
14use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
15
16#[cfg(feature = "canon")]
17use canonical::{Canon, CanonError, Sink, Source};
18#[cfg(feature = "canon")]
19use canonical_derive::Canon;
20#[cfg(feature = "serde_req")]
21use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
22
23#[derive(Copy, Clone, HexDebug, Encode, Decode, Serialize, Deserialize)]
30pub struct G2Affine {
31 pub(crate) x: Fp2,
32 pub(crate) y: Fp2,
33 infinity: Choice,
34}
35
36#[cfg(feature = "canon")]
37impl Canon for G2Affine {
38 fn encode(&self, sink: &mut Sink) {
39 sink.copy_bytes(&self.to_bytes());
40 }
41
42 fn decode(source: &mut Source) -> Result<Self, CanonError> {
43 let mut bytes = [0u8; Self::SIZE];
44
45 bytes.copy_from_slice(source.read_bytes(Self::SIZE));
46
47 Self::from_bytes(&bytes).map_err(|_| CanonError::InvalidEncoding)
48 }
49
50 fn encoded_len(&self) -> usize {
51 Self::SIZE
52 }
53}
54
55impl Default for G2Affine {
56 fn default() -> G2Affine {
57 G2Affine::identity()
58 }
59}
60
61impl<'a> From<&'a G2Projective> for G2Affine {
62 fn from(p: &'a G2Projective) -> G2Affine {
63 let zinv = p.z.invert().unwrap_or(Fp2::zero());
64 let zinv2 = zinv.square();
65 let x = p.x * zinv2;
66 let zinv3 = zinv2 * zinv;
67 let y = p.y * zinv3;
68
69 let tmp = G2Affine {
70 x,
71 y,
72 infinity: Choice::from(0u8),
73 };
74
75 G2Affine::conditional_select(&tmp, &G2Affine::identity(), zinv.is_zero())
76 }
77}
78
79impl From<G2Projective> for G2Affine {
80 fn from(p: G2Projective) -> G2Affine {
81 G2Affine::from(&p)
82 }
83}
84
85impl ConstantTimeEq for G2Affine {
86 fn ct_eq(&self, other: &Self) -> Choice {
87 (self.infinity & other.infinity)
92 | ((!self.infinity)
93 & (!other.infinity)
94 & self.x.ct_eq(&other.x)
95 & self.y.ct_eq(&other.y))
96 }
97}
98
99impl ConditionallySelectable for G2Affine {
100 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
101 G2Affine {
102 x: Fp2::conditional_select(&a.x, &b.x, choice),
103 y: Fp2::conditional_select(&a.y, &b.y, choice),
104 infinity: Choice::conditional_select(&a.infinity, &b.infinity, choice),
105 }
106 }
107}
108
109impl Eq for G2Affine {}
110impl PartialEq for G2Affine {
111 #[inline]
112 fn eq(&self, other: &Self) -> bool {
113 bool::from(self.ct_eq(other))
114 }
115}
116
117impl Serializable<96> for G2Affine {
118 type Error = BytesError;
119
120 fn to_bytes(&self) -> [u8; Self::SIZE] {
123 let x = Fp2::conditional_select(&self.x, &Fp2::zero(), self.infinity);
126
127 let mut res = [0; Self::SIZE];
128
129 (&mut res[0..48]).copy_from_slice(&x.c1.to_bytes()[..]);
130 (&mut res[48..96]).copy_from_slice(&x.c0.to_bytes()[..]);
131
132 res[0] |= 1u8 << 7;
134
135 res[0] |= u8::conditional_select(&0u8, &(1u8 << 6), self.infinity);
137
138 res[0] |= u8::conditional_select(
142 &0u8,
143 &(1u8 << 5),
144 (!self.infinity) & self.y.lexicographically_largest(),
145 );
146
147 res
148 }
149
150 fn from_bytes(buf: &[u8; Self::SIZE]) -> Result<Self, Self::Error> {
153 let compression_flag_set = Choice::from((buf[0] >> 7) & 1);
158 let infinity_flag_set = Choice::from((buf[0] >> 6) & 1);
159 let sort_flag_set = Choice::from((buf[0] >> 5) & 1);
160
161 let xc1 = {
163 let mut tmp = [0; 48];
164 tmp.copy_from_slice(&buf[0..48]);
165
166 tmp[0] &= 0b0001_1111;
168
169 Fp::from_bytes(&tmp)
170 };
171 let xc0 = {
172 let mut tmp = [0; 48];
173 tmp.copy_from_slice(&buf[48..96]);
174
175 Fp::from_bytes(&tmp)
176 };
177
178 let x: Option<Self> = xc1
179 .and_then(|xc1| {
180 xc0.and_then(|xc0| {
181 let x = Fp2 { c0: xc0, c1: xc1 };
182
183 CtOption::new(
190 G2Affine::identity(),
191 infinity_flag_set & compression_flag_set & (!sort_flag_set) & x.is_zero(), )
196 .or_else(|| {
197 ((x.square() * x) + B).sqrt().and_then(|y| {
199 let y = Fp2::conditional_select(
201 &y,
202 &-y,
203 y.lexicographically_largest() ^ sort_flag_set,
204 );
205
206 CtOption::new(
207 G2Affine {
208 x,
209 y,
210 infinity: infinity_flag_set,
211 },
212 (!infinity_flag_set) & compression_flag_set, )
215 })
216 })
217 })
218 })
219 .into();
220
221 match x {
222 Some(x) if x.is_torsion_free().unwrap_u8() == 1 => Ok(x),
223 _ => Err(BytesError::InvalidData),
224 }
225 }
226}
227
228#[cfg(feature = "serde_req")]
229impl Serialize for G2Affine {
230 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
231 where
232 S: Serializer,
233 {
234 use serde::ser::SerializeTuple;
235 let mut tup = serializer.serialize_tuple(Self::SIZE)?;
236 for byte in self.to_bytes().iter() {
237 tup.serialize_element(byte)?;
238 }
239 tup.end()
240 }
241}
242
243#[cfg(feature = "serde_req")]
244impl<'de> Deserialize<'de> for G2Affine {
245 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
246 where
247 D: Deserializer<'de>,
248 {
249 struct G2AffineVisitor;
250
251 impl<'de> Visitor<'de> for G2AffineVisitor {
252 type Value = G2Affine;
253
254 fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
255 formatter.write_str("a 48-byte cannonical compressed G2Affine point from Bls12_381")
256 }
257
258 fn visit_seq<A>(self, mut seq: A) -> Result<G2Affine, A::Error>
259 where
260 A: serde::de::SeqAccess<'de>,
261 {
262 let mut bytes = [0u8; G2Affine::SIZE];
263 for i in 0..G2Affine::SIZE {
264 bytes[i] = seq
265 .next_element()?
266 .ok_or(serde::de::Error::invalid_length(i, &"expected 48 bytes"))?;
267 }
268
269 G2Affine::from_bytes(&bytes).map_err(|_| {
270 serde::de::Error::custom(&"compressed G2Affine was not canonically encoded")
271 })
272 }
273 }
274
275 deserializer.deserialize_tuple(Self::SIZE, G2AffineVisitor)
276 }
277}
278
279impl<'a> Neg for &'a G2Affine {
280 type Output = G2Affine;
281
282 #[inline]
283 fn neg(self) -> G2Affine {
284 G2Affine {
285 x: self.x,
286 y: Fp2::conditional_select(&-self.y, &Fp2::one(), self.infinity),
287 infinity: self.infinity,
288 }
289 }
290}
291
292impl Neg for G2Affine {
293 type Output = G2Affine;
294
295 #[inline]
296 fn neg(self) -> G2Affine {
297 -&self
298 }
299}
300
301impl<'a, 'b> Add<&'b G2Projective> for &'a G2Affine {
302 type Output = G2Projective;
303
304 #[inline]
305 fn add(self, rhs: &'b G2Projective) -> G2Projective {
306 rhs.add_mixed(self)
307 }
308}
309
310impl<'a, 'b> Add<&'b G2Affine> for &'a G2Projective {
311 type Output = G2Projective;
312
313 #[inline]
314 fn add(self, rhs: &'b G2Affine) -> G2Projective {
315 self.add_mixed(rhs)
316 }
317}
318
319impl<'a, 'b> Sub<&'b G2Projective> for &'a G2Affine {
320 type Output = G2Projective;
321
322 #[inline]
323 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
324 self + (-rhs)
325 }
326}
327
328impl<'a, 'b> Sub<&'b G2Affine> for &'a G2Projective {
329 type Output = G2Projective;
330
331 #[inline]
332 fn sub(self, rhs: &'b G2Affine) -> G2Projective {
333 self + (-rhs)
334 }
335}
336
337impl<T> Sum<T> for G2Projective
338where
339 T: Borrow<G2Projective>,
340{
341 fn sum<I>(iter: I) -> Self
342 where
343 I: Iterator<Item = T>,
344 {
345 iter.fold(Self::identity(), |acc, item| acc + item.borrow())
346 }
347}
348
349impl_binops_additive!(G2Projective, G2Affine);
350impl_binops_additive_specify_output!(G2Affine, G2Projective, G2Projective);
351
352const B: Fp2 = Fp2 {
353 c0: Fp::from_raw_unchecked([
354 0xaa270000000cfff3,
355 0x53cc0032fc34000a,
356 0x478fe97a6b0a807f,
357 0xb1d37ebee6ba24d7,
358 0x8ec9733bbf78ab2f,
359 0x9d645513d83de7e,
360 ]),
361 c1: Fp::from_raw_unchecked([
362 0xaa270000000cfff3,
363 0x53cc0032fc34000a,
364 0x478fe97a6b0a807f,
365 0xb1d37ebee6ba24d7,
366 0x8ec9733bbf78ab2f,
367 0x9d645513d83de7e,
368 ]),
369};
370
371impl G2Affine {
372 pub const RAW_SIZE: usize = 193;
374
375 pub fn identity() -> G2Affine {
377 G2Affine {
378 x: Fp2::zero(),
379 y: Fp2::one(),
380 infinity: Choice::from(1u8),
381 }
382 }
383
384 pub fn generator() -> G2Affine {
387 G2Affine {
388 x: Fp2 {
389 c0: Fp::from_raw_unchecked([
390 0xf5f28fa202940a10,
391 0xb3f5fb2687b4961a,
392 0xa1a893b53e2ae580,
393 0x9894999d1a3caee9,
394 0x6f67b7631863366b,
395 0x58191924350bcd7,
396 ]),
397 c1: Fp::from_raw_unchecked([
398 0xa5a9c0759e23f606,
399 0xaaa0c59dbccd60c3,
400 0x3bb17e18e2867806,
401 0x1b1ab6cc8541b367,
402 0xc2b6ed0ef2158547,
403 0x11922a097360edf3,
404 ]),
405 },
406 y: Fp2 {
407 c0: Fp::from_raw_unchecked([
408 0x4c730af860494c4a,
409 0x597cfa1f5e369c5a,
410 0xe7e6856caa0a635a,
411 0xbbefb5e96e0d495f,
412 0x7d3a975f0ef25a2,
413 0x83fd8e7e80dae5,
414 ]),
415 c1: Fp::from_raw_unchecked([
416 0xadc0fc92df64b05d,
417 0x18aa270a2b1461dc,
418 0x86adac6a3be4eba0,
419 0x79495c4ec93da33a,
420 0xe7175850a43ccaed,
421 0xb2bc2a163de1bf2,
422 ]),
423 },
424 infinity: Choice::from(0u8),
425 }
426 }
427
428 pub fn to_raw_bytes(&self) -> [u8; Self::RAW_SIZE] {
435 let mut bytes = [0u8; Self::RAW_SIZE];
436 let chunks = bytes.chunks_mut(8);
437
438 self.x
439 .c0
440 .internal_repr()
441 .iter()
442 .chain(self.x.c1.internal_repr().iter())
443 .chain(self.y.c0.internal_repr().iter())
444 .chain(self.y.c1.internal_repr().iter())
445 .zip(chunks)
446 .for_each(|(n, c)| c.copy_from_slice(&n.to_le_bytes()));
447
448 bytes[Self::RAW_SIZE - 1] = self.infinity.unwrap_u8();
449
450 bytes
451 }
452
453 pub unsafe fn from_slice_unchecked(bytes: &[u8]) -> Self {
463 let mut xc0 = [0u64; 6];
464 let mut xc1 = [0u64; 6];
465 let mut yc0 = [0u64; 6];
466 let mut yc1 = [0u64; 6];
467 let mut z = [0u8; 8];
468
469 xc0.iter_mut()
470 .chain(xc1.iter_mut())
471 .chain(yc0.iter_mut())
472 .chain(yc1.iter_mut())
473 .zip(bytes.chunks_exact(8))
474 .for_each(|(n, c)| {
475 z.copy_from_slice(c);
476 *n = u64::from_le_bytes(z);
477 });
478
479 let c0 = Fp::from_raw_unchecked(xc0);
480 let c1 = Fp::from_raw_unchecked(xc1);
481 let x = Fp2 { c0, c1 };
482
483 let c0 = Fp::from_raw_unchecked(yc0);
484 let c1 = Fp::from_raw_unchecked(yc1);
485 let y = Fp2 { c0, c1 };
486
487 let infinity = if bytes.len() >= Self::RAW_SIZE {
488 bytes[Self::RAW_SIZE - 1].into()
489 } else {
490 0u8.into()
491 };
492
493 Self { x, y, infinity }
494 }
495
496 #[inline]
498 pub fn is_identity(&self) -> Choice {
499 self.infinity
500 }
501
502 pub fn is_torsion_free(&self) -> Choice {
506 const FQ_MODULUS_BYTES: [u8; 32] = [
507 1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8,
508 216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115,
509 ];
510
511 G2Projective::from(*self)
513 .multiply(&FQ_MODULUS_BYTES)
514 .is_identity()
515 }
516
517 pub fn is_on_curve(&self) -> Choice {
520 (self.y.square() - (self.x.square() * self.x)).ct_eq(&B) | self.infinity
522 }
523}
524
525#[derive(Copy, Clone, Debug)]
527#[cfg_attr(feature = "canon", derive(Canon))]
528pub struct G2Projective {
529 pub(crate) x: Fp2,
530 pub(crate) y: Fp2,
531 pub(crate) z: Fp2,
532}
533
534impl<'a> From<&'a G2Affine> for G2Projective {
535 fn from(p: &'a G2Affine) -> G2Projective {
536 G2Projective {
537 x: p.x,
538 y: p.y,
539 z: Fp2::conditional_select(&Fp2::one(), &Fp2::zero(), p.infinity),
540 }
541 }
542}
543
544impl From<G2Affine> for G2Projective {
545 fn from(p: G2Affine) -> G2Projective {
546 G2Projective::from(&p)
547 }
548}
549
550impl ConstantTimeEq for G2Projective {
551 fn ct_eq(&self, other: &Self) -> Choice {
552 let z = other.z.square();
555 let x1 = self.x * z;
556 let z = z * other.z;
557 let y1 = self.y * z;
558 let z = self.z.square();
559 let x2 = other.x * z;
560 let z = z * self.z;
561 let y2 = other.y * z;
562
563 let self_is_zero = self.z.is_zero();
564 let other_is_zero = other.z.is_zero();
565
566 (self_is_zero & other_is_zero) | ((!self_is_zero) & (!other_is_zero) & x1.ct_eq(&x2) & y1.ct_eq(&y2))
568 }
570}
571
572impl ConditionallySelectable for G2Projective {
573 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
574 G2Projective {
575 x: Fp2::conditional_select(&a.x, &b.x, choice),
576 y: Fp2::conditional_select(&a.y, &b.y, choice),
577 z: Fp2::conditional_select(&a.z, &b.z, choice),
578 }
579 }
580}
581
582impl Eq for G2Projective {}
583impl PartialEq for G2Projective {
584 #[inline]
585 fn eq(&self, other: &Self) -> bool {
586 bool::from(self.ct_eq(other))
587 }
588}
589
590impl<'a> Neg for &'a G2Projective {
591 type Output = G2Projective;
592
593 #[inline]
594 fn neg(self) -> G2Projective {
595 G2Projective {
596 x: self.x,
597 y: -self.y,
598 z: self.z,
599 }
600 }
601}
602
603impl Neg for G2Projective {
604 type Output = G2Projective;
605
606 #[inline]
607 fn neg(self) -> G2Projective {
608 -&self
609 }
610}
611
612impl<'a, 'b> Add<&'b G2Projective> for &'a G2Projective {
613 type Output = G2Projective;
614
615 #[inline]
616 fn add(self, rhs: &'b G2Projective) -> G2Projective {
617 self.add(rhs)
618 }
619}
620
621impl<'a, 'b> Sub<&'b G2Projective> for &'a G2Projective {
622 type Output = G2Projective;
623
624 #[inline]
625 fn sub(self, rhs: &'b G2Projective) -> G2Projective {
626 self + (-rhs)
627 }
628}
629
630impl<'a, 'b> Mul<&'b BlsScalar> for &'a G2Projective {
631 type Output = G2Projective;
632
633 fn mul(self, other: &'b BlsScalar) -> Self::Output {
634 self.multiply(&other.to_bytes())
635 }
636}
637
638impl<'a, 'b> Mul<&'b BlsScalar> for &'a G2Affine {
639 type Output = G2Projective;
640
641 fn mul(self, other: &'b BlsScalar) -> Self::Output {
642 G2Projective::from(self).multiply(&other.to_bytes())
643 }
644}
645
646impl_binops_additive!(G2Projective, G2Projective);
647impl_binops_multiplicative!(G2Projective, BlsScalar);
648impl_binops_multiplicative_mixed!(G2Affine, BlsScalar, G2Projective);
649
650impl G2Projective {
651 pub fn identity() -> G2Projective {
653 G2Projective {
654 x: Fp2::zero(),
655 y: Fp2::one(),
656 z: Fp2::zero(),
657 }
658 }
659
660 pub fn generator() -> G2Projective {
663 G2Projective {
664 x: Fp2 {
665 c0: Fp::from_raw_unchecked([
666 0xf5f28fa202940a10,
667 0xb3f5fb2687b4961a,
668 0xa1a893b53e2ae580,
669 0x9894999d1a3caee9,
670 0x6f67b7631863366b,
671 0x58191924350bcd7,
672 ]),
673 c1: Fp::from_raw_unchecked([
674 0xa5a9c0759e23f606,
675 0xaaa0c59dbccd60c3,
676 0x3bb17e18e2867806,
677 0x1b1ab6cc8541b367,
678 0xc2b6ed0ef2158547,
679 0x11922a097360edf3,
680 ]),
681 },
682 y: Fp2 {
683 c0: Fp::from_raw_unchecked([
684 0x4c730af860494c4a,
685 0x597cfa1f5e369c5a,
686 0xe7e6856caa0a635a,
687 0xbbefb5e96e0d495f,
688 0x7d3a975f0ef25a2,
689 0x83fd8e7e80dae5,
690 ]),
691 c1: Fp::from_raw_unchecked([
692 0xadc0fc92df64b05d,
693 0x18aa270a2b1461dc,
694 0x86adac6a3be4eba0,
695 0x79495c4ec93da33a,
696 0xe7175850a43ccaed,
697 0xb2bc2a163de1bf2,
698 ]),
699 },
700 z: Fp2::one(),
701 }
702 }
703
704 pub fn double(&self) -> G2Projective {
706 let a = self.x.square();
711 let b = self.y.square();
712 let c = b.square();
713 let d = self.x + b;
714 let d = d.square();
715 let d = d - a - c;
716 let d = d + d;
717 let e = a + a + a;
718 let f = e.square();
719 let z3 = self.z * self.y;
720 let z3 = z3 + z3;
721 let x3 = f - (d + d);
722 let c = c + c;
723 let c = c + c;
724 let c = c + c;
725 let y3 = e * (d - x3) - c;
726
727 let tmp = G2Projective {
728 x: x3,
729 y: y3,
730 z: z3,
731 };
732
733 G2Projective::conditional_select(&tmp, &G2Projective::identity(), self.is_identity())
734 }
735
736 pub fn add(&self, rhs: &G2Projective) -> G2Projective {
738 let f1 = self.is_identity();
744 let res = G2Projective::conditional_select(self, rhs, f1);
745 let f2 = rhs.is_identity();
746
747 let z = rhs.z.square();
749 let u1 = self.x * z;
750 let z = z * rhs.z;
751 let s1 = self.y * z;
752 let z = self.z.square();
753 let u2 = rhs.x * z;
754 let z = z * self.z;
755 let s2 = rhs.y * z;
756 let f3 = u1.ct_eq(&u2) & (!s1.ct_eq(&s2));
757 let res =
758 G2Projective::conditional_select(&res, &G2Projective::identity(), (!f1) & (!f2) & f3);
759
760 let t = u1 + u2;
761 let m = s1 + s2;
762 let rr = t.square();
763 let m_alt = -u2;
764 let tt = u1 * m_alt;
765 let rr = rr + tt;
766
767 let degenerate = m.is_zero() & rr.is_zero();
770 let rr_alt = s1 + s1;
771 let m_alt = m_alt + u1;
772 let rr_alt = Fp2::conditional_select(&rr_alt, &rr, !degenerate);
773 let m_alt = Fp2::conditional_select(&m_alt, &m, !degenerate);
774
775 let n = m_alt.square();
776 let q = n * t;
777
778 let n = n.square();
779 let n = Fp2::conditional_select(&n, &m, degenerate);
780 let t = rr_alt.square();
781 let z3 = m_alt * self.z * rhs.z; let z3 = z3 + z3;
783 let q = -q;
784 let t = t + q;
785 let x3 = t;
786 let t = t + t;
787 let t = t + q;
788 let t = t * rr_alt;
789 let t = t + n;
790 let y3 = -t;
791 let x3 = x3 + x3;
792 let x3 = x3 + x3;
793 let y3 = y3 + y3;
794 let y3 = y3 + y3;
795
796 let tmp = G2Projective {
797 x: x3,
798 y: y3,
799 z: z3,
800 };
801
802 G2Projective::conditional_select(&res, &tmp, (!f1) & (!f2) & (!f3))
803 }
804
805 pub fn add_mixed(&self, rhs: &G2Affine) -> G2Projective {
807 let f1 = self.is_identity();
813 let res = G2Projective::conditional_select(self, &G2Projective::from(rhs), f1);
814 let f2 = rhs.is_identity();
815
816 let u1 = self.x;
818 let s1 = self.y;
819 let z = self.z.square();
820 let u2 = rhs.x * z;
821 let z = z * self.z;
822 let s2 = rhs.y * z;
823 let f3 = u1.ct_eq(&u2) & (!s1.ct_eq(&s2));
824 let res =
825 G2Projective::conditional_select(&res, &G2Projective::identity(), (!f1) & (!f2) & f3);
826
827 let t = u1 + u2;
828 let m = s1 + s2;
829 let rr = t.square();
830 let m_alt = -u2;
831 let tt = u1 * m_alt;
832 let rr = rr + tt;
833
834 let degenerate = m.is_zero() & rr.is_zero();
837 let rr_alt = s1 + s1;
838 let m_alt = m_alt + u1;
839 let rr_alt = Fp2::conditional_select(&rr_alt, &rr, !degenerate);
840 let m_alt = Fp2::conditional_select(&m_alt, &m, !degenerate);
841
842 let n = m_alt.square();
843 let q = n * t;
844
845 let n = n.square();
846 let n = Fp2::conditional_select(&n, &m, degenerate);
847 let t = rr_alt.square();
848 let z3 = m_alt * self.z;
849 let z3 = z3 + z3;
850 let q = -q;
851 let t = t + q;
852 let x3 = t;
853 let t = t + t;
854 let t = t + q;
855 let t = t * rr_alt;
856 let t = t + n;
857 let y3 = -t;
858 let x3 = x3 + x3;
859 let x3 = x3 + x3;
860 let y3 = y3 + y3;
861 let y3 = y3 + y3;
862
863 let tmp = G2Projective {
864 x: x3,
865 y: y3,
866 z: z3,
867 };
868
869 G2Projective::conditional_select(&res, &tmp, (!f1) & (!f2) & (!f3))
870 }
871
872 fn multiply(&self, by: &[u8]) -> G2Projective {
873 let mut acc = G2Projective::identity();
874
875 for bit in by
882 .iter()
883 .rev()
884 .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
885 .skip(1)
886 {
887 acc = acc.double();
888 acc = G2Projective::conditional_select(&acc, &(acc + self), bit);
889 }
890
891 acc
892 }
893
894 #[cfg(feature = "endo")]
895 fn psi(&self) -> G2Projective {
896 let psi_coeff_x = Fp2 {
898 c0: Fp::zero(),
899 c1: Fp::from_raw_unchecked([
900 0x890dc9e4867545c3,
901 0x2af322533285a5d5,
902 0x50880866309b7e2c,
903 0xa20d1b8c7e881024,
904 0x14e4f04fe2db9068,
905 0x14e56d3f1564853a,
906 ]),
907 };
908 let psi_coeff_y = Fp2 {
910 c0: Fp::from_raw_unchecked([
911 0x3e2f585da55c9ad1,
912 0x4294213d86c18183,
913 0x382844c88b623732,
914 0x92ad2afd19103e18,
915 0x1d794e4fac7cf0b9,
916 0x0bd592fc7d825ec8,
917 ]),
918 c1: Fp::from_raw_unchecked([
919 0x7bcfa7a25aa30fda,
920 0xdc17dec12a927e7c,
921 0x2f088dd86b4ebef1,
922 0xd1ca2087da74d4a7,
923 0x2da2596696cebc1d,
924 0x0e2b7eedbbfd87d2,
925 ]),
926 };
927
928 G2Projective {
929 x: self.x.frobenius_map() * psi_coeff_x,
931 y: self.y.frobenius_map() * psi_coeff_y,
933 z: self.z.frobenius_map(),
935 }
936 }
937
938 #[cfg(feature = "endo")]
939 fn psi2(&self) -> G2Projective {
940 let psi2_coeff_x = Fp2 {
942 c0: Fp::from_raw_unchecked([
943 0xcd03c9e48671f071,
944 0x5dab22461fcda5d2,
945 0x587042afd3851b95,
946 0x8eb60ebe01bacb9e,
947 0x03f97d6e83d050d2,
948 0x18f0206554638741,
949 ]),
950 c1: Fp::zero(),
951 };
952
953 G2Projective {
954 x: self.x.frobenius_map().frobenius_map() * psi2_coeff_x,
956 y: self.y.frobenius_map().frobenius_map().neg(),
958 z: self.z,
960 }
961 }
962
963 #[cfg(feature = "endo")]
965 fn mul_by_x(&self) -> G2Projective {
966 let mut xself = G2Projective::identity();
967 let mut x = crate::BLS_X >> 1;
969 let mut acc = *self;
970 while x != 0 {
971 acc = acc.double();
972 if x % 2 == 1 {
973 xself += acc;
974 }
975 x >>= 1;
976 }
977 if crate::BLS_X_IS_NEGATIVE {
979 xself = -xself;
980 }
981 xself
982 }
983
984 pub fn clear_cofactor(&self) -> G2Projective {
993 #[cfg(feature = "endo")]
994 fn clear_cofactor(this: &G2Projective) -> G2Projective {
995 let t1 = this.mul_by_x(); let t2 = this.psi(); this.double().psi2() + (t1 + t2).mul_by_x() - t1 - t2 - this }
1004
1005 #[cfg(not(feature = "endo"))]
1006 fn clear_cofactor(this: &G2Projective) -> G2Projective {
1007 this.multiply(&[
1008 0x51, 0x55, 0xa9, 0xaa, 0x5, 0x0, 0x2, 0xe8, 0xb4, 0xf6, 0xbb, 0xde, 0xa, 0x4c,
1009 0x89, 0x59, 0xa3, 0xf6, 0x89, 0x66, 0xc0, 0xcb, 0x54, 0xe9, 0x1a, 0x7c, 0x47, 0xd7,
1010 0x69, 0xec, 0xc0, 0x2e, 0xb0, 0x12, 0x12, 0x5d, 0x1, 0xbf, 0x82, 0x6d, 0x95, 0xdb,
1011 0x31, 0x87, 0x17, 0x2f, 0x9c, 0x32, 0xe1, 0xff, 0x8, 0x15, 0x3, 0xff, 0x86, 0x99,
1012 0x68, 0xd7, 0x5a, 0x14, 0xe9, 0xa8, 0xe2, 0x88, 0x28, 0x35, 0x1b, 0xa9, 0xe, 0x6a,
1013 0x4c, 0x58, 0xb3, 0x75, 0xee, 0xf2, 0x8, 0x9f, 0xc6, 0xb,
1014 ])
1015 }
1016
1017 clear_cofactor(self)
1018 }
1019
1020 pub fn batch_normalize(p: &[Self], q: &mut [G2Affine]) {
1023 assert_eq!(p.len(), q.len());
1024
1025 let mut acc = Fp2::one();
1026 for (p, q) in p.iter().zip(q.iter_mut()) {
1027 q.x = acc;
1030
1031 acc = Fp2::conditional_select(&(acc * p.z), &acc, p.is_identity());
1033 }
1034
1035 acc = acc.invert().unwrap();
1038
1039 for (p, q) in p.iter().rev().zip(q.iter_mut().rev()) {
1040 let skip = p.is_identity();
1041
1042 let tmp = q.x * acc;
1044
1045 acc = Fp2::conditional_select(&(acc * p.z), &acc, skip);
1047
1048 let tmp2 = tmp.square();
1050 let tmp3 = tmp2 * tmp;
1051
1052 q.x = p.x * tmp2;
1053 q.y = p.y * tmp3;
1054 q.infinity = Choice::from(0u8);
1055
1056 *q = G2Affine::conditional_select(&q, &G2Affine::identity(), skip);
1057 }
1058 }
1059
1060 #[inline]
1062 pub fn is_identity(&self) -> Choice {
1063 self.z.is_zero()
1064 }
1065
1066 pub fn is_on_curve(&self) -> Choice {
1069 (self.y.square() - (self.x.square() * self.x))
1072 .ct_eq(&((self.z.square() * self.z).square() * B))
1073 | self.z.is_zero()
1074 }
1075}
1076
1077#[cfg(test)]
1078mod tests {
1079 use super::*;
1080
1081 #[test]
1082 fn test_is_on_curve() {
1083 assert!(bool::from(G2Affine::identity().is_on_curve()));
1084 assert!(bool::from(G2Affine::generator().is_on_curve()));
1085 assert!(bool::from(G2Projective::identity().is_on_curve()));
1086 assert!(bool::from(G2Projective::generator().is_on_curve()));
1087
1088 let z = Fp2 {
1089 c0: Fp::from_raw_unchecked([
1090 0xba7afa1f9a6fe250,
1091 0xfa0f5b595eafe731,
1092 0x3bdc477694c306e7,
1093 0x2149be4b3949fa24,
1094 0x64aa6e0649b2078c,
1095 0x12b108ac33643c3e,
1096 ]),
1097 c1: Fp::from_raw_unchecked([
1098 0x125325df3d35b5a8,
1099 0xdc469ef5555d7fe3,
1100 0x2d716d2443106a9,
1101 0x5a1db59a6ff37d0,
1102 0x7cf7784e5300bb8f,
1103 0x16a88922c7a5e844,
1104 ]),
1105 };
1106
1107 let gen = G2Affine::generator();
1108 let mut test = G2Projective {
1109 x: gen.x * (z.square()),
1110 y: gen.y * (z.square() * z),
1111 z,
1112 };
1113
1114 assert!(bool::from(test.is_on_curve()));
1115
1116 test.x = z;
1117 assert!(!bool::from(test.is_on_curve()));
1118 }
1119
1120 #[test]
1121 fn test_affine_point_equality() {
1122 let a = G2Affine::generator();
1123 let b = G2Affine::identity();
1124
1125 assert!(a == a);
1126 assert!(b == b);
1127 assert!(a != b);
1128 assert!(b != a);
1129 }
1130
1131 #[test]
1132 fn test_projective_point_equality() {
1133 let a = G2Projective::generator();
1134 let b = G2Projective::identity();
1135
1136 assert!(a == a);
1137 assert!(b == b);
1138 assert!(a != b);
1139 assert!(b != a);
1140
1141 let z = Fp2 {
1142 c0: Fp::from_raw_unchecked([
1143 0xba7afa1f9a6fe250,
1144 0xfa0f5b595eafe731,
1145 0x3bdc477694c306e7,
1146 0x2149be4b3949fa24,
1147 0x64aa6e0649b2078c,
1148 0x12b108ac33643c3e,
1149 ]),
1150 c1: Fp::from_raw_unchecked([
1151 0x125325df3d35b5a8,
1152 0xdc469ef5555d7fe3,
1153 0x2d716d2443106a9,
1154 0x5a1db59a6ff37d0,
1155 0x7cf7784e5300bb8f,
1156 0x16a88922c7a5e844,
1157 ]),
1158 };
1159
1160 let mut c = G2Projective {
1161 x: a.x * (z.square()),
1162 y: a.y * (z.square() * z),
1163 z,
1164 };
1165 assert!(bool::from(c.is_on_curve()));
1166
1167 assert!(a == c);
1168 assert!(b != c);
1169 assert!(c == a);
1170 assert!(c != b);
1171
1172 c.y = -c.y;
1173 assert!(bool::from(c.is_on_curve()));
1174
1175 assert!(a != c);
1176 assert!(b != c);
1177 assert!(c != a);
1178 assert!(c != b);
1179
1180 c.y = -c.y;
1181 c.x = z;
1182 assert!(!bool::from(c.is_on_curve()));
1183 assert!(a != b);
1184 assert!(a != c);
1185 assert!(b != c);
1186 }
1187
1188 #[test]
1189 fn test_conditionally_select_affine() {
1190 let a = G2Affine::generator();
1191 let b = G2Affine::identity();
1192
1193 assert_eq!(G2Affine::conditional_select(&a, &b, Choice::from(0u8)), a);
1194 assert_eq!(G2Affine::conditional_select(&a, &b, Choice::from(1u8)), b);
1195 }
1196
1197 #[test]
1198 fn test_conditionally_select_projective() {
1199 let a = G2Projective::generator();
1200 let b = G2Projective::identity();
1201
1202 assert_eq!(
1203 G2Projective::conditional_select(&a, &b, Choice::from(0u8)),
1204 a
1205 );
1206 assert_eq!(
1207 G2Projective::conditional_select(&a, &b, Choice::from(1u8)),
1208 b
1209 );
1210 }
1211
1212 #[test]
1213 fn test_projective_to_affine() {
1214 let a = G2Projective::generator();
1215 let b = G2Projective::identity();
1216
1217 assert!(bool::from(G2Affine::from(a).is_on_curve()));
1218 assert!(!bool::from(G2Affine::from(a).is_identity()));
1219 assert!(bool::from(G2Affine::from(b).is_on_curve()));
1220 assert!(bool::from(G2Affine::from(b).is_identity()));
1221
1222 let z = Fp2 {
1223 c0: Fp::from_raw_unchecked([
1224 0xba7afa1f9a6fe250,
1225 0xfa0f5b595eafe731,
1226 0x3bdc477694c306e7,
1227 0x2149be4b3949fa24,
1228 0x64aa6e0649b2078c,
1229 0x12b108ac33643c3e,
1230 ]),
1231 c1: Fp::from_raw_unchecked([
1232 0x125325df3d35b5a8,
1233 0xdc469ef5555d7fe3,
1234 0x2d716d2443106a9,
1235 0x5a1db59a6ff37d0,
1236 0x7cf7784e5300bb8f,
1237 0x16a88922c7a5e844,
1238 ]),
1239 };
1240
1241 let c = G2Projective {
1242 x: a.x * (z.square()),
1243 y: a.y * (z.square() * z),
1244 z,
1245 };
1246
1247 assert_eq!(G2Affine::from(c), G2Affine::generator());
1248 }
1249
1250 #[test]
1251 fn test_affine_to_projective() {
1252 let a = G2Affine::generator();
1253 let b = G2Affine::identity();
1254
1255 assert!(bool::from(G2Projective::from(a).is_on_curve()));
1256 assert!(!bool::from(G2Projective::from(a).is_identity()));
1257 assert!(bool::from(G2Projective::from(b).is_on_curve()));
1258 assert!(bool::from(G2Projective::from(b).is_identity()));
1259 }
1260
1261 #[test]
1262 fn test_doubling() {
1263 {
1264 let tmp = G2Projective::identity().double();
1265 assert!(bool::from(tmp.is_identity()));
1266 assert!(bool::from(tmp.is_on_curve()));
1267 }
1268 {
1269 let tmp = G2Projective::generator().double();
1270 assert!(!bool::from(tmp.is_identity()));
1271 assert!(bool::from(tmp.is_on_curve()));
1272
1273 assert_eq!(
1274 G2Affine::from(tmp),
1275 G2Affine {
1276 x: Fp2 {
1277 c0: Fp::from_raw_unchecked([
1278 0xe9d9e2da9620f98b,
1279 0x54f1199346b97f36,
1280 0x3db3b820376bed27,
1281 0xcfdb31c9b0b64f4c,
1282 0x41d7c12786354493,
1283 0x5710794c255c064
1284 ]),
1285 c1: Fp::from_raw_unchecked([
1286 0xd6c1d3ca6ea0d06e,
1287 0xda0cbd905595489f,
1288 0x4f5352d43479221d,
1289 0x8ade5d736f8c97e0,
1290 0x48cc8433925ef70e,
1291 0x8d7ea71ea91ef81
1292 ]),
1293 },
1294 y: Fp2 {
1295 c0: Fp::from_raw_unchecked([
1296 0x15ba26eb4b0d186f,
1297 0xd086d64b7e9e01e,
1298 0xc8b848dd652f4c78,
1299 0xeecf46a6123bae4f,
1300 0x255e8dd8b6dc812a,
1301 0x164142af21dcf93f
1302 ]),
1303 c1: Fp::from_raw_unchecked([
1304 0xf9b4a1a895984db4,
1305 0xd417b114cccff748,
1306 0x6856301fc89f086e,
1307 0x41c777878931e3da,
1308 0x3556b155066a2105,
1309 0xacf7d325cb89cf
1310 ]),
1311 },
1312 infinity: Choice::from(0u8)
1313 }
1314 );
1315 }
1316 }
1317
1318 #[test]
1319 fn test_projective_addition() {
1320 {
1321 let a = G2Projective::identity();
1322 let b = G2Projective::identity();
1323 let c = a + b;
1324 assert!(bool::from(c.is_identity()));
1325 assert!(bool::from(c.is_on_curve()));
1326 }
1327 {
1328 let a = G2Projective::identity();
1329 let mut b = G2Projective::generator();
1330 {
1331 let z = Fp2 {
1332 c0: Fp::from_raw_unchecked([
1333 0xba7afa1f9a6fe250,
1334 0xfa0f5b595eafe731,
1335 0x3bdc477694c306e7,
1336 0x2149be4b3949fa24,
1337 0x64aa6e0649b2078c,
1338 0x12b108ac33643c3e,
1339 ]),
1340 c1: Fp::from_raw_unchecked([
1341 0x125325df3d35b5a8,
1342 0xdc469ef5555d7fe3,
1343 0x2d716d2443106a9,
1344 0x5a1db59a6ff37d0,
1345 0x7cf7784e5300bb8f,
1346 0x16a88922c7a5e844,
1347 ]),
1348 };
1349
1350 b = G2Projective {
1351 x: b.x * (z.square()),
1352 y: b.y * (z.square() * z),
1353 z,
1354 };
1355 }
1356 let c = a + b;
1357 assert!(!bool::from(c.is_identity()));
1358 assert!(bool::from(c.is_on_curve()));
1359 assert!(c == G2Projective::generator());
1360 }
1361 {
1362 let a = G2Projective::identity();
1363 let mut b = G2Projective::generator();
1364 {
1365 let z = Fp2 {
1366 c0: Fp::from_raw_unchecked([
1367 0xba7afa1f9a6fe250,
1368 0xfa0f5b595eafe731,
1369 0x3bdc477694c306e7,
1370 0x2149be4b3949fa24,
1371 0x64aa6e0649b2078c,
1372 0x12b108ac33643c3e,
1373 ]),
1374 c1: Fp::from_raw_unchecked([
1375 0x125325df3d35b5a8,
1376 0xdc469ef5555d7fe3,
1377 0x2d716d2443106a9,
1378 0x5a1db59a6ff37d0,
1379 0x7cf7784e5300bb8f,
1380 0x16a88922c7a5e844,
1381 ]),
1382 };
1383
1384 b = G2Projective {
1385 x: b.x * (z.square()),
1386 y: b.y * (z.square() * z),
1387 z,
1388 };
1389 }
1390 let c = b + a;
1391 assert!(!bool::from(c.is_identity()));
1392 assert!(bool::from(c.is_on_curve()));
1393 assert!(c == G2Projective::generator());
1394 }
1395 {
1396 let a = G2Projective::generator().double().double(); let b = G2Projective::generator().double(); let c = a + b;
1399
1400 let mut d = G2Projective::generator();
1401 for _ in 0..5 {
1402 d = d + G2Projective::generator();
1403 }
1404 assert!(!bool::from(c.is_identity()));
1405 assert!(bool::from(c.is_on_curve()));
1406 assert!(!bool::from(d.is_identity()));
1407 assert!(bool::from(d.is_on_curve()));
1408 assert_eq!(c, d);
1409 }
1410
1411 {
1413 let beta = Fp2 {
1414 c0: Fp::from_raw_unchecked([
1415 0xcd03c9e48671f071,
1416 0x5dab22461fcda5d2,
1417 0x587042afd3851b95,
1418 0x8eb60ebe01bacb9e,
1419 0x3f97d6e83d050d2,
1420 0x18f0206554638741,
1421 ]),
1422 c1: Fp::zero(),
1423 };
1424 let beta = beta.square();
1425 let a = G2Projective::generator().double().double();
1426 let b = G2Projective {
1427 x: a.x * beta,
1428 y: -a.y,
1429 z: a.z,
1430 };
1431 assert!(bool::from(a.is_on_curve()));
1432 assert!(bool::from(b.is_on_curve()));
1433
1434 let c = a + b;
1435 assert_eq!(
1436 G2Affine::from(c),
1437 G2Affine::from(G2Projective {
1438 x: Fp2 {
1439 c0: Fp::from_raw_unchecked([
1440 0x705abc799ca773d3,
1441 0xfe132292c1d4bf08,
1442 0xf37ece3e07b2b466,
1443 0x887e1c43f447e301,
1444 0x1e0970d033bc77e8,
1445 0x1985c81e20a693f2
1446 ]),
1447 c1: Fp::from_raw_unchecked([
1448 0x1d79b25db36ab924,
1449 0x23948e4d529639d3,
1450 0x471ba7fb0d006297,
1451 0x2c36d4b4465dc4c0,
1452 0x82bbc3cfec67f538,
1453 0x51d2728b67bf952
1454 ])
1455 },
1456 y: Fp2 {
1457 c0: Fp::from_raw_unchecked([
1458 0x41b1bbf6576c0abf,
1459 0xb6cc93713f7a0f9a,
1460 0x6b65b43e48f3f01f,
1461 0xfb7a4cfcaf81be4f,
1462 0x3e32dadc6ec22cb6,
1463 0xbb0fc49d79807e3
1464 ]),
1465 c1: Fp::from_raw_unchecked([
1466 0x7d1397788f5f2ddf,
1467 0xab2907144ff0d8e8,
1468 0x5b7573e0cdb91f92,
1469 0x4cb8932dd31daf28,
1470 0x62bbfac6db052a54,
1471 0x11f95c16d14c3bbe
1472 ])
1473 },
1474 z: Fp2::one()
1475 })
1476 );
1477 assert!(!bool::from(c.is_identity()));
1478 assert!(bool::from(c.is_on_curve()));
1479 }
1480 }
1481
1482 #[test]
1483 fn test_mixed_addition() {
1484 {
1485 let a = G2Affine::identity();
1486 let b = G2Projective::identity();
1487 let c = a + b;
1488 assert!(bool::from(c.is_identity()));
1489 assert!(bool::from(c.is_on_curve()));
1490 }
1491 {
1492 let a = G2Affine::identity();
1493 let mut b = G2Projective::generator();
1494 {
1495 let z = Fp2 {
1496 c0: Fp::from_raw_unchecked([
1497 0xba7afa1f9a6fe250,
1498 0xfa0f5b595eafe731,
1499 0x3bdc477694c306e7,
1500 0x2149be4b3949fa24,
1501 0x64aa6e0649b2078c,
1502 0x12b108ac33643c3e,
1503 ]),
1504 c1: Fp::from_raw_unchecked([
1505 0x125325df3d35b5a8,
1506 0xdc469ef5555d7fe3,
1507 0x2d716d2443106a9,
1508 0x5a1db59a6ff37d0,
1509 0x7cf7784e5300bb8f,
1510 0x16a88922c7a5e844,
1511 ]),
1512 };
1513
1514 b = G2Projective {
1515 x: b.x * (z.square()),
1516 y: b.y * (z.square() * z),
1517 z,
1518 };
1519 }
1520 let c = a + b;
1521 assert!(!bool::from(c.is_identity()));
1522 assert!(bool::from(c.is_on_curve()));
1523 assert!(c == G2Projective::generator());
1524 }
1525 {
1526 let a = G2Affine::identity();
1527 let mut b = G2Projective::generator();
1528 {
1529 let z = Fp2 {
1530 c0: Fp::from_raw_unchecked([
1531 0xba7afa1f9a6fe250,
1532 0xfa0f5b595eafe731,
1533 0x3bdc477694c306e7,
1534 0x2149be4b3949fa24,
1535 0x64aa6e0649b2078c,
1536 0x12b108ac33643c3e,
1537 ]),
1538 c1: Fp::from_raw_unchecked([
1539 0x125325df3d35b5a8,
1540 0xdc469ef5555d7fe3,
1541 0x2d716d2443106a9,
1542 0x5a1db59a6ff37d0,
1543 0x7cf7784e5300bb8f,
1544 0x16a88922c7a5e844,
1545 ]),
1546 };
1547
1548 b = G2Projective {
1549 x: b.x * (z.square()),
1550 y: b.y * (z.square() * z),
1551 z,
1552 };
1553 }
1554 let c = b + a;
1555 assert!(!bool::from(c.is_identity()));
1556 assert!(bool::from(c.is_on_curve()));
1557 assert!(c == G2Projective::generator());
1558 }
1559 {
1560 let a = G2Projective::generator().double().double(); let b = G2Projective::generator().double(); let c = a + b;
1563
1564 let mut d = G2Projective::generator();
1565 for _ in 0..5 {
1566 d = d + G2Affine::generator();
1567 }
1568 assert!(!bool::from(c.is_identity()));
1569 assert!(bool::from(c.is_on_curve()));
1570 assert!(!bool::from(d.is_identity()));
1571 assert!(bool::from(d.is_on_curve()));
1572 assert_eq!(c, d);
1573 }
1574
1575 {
1577 let beta = Fp2 {
1578 c0: Fp::from_raw_unchecked([
1579 0xcd03c9e48671f071,
1580 0x5dab22461fcda5d2,
1581 0x587042afd3851b95,
1582 0x8eb60ebe01bacb9e,
1583 0x3f97d6e83d050d2,
1584 0x18f0206554638741,
1585 ]),
1586 c1: Fp::zero(),
1587 };
1588 let beta = beta.square();
1589 let a = G2Projective::generator().double().double();
1590 let b = G2Projective {
1591 x: a.x * beta,
1592 y: -a.y,
1593 z: a.z,
1594 };
1595 let a = G2Affine::from(a);
1596 assert!(bool::from(a.is_on_curve()));
1597 assert!(bool::from(b.is_on_curve()));
1598
1599 let c = a + b;
1600 assert_eq!(
1601 G2Affine::from(c),
1602 G2Affine::from(G2Projective {
1603 x: Fp2 {
1604 c0: Fp::from_raw_unchecked([
1605 0x705abc799ca773d3,
1606 0xfe132292c1d4bf08,
1607 0xf37ece3e07b2b466,
1608 0x887e1c43f447e301,
1609 0x1e0970d033bc77e8,
1610 0x1985c81e20a693f2
1611 ]),
1612 c1: Fp::from_raw_unchecked([
1613 0x1d79b25db36ab924,
1614 0x23948e4d529639d3,
1615 0x471ba7fb0d006297,
1616 0x2c36d4b4465dc4c0,
1617 0x82bbc3cfec67f538,
1618 0x51d2728b67bf952
1619 ])
1620 },
1621 y: Fp2 {
1622 c0: Fp::from_raw_unchecked([
1623 0x41b1bbf6576c0abf,
1624 0xb6cc93713f7a0f9a,
1625 0x6b65b43e48f3f01f,
1626 0xfb7a4cfcaf81be4f,
1627 0x3e32dadc6ec22cb6,
1628 0xbb0fc49d79807e3
1629 ]),
1630 c1: Fp::from_raw_unchecked([
1631 0x7d1397788f5f2ddf,
1632 0xab2907144ff0d8e8,
1633 0x5b7573e0cdb91f92,
1634 0x4cb8932dd31daf28,
1635 0x62bbfac6db052a54,
1636 0x11f95c16d14c3bbe
1637 ])
1638 },
1639 z: Fp2::one()
1640 })
1641 );
1642 assert!(!bool::from(c.is_identity()));
1643 assert!(bool::from(c.is_on_curve()));
1644 }
1645 }
1646
1647 #[test]
1648 fn test_projective_negation_and_subtraction() {
1649 let a = G2Projective::generator().double();
1650 assert_eq!(a + (-a), G2Projective::identity());
1651 assert_eq!(a + (-a), a - a);
1652 }
1653
1654 #[test]
1655 fn test_affine_negation_and_subtraction() {
1656 let a = G2Affine::generator();
1657 assert_eq!(G2Projective::from(a) + (-a), G2Projective::identity());
1658 assert_eq!(G2Projective::from(a) + (-a), G2Projective::from(a) - a);
1659 }
1660
1661 #[test]
1662 fn test_projective_scalar_multiplication() {
1663 let g = G2Projective::generator();
1664 let a = BlsScalar::from_raw([
1665 0x2b568297a56da71c,
1666 0xd8c39ecb0ef375d1,
1667 0x435c38da67bfbf96,
1668 0x8088a05026b659b2,
1669 ]);
1670 let b = BlsScalar::from_raw([
1671 0x785fdd9b26ef8b85,
1672 0xc997f25837695c18,
1673 0x4c8dbc39e7b756c1,
1674 0x70d9b6cc6d87df20,
1675 ]);
1676 let c = a * b;
1677
1678 assert_eq!((g * a) * b, g * c);
1679 }
1680
1681 #[test]
1682 fn test_affine_scalar_multiplication() {
1683 let g = G2Affine::generator();
1684 let a = BlsScalar::from_raw([
1685 0x2b568297a56da71c,
1686 0xd8c39ecb0ef375d1,
1687 0x435c38da67bfbf96,
1688 0x8088a05026b659b2,
1689 ]);
1690 let b = BlsScalar::from_raw([
1691 0x785fdd9b26ef8b85,
1692 0xc997f25837695c18,
1693 0x4c8dbc39e7b756c1,
1694 0x70d9b6cc6d87df20,
1695 ]);
1696 let c = a * b;
1697
1698 assert_eq!(G2Affine::from(g * a) * b, g * c);
1699 }
1700
1701 #[test]
1702 fn test_is_torsion_free() {
1703 let a = G2Affine {
1704 x: Fp2 {
1705 c0: Fp::from_raw_unchecked([
1706 0x89f550c813db6431,
1707 0xa50be8c456cd8a1a,
1708 0xa45b374114cae851,
1709 0xbb6190f5bf7fff63,
1710 0x970ca02c3ba80bc7,
1711 0x2b85d24e840fbac,
1712 ]),
1713 c1: Fp::from_raw_unchecked([
1714 0x6888bc53d70716dc,
1715 0x3dea6b4117682d70,
1716 0xd8f5f930500ca354,
1717 0x6b5ecb6556f5c155,
1718 0xc96bef0434778ab0,
1719 0x5081505515006ad,
1720 ]),
1721 },
1722 y: Fp2 {
1723 c0: Fp::from_raw_unchecked([
1724 0x3cf1ea0d434b0f40,
1725 0x1a0dc610e603e333,
1726 0x7f89956160c72fa0,
1727 0x25ee03decf6431c5,
1728 0xeee8e206ec0fe137,
1729 0x97592b226dfef28,
1730 ]),
1731 c1: Fp::from_raw_unchecked([
1732 0x71e8bb5f29247367,
1733 0xa5fe049e211831ce,
1734 0xce6b354502a3896,
1735 0x93b012000997314e,
1736 0x6759f3b6aa5b42ac,
1737 0x156944c4dfe92bbb,
1738 ]),
1739 },
1740 infinity: Choice::from(0u8),
1741 };
1742 assert!(!bool::from(a.is_torsion_free()));
1743
1744 assert!(bool::from(G2Affine::identity().is_torsion_free()));
1745 assert!(bool::from(G2Affine::generator().is_torsion_free()));
1746 }
1747
1748 #[cfg(feature = "endo")]
1749 #[test]
1750 fn test_mul_by_x() {
1751 let generator = G2Projective::generator();
1754 let x = if crate::BLS_X_IS_NEGATIVE {
1755 -BlsScalar::from(crate::BLS_X)
1756 } else {
1757 BlsScalar::from(crate::BLS_X)
1758 };
1759 assert_eq!(generator.mul_by_x(), generator * x);
1760
1761 let point = G2Projective::generator() * BlsScalar::from(42);
1762 assert_eq!(point.mul_by_x(), point * x);
1763 }
1764
1765 #[cfg(feature = "endo")]
1766 #[test]
1767 fn test_psi() {
1768 let generator = G2Projective::generator();
1769
1770 let point = G2Projective {
1772 x: Fp2 {
1773 c0: Fp::from_raw_unchecked([
1774 0xee4c8cb7c047eaf2,
1775 0x44ca22eee036b604,
1776 0x33b3affb2aefe101,
1777 0x15d3e45bbafaeb02,
1778 0x7bfc2154cd7419a4,
1779 0x0a2d0c2b756e5edc,
1780 ]),
1781 c1: Fp::from_raw_unchecked([
1782 0xfc224361029a8777,
1783 0x4cbf2baab8740924,
1784 0xc5008c6ec6592c89,
1785 0xecc2c57b472a9c2d,
1786 0x8613eafd9d81ffb1,
1787 0x10fe54daa2d3d495,
1788 ]),
1789 },
1790 y: Fp2 {
1791 c0: Fp::from_raw_unchecked([
1792 0x7de7edc43953b75c,
1793 0x58be1d2de35e87dc,
1794 0x5731d30b0e337b40,
1795 0xbe93b60cfeaae4c9,
1796 0x8b22c203764bedca,
1797 0x01616c8d1033b771,
1798 ]),
1799 c1: Fp::from_raw_unchecked([
1800 0xea126fe476b5733b,
1801 0x85cee68b5dae1652,
1802 0x98247779f7272b04,
1803 0xa649c8b468c6e808,
1804 0xb5b9a62dff0c4e45,
1805 0x1555b67fc7bbe73d,
1806 ]),
1807 },
1808 z: Fp2 {
1809 c0: Fp::from_raw_unchecked([
1810 0x0ef2ddffab187c0a,
1811 0x2424522b7d5ecbfc,
1812 0xc6f341a3398054f4,
1813 0x5523ddf409502df0,
1814 0xd55c0b5a88e0dd97,
1815 0x066428d704923e52,
1816 ]),
1817 c1: Fp::from_raw_unchecked([
1818 0x538bbe0c95b4878d,
1819 0xad04a50379522881,
1820 0x6d5c05bf5c12fb64,
1821 0x4ce4a069a2d34787,
1822 0x59ea6c8d0dffaeaf,
1823 0x0d42a083a75bd6f3,
1824 ]),
1825 },
1826 };
1827 assert!(bool::from(point.is_on_curve()));
1828
1829 assert_eq!(generator.psi2(), generator.psi().psi());
1831 assert_eq!(point.psi2(), point.psi().psi());
1832 assert_eq!(generator.double().psi(), generator.psi().double());
1834 assert_eq!(point.psi() + generator.psi(), (point + generator).psi());
1835 let mut normalized_point = [G2Affine::identity()];
1837 G2Projective::batch_normalize(&[point], &mut normalized_point);
1838 let normalized_point = G2Projective::from(normalized_point[0]);
1839 assert_eq!(point.psi(), normalized_point.psi());
1840 assert_eq!(point.psi2(), normalized_point.psi2());
1841 }
1842
1843 #[test]
1844 fn test_clear_cofactor() {
1845 let point = G2Projective {
1847 x: Fp2 {
1848 c0: Fp::from_raw_unchecked([
1849 0xee4c8cb7c047eaf2,
1850 0x44ca22eee036b604,
1851 0x33b3affb2aefe101,
1852 0x15d3e45bbafaeb02,
1853 0x7bfc2154cd7419a4,
1854 0x0a2d0c2b756e5edc,
1855 ]),
1856 c1: Fp::from_raw_unchecked([
1857 0xfc224361029a8777,
1858 0x4cbf2baab8740924,
1859 0xc5008c6ec6592c89,
1860 0xecc2c57b472a9c2d,
1861 0x8613eafd9d81ffb1,
1862 0x10fe54daa2d3d495,
1863 ]),
1864 },
1865 y: Fp2 {
1866 c0: Fp::from_raw_unchecked([
1867 0x7de7edc43953b75c,
1868 0x58be1d2de35e87dc,
1869 0x5731d30b0e337b40,
1870 0xbe93b60cfeaae4c9,
1871 0x8b22c203764bedca,
1872 0x01616c8d1033b771,
1873 ]),
1874 c1: Fp::from_raw_unchecked([
1875 0xea126fe476b5733b,
1876 0x85cee68b5dae1652,
1877 0x98247779f7272b04,
1878 0xa649c8b468c6e808,
1879 0xb5b9a62dff0c4e45,
1880 0x1555b67fc7bbe73d,
1881 ]),
1882 },
1883 z: Fp2 {
1884 c0: Fp::from_raw_unchecked([
1885 0x0ef2ddffab187c0a,
1886 0x2424522b7d5ecbfc,
1887 0xc6f341a3398054f4,
1888 0x5523ddf409502df0,
1889 0xd55c0b5a88e0dd97,
1890 0x066428d704923e52,
1891 ]),
1892 c1: Fp::from_raw_unchecked([
1893 0x538bbe0c95b4878d,
1894 0xad04a50379522881,
1895 0x6d5c05bf5c12fb64,
1896 0x4ce4a069a2d34787,
1897 0x59ea6c8d0dffaeaf,
1898 0x0d42a083a75bd6f3,
1899 ]),
1900 },
1901 };
1902
1903 assert!(bool::from(point.is_on_curve()));
1904 assert!(!bool::from(G2Affine::from(point).is_torsion_free()));
1905 let cleared_point = point.clear_cofactor();
1906
1907 assert!(bool::from(cleared_point.is_on_curve()));
1908 assert!(bool::from(G2Affine::from(cleared_point).is_torsion_free()));
1909
1910 let generator = G2Projective::generator();
1913 assert!(bool::from(generator.clear_cofactor().is_on_curve()));
1914 let id = G2Projective::identity();
1915 assert!(bool::from(id.clear_cofactor().is_on_curve()));
1916
1917 let h_eff_modq: [u8; 32] = [
1920 0xff, 0xff, 0x01, 0x00, 0x04, 0x00, 0x02, 0xa4, 0x09, 0x90, 0x06, 0x00, 0x04, 0x90,
1921 0x16, 0xb1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1922 0x00, 0x00, 0x00, 0x00,
1923 ];
1924 assert_eq!(generator.clear_cofactor(), generator.multiply(&h_eff_modq));
1925 assert_eq!(
1926 cleared_point.clear_cofactor(),
1927 cleared_point.multiply(&h_eff_modq)
1928 );
1929 }
1930
1931 #[test]
1932 fn test_batch_normalize() {
1933 let a = G2Projective::generator().double();
1934 let b = a.double();
1935 let c = b.double();
1936
1937 for a_identity in (0..1).map(|n| n == 1) {
1938 for b_identity in (0..1).map(|n| n == 1) {
1939 for c_identity in (0..1).map(|n| n == 1) {
1940 let mut v = [a, b, c];
1941 if a_identity {
1942 v[0] = G2Projective::identity()
1943 }
1944 if b_identity {
1945 v[1] = G2Projective::identity()
1946 }
1947 if c_identity {
1948 v[2] = G2Projective::identity()
1949 }
1950
1951 let mut t = [
1952 G2Affine::identity(),
1953 G2Affine::identity(),
1954 G2Affine::identity(),
1955 ];
1956 let expected = [
1957 G2Affine::from(v[0]),
1958 G2Affine::from(v[1]),
1959 G2Affine::from(v[2]),
1960 ];
1961
1962 G2Projective::batch_normalize(&v[..], &mut t[..]);
1963
1964 assert_eq!(&t[..], &expected[..]);
1965 }
1966 }
1967 }
1968 }
1969
1970 #[test]
1971 #[cfg(feature = "serde_req")]
1972 fn g2_affine_serde_roundtrip() {
1973 use bincode;
1974
1975 let gen = G2Affine::generator();
1976 let ser = bincode::serialize(&gen).unwrap();
1977 let deser: G2Affine = bincode::deserialize(&ser).unwrap();
1978
1979 assert_eq!(gen, deser);
1980 }
1981
1982 #[test]
1983 fn g2_affine_bytes_unchecked() {
1984 let gen = G2Affine::generator();
1985 let ident = G2Affine::identity();
1986
1987 let gen_p = gen.to_raw_bytes();
1988 let gen_p = unsafe { G2Affine::from_slice_unchecked(&gen_p) };
1989
1990 let ident_p = ident.to_raw_bytes();
1991 let ident_p = unsafe { G2Affine::from_slice_unchecked(&ident_p) };
1992
1993 assert_eq!(gen, gen_p);
1994 assert_eq!(ident, ident_p);
1995 }
1996
1997 #[test]
1998 fn g2_affine_hex() {
1999 use dusk_bytes::ParseHexStr;
2000
2001 let gen = G2Affine::generator();
2002 let ident = G2Affine::identity();
2003
2004 let gen_p = format!("{:x}", gen);
2005 let gen_p = G2Affine::from_hex_str(gen_p.as_str()).unwrap();
2006
2007 let ident_p = format!("{:x}", ident);
2008 let ident_p = G2Affine::from_hex_str(ident_p.as_str()).unwrap();
2009
2010 assert_eq!(gen, gen_p);
2011 assert_eq!(ident, ident_p);
2012 }
2013}