1#![allow(clippy::suspicious_arithmetic_impl)]
2use crate::bn256::curve::*;
3use crate::bn256::fq::*;
4use crate::bn256::fq12::*;
5use crate::bn256::fq2::*;
6use crate::bn256::fq6::FROBENIUS_COEFF_FQ6_C1;
7use crate::bn256::fr::*;
8use crate::ff::{Field, PrimeField};
9use crate::group::cofactor::CofactorCurveAffine;
10use crate::group::Group;
11use core::borrow::Borrow;
12use core::iter::Sum;
13use core::ops::{Add, Mul, MulAssign, Neg, Sub};
14use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
15use rand_core::RngCore;
16use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
17
18pub const BN_X: u64 = 4965661367192848881;
19
20pub const SIX_U_PLUS_2_NAF: [i8; 65] = [
22 0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0,
23 1, 1, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0,
24 0, 1, 0, 1, 1,
25];
26
27pub const XI_TO_Q_MINUS_1_OVER_2: Fq2 = Fq2 {
28 c0: Fq([
29 0xe4bbdd0c2936b629,
30 0xbb30f162e133bacb,
31 0x31a9d1b6f9645366,
32 0x253570bea500f8dd,
33 ]),
34 c1: Fq([
35 0xa1d77ce45ffe77c7,
36 0x07affd117826d1db,
37 0x6d16bd27bb7edc6b,
38 0x2c87200285defecc,
39 ]),
40};
41
42impl PairingCurveAffine for G1Affine {
43 type Pair = G2Affine;
44 type PairingResult = Gt;
45
46 fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
47 pairing(self, other)
48 }
49}
50
51impl PairingCurveAffine for G2Affine {
52 type Pair = G1Affine;
53 type PairingResult = Gt;
54
55 fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
56 pairing(other, self)
57 }
58}
59
60#[derive(Copy, Clone, Debug, Default)]
61pub struct Gt(pub(crate) Fq12);
62
63impl std::fmt::Display for Gt {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 write!(f, "{self:?}")
66 }
67}
68
69impl ConstantTimeEq for Gt {
70 fn ct_eq(&self, other: &Self) -> Choice {
71 self.0.ct_eq(&other.0)
72 }
73}
74
75impl ConditionallySelectable for Gt {
76 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
77 Gt(Fq12::conditional_select(&a.0, &b.0, choice))
78 }
79}
80
81impl Eq for Gt {}
82impl PartialEq for Gt {
83 #[inline]
84 fn eq(&self, other: &Self) -> bool {
85 bool::from(self.ct_eq(other))
86 }
87}
88
89impl Gt {
90 pub fn identity() -> Gt {
92 Gt(Fq12::ONE)
93 }
94
95 pub fn double(&self) -> Gt {
97 Gt(self.0.square())
98 }
99}
100
101impl<'a> Neg for &'a Gt {
102 type Output = Gt;
103
104 #[inline]
105 fn neg(self) -> Gt {
106 let mut u = self.0;
108 u.conjugate();
109 Gt(u)
110 }
111}
112
113impl Neg for Gt {
114 type Output = Gt;
115
116 #[inline]
117 fn neg(self) -> Gt {
118 -&self
119 }
120}
121
122impl<'a, 'b> Add<&'b Gt> for &'a Gt {
123 type Output = Gt;
124
125 #[inline]
126 fn add(self, rhs: &'b Gt) -> Gt {
127 Gt(self.0 * rhs.0)
128 }
129}
130
131impl<'a, 'b> Sub<&'b Gt> for &'a Gt {
132 type Output = Gt;
133
134 #[inline]
135 fn sub(self, rhs: &'b Gt) -> Gt {
136 self + (-rhs)
137 }
138}
139
140impl<'a, 'b> Mul<&'b Fr> for &'a Gt {
141 type Output = Gt;
142
143 fn mul(self, other: &'b Fr) -> Self::Output {
144 let mut acc = Gt::identity();
145
146 for bit in other
147 .to_repr()
148 .iter()
149 .rev()
150 .flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
151 .skip(1)
152 {
153 acc = acc.double();
154 acc = Gt::conditional_select(&acc, &(acc + self), bit);
155 }
156
157 acc
158 }
159}
160
161use crate::{
162 impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output,
163 impl_binops_multiplicative, impl_binops_multiplicative_mixed, impl_sub_binop_specify_output,
164};
165impl_binops_additive!(Gt, Gt);
166impl_binops_multiplicative!(Gt, Fr);
167
168impl<T> Sum<T> for Gt
169where
170 T: Borrow<Gt>,
171{
172 fn sum<I>(iter: I) -> Self
173 where
174 I: Iterator<Item = T>,
175 {
176 iter.fold(Self::identity(), |acc, item| acc + item.borrow())
177 }
178}
179
180impl Group for Gt {
181 type Scalar = Fr;
182
183 fn random(_: impl RngCore) -> Self {
184 unimplemented!();
185 }
186
187 fn identity() -> Self {
188 Self::identity()
189 }
190
191 fn generator() -> Self {
192 unimplemented!();
193 }
194
195 fn is_identity(&self) -> Choice {
196 self.ct_eq(&Self::identity())
197 }
198
199 #[must_use]
200 fn double(&self) -> Self {
201 self.double()
202 }
203}
204
205#[derive(Clone, Debug)]
206pub struct G2Prepared {
207 pub(crate) coeffs: Vec<(Fq2, Fq2, Fq2)>,
208 pub(crate) infinity: bool,
209}
210
211impl G2Prepared {
212 pub fn is_zero(&self) -> bool {
213 self.infinity
214 }
215
216 pub fn from_affine(q: G2Affine) -> Self {
217 if bool::from(q.is_identity()) {
218 return G2Prepared {
219 coeffs: vec![],
220 infinity: true,
221 };
222 }
223
224 fn doubling_step(r: &mut G2) -> (Fq2, Fq2, Fq2) {
225 let mut tmp0 = r.x;
227 tmp0.square_assign();
228
229 let mut tmp1 = r.y;
230 tmp1.square_assign();
231
232 let mut tmp2 = tmp1;
233 tmp2.square_assign();
234
235 let mut tmp3 = tmp1;
236 tmp3 += &r.x;
237 tmp3.square_assign();
238 tmp3 -= &tmp0;
239 tmp3 -= &tmp2;
240 tmp3.double_assign();
241
242 let mut tmp4 = tmp0;
243 tmp4.double_assign();
244 tmp4 += &tmp0;
245
246 let mut tmp6 = r.x;
247 tmp6 += &tmp4;
248
249 let mut tmp5 = tmp4;
250 tmp5.square_assign();
251
252 let mut zsquared = r.z;
253 zsquared.square_assign();
254
255 r.x = tmp5;
256 r.x -= &tmp3;
257 r.x -= &tmp3;
258
259 r.z += &r.y;
260 r.z.square_assign();
261 r.z -= &tmp1;
262 r.z -= &zsquared;
263
264 r.y = tmp3;
265 r.y -= &r.x;
266 r.y.mul_assign(&tmp4);
267
268 tmp2.double_assign();
269 tmp2.double_assign();
270 tmp2.double_assign();
271
272 r.y -= &tmp2;
273
274 tmp3 = tmp4;
279 tmp3.mul_assign(&zsquared);
280 tmp3.double_assign();
281 tmp3 = tmp3.neg();
282
283 tmp6.square_assign();
285 tmp6 -= &tmp0;
286 tmp6 -= &tmp5;
287
288 tmp1.double_assign();
289 tmp1.double_assign();
290
291 tmp6 -= &tmp1;
292
293 tmp0 = r.z;
295 tmp0.mul_assign(&zsquared);
296 tmp0.double_assign();
297
298 (tmp0, tmp3, tmp6)
299 }
300
301 fn addition_step(r: &mut G2, q: &G2Affine) -> (Fq2, Fq2, Fq2) {
302 let mut zsquared = r.z;
304 zsquared.square_assign();
305
306 let mut ysquared = q.y;
307 ysquared.square_assign();
308
309 let mut t0 = zsquared;
311 t0.mul_assign(&q.x);
312
313 let mut t1 = q.y;
315 t1 += &r.z;
316 t1.square_assign();
317 t1 -= &ysquared;
318 t1 -= &zsquared;
319 t1.mul_assign(&zsquared);
320
321 let mut t2 = t0;
323 t2 -= &r.x;
324
325 let mut t3 = t2;
327 t3.square_assign();
328
329 let mut t4 = t3;
331 t4.double_assign();
332 t4.double_assign();
333
334 let mut t5 = t4;
336 t5.mul_assign(&t2);
337
338 let mut t6 = t1;
340 t6 -= &r.y;
341 t6 -= &r.y;
342
343 let mut t9 = t6;
345 t9.mul_assign(&q.x);
346
347 let mut t7 = t4;
349 t7.mul_assign(&r.x);
350
351 r.x = t6;
353 r.x.square_assign();
354 r.x -= &t5;
355 r.x -= &t7;
356 r.x -= &t7;
357
358 r.z += &t2;
360 r.z.square_assign();
361 r.z -= &zsquared;
362 r.z -= &t3;
363
364 let mut t10 = q.y;
366 t10 += &r.z;
367
368 let mut t8 = t7;
370 t8 -= &r.x;
371 t8.mul_assign(&t6);
372
373 t0 = r.y;
375 t0.mul_assign(&t5);
376 t0.double_assign();
377
378 r.y = t8;
380 r.y -= &t0;
381
382 t10.square_assign();
384 t10 -= &ysquared;
385
386 let mut ztsquared = r.z;
387 ztsquared.square_assign();
388
389 t10 -= &ztsquared;
390
391 t9.double_assign();
393 t9 -= &t10;
394
395 t10 = r.z;
397 t10.double_assign();
398
399 t6 = t6.neg();
401
402 t1 = t6;
403 t1.double_assign();
404
405 (t10, t1, t9)
407 }
408
409 let mut coeffs = vec![];
410 let mut r: G2 = q.into();
411
412 let mut negq = q;
413 negq = -negq;
414
415 for i in (1..SIX_U_PLUS_2_NAF.len()).rev() {
416 coeffs.push(doubling_step(&mut r));
417 let x = SIX_U_PLUS_2_NAF[i - 1];
418 match x {
419 1 => {
420 coeffs.push(addition_step(&mut r, &q));
421 }
422 -1 => {
423 coeffs.push(addition_step(&mut r, &negq));
424 }
425 _ => continue,
426 }
427 }
428
429 let mut q1 = q;
430
431 q1.x.c1 = q1.x.c1.neg();
432 q1.x.mul_assign(&FROBENIUS_COEFF_FQ6_C1[1]);
433
434 q1.y.c1 = q1.y.c1.neg();
435 q1.y.mul_assign(&XI_TO_Q_MINUS_1_OVER_2);
436
437 coeffs.push(addition_step(&mut r, &q1));
438
439 let mut minusq2 = q;
440 minusq2.x.mul_assign(&FROBENIUS_COEFF_FQ6_C1[2]);
441
442 coeffs.push(addition_step(&mut r, &minusq2));
443
444 G2Prepared {
445 coeffs,
446 infinity: false,
447 }
448 }
449}
450
451impl From<G2Affine> for G2Prepared {
452 fn from(q: G2Affine) -> G2Prepared {
453 G2Prepared::from_affine(q)
454 }
455}
456
457impl MillerLoopResult for Gt {
458 type Gt = Self;
459 fn final_exponentiation(&self) -> Gt {
461 fn exp_by_x(f: &mut Fq12) {
462 let x = BN_X;
463 let mut res = Fq12::ONE;
464 for i in (0..64).rev() {
465 res.cyclotomic_square();
466 if ((x >> i) & 1) == 1 {
467 res.mul_assign(f);
468 }
469 }
470 *f = res;
471 }
472
473 let r = self.0;
474 let mut f1 = self.0;
475 f1.conjugate();
476
477 Gt(r.invert()
478 .map(|mut f2| {
479 let mut r = f1;
480 r.mul_assign(&f2);
481 f2 = r;
482 r.frobenius_map(2);
483 r.mul_assign(&f2);
484
485 let mut fp = r;
486 fp.frobenius_map(1);
487
488 let mut fp2 = r;
489 fp2.frobenius_map(2);
490 let mut fp3 = fp2;
491 fp3.frobenius_map(1);
492
493 let mut fu = r;
494 exp_by_x(&mut fu);
495
496 let mut fu2 = fu;
497 exp_by_x(&mut fu2);
498
499 let mut fu3 = fu2;
500 exp_by_x(&mut fu3);
501
502 let mut y3 = fu;
503 y3.frobenius_map(1);
504
505 let mut fu2p = fu2;
506 fu2p.frobenius_map(1);
507
508 let mut fu3p = fu3;
509 fu3p.frobenius_map(1);
510
511 let mut y2 = fu2;
512 y2.frobenius_map(2);
513
514 let mut y0 = fp;
515 y0.mul_assign(&fp2);
516 y0.mul_assign(&fp3);
517
518 let mut y1 = r;
519 y1.conjugate();
520
521 let mut y5 = fu2;
522 y5.conjugate();
523
524 y3.conjugate();
525
526 let mut y4 = fu;
527 y4.mul_assign(&fu2p);
528 y4.conjugate();
529
530 let mut y6 = fu3;
531 y6.mul_assign(&fu3p);
532 y6.conjugate();
533
534 y6.cyclotomic_square();
535 y6.mul_assign(&y4);
536 y6.mul_assign(&y5);
537
538 let mut t1 = y3;
539 t1.mul_assign(&y5);
540 t1.mul_assign(&y6);
541
542 y6.mul_assign(&y2);
543
544 t1.cyclotomic_square();
545 t1.mul_assign(&y6);
546 t1.cyclotomic_square();
547
548 let mut t0 = t1;
549 t0.mul_assign(&y1);
550
551 t1.mul_assign(&y0);
552
553 t0.cyclotomic_square();
554 t0.mul_assign(&t1);
555
556 t0
557 })
558 .unwrap())
559 }
560}
561
562pub fn multi_miller_loop(terms: &[(&G1Affine, &G2Prepared)]) -> Gt {
563 let mut pairs = vec![];
564 for &(p, q) in terms {
565 if !bool::from(p.is_identity()) && !q.is_zero() {
566 pairs.push((p, q.coeffs.iter()));
567 }
568 }
569
570 fn ell(f: &mut Fq12, coeffs: &(Fq2, Fq2, Fq2), p: &G1Affine) {
572 let mut c0 = coeffs.0;
573 let mut c1 = coeffs.1;
574
575 c0.c0.mul_assign(&p.y);
576 c0.c1.mul_assign(&p.y);
577
578 c1.c0.mul_assign(&p.x);
579 c1.c1.mul_assign(&p.x);
580
581 f.mul_by_034(&c0, &c1, &coeffs.2);
583 }
584
585 let mut f = Fq12::ONE;
586
587 for i in (1..SIX_U_PLUS_2_NAF.len()).rev() {
588 if i != SIX_U_PLUS_2_NAF.len() - 1 {
589 f.square_assign();
590 }
591 for &mut (p, ref mut coeffs) in &mut pairs {
592 ell(&mut f, coeffs.next().unwrap(), p);
593 }
594 let x = SIX_U_PLUS_2_NAF[i - 1];
595 match x {
596 1 => {
597 for &mut (p, ref mut coeffs) in &mut pairs {
598 ell(&mut f, coeffs.next().unwrap(), p);
599 }
600 }
601 -1 => {
602 for &mut (p, ref mut coeffs) in &mut pairs {
603 ell(&mut f, coeffs.next().unwrap(), p);
604 }
605 }
606 _ => continue,
607 }
608 }
609
610 for &mut (p, ref mut coeffs) in &mut pairs {
611 ell(&mut f, coeffs.next().unwrap(), p);
612 }
613
614 for &mut (p, ref mut coeffs) in &mut pairs {
615 ell(&mut f, coeffs.next().unwrap(), p);
616 }
617
618 for &mut (_p, ref mut coeffs) in &mut pairs {
619 assert_eq!(coeffs.next(), None);
620 }
621
622 Gt(f)
623}
624
625pub fn pairing(g1: &G1Affine, g2: &G2Affine) -> Gt {
626 let g2 = G2Prepared::from_affine(*g2);
627 let terms: &[(&G1Affine, &G2Prepared)] = &[(g1, &g2)];
628 let u = multi_miller_loop(terms);
629 u.final_exponentiation()
630}
631
632#[derive(Clone, Debug)]
633pub struct Bn256;
634
635impl Engine for Bn256 {
636 type Fr = Fr;
637 type G1 = G1;
638 type G1Affine = G1Affine;
639 type G2 = G2;
640 type G2Affine = G2Affine;
641 type Gt = Gt;
642
643 fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
644 pairing(p, q)
645 }
646}
647
648impl MultiMillerLoop for Bn256 {
649 type G2Prepared = G2Prepared;
650 type Result = Gt;
651
652 fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result {
653 multi_miller_loop(terms)
654 }
655}
656
657#[cfg(test)]
658use rand::SeedableRng;
659#[cfg(test)]
660use rand_xorshift::XorShiftRng;
661
662#[test]
663fn test_pairing() {
664 let g1 = G1::generator();
665 let mut g2 = G2::generator();
666 g2 = g2.double();
667 let pair12 = Bn256::pairing(&G1Affine::from(g1), &G2Affine::from(g2));
668
669 let mut g1 = G1::generator();
670 let g2 = G2::generator();
671 g1 = g1.double();
672 let pair21 = Bn256::pairing(&G1Affine::from(g1), &G2Affine::from(g2));
673
674 assert_eq!(pair12, pair21);
675
676 let g1 = G1::generator();
677 let mut g2 = G2::generator();
678 g2 = g2.double().double();
679 let pair12 = Bn256::pairing(&G1Affine::from(g1), &G2Affine::from(g2));
680
681 let mut g1 = G1::generator();
682 let mut g2 = G2::generator();
683 g1 = g1.double();
684 g2 = g2.double();
685 let pair21 = Bn256::pairing(&G1Affine::from(g1), &G2Affine::from(g2));
686
687 assert_eq!(pair12, pair21);
688
689 let mut rng = XorShiftRng::from_seed([
690 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
691 0xe5,
692 ]);
693 for _ in 0..1000 {
694 let a = Fr::random(&mut rng);
695 let b = Fr::random(&mut rng);
696
697 let mut g1 = G1::generator();
698 g1.mul_assign(a);
699
700 let mut g2 = G2::generator();
701 g1.mul_assign(b);
702
703 let pair_ab = Bn256::pairing(&G1Affine::from(g1), &G2Affine::from(g2));
704
705 g1 = G1::generator();
706 g1.mul_assign(b);
707
708 g2 = G2::generator();
709 g1.mul_assign(a);
710
711 let pair_ba = Bn256::pairing(&G1Affine::from(g1), &G2Affine::from(g2));
712
713 assert_eq!(pair_ab, pair_ba);
714 }
715}
716
717#[test]
718fn random_bilinearity_tests() {
719 let mut rng = XorShiftRng::from_seed([
720 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
721 0xe5,
722 ]);
723
724 for _ in 0..1000 {
725 let mut a = G1::generator();
726 let ka = Fr::random(&mut rng);
727 a.mul_assign(ka);
728
729 let mut b = G2::generator();
730 let kb = Fr::random(&mut rng);
731 b.mul_assign(kb);
732
733 let c = Fr::random(&mut rng);
734 let d = Fr::random(&mut rng);
735
736 let mut ac = a;
737 ac.mul_assign(c);
738
739 let mut ad = a;
740 ad.mul_assign(d);
741
742 let mut bc = b;
743 bc.mul_assign(c);
744
745 let mut bd = b;
746 bd.mul_assign(d);
747
748 let acbd = Bn256::pairing(&G1Affine::from(ac), &G2Affine::from(bd));
749 let adbc = Bn256::pairing(&G1Affine::from(ad), &G2Affine::from(bc));
750
751 let mut cd = c;
752 cd.mul_assign(&d);
753
754 cd *= Fr([1, 0, 0, 0]);
755
756 let abcd = Gt(Bn256::pairing(&G1Affine::from(a), &G2Affine::from(b))
757 .0
758 .pow_vartime(cd.0));
759
760 assert_eq!(acbd, adbc);
761 assert_eq!(acbd, abcd);
762 }
763}
764
765#[test]
766pub fn engine_tests() {
767 let mut rng = XorShiftRng::from_seed([
768 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
769 0xe5,
770 ]);
771
772 for _ in 0..10 {
773 let a = G1Affine::from(G1::random(&mut rng));
774 let b = G2Affine::from(G2::random(&mut rng));
775
776 assert!(a.pairing_with(&b) == b.pairing_with(&a));
777 assert!(a.pairing_with(&b) == pairing(&a, &b));
778 }
779
780 for _ in 0..1000 {
781 let z1 = G1Affine::identity();
782 let z2 = G2Prepared::from(G2Affine::identity());
783
784 let a = G1Affine::from(G1::random(&mut rng));
785 let b = G2Prepared::from(G2Affine::from(G2::random(&mut rng)));
786 let c = G1Affine::from(G1::random(&mut rng));
787 let d = G2Prepared::from(G2Affine::from(G2::random(&mut rng)));
788
789 assert_eq!(
790 Fq12::ONE,
791 multi_miller_loop(&[(&z1, &b)]).final_exponentiation().0,
792 );
793
794 assert_eq!(
795 Fq12::ONE,
796 multi_miller_loop(&[(&a, &z2)]).final_exponentiation().0,
797 );
798
799 assert_eq!(
800 multi_miller_loop(&[(&z1, &b), (&c, &d)]).final_exponentiation(),
801 multi_miller_loop(&[(&a, &z2), (&c, &d)]).final_exponentiation(),
802 );
803
804 assert_eq!(
805 multi_miller_loop(&[(&a, &b), (&z1, &d)]).final_exponentiation(),
806 multi_miller_loop(&[(&a, &b), (&c, &z2)]).final_exponentiation(),
807 );
808 }
809}
810
811#[test]
812fn random_miller_loop_tests() {
813 let mut rng = XorShiftRng::from_seed([
814 0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
815 0xe5,
816 ]);
817
818 for _ in 0..1000 {
820 let a = G1Affine::from(G1::random(&mut rng));
821 let b = G2Affine::from(G2::random(&mut rng));
822 let c = G1Affine::from(G1::random(&mut rng));
823 let d = G2Affine::from(G2::random(&mut rng));
824
825 let ab = pairing(&a, &b);
826 let cd = pairing(&c, &d);
827
828 let mut abcd = ab;
829 abcd = Gt(abcd.0 * cd.0);
830
831 let b = G2Prepared::from(b);
832 let d = G2Prepared::from(d);
833
834 let abcd_with_double_loop = multi_miller_loop(&[(&a, &b), (&c, &d)]).final_exponentiation();
835
836 assert_eq!(abcd, abcd_with_double_loop);
837 }
838}