Clearmatics Libff  0.1
C++ library for Finite Fields and Elliptic Curves
mnt6_pairing.cpp
Go to the documentation of this file.
1 
14 #include <cassert>
21 
22 namespace libff
23 {
24 
26 {
27  return (
28  this->PX == other.PX && this->PY == other.PY &&
29  this->PX_twist == other.PX_twist && this->PY_twist == other.PY_twist);
30 }
31 
32 std::ostream &operator<<(std::ostream &out, const mnt6_ate_G1_precomp &prec_P)
33 {
34  out << prec_P.PX << OUTPUT_SEPARATOR << prec_P.PY << OUTPUT_SEPARATOR
35  << prec_P.PX_twist << OUTPUT_SEPARATOR << prec_P.PY_twist;
36 
37  return out;
38 }
39 
40 std::istream &operator>>(std::istream &in, mnt6_ate_G1_precomp &prec_P)
41 {
42  in >> prec_P.PX;
44  in >> prec_P.PY;
46  in >> prec_P.PX_twist;
48  in >> prec_P.PY_twist;
49 
50  return in;
51 }
52 
54 {
55  return (
56  this->c_H == other.c_H && this->c_4C == other.c_4C &&
57  this->c_J == other.c_J && this->c_L == other.c_L);
58 }
59 
60 std::ostream &operator<<(std::ostream &out, const mnt6_ate_dbl_coeffs &dc)
61 {
62  out << dc.c_H << OUTPUT_SEPARATOR << dc.c_4C << OUTPUT_SEPARATOR << dc.c_J
63  << OUTPUT_SEPARATOR << dc.c_L;
64  return out;
65 }
66 
67 std::istream &operator>>(std::istream &in, mnt6_ate_dbl_coeffs &dc)
68 {
69  in >> dc.c_H;
71  in >> dc.c_4C;
73  in >> dc.c_J;
75  in >> dc.c_L;
76 
77  return in;
78 }
79 
81 {
82  return (this->c_L1 == other.c_L1 && this->c_RZ == other.c_RZ);
83 }
84 
85 std::ostream &operator<<(std::ostream &out, const mnt6_ate_add_coeffs &ac)
86 {
87  out << ac.c_L1 << OUTPUT_SEPARATOR << ac.c_RZ;
88  return out;
89 }
90 
91 std::istream &operator>>(std::istream &in, mnt6_ate_add_coeffs &ac)
92 {
93  in >> ac.c_L1;
95  in >> ac.c_RZ;
96 
97  return in;
98 }
99 
101 {
102  return (
103  this->QX == other.QX && this->QY == other.QY &&
104  this->QY2 == other.QY2 && this->QX_over_twist == other.QX_over_twist &&
105  this->QY_over_twist == other.QY_over_twist &&
106  this->dbl_coeffs == other.dbl_coeffs &&
107  this->add_coeffs == other.add_coeffs);
108 }
109 
110 std::ostream &operator<<(std::ostream &out, const mnt6_ate_G2_precomp &prec_Q)
111 {
112  out << prec_Q.QX << OUTPUT_SEPARATOR << prec_Q.QY << OUTPUT_SEPARATOR
113  << prec_Q.QY2 << OUTPUT_SEPARATOR << prec_Q.QX_over_twist
114  << OUTPUT_SEPARATOR << prec_Q.QY_over_twist << "\n";
115  out << prec_Q.dbl_coeffs.size() << "\n";
116  for (const mnt6_ate_dbl_coeffs &dc : prec_Q.dbl_coeffs) {
117  out << dc << OUTPUT_NEWLINE;
118  }
119  out << prec_Q.add_coeffs.size() << "\n";
120  for (const mnt6_ate_add_coeffs &ac : prec_Q.add_coeffs) {
121  out << ac << OUTPUT_NEWLINE;
122  }
123 
124  return out;
125 }
126 
127 std::istream &operator>>(std::istream &in, mnt6_ate_G2_precomp &prec_Q)
128 {
129  in >> prec_Q.QX;
131  in >> prec_Q.QY;
133  in >> prec_Q.QY2;
135  in >> prec_Q.QX_over_twist;
137  in >> prec_Q.QY_over_twist;
138  consume_newline(in);
139 
140  prec_Q.dbl_coeffs.clear();
141  size_t dbl_s;
142  in >> dbl_s;
143  consume_newline(in);
144 
145  prec_Q.dbl_coeffs.reserve(dbl_s);
146 
147  for (size_t i = 0; i < dbl_s; ++i) {
149  in >> dc;
151  prec_Q.dbl_coeffs.emplace_back(dc);
152  }
153 
154  prec_Q.add_coeffs.clear();
155  size_t add_s;
156  in >> add_s;
157  consume_newline(in);
158 
159  prec_Q.add_coeffs.reserve(add_s);
160 
161  for (size_t i = 0; i < add_s; ++i) {
163  in >> ac;
165  prec_Q.add_coeffs.emplace_back(ac);
166  }
167 
168  return in;
169 }
170 
171 /* final exponentiations */
172 
174  const mnt6_Fq6 &elt, const mnt6_Fq6 &elt_inv)
175 {
176  enter_block("Call to mnt6_final_exponentiation_last_chunk");
177  const mnt6_Fq6 elt_q = elt.Frobenius_map(1);
179  mnt6_Fq6 w0_part;
181  w0_part =
183  } else {
185  }
186  mnt6_Fq6 result = w1_part * w0_part;
187  leave_block("Call to mnt6_final_exponentiation_last_chunk");
188 
189  return result;
190 }
191 
193  const mnt6_Fq6 &elt, const mnt6_Fq6 &elt_inv)
194 {
195  enter_block("Call to mnt6_final_exponentiation_first_chunk");
196 
197  /* (q^3-1)*(q+1) */
198 
199  /* elt_q3 = elt^(q^3) */
200  const mnt6_Fq6 elt_q3 = elt.Frobenius_map(3);
201  /* elt_q3_over_elt = elt^(q^3-1) */
202  const mnt6_Fq6 elt_q3_over_elt = elt_q3 * elt_inv;
203  /* alpha = elt^((q^3-1) * q) */
204  const mnt6_Fq6 alpha = elt_q3_over_elt.Frobenius_map(1);
205  /* beta = elt^((q^3-1)*(q+1) */
206  const mnt6_Fq6 beta = alpha * elt_q3_over_elt;
207  leave_block("Call to mnt6_final_exponentiation_first_chunk");
208  return beta;
209 }
210 
212 {
213  enter_block("Call to mnt6_final_exponentiation");
214  const mnt6_Fq6 elt_inv = elt.inverse();
215  const mnt6_Fq6 elt_to_first_chunk =
217  const mnt6_Fq6 elt_inv_to_first_chunk =
220  elt_to_first_chunk, elt_inv_to_first_chunk);
221  leave_block("Call to mnt6_final_exponentiation");
222 
223  return result;
224 }
225 
226 /* affine ate miller loop */
227 
229  const mnt6_G1 &P)
230 {
231  enter_block("Call to mnt6_affine_ate_precompute_G1");
232 
233  mnt6_G1 Pcopy = P;
234  Pcopy.to_affine_coordinates();
235 
237  result.PX = Pcopy.X;
238  result.PY = Pcopy.Y;
239  result.PY_twist_squared = Pcopy.Y * mnt6_twist.squared();
240 
241  leave_block("Call to mnt6_affine_ate_precompute_G1");
242  return result;
243 }
244 
246  const mnt6_G2 &Q)
247 {
248  enter_block("Call to mnt6_affine_ate_precompute_G2");
249 
250  mnt6_G2 Qcopy(Q);
251  Qcopy.to_affine_coordinates();
252 
254  result.QX = Qcopy.X;
255  result.QY = Qcopy.Y;
256 
257  mnt6_Fq3 RX = Qcopy.X;
258  mnt6_Fq3 RY = Qcopy.Y;
259 
261  bool found_nonzero = false;
262 
263  std::vector<long> NAF = find_wnaf(1, loop_count);
264  for (long i = NAF.size() - 1; i >= 0; --i) {
265  if (!found_nonzero) {
266  /* this skips the MSB itself */
267  found_nonzero |= (NAF[i] != 0);
268  continue;
269  }
270 
272  c.old_RX = RX;
273  c.old_RY = RY;
274  mnt6_Fq3 old_RX_2 = c.old_RX.squared();
275  c.gamma = (old_RX_2 + old_RX_2 + old_RX_2 + mnt6_twist_coeff_a) *
276  (c.old_RY + c.old_RY).inverse();
277  c.gamma_twist = c.gamma * mnt6_twist;
278  c.gamma_X = c.gamma * c.old_RX;
279  result.coeffs.push_back(c);
280 
281  RX = c.gamma.squared() - (c.old_RX + c.old_RX);
282  RY = c.gamma * (c.old_RX - RX) - c.old_RY;
283 
284  if (NAF[i] != 0) {
286  c.old_RX = RX;
287  c.old_RY = RY;
288  if (NAF[i] > 0) {
289  c.gamma =
290  (c.old_RY - result.QY) * (c.old_RX - result.QX).inverse();
291  } else {
292  c.gamma =
293  (c.old_RY + result.QY) * (c.old_RX - result.QX).inverse();
294  }
295  c.gamma_twist = c.gamma * mnt6_twist;
296  c.gamma_X = c.gamma * result.QX;
297  result.coeffs.push_back(c);
298 
299  RX = c.gamma.squared() - (c.old_RX + result.QX);
300  RY = c.gamma * (c.old_RX - RX) - c.old_RY;
301  }
302  }
303 
304  /* TODO: maybe handle neg
305  if (mnt6_ate_is_loop_count_neg)
306  {
307  mnt6_ate_add_coeffs ac;
308  mnt6_affine_ate_dbl_coeffs c;
309  c.old_RX = RX;
310  c.old_RY = -RY;
311  old_RX_2 = c.old_RY.squared();
312  c.gamma = (old_RX_2 + old_RX_2 + old_RX_2 + mnt6_coeff_a) *
313  (c.old_RY + c.old_RY).inverse(); c.gamma_twist = c.gamma * mnt6_twist;
314  c.gamma_X = c.gamma * c.old_RX;
315  result.coeffs.push_back(c);
316  }
317  */
318 
319  leave_block("Call to mnt6_affine_ate_precompute_G2");
320  return result;
321 }
322 
324  const mnt6_affine_ate_G1_precomputation &prec_P,
325  const mnt6_affine_ate_G2_precomputation &prec_Q)
326 {
327  enter_block("Call to mnt6_affine_ate_miller_loop");
328 
329  mnt6_Fq6 f = mnt6_Fq6::one();
330 
332  bool found_nonzero = false;
333  size_t idx = 0;
334 
335  std::vector<long> NAF = find_wnaf(1, loop_count);
336  for (long i = NAF.size() - 1; i >= 0; --i) {
337  if (!found_nonzero) {
338  /* this skips the MSB itself */
339  found_nonzero |= (NAF[i] != 0);
340  continue;
341  }
342 
343  /* code below gets executed for all bits (EXCEPT the MSB itself) of
344  mnt6_param_p (skipping leading zeros) in MSB to LSB
345  order */
346  mnt6_affine_ate_coeffs c = prec_Q.coeffs[idx++];
347 
348  mnt6_Fq6 g_RR_at_P = mnt6_Fq6(
349  prec_P.PY_twist_squared,
350  -prec_P.PX * c.gamma_twist + c.gamma_X - c.old_RY);
351  f = f.squared().mul_by_2345(g_RR_at_P);
352 
353  if (NAF[i] != 0) {
354  mnt6_affine_ate_coeffs c = prec_Q.coeffs[idx++];
355  mnt6_Fq6 g_RQ_at_P;
356  if (NAF[i] > 0) {
357  g_RQ_at_P = mnt6_Fq6(
358  prec_P.PY_twist_squared,
359  -prec_P.PX * c.gamma_twist + c.gamma_X - prec_Q.QY);
360  } else {
361  g_RQ_at_P = mnt6_Fq6(
362  prec_P.PY_twist_squared,
363  -prec_P.PX * c.gamma_twist + c.gamma_X + prec_Q.QY);
364  }
365  f = f.mul_by_2345(g_RQ_at_P);
366  }
367  }
368 
369  /* TODO: maybe handle neg
370  if (mnt6_ate_is_loop_count_neg)
371  {
372  // TODO:
373  mnt6_affine_ate_coeffs ac = prec_Q.coeffs[idx++];
374  mnt6_Fq6 g_RnegR_at_P = mnt6_Fq6(prec_P.PY_twist_squared,
375  - prec_P.PX * c.gamma_twist +
376  c.gamma_X - c.old_RY); f = (f * g_RnegR_at_P).inverse();
377  }
378  */
379 
380  leave_block("Call to mnt6_affine_ate_miller_loop");
381 
382  return f;
383 }
384 
385 /* ate pairing */
386 
392 
393  void print() const
394  {
395  printf("extended mnt6_G2 projective X/Y/Z/T:\n");
396  X.print();
397  Y.print();
398  Z.print();
399  T.print();
400  }
401 
402  void test_invariant() const { assert(T == Z.squared()); }
403 };
404 
407 {
408  const mnt6_Fq3 X = current.X, Y = current.Y, Z = current.Z, T = current.T;
409 
410  const mnt6_Fq3 A = T.squared(); // A = T1^2
411  const mnt6_Fq3 B = X.squared(); // B = X1^2
412  const mnt6_Fq3 C = Y.squared(); // C = Y1^2
413  const mnt6_Fq3 D = C.squared(); // D = C^2
414  const mnt6_Fq3 E = (X + C).squared() - B - D; // E = (X1+C)^2-B-D
415  const mnt6_Fq3 F = (B + B + B) + mnt6_twist_coeff_a * A; // F = 3*B + a *A
416  const mnt6_Fq3 G = F.squared(); // G = F^2
417 
418  current.X = -(E + E + E + E) + G; // X3 = -4*E+G
419  current.Y =
420  -mnt6_Fq("8") * D + F * (E + E - current.X); // Y3 = -8*D+F*(2*E-X3)
421  current.Z = (Y + Z).squared() - C - Z.squared(); // Z3 = (Y1+Z1)^2-C-Z1^2
422  current.T = current.Z.squared(); // T3 = Z3^2
423 
424  dc.c_H = (current.Z + T).squared() - current.T - A; // H = (Z3+T1)^2-T3-A
425  dc.c_4C = C + C + C + C; // fourC = 4*C
426  dc.c_J = (F + T).squared() - G - A; // J = (F+T1)^2-G-A
427  dc.c_L = (F + X).squared() - G - B; // L = (F+X1)^2-G-B
428 
429 #ifdef DEBUG
430  current.test_invariant();
431 #endif
432 }
433 
435  const mnt6_Fq3 base_X,
436  const mnt6_Fq3 base_Y,
437  const mnt6_Fq3 base_Y_squared,
440 {
441  const mnt6_Fq3 X1 = current.X, Y1 = current.Y, Z1 = current.Z,
442  T1 = current.T;
443  const mnt6_Fq3 &x2 = base_X, &y2 = base_Y, &y2_squared = base_Y_squared;
444 
445  const mnt6_Fq3 B = x2 * T1; // B = x2 * T1
446  const mnt6_Fq3 D = ((y2 + Z1).squared() - y2_squared - T1) *
447  T1; // D = ((y2 + Z1)^2 - y2squared - T1) * T1
448  const mnt6_Fq3 H = B - X1; // H = B - X1
449  const mnt6_Fq3 I = H.squared(); // I = H^2
450  const mnt6_Fq3 E = I + I + I + I; // E = 4*I
451  const mnt6_Fq3 J = H * E; // J = H * E
452  const mnt6_Fq3 V = X1 * E; // V = X1 * E
453  const mnt6_Fq3 L1 = D - (Y1 + Y1); // L1 = D - 2 * Y1
454 
455  current.X = L1.squared() - J - (V + V); // X3 = L1^2 - J - 2*V
456  current.Y =
457  L1 * (V - current.X) - (Y1 + Y1) * J; // Y3 = L1 * (V-X3) - 2*Y1 * J
458  current.Z = (Z1 + H).squared() - T1 - I; // Z3 = (Z1 + H)^2 - T1 - I
459  current.T = current.Z.squared(); // T3 = Z3^2
460 
461  ac.c_L1 = L1;
462  ac.c_RZ = current.Z;
463 #ifdef DEBUG
464  current.test_invariant();
465 #endif
466 }
467 
469 {
470  enter_block("Call to mnt6_ate_precompute_G1");
471 
472  mnt6_G1 Pcopy = P;
473  Pcopy.to_affine_coordinates();
474 
475  mnt6_ate_G1_precomp result;
476  result.PX = Pcopy.X;
477  result.PY = Pcopy.Y;
478  result.PX_twist = Pcopy.X * mnt6_twist;
479  result.PY_twist = Pcopy.Y * mnt6_twist;
480 
481  leave_block("Call to mnt6_ate_precompute_G1");
482  return result;
483 }
484 
486 {
487  enter_block("Call to mnt6_ate_precompute_G2");
488 
489  mnt6_G2 Qcopy(Q);
490  Qcopy.to_affine_coordinates();
491 
492  mnt6_Fq3 mnt6_twist_inv =
493  mnt6_twist.inverse(); // could add to global params if needed
494 
495  mnt6_ate_G2_precomp result;
496  result.QX = Qcopy.X;
497  result.QY = Qcopy.Y;
498  result.QY2 = Qcopy.Y.squared();
499  result.QX_over_twist = Qcopy.X * mnt6_twist_inv;
500  result.QY_over_twist = Qcopy.Y * mnt6_twist_inv;
501 
503  R.X = Qcopy.X;
504  R.Y = Qcopy.Y;
505  R.Z = mnt6_Fq3::one();
506  R.T = mnt6_Fq3::one();
507 
509  bool found_one = false;
510  for (long i = loop_count.max_bits() - 1; i >= 0; --i) {
511  const bool bit = loop_count.test_bit(i);
512 
513  if (!found_one) {
514  /* this skips the MSB itself */
515  found_one |= bit;
516  continue;
517  }
518 
521  result.dbl_coeffs.push_back(dc);
522 
523  if (bit) {
526  result.QX, result.QY, result.QY2, R, ac);
527  result.add_coeffs.push_back(ac);
528  }
529  }
530 
532  mnt6_Fq3 RZ_inv = R.Z.inverse();
533  mnt6_Fq3 RZ2_inv = RZ_inv.squared();
534  mnt6_Fq3 RZ3_inv = RZ2_inv * RZ_inv;
535  mnt6_Fq3 minus_R_affine_X = R.X * RZ2_inv;
536  mnt6_Fq3 minus_R_affine_Y = -R.Y * RZ3_inv;
537  mnt6_Fq3 minus_R_affine_Y2 = minus_R_affine_Y.squared();
540  minus_R_affine_X, minus_R_affine_Y, minus_R_affine_Y2, R, ac);
541  result.add_coeffs.push_back(ac);
542  }
543 
544  leave_block("Call to mnt6_ate_precompute_G2");
545  return result;
546 }
547 
549  const mnt6_ate_G1_precomp &prec_P, const mnt6_ate_G2_precomp &prec_Q)
550 {
551  enter_block("Call to mnt6_ate_miller_loop");
552 
553  mnt6_Fq3 L1_coeff = mnt6_Fq3(prec_P.PX, mnt6_Fq::zero(), mnt6_Fq::zero()) -
554  prec_Q.QX_over_twist;
555 
556  mnt6_Fq6 f = mnt6_Fq6::one();
557 
558  bool found_one = false;
559  size_t dbl_idx = 0;
560  size_t add_idx = 0;
561 
563 
564  for (long i = loop_count.max_bits() - 1; i >= 0; --i) {
565  const bool bit = loop_count.test_bit(i);
566 
567  if (!found_one) {
568  /* this skips the MSB itself */
569  found_one |= bit;
570  continue;
571  }
572 
573  /* code below gets executed for all bits (EXCEPT the MSB itself) of
574  mnt6_param_p (skipping leading zeros) in MSB to LSB
575  order */
576  mnt6_ate_dbl_coeffs dc = prec_Q.dbl_coeffs[dbl_idx++];
577 
578  mnt6_Fq6 g_RR_at_P = mnt6_Fq6(
579  -dc.c_4C - dc.c_J * prec_P.PX_twist + dc.c_L,
580  dc.c_H * prec_P.PY_twist);
581  f = f.squared() * g_RR_at_P;
582 
583  if (bit) {
584  mnt6_ate_add_coeffs ac = prec_Q.add_coeffs[add_idx++];
585  mnt6_Fq6 g_RQ_at_P = mnt6_Fq6(
586  ac.c_RZ * prec_P.PY_twist,
587  -(prec_Q.QY_over_twist * ac.c_RZ + L1_coeff * ac.c_L1));
588  f = f * g_RQ_at_P;
589  }
590  }
591 
593  mnt6_ate_add_coeffs ac = prec_Q.add_coeffs[add_idx++];
594  mnt6_Fq6 g_RnegR_at_P = mnt6_Fq6(
595  ac.c_RZ * prec_P.PY_twist,
596  -(prec_Q.QY_over_twist * ac.c_RZ + L1_coeff * ac.c_L1));
597  f = (f * g_RnegR_at_P).inverse();
598  }
599 
600  leave_block("Call to mnt6_ate_miller_loop");
601 
602  return f;
603 }
604 
606  const mnt6_ate_G1_precomp &prec_P1,
607  const mnt6_ate_G2_precomp &prec_Q1,
608  const mnt6_ate_G1_precomp &prec_P2,
609  const mnt6_ate_G2_precomp &prec_Q2)
610 {
611  enter_block("Call to mnt6_ate_double_miller_loop");
612 
613  mnt6_Fq3 L1_coeff1 =
614  mnt6_Fq3(prec_P1.PX, mnt6_Fq::zero(), mnt6_Fq::zero()) -
615  prec_Q1.QX_over_twist;
616  mnt6_Fq3 L1_coeff2 =
617  mnt6_Fq3(prec_P2.PX, mnt6_Fq::zero(), mnt6_Fq::zero()) -
618  prec_Q2.QX_over_twist;
619 
620  mnt6_Fq6 f = mnt6_Fq6::one();
621 
622  bool found_one = false;
623  size_t dbl_idx = 0;
624  size_t add_idx = 0;
625 
627 
628  for (long i = loop_count.max_bits() - 1; i >= 0; --i) {
629  const bool bit = loop_count.test_bit(i);
630 
631  if (!found_one) {
632  /* this skips the MSB itself */
633  found_one |= bit;
634  continue;
635  }
636 
637  /* code below gets executed for all bits (EXCEPT the MSB itself) of
638  mnt6_param_p (skipping leading zeros) in MSB to LSB
639  order */
640  mnt6_ate_dbl_coeffs dc1 = prec_Q1.dbl_coeffs[dbl_idx];
641  mnt6_ate_dbl_coeffs dc2 = prec_Q2.dbl_coeffs[dbl_idx];
642  ++dbl_idx;
643 
644  mnt6_Fq6 g_RR_at_P1 = mnt6_Fq6(
645  -dc1.c_4C - dc1.c_J * prec_P1.PX_twist + dc1.c_L,
646  dc1.c_H * prec_P1.PY_twist);
647 
648  mnt6_Fq6 g_RR_at_P2 = mnt6_Fq6(
649  -dc2.c_4C - dc2.c_J * prec_P2.PX_twist + dc2.c_L,
650  dc2.c_H * prec_P2.PY_twist);
651 
652  f = f.squared() * g_RR_at_P1 * g_RR_at_P2;
653 
654  if (bit) {
655  mnt6_ate_add_coeffs ac1 = prec_Q1.add_coeffs[add_idx];
656  mnt6_ate_add_coeffs ac2 = prec_Q2.add_coeffs[add_idx];
657  ++add_idx;
658 
659  mnt6_Fq6 g_RQ_at_P1 = mnt6_Fq6(
660  ac1.c_RZ * prec_P1.PY_twist,
661  -(prec_Q1.QY_over_twist * ac1.c_RZ + L1_coeff1 * ac1.c_L1));
662  mnt6_Fq6 g_RQ_at_P2 = mnt6_Fq6(
663  ac2.c_RZ * prec_P2.PY_twist,
664  -(prec_Q2.QY_over_twist * ac2.c_RZ + L1_coeff2 * ac2.c_L1));
665 
666  f = f * g_RQ_at_P1 * g_RQ_at_P2;
667  }
668  }
669 
671  mnt6_ate_add_coeffs ac1 = prec_Q1.add_coeffs[add_idx];
672  mnt6_ate_add_coeffs ac2 = prec_Q2.add_coeffs[add_idx];
673  ++add_idx;
674  mnt6_Fq6 g_RnegR_at_P1 = mnt6_Fq6(
675  ac1.c_RZ * prec_P1.PY_twist,
676  -(prec_Q1.QY_over_twist * ac1.c_RZ + L1_coeff1 * ac1.c_L1));
677  mnt6_Fq6 g_RnegR_at_P2 = mnt6_Fq6(
678  ac2.c_RZ * prec_P2.PY_twist,
679  -(prec_Q2.QY_over_twist * ac2.c_RZ + L1_coeff2 * ac2.c_L1));
680 
681  f = (f * g_RnegR_at_P1 * g_RnegR_at_P2).inverse();
682  }
683 
684  leave_block("Call to mnt6_ate_double_miller_loop");
685 
686  return f;
687 }
688 
690 {
691  enter_block("Call to mnt6_ate_pairing");
694  mnt6_Fq6 result = mnt6_ate_miller_loop(prec_P, prec_Q);
695  leave_block("Call to mnt6_ate_pairing");
696  return result;
697 }
698 
700 {
701  enter_block("Call to mnt6_ate_reduced_pairing");
702  const mnt6_Fq6 f = mnt6_ate_pairing(P, Q);
703  const mnt6_GT result = mnt6_final_exponentiation(f);
704  leave_block("Call to mnt6_ate_reduced_pairing");
705  return result;
706 }
707 
709 {
710  return mnt6_ate_precompute_G1(P);
711 }
712 
714 {
715  return mnt6_ate_precompute_G2(Q);
716 }
717 
719  const mnt6_G1_precomp &prec_P, const mnt6_G2_precomp &prec_Q)
720 {
721  return mnt6_ate_miller_loop(prec_P, prec_Q);
722 }
723 
725  const mnt6_G1_precomp &prec_P1,
726  const mnt6_G2_precomp &prec_Q1,
727  const mnt6_G1_precomp &prec_P2,
728  const mnt6_G2_precomp &prec_Q2)
729 {
730  return mnt6_ate_double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2);
731 }
732 
734 {
735  return mnt6_ate_pairing(P, Q);
736 }
737 
739 {
740  return mnt6_ate_reduced_pairing(P, Q);
741 }
742 
744 {
745  const mnt6_affine_ate_G1_precomputation prec_P =
747  const mnt6_affine_ate_G2_precomputation prec_Q =
749  const mnt6_Fq6 f = mnt6_affine_ate_miller_loop(prec_P, prec_Q);
750  const mnt6_GT result = mnt6_final_exponentiation(f);
751  return result;
752 }
753 
754 } // namespace libff
libff::Fp6_2over3_model::one
static Fp6_2over3_model< n, modulus > one()
libff::mnt6_ate_G2_precomp::QX_over_twist
mnt6_Fq3 QX_over_twist
Definition: mnt6_pairing.hpp:102
libff::mnt6_ate_loop_count
bigint< mnt6_q_limbs > mnt6_ate_loop_count
Definition: mnt6_init.cpp:36
libff::mnt6_affine_ate_G1_precomputation::PY_twist_squared
mnt6_Fq3 PY_twist_squared
Definition: mnt6_pairing.hpp:34
libff::mnt6_affine_ate_G2_precomputation::QX
mnt6_Fq3 QX
Definition: mnt6_pairing.hpp:47
libff::Fp3_model::print
void print() const
Definition: fp3.hpp:77
libff::mnt6_ate_G2_precomp::dbl_coeffs
std::vector< mnt6_ate_dbl_coeffs > dbl_coeffs
Definition: mnt6_pairing.hpp:104
libff::enter_block
void enter_block(const std::string &msg, const bool indent)
Definition: profiling.cpp:271
libff::mnt6_ate_precompute_G2
mnt6_ate_G2_precomp mnt6_ate_precompute_G2(const mnt6_G2 &Q)
Definition: mnt6_pairing.cpp:485
libff
Definition: ffi.cpp:8
libff::mnt6_ate_G2_precomp::QY2
mnt6_Fq3 QY2
Definition: mnt6_pairing.hpp:101
libff::Fp3_model< mnt6_q_limbs, mnt6_modulus_q >::one
static Fp3_model< n, modulus > one()
libff::mnt6_final_exponent_last_chunk_w1
bigint< mnt6_q_limbs > mnt6_final_exponent_last_chunk_w1
Definition: mnt6_init.cpp:41
libff::mnt6_affine_ate_coeffs::gamma
mnt6_Fq3 gamma
Definition: mnt6_pairing.hpp:41
libff::mnt6_ate_G2_precomp::add_coeffs
std::vector< mnt6_ate_add_coeffs > add_coeffs
Definition: mnt6_pairing.hpp:105
libff::mnt6_Fq
Fp_model< mnt6_q_limbs, mnt6_modulus_q > mnt6_Fq
Definition: mnt6_init.hpp:37
libff::mnt6_ate_dbl_coeffs::c_H
mnt6_Fq3 c_H
Definition: mnt6_pairing.hpp:77
libff::doubling_step_for_flipped_miller_loop
void doubling_step_for_flipped_miller_loop(const alt_bn128_Fq two_inv, alt_bn128_G2 &current, alt_bn128_ate_ell_coeffs &c)
Definition: alt_bn128_pairing.cpp:246
libff::mnt6_affine_ate_coeffs::gamma_X
mnt6_Fq3 gamma_X
Definition: mnt6_pairing.hpp:43
libff::mnt6_affine_ate_G2_precomputation::coeffs
std::vector< mnt6_affine_ate_coeffs > coeffs
Definition: mnt6_pairing.hpp:49
libff::Fp_model< mnt6_q_limbs, mnt6_modulus_q >::zero
static const Fp_model< n, modulus > & zero()
libff::mnt6_ate_miller_loop
mnt6_Fq6 mnt6_ate_miller_loop(const mnt6_ate_G1_precomp &prec_P, const mnt6_ate_G2_precomp &prec_Q)
Definition: mnt6_pairing.cpp:548
libff::mnt6_ate_G2_precomp::QX
mnt6_Fq3 QX
Definition: mnt6_pairing.hpp:99
libff::extended_mnt6_G2_projective
Definition: mnt6_pairing.cpp:387
libff::mnt6_ate_dbl_coeffs::c_L
mnt6_Fq3 c_L
Definition: mnt6_pairing.hpp:80
libff::operator>>
std::istream & operator>>(std::istream &in, alt_bn128_G1 &g)
Definition: alt_bn128_g1.cpp:446
libff::mnt6_G2::X
mnt6_Fq3 X
Definition: mnt6_g2.hpp:51
libff::mnt6_affine_reduced_pairing
mnt6_GT mnt6_affine_reduced_pairing(const mnt6_G1 &P, const mnt6_G2 &Q)
Definition: mnt6_pairing.cpp:743
libff::mnt6_ate_G2_precomp::QY
mnt6_Fq3 QY
Definition: mnt6_pairing.hpp:100
libff::extended_mnt6_G2_projective::Z
mnt6_Fq3 Z
Definition: mnt6_pairing.cpp:390
libff::mixed_addition_step_for_flipped_miller_loop
void mixed_addition_step_for_flipped_miller_loop(const alt_bn128_G2 base, alt_bn128_G2 &current, alt_bn128_ate_ell_coeffs &c)
Definition: alt_bn128_pairing.cpp:290
libff::extended_mnt6_G2_projective::Y
mnt6_Fq3 Y
Definition: mnt6_pairing.cpp:389
libff::mnt6_ate_G1_precomp::PY
mnt6_Fq PY
Definition: mnt6_pairing.hpp:65
libff::mnt6_ate_dbl_coeffs::operator==
bool operator==(const mnt6_ate_dbl_coeffs &other) const
Definition: mnt6_pairing.cpp:53
libff::mnt6_ate_G2_precomp::operator==
bool operator==(const mnt6_ate_G2_precomp &other) const
Definition: mnt6_pairing.cpp:100
libff::mnt6_ate_add_coeffs::c_RZ
mnt6_Fq3 c_RZ
Definition: mnt6_pairing.hpp:90
libff::mnt6_ate_G2_precomp
Definition: mnt6_pairing.hpp:98
libff::mnt6_ate_reduced_pairing
mnt6_GT mnt6_ate_reduced_pairing(const mnt6_G1 &P, const mnt6_G2 &Q)
Definition: mnt6_pairing.cpp:699
libff::mnt6_affine_ate_G2_precomputation::QY
mnt6_Fq3 QY
Definition: mnt6_pairing.hpp:48
libff::mnt6_ate_G1_precomp::PY_twist
mnt6_Fq3 PY_twist
Definition: mnt6_pairing.hpp:67
libff::mnt6_affine_ate_precompute_G2
mnt6_affine_ate_G2_precomputation mnt6_affine_ate_precompute_G2(const mnt6_G2 &Q)
Definition: mnt6_pairing.cpp:245
libff::mnt6_miller_loop
mnt6_Fq6 mnt6_miller_loop(const mnt6_G1_precomp &prec_P, const mnt6_G2_precomp &prec_Q)
Definition: mnt6_pairing.cpp:718
libff::mnt6_ate_pairing
mnt6_Fq6 mnt6_ate_pairing(const mnt6_G1 &P, const mnt6_G2 &Q)
Definition: mnt6_pairing.cpp:689
libff::mnt6_G1::to_affine_coordinates
void to_affine_coordinates()
Definition: mnt6_g1.cpp:71
libff::mnt6_reduced_pairing
mnt6_GT mnt6_reduced_pairing(const mnt6_G1 &P, const mnt6_G2 &Q)
Definition: mnt6_pairing.cpp:738
mnt6_pairing.hpp
OUTPUT_SEPARATOR
#define OUTPUT_SEPARATOR
Definition: serialization.hpp:69
libff::mnt6_twist
mnt6_Fq3 mnt6_twist
Definition: mnt6_init.cpp:24
libff::mnt6_ate_dbl_coeffs::c_4C
mnt6_Fq3 c_4C
Definition: mnt6_pairing.hpp:78
libff::bigint::max_bits
static constexpr size_t max_bits()
The number of bits representable by this bigint type.
Definition: bigint.hpp:51
libff::mnt6_final_exponentiation_last_chunk
mnt6_Fq6 mnt6_final_exponentiation_last_chunk(const mnt6_Fq6 &elt, const mnt6_Fq6 &elt_inv)
Definition: mnt6_pairing.cpp:173
libff::mnt6_ate_G1_precomp
Definition: mnt6_pairing.hpp:63
libff::mnt6_ate_dbl_coeffs
Definition: mnt6_pairing.hpp:76
libff::mnt6_affine_ate_coeffs::old_RY
mnt6_Fq3 old_RY
Definition: mnt6_pairing.hpp:40
libff::mnt6_ate_G1_precomp::operator==
bool operator==(const mnt6_ate_G1_precomp &other) const
Definition: mnt6_pairing.cpp:25
libff::mnt6_G2
Definition: mnt6_g2.hpp:26
libff::mnt6_G2::Y
mnt6_Fq3 Y
Definition: mnt6_g2.hpp:51
libff::mnt6_affine_ate_G1_precomputation
Definition: mnt6_pairing.hpp:31
libff::mnt6_double_miller_loop
mnt6_Fq6 mnt6_double_miller_loop(const mnt6_G1_precomp &prec_P1, const mnt6_G2_precomp &prec_Q1, const mnt6_G1_precomp &prec_P2, const mnt6_G2_precomp &prec_Q2)
Definition: mnt6_pairing.cpp:724
libff::mnt6_twist_coeff_a
mnt6_Fq3 mnt6_twist_coeff_a
Definition: mnt6_init.cpp:25
libff::mnt6_precompute_G1
mnt6_G1_precomp mnt6_precompute_G1(const mnt6_G1 &P)
Definition: mnt6_pairing.cpp:708
libff::mnt6_final_exponentiation_first_chunk
mnt6_Fq6 mnt6_final_exponentiation_first_chunk(const mnt6_Fq6 &elt, const mnt6_Fq6 &elt_inv)
Definition: mnt6_pairing.cpp:192
libff::consume_OUTPUT_SEPARATOR
void consume_OUTPUT_SEPARATOR(std::istream &in)
mnt6_g2.hpp
libff::mnt6_affine_ate_coeffs::old_RX
mnt6_Fq3 old_RX
Definition: mnt6_pairing.hpp:39
libff::bigint
Definition: bigint.hpp:20
libff::mnt6_G1::X
mnt6_Fq X
Definition: mnt6_g1.hpp:49
libff::mnt6_ate_G1_precomp::PX
mnt6_Fq PX
Definition: mnt6_pairing.hpp:64
libff::Fp6_2over3_model::Frobenius_map
Fp6_2over3_model Frobenius_map(unsigned long power) const
libff::extended_mnt6_G2_projective::test_invariant
void test_invariant() const
Definition: mnt6_pairing.cpp:402
libff::mnt6_Fq3
Fp3_model< mnt6_q_limbs, mnt6_modulus_q > mnt6_Fq3
Definition: mnt6_init.hpp:38
libff::mnt6_ate_double_miller_loop
mnt6_Fq6 mnt6_ate_double_miller_loop(const mnt6_ate_G1_precomp &prec_P1, const mnt6_ate_G2_precomp &prec_Q1, const mnt6_ate_G1_precomp &prec_P2, const mnt6_ate_G2_precomp &prec_Q2)
Definition: mnt6_pairing.cpp:605
libff::mnt6_affine_ate_coeffs
Definition: mnt6_pairing.hpp:37
libff::mnt6_Fq6
Fp6_2over3_model< mnt6_q_limbs, mnt6_modulus_q > mnt6_Fq6
Definition: mnt6_init.hpp:39
libff::mnt6_ate_G2_precomp::QY_over_twist
mnt6_Fq3 QY_over_twist
Definition: mnt6_pairing.hpp:103
libff::mnt6_ate_add_coeffs::operator==
bool operator==(const mnt6_ate_add_coeffs &other) const
Definition: mnt6_pairing.cpp:80
libff::mnt6_ate_dbl_coeffs::c_J
mnt6_Fq3 c_J
Definition: mnt6_pairing.hpp:79
libff::Fp3_model
Definition: fp3.hpp:18
libff::mnt6_G1
Definition: mnt6_g1.hpp:26
libff::mnt6_affine_ate_G2_precomputation
Definition: mnt6_pairing.hpp:46
libff::mnt6_affine_ate_G1_precomputation::PX
mnt6_Fq PX
Definition: mnt6_pairing.hpp:32
libff::mnt6_precompute_G2
mnt6_G2_precomp mnt6_precompute_G2(const mnt6_G2 &Q)
Definition: mnt6_pairing.cpp:713
libff::mnt6_G1::Y
mnt6_Fq Y
Definition: mnt6_g1.hpp:49
libff::extended_mnt6_G2_projective::X
mnt6_Fq3 X
Definition: mnt6_pairing.cpp:388
libff::mnt6_affine_ate_miller_loop
mnt6_Fq6 mnt6_affine_ate_miller_loop(const mnt6_affine_ate_G1_precomputation &prec_P, const mnt6_affine_ate_G2_precomputation &prec_Q)
Definition: mnt6_pairing.cpp:323
libff::mnt6_ate_add_coeffs
Definition: mnt6_pairing.hpp:88
libff::Fp6_2over3_model::mul_by_2345
Fp6_2over3_model mul_by_2345(const Fp6_2over3_model &other) const
libff::operator<<
std::ostream & operator<<(std::ostream &out, const alt_bn128_G1 &g)
Definition: alt_bn128_g1.cpp:436
libff::Fp3_model::inverse
Fp3_model inverse() const
libff::consume_OUTPUT_NEWLINE
void consume_OUTPUT_NEWLINE(std::istream &in)
mnt6_init.hpp
libff::Fp6_2over3_model::cyclotomic_exp
Fp6_2over3_model cyclotomic_exp(const bigint< m > &exponent) const
libff::find_wnaf
std::vector< long > find_wnaf(const size_t window_size, const bigint< n > &scalar)
libff::mnt6_pairing
mnt6_Fq6 mnt6_pairing(const mnt6_G1 &P, const mnt6_G2 &Q)
Definition: mnt6_pairing.cpp:733
profiling.hpp
wnaf.hpp
mnt6_g1.hpp
libff::leave_block
void leave_block(const std::string &msg, const bool indent)
Definition: profiling.cpp:305
libff::mnt6_affine_ate_coeffs::gamma_twist
mnt6_Fq3 gamma_twist
Definition: mnt6_pairing.hpp:42
OUTPUT_NEWLINE
#define OUTPUT_NEWLINE
Definition: serialization.hpp:68
libff::mnt6_ate_is_loop_count_neg
bool mnt6_ate_is_loop_count_neg
Definition: mnt6_init.cpp:37
libff::Fp6_2over3_model
Definition: fp6_2over3.hpp:26
libff::bigint::test_bit
bool test_bit(const std::size_t bitno) const
libff::mnt6_final_exponent_last_chunk_is_w0_neg
bool mnt6_final_exponent_last_chunk_is_w0_neg
Definition: mnt6_init.cpp:40
libff::mnt6_final_exponent_last_chunk_abs_of_w0
bigint< mnt6_q_limbs > mnt6_final_exponent_last_chunk_abs_of_w0
Definition: mnt6_init.cpp:39
libff::consume_newline
void consume_newline(std::istream &in)
libff::Fp3_model::squared
Fp3_model squared() const
libff::mnt6_ate_add_coeffs::c_L1
mnt6_Fq3 c_L1
Definition: mnt6_pairing.hpp:89
libff::mnt6_affine_ate_precompute_G1
mnt6_affine_ate_G1_precomputation mnt6_affine_ate_precompute_G1(const mnt6_G1 &P)
Definition: mnt6_pairing.cpp:228
libff::mnt6_ate_G1_precomp::PX_twist
mnt6_Fq3 PX_twist
Definition: mnt6_pairing.hpp:66
libff::mnt6_final_exponentiation
mnt6_GT mnt6_final_exponentiation(const mnt6_Fq6 &elt)
Definition: mnt6_pairing.cpp:211
libff::Fp6_2over3_model::inverse
Fp6_2over3_model inverse() const
libff::Fp6_2over3_model::squared
Fp6_2over3_model squared() const
libff::mnt6_G2::to_affine_coordinates
void to_affine_coordinates()
Definition: mnt6_g2.cpp:109
libff::extended_mnt6_G2_projective::T
mnt6_Fq3 T
Definition: mnt6_pairing.cpp:391
libff::mnt6_affine_ate_G1_precomputation::PY
mnt6_Fq PY
Definition: mnt6_pairing.hpp:33
libff::mnt6_ate_precompute_G1
mnt6_ate_G1_precomp mnt6_ate_precompute_G1(const mnt6_G1 &P)
Definition: mnt6_pairing.cpp:468
libff::extended_mnt6_G2_projective::print
void print() const
Definition: mnt6_pairing.cpp:393