zksync_pairing/compact_bn256/
mod.rs1mod ec;
2pub mod fq;
3pub mod fq12;
4pub mod fq2;
5pub mod fq6;
6pub mod fr;
7
8pub use self::ec::{G1Affine, G1Compressed, G1Prepared, G1Uncompressed, G2Affine, G2Compressed, G2Prepared, G2Uncompressed, G1, G2};
12pub use self::fq::{Fq, FqRepr, FROBENIUS_COEFF_FQ6_C1, XI_TO_Q_MINUS_1_OVER_2};
13pub use self::fq12::Fq12;
14pub use self::fq2::Fq2;
15pub use self::fq6::Fq6;
16pub use self::fr::{Fr, FrRepr};
17
18use super::{CurveAffine, Engine};
19
20use ff::{Field, ScalarEngine};
21
22#[derive(Clone, Copy, Debug)]
23pub struct Bn256;
24
25pub const BN_U: u64 = 4965661367192848881;
27
28pub const SIX_U_PLUS_2_NAF: [i8; 65] = [
30 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, 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, 0, 1,
31 0, 1, 1,
32];
33
34impl ScalarEngine for Bn256 {
35 type Fr = Fr;
36}
37
38impl Engine for Bn256 {
39 type G1 = G1;
40 type G1Affine = G1Affine;
41 type G2 = G2;
42 type G2Affine = G2Affine;
43 type Fq = Fq;
44 type Fqe = Fq2;
45 type Fqk = Fq12;
46
47 fn miller_loop<'a, I>(i: I) -> Self::Fqk
48 where
49 I: IntoIterator<Item = &'a (&'a <Self::G1Affine as CurveAffine>::Prepared, &'a <Self::G2Affine as CurveAffine>::Prepared)>,
50 {
51 let mut pairs = vec![];
52 for &(p, q) in i {
53 if !p.is_zero() && !q.is_zero() {
54 pairs.push((p, q.coeffs.iter()));
55 }
56 }
57
58 fn ell(f: &mut Fq12, coeffs: &(Fq2, Fq2, Fq2), p: &G1Affine) {
60 let mut c0 = coeffs.0;
61 let mut c1 = coeffs.1;
62
63 c0.c0.mul_assign(&p.y);
64 c0.c1.mul_assign(&p.y);
65
66 c1.c0.mul_assign(&p.x);
67 c1.c1.mul_assign(&p.x);
68
69 f.mul_by_034(&c0, &c1, &coeffs.2);
71 }
72
73 let mut f = Fq12::one();
74
75 for i in (1..SIX_U_PLUS_2_NAF.len()).rev() {
76 if i != SIX_U_PLUS_2_NAF.len() - 1 {
77 f.square();
78 }
79 for &mut (p, ref mut coeffs) in &mut pairs {
80 ell(&mut f, coeffs.next().unwrap(), &p.0);
81 }
82 let x = SIX_U_PLUS_2_NAF[i - 1];
83 match x {
84 1 => {
85 for &mut (p, ref mut coeffs) in &mut pairs {
86 ell(&mut f, coeffs.next().unwrap(), &p.0);
87 }
88 }
89 -1 => {
90 for &mut (p, ref mut coeffs) in &mut pairs {
91 ell(&mut f, coeffs.next().unwrap(), &p.0);
92 }
93 }
94 _ => continue,
95 }
96 }
97
98 for &mut (p, ref mut coeffs) in &mut pairs {
101 ell(&mut f, coeffs.next().unwrap(), &p.0);
102 }
103
104 for &mut (p, ref mut coeffs) in &mut pairs {
105 ell(&mut f, coeffs.next().unwrap(), &p.0);
106 }
107
108 for &mut (_p, ref mut coeffs) in &mut pairs {
109 assert_eq!(coeffs.next(), None);
110 }
111
112 f
113 }
114
115 fn final_exponentiation(r: &Fq12) -> Option<Fq12> {
116 let mut f1 = *r;
117 f1.conjugate();
118
119 match r.inverse() {
120 Some(mut f2) => {
121 let mut r = f1;
122 r.mul_assign(&f2);
123 f2 = r;
124 r.frobenius_map(2);
125 r.mul_assign(&f2);
126
127 fn exp_by_x(f: &mut Fq12, x: u64) {
128 *f = f.pow(&[x]);
129 }
130
131 let x = BN_U;
132
133 let mut fp = r;
134 fp.frobenius_map(1);
135
136 let mut fp2 = r;
137 fp2.frobenius_map(2);
138 let mut fp3 = fp2;
139 fp3.frobenius_map(1);
140
141 let mut fu = r;
142 exp_by_x(&mut fu, x);
143
144 let mut fu2 = fu;
145 exp_by_x(&mut fu2, x);
146
147 let mut fu3 = fu2;
148 exp_by_x(&mut fu3, x);
149
150 let mut y3 = fu;
151 y3.frobenius_map(1);
152
153 let mut fu2p = fu2;
154 fu2p.frobenius_map(1);
155
156 let mut fu3p = fu3;
157 fu3p.frobenius_map(1);
158
159 let mut y2 = fu2;
160 y2.frobenius_map(2);
161
162 let mut y0 = fp;
163 y0.mul_assign(&fp2);
164 y0.mul_assign(&fp3);
165
166 let mut y1 = r;
167 y1.conjugate();
168
169 let mut y5 = fu2;
170 y5.conjugate();
171
172 y3.conjugate();
173
174 let mut y4 = fu;
175 y4.mul_assign(&fu2p);
176 y4.conjugate();
177
178 let mut y6 = fu3;
179 y6.mul_assign(&fu3p);
180 y6.conjugate();
181
182 y6.square();
183 y6.mul_assign(&y4);
184 y6.mul_assign(&y5);
185
186 let mut t1 = y3;
187 t1.mul_assign(&y5);
188 t1.mul_assign(&y6);
189
190 y6.mul_assign(&y2);
191
192 t1.square();
193 t1.mul_assign(&y6);
194 t1.square();
195
196 let mut t0 = t1;
197 t0.mul_assign(&y1);
198
199 t1.mul_assign(&y0);
200
201 t0.square();
202 t0.mul_assign(&t1);
203
204 Some(t0)
205 }
206 None => None,
207 }
208 }
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 q.is_zero() {
218 return G2Prepared { coeffs: vec![], infinity: true };
219 }
220
221 fn doubling_step(r: &mut G2) -> (Fq2, Fq2, Fq2) {
222 let mut tmp0 = r.x;
224 tmp0.square();
225
226 let mut tmp1 = r.y;
227 tmp1.square();
228
229 let mut tmp2 = tmp1;
230 tmp2.square();
231
232 let mut tmp3 = tmp1;
233 tmp3.add_assign(&r.x);
234 tmp3.square();
235 tmp3.sub_assign(&tmp0);
236 tmp3.sub_assign(&tmp2);
237 tmp3.double();
238
239 let mut tmp4 = tmp0;
240 tmp4.double();
241 tmp4.add_assign(&tmp0);
242
243 let mut tmp6 = r.x;
244 tmp6.add_assign(&tmp4);
245
246 let mut tmp5 = tmp4;
247 tmp5.square();
248
249 let mut zsquared = r.z;
250 zsquared.square();
251
252 r.x = tmp5;
253 r.x.sub_assign(&tmp3);
254 r.x.sub_assign(&tmp3);
255
256 r.z.add_assign(&r.y);
257 r.z.square();
258 r.z.sub_assign(&tmp1);
259 r.z.sub_assign(&zsquared);
260
261 r.y = tmp3;
262 r.y.sub_assign(&r.x);
263 r.y.mul_assign(&tmp4);
264
265 tmp2.double();
266 tmp2.double();
267 tmp2.double();
268
269 r.y.sub_assign(&tmp2);
270
271 tmp3 = tmp4;
276 tmp3.mul_assign(&zsquared);
277 tmp3.double();
278 tmp3.negate();
279
280 tmp6.square();
282 tmp6.sub_assign(&tmp0);
283 tmp6.sub_assign(&tmp5);
284
285 tmp1.double();
286 tmp1.double();
287
288 tmp6.sub_assign(&tmp1);
289
290 tmp0 = r.z;
292 tmp0.mul_assign(&zsquared);
293 tmp0.double();
294
295 (tmp0, tmp3, tmp6)
296 }
297
298 fn addition_step(r: &mut G2, q: &G2Affine) -> (Fq2, Fq2, Fq2) {
299 let mut zsquared = r.z;
301 zsquared.square();
302
303 let mut ysquared = q.y;
304 ysquared.square();
305
306 let mut t0 = zsquared;
308 t0.mul_assign(&q.x);
309
310 let mut t1 = q.y;
312 t1.add_assign(&r.z);
313 t1.square();
314 t1.sub_assign(&ysquared);
315 t1.sub_assign(&zsquared);
316 t1.mul_assign(&zsquared);
317
318 let mut t2 = t0;
320 t2.sub_assign(&r.x);
321
322 let mut t3 = t2;
324 t3.square();
325
326 let mut t4 = t3;
328 t4.double();
329 t4.double();
330
331 let mut t5 = t4;
333 t5.mul_assign(&t2);
334
335 let mut t6 = t1;
337 t6.sub_assign(&r.y);
338 t6.sub_assign(&r.y);
339
340 let mut t9 = t6;
342 t9.mul_assign(&q.x);
343
344 let mut t7 = t4;
346 t7.mul_assign(&r.x);
347
348 r.x = t6;
350 r.x.square();
351 r.x.sub_assign(&t5);
352 r.x.sub_assign(&t7);
353 r.x.sub_assign(&t7);
354
355 r.z.add_assign(&t2);
357 r.z.square();
358 r.z.sub_assign(&zsquared);
359 r.z.sub_assign(&t3);
360
361 let mut t10 = q.y;
363 t10.add_assign(&r.z);
364
365 let mut t8 = t7;
367 t8.sub_assign(&r.x);
368 t8.mul_assign(&t6);
369
370 t0 = r.y;
372 t0.mul_assign(&t5);
373 t0.double();
374
375 r.y = t8;
377 r.y.sub_assign(&t0);
378
379 t10.square();
381 t10.sub_assign(&ysquared);
382
383 let mut ztsquared = r.z;
384 ztsquared.square();
385
386 t10.sub_assign(&ztsquared);
387
388 t9.double();
390 t9.sub_assign(&t10);
391
392 t10 = r.z;
394 t10.double();
395
396 t6.negate();
398
399 t1 = t6;
400 t1.double();
401
402 (t10, t1, t9)
404 }
405
406 let mut coeffs = vec![];
407 let mut r: G2 = q.into();
408
409 let mut negq = q;
410 negq.negate();
411
412 for i in (1..SIX_U_PLUS_2_NAF.len()).rev() {
413 coeffs.push(doubling_step(&mut r));
414 let x = SIX_U_PLUS_2_NAF[i - 1];
415 match x {
416 1 => {
417 coeffs.push(addition_step(&mut r, &q));
418 }
419 -1 => {
420 coeffs.push(addition_step(&mut r, &negq));
421 }
422 _ => continue,
423 }
424 }
425
426 let mut q1 = q;
427
428 q1.x.c1.negate();
429 q1.x.mul_assign(&FROBENIUS_COEFF_FQ6_C1[1]);
430
431 q1.y.c1.negate();
432 q1.y.mul_assign(&XI_TO_Q_MINUS_1_OVER_2);
433
434 coeffs.push(addition_step(&mut r, &q1));
435
436 let mut minusq2 = q;
437 minusq2.x.mul_assign(&FROBENIUS_COEFF_FQ6_C1[2]);
438
439 coeffs.push(addition_step(&mut r, &minusq2));
440
441 G2Prepared { coeffs, infinity: false }
442 }
443}
444
445#[cfg(test)]
446use rand::{Rand, SeedableRng, XorShiftRng};
447
448#[test]
449fn test_pairing() {
450 use crate::CurveProjective;
451 let mut g1 = G1::one();
452
453 let mut g2 = G2::one();
454 g2.double();
455
456 let pair12 = Bn256::pairing(g1, g2);
457
458 g1 = G1::one();
459 g1.double();
460
461 g2 = G2::one();
462
463 let pair21 = Bn256::pairing(g1, g2);
464
465 assert_eq!(pair12, pair21);
466
467 g1 = G1::one();
470 g1.double();
471 g1.double();
472
473 let pair41 = Bn256::pairing(g1, g2);
474
475 g1 = G1::one();
476 g1.double();
477
478 g2.double();
479
480 let pair22 = Bn256::pairing(g1, g2);
481
482 assert_eq!(pair41, pair22);
483
484 g1 = G1::one();
485 g1.double();
486 g1.add_assign(&G1::one());
487
488 g2 = G2::one();
489 g2.double();
490
491 let pair32 = Bn256::pairing(g1, g2);
492
493 g2 = G2::one();
494 g2.double();
495 g2.add_assign(&G2::one());
496
497 g1 = G1::one();
498 g1.double();
499
500 let pair23 = Bn256::pairing(g1, g2);
501
502 assert_eq!(pair23, pair32);
503
504 let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
505
506 for _ in 0..1000 {
507 let a = Fr::rand(&mut rng);
508 let b = Fr::rand(&mut rng);
509
510 let mut g1 = G1::one();
511 g1.mul_assign(a);
512
513 let mut g2 = G2::one();
514 g1.mul_assign(b);
515
516 let pair_ab = Bn256::pairing(g1, g2);
517
518 g1 = G1::one();
519 g1.mul_assign(b);
520
521 g2 = G2::one();
522 g1.mul_assign(a);
523
524 let pair_ba = Bn256::pairing(g1, g2);
525
526 assert_eq!(pair_ab, pair_ba);
527 }
528}
529
530#[test]
531fn random_bilinearity_tests() {
532 use crate::CurveProjective;
533 use ff::PrimeField;
534
535 let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
536
537 for _ in 0..1000 {
538 let mut a = G1::one();
539 let ka = Fr::rand(&mut rng);
540 a.mul_assign(ka);
541 let mut b = G2::one();
542 let kb = Fr::rand(&mut rng);
543 b.mul_assign(kb);
544
545 let c = Fr::rand(&mut rng);
546 let d = Fr::rand(&mut rng);
547
548 let mut ac = a;
549 ac.mul_assign(c);
550
551 let mut ad = a;
552 ad.mul_assign(d);
553
554 let mut bc = b;
555 bc.mul_assign(c);
556
557 let mut bd = b;
558 bd.mul_assign(d);
559
560 let acbd = Bn256::pairing(ac, bd);
561 let adbc = Bn256::pairing(ad, bc);
562
563 let mut cd = c;
564 cd.mul_assign(&d);
565
566 let abcd = Bn256::pairing(a, b).pow(cd.into_repr());
567
568 assert_eq!(acbd, adbc);
569 assert_eq!(acbd, abcd);
570 }
571}
572
573#[test]
574#[ignore] fn bn256_engine_tests() {
576 crate::tests::engine::engine_tests::<Bn256>();
577}