1 /** @file
2  *****************************************************************************
3  * @author     This file is part of libff, developed by SCIPR Lab
4  *             and contributors (see AUTHORS).
5  * @copyright  MIT license (see LICENSE file)
6  *****************************************************************************/
7 
8 #include <cassert>
9 
10 #include <libff/algebra/curves/alt_bn128/alt_bn128_g1.hpp>
11 #include <libff/algebra/curves/alt_bn128/alt_bn128_g2.hpp>
12 #include <libff/algebra/curves/alt_bn128/alt_bn128_init.hpp>
13 #include <libff/algebra/curves/alt_bn128/alt_bn128_pairing.hpp>
14 #include <libff/common/profiling.hpp>
15 
16 namespace libff {
17 
operator ==(const alt_bn128_ate_G1_precomp & other) const18 bool alt_bn128_ate_G1_precomp::operator==(const alt_bn128_ate_G1_precomp &other) const
19 {
20     return (this->PX == other.PX &&
21             this->PY == other.PY);
22 }
23 
operator <<(std::ostream & out,const alt_bn128_ate_G1_precomp & prec_P)24 std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_G1_precomp &prec_P)
25 {
26     out << prec_P.PX << OUTPUT_SEPARATOR << prec_P.PY;
27 
28     return out;
29 }
30 
operator >>(std::istream & in,alt_bn128_ate_G1_precomp & prec_P)31 std::istream& operator>>(std::istream &in, alt_bn128_ate_G1_precomp &prec_P)
32 {
33     in >> prec_P.PX;
34     consume_OUTPUT_SEPARATOR(in);
35     in >> prec_P.PY;
36 
37     return in;
38 }
39 
operator ==(const alt_bn128_ate_ell_coeffs & other) const40 bool  alt_bn128_ate_ell_coeffs::operator==(const alt_bn128_ate_ell_coeffs &other) const
41 {
42     return (this->ell_0 == other.ell_0 &&
43             this->ell_VW == other.ell_VW &&
44             this->ell_VV == other.ell_VV);
45 }
46 
operator <<(std::ostream & out,const alt_bn128_ate_ell_coeffs & c)47 std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_ell_coeffs &c)
48 {
49     out << c.ell_0 << OUTPUT_SEPARATOR << c.ell_VW << OUTPUT_SEPARATOR << c.ell_VV;
50     return out;
51 }
52 
operator >>(std::istream & in,alt_bn128_ate_ell_coeffs & c)53 std::istream& operator>>(std::istream &in, alt_bn128_ate_ell_coeffs &c)
54 {
55     in >> c.ell_0;
56     consume_OUTPUT_SEPARATOR(in);
57     in >> c.ell_VW;
58     consume_OUTPUT_SEPARATOR(in);
59     in >> c.ell_VV;
60 
61     return in;
62 }
63 
operator ==(const alt_bn128_ate_G2_precomp & other) const64 bool alt_bn128_ate_G2_precomp::operator==(const alt_bn128_ate_G2_precomp &other) const
65 {
66     return (this->QX == other.QX &&
67             this->QY == other.QY &&
68             this->coeffs == other.coeffs);
69 }
70 
operator <<(std::ostream & out,const alt_bn128_ate_G2_precomp & prec_Q)71 std::ostream& operator<<(std::ostream& out, const alt_bn128_ate_G2_precomp &prec_Q)
72 {
73     out << prec_Q.QX << OUTPUT_SEPARATOR << prec_Q.QY << "\n";
74     out << prec_Q.coeffs.size() << "\n";
75     for (const alt_bn128_ate_ell_coeffs &c : prec_Q.coeffs)
76     {
77         out << c << OUTPUT_NEWLINE;
78     }
79     return out;
80 }
81 
operator >>(std::istream & in,alt_bn128_ate_G2_precomp & prec_Q)82 std::istream& operator>>(std::istream& in, alt_bn128_ate_G2_precomp &prec_Q)
83 {
84     in >> prec_Q.QX;
85     consume_OUTPUT_SEPARATOR(in);
86     in >> prec_Q.QY;
87     consume_newline(in);
88 
89     prec_Q.coeffs.clear();
90     size_t s;
91     in >> s;
92 
93     consume_newline(in);
94 
95     prec_Q.coeffs.reserve(s);
96 
97     for (size_t i = 0; i < s; ++i)
98     {
99         alt_bn128_ate_ell_coeffs c;
100         in >> c;
101         consume_OUTPUT_NEWLINE(in);
102         prec_Q.coeffs.emplace_back(c);
103     }
104 
105     return in;
106 }
107 
108 /* final exponentiations */
109 
alt_bn128_final_exponentiation_first_chunk(const alt_bn128_Fq12 & elt)110 alt_bn128_Fq12 alt_bn128_final_exponentiation_first_chunk(const alt_bn128_Fq12 &elt)
111 {
112     enter_block("Call to alt_bn128_final_exponentiation_first_chunk");
113 
114     /*
115       Computes result = elt^((q^6-1)*(q^2+1)).
116       Follows, e.g., Beuchat et al page 9, by computing result as follows:
117          elt^((q^6-1)*(q^2+1)) = (conj(elt) * elt^(-1))^(q^2+1)
118       More precisely:
119       A = conj(elt)
120       B = elt.inverse()
121       C = A * B
122       D = C.Frobenius_map(2)
123       result = D * C
124     */
125 
126     const alt_bn128_Fq12 A = alt_bn128_Fq12(elt.c0,-elt.c1);
127     const alt_bn128_Fq12 B = elt.inverse();
128     const alt_bn128_Fq12 C = A * B;
129     const alt_bn128_Fq12 D = C.Frobenius_map(2);
130     const alt_bn128_Fq12 result = D * C;
131 
132     leave_block("Call to alt_bn128_final_exponentiation_first_chunk");
133 
134     return result;
135 }
136 
alt_bn128_exp_by_neg_z(const alt_bn128_Fq12 & elt)137 alt_bn128_Fq12 alt_bn128_exp_by_neg_z(const alt_bn128_Fq12 &elt)
138 {
139     enter_block("Call to alt_bn128_exp_by_neg_z");
140 
141     alt_bn128_Fq12 result = elt.cyclotomic_exp(alt_bn128_final_exponent_z);
142     if (!alt_bn128_final_exponent_is_z_neg)
143     {
144         result = result.unitary_inverse();
145     }
146 
147     leave_block("Call to alt_bn128_exp_by_neg_z");
148 
149     return result;
150 }
151 
alt_bn128_final_exponentiation_last_chunk(const alt_bn128_Fq12 & elt)152 alt_bn128_Fq12 alt_bn128_final_exponentiation_last_chunk(const alt_bn128_Fq12 &elt)
153 {
154     enter_block("Call to alt_bn128_final_exponentiation_last_chunk");
155 
156     /*
157       Follows Laura Fuentes-Castaneda et al. "Faster hashing to G2"
158       by computing:
159 
160       result = elt^(q^3 * (12*z^3 + 6z^2 + 4z - 1) +
161                     q^2 * (12*z^3 + 6z^2 + 6z) +
162                     q   * (12*z^3 + 6z^2 + 4z) +
163                     1   * (12*z^3 + 12z^2 + 6z + 1))
164       which equals
165 
166       result = elt^( 2z * ( 6z^2 + 3z + 1 ) * (q^4 - q^2 + 1)/r ).
167 
168       Using the following addition chain:
169 
170       A = exp_by_neg_z(elt)  // = elt^(-z)
171       B = A^2                // = elt^(-2*z)
172       C = B^2                // = elt^(-4*z)
173       D = C * B              // = elt^(-6*z)
174       E = exp_by_neg_z(D)    // = elt^(6*z^2)
175       F = E^2                // = elt^(12*z^2)
176       G = epx_by_neg_z(F)    // = elt^(-12*z^3)
177       H = conj(D)            // = elt^(6*z)
178       I = conj(G)            // = elt^(12*z^3)
179       J = I * E              // = elt^(12*z^3 + 6*z^2)
180       K = J * H              // = elt^(12*z^3 + 6*z^2 + 6*z)
181       L = K * B              // = elt^(12*z^3 + 6*z^2 + 4*z)
182       M = K * E              // = elt^(12*z^3 + 12*z^2 + 6*z)
183       N = M * elt            // = elt^(12*z^3 + 12*z^2 + 6*z + 1)
184       O = L.Frobenius_map(1) // = elt^(q*(12*z^3 + 6*z^2 + 4*z))
185       P = O * N              // = elt^(q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1))
186       Q = K.Frobenius_map(2) // = elt^(q^2 * (12*z^3 + 6*z^2 + 6*z))
187       R = Q * P              // = elt^(q^2 * (12*z^3 + 6*z^2 + 6*z) + q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1))
188       S = conj(elt)          // = elt^(-1)
189       T = S * L              // = elt^(12*z^3 + 6*z^2 + 4*z - 1)
190       U = T.Frobenius_map(3) // = elt^(q^3(12*z^3 + 6*z^2 + 4*z - 1))
191       V = U * R              // = elt^(q^3(12*z^3 + 6*z^2 + 4*z - 1) + q^2 * (12*z^3 + 6*z^2 + 6*z) + q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1))
192       result = V
193 
194     */
195 
196     const alt_bn128_Fq12 A = alt_bn128_exp_by_neg_z(elt);
197     const alt_bn128_Fq12 B = A.cyclotomic_squared();
198     const alt_bn128_Fq12 C = B.cyclotomic_squared();
199     const alt_bn128_Fq12 D = C * B;
200     const alt_bn128_Fq12 E = alt_bn128_exp_by_neg_z(D);
201     const alt_bn128_Fq12 F = E.cyclotomic_squared();
202     const alt_bn128_Fq12 G = alt_bn128_exp_by_neg_z(F);
203     const alt_bn128_Fq12 H = D.unitary_inverse();
204     const alt_bn128_Fq12 I = G.unitary_inverse();
205     const alt_bn128_Fq12 J = I * E;
206     const alt_bn128_Fq12 K = J * H;
207     const alt_bn128_Fq12 L = K * B;
208     const alt_bn128_Fq12 M = K * E;
209     const alt_bn128_Fq12 N = M * elt;
210     const alt_bn128_Fq12 O = L.Frobenius_map(1);
211     const alt_bn128_Fq12 P = O * N;
212     const alt_bn128_Fq12 Q = K.Frobenius_map(2);
213     const alt_bn128_Fq12 R = Q * P;
214     const alt_bn128_Fq12 S = elt.unitary_inverse();
215     const alt_bn128_Fq12 T = S * L;
216     const alt_bn128_Fq12 U = T.Frobenius_map(3);
217     const alt_bn128_Fq12 V = U * R;
218 
219     const alt_bn128_Fq12 result = V;
220 
221     leave_block("Call to alt_bn128_final_exponentiation_last_chunk");
222 
223     return result;
224 }
225 
alt_bn128_final_exponentiation(const alt_bn128_Fq12 & elt)226 alt_bn128_GT alt_bn128_final_exponentiation(const alt_bn128_Fq12 &elt)
227 {
228     enter_block("Call to alt_bn128_final_exponentiation");
229     /* OLD naive version:
230         alt_bn128_GT result = elt^alt_bn128_final_exponent;
231     */
232     alt_bn128_Fq12 A = alt_bn128_final_exponentiation_first_chunk(elt);
233     alt_bn128_GT result = alt_bn128_final_exponentiation_last_chunk(A);
234 
235     leave_block("Call to alt_bn128_final_exponentiation");
236     return result;
237 }
238 
239 /* ate pairing */
240 
doubling_step_for_flipped_miller_loop(const alt_bn128_Fq two_inv,alt_bn128_G2 & current,alt_bn128_ate_ell_coeffs & c)241 void doubling_step_for_flipped_miller_loop(const alt_bn128_Fq two_inv,
242                                            alt_bn128_G2 &current,
243                                            alt_bn128_ate_ell_coeffs &c)
244 {
245     const alt_bn128_Fq2 X = current.X, Y = current.Y, Z = current.Z;
246 
247     const alt_bn128_Fq2 A = two_inv * (X * Y);                     // A = X1 * Y1 / 2
248     const alt_bn128_Fq2 B = Y.squared();                           // B = Y1^2
249     const alt_bn128_Fq2 C = Z.squared();                           // C = Z1^2
250     const alt_bn128_Fq2 D = C+C+C;                                 // D = 3 * C
251     const alt_bn128_Fq2 E = alt_bn128_twist_coeff_b * D;             // E = twist_b * D
252     const alt_bn128_Fq2 F = E+E+E;                                 // F = 3 * E
253     const alt_bn128_Fq2 G = two_inv * (B+F);                       // G = (B+F)/2
254     const alt_bn128_Fq2 H = (Y+Z).squared() - (B+C);               // H = (Y1+Z1)^2-(B+C)
255     const alt_bn128_Fq2 I = E-B;                                   // I = E-B
256     const alt_bn128_Fq2 J = X.squared();                           // J = X1^2
257     const alt_bn128_Fq2 E_squared = E.squared();                   // E_squared = E^2
258 
259     current.X = A * (B-F);                                       // X3 = A * (B-F)
260     current.Y = G.squared() - (E_squared+E_squared+E_squared);   // Y3 = G^2 - 3*E^2
261     current.Z = B * H;                                           // Z3 = B * H
262     c.ell_0 = alt_bn128_twist * I;                                 // ell_0 = xi * I
263     c.ell_VW = -H;                                               // ell_VW = - H (later: * yP)
264     c.ell_VV = J+J+J;                                            // ell_VV = 3*J (later: * xP)
265 }
266 
mixed_addition_step_for_flipped_miller_loop(const alt_bn128_G2 base,alt_bn128_G2 & current,alt_bn128_ate_ell_coeffs & c)267 void mixed_addition_step_for_flipped_miller_loop(const alt_bn128_G2 base,
268                                                  alt_bn128_G2 &current,
269                                                  alt_bn128_ate_ell_coeffs &c)
270 {
271     const alt_bn128_Fq2 X1 = current.X, Y1 = current.Y, Z1 = current.Z;
272     const alt_bn128_Fq2 &x2 = base.X, &y2 = base.Y;
273 
274     const alt_bn128_Fq2 D = X1 - x2 * Z1;          // D = X1 - X2*Z1
275     const alt_bn128_Fq2 E = Y1 - y2 * Z1;          // E = Y1 - Y2*Z1
276     const alt_bn128_Fq2 F = D.squared();           // F = D^2
277     const alt_bn128_Fq2 G = E.squared();           // G = E^2
278     const alt_bn128_Fq2 H = D*F;                   // H = D*F
279     const alt_bn128_Fq2 I = X1 * F;                // I = X1 * F
280     const alt_bn128_Fq2 J = H + Z1*G - (I+I);      // J = H + Z1*G - (I+I)
281 
282     current.X = D * J;                           // X3 = D*J
283     current.Y = E * (I-J)-(H * Y1);              // Y3 = E*(I-J)-(H*Y1)
284     current.Z = Z1 * H;                          // Z3 = Z1*H
285     c.ell_0 = alt_bn128_twist * (E * x2 - D * y2); // ell_0 = xi * (E * X2 - D * Y2)
286     c.ell_VV = - E;                              // ell_VV = - E (later: * xP)
287     c.ell_VW = D;                                // ell_VW = D (later: * yP    )
288 }
289 
alt_bn128_ate_precompute_G1(const alt_bn128_G1 & P)290 alt_bn128_ate_G1_precomp alt_bn128_ate_precompute_G1(const alt_bn128_G1& P)
291 {
292     enter_block("Call to alt_bn128_ate_precompute_G1");
293 
294     alt_bn128_G1 Pcopy = P;
295     Pcopy.to_affine_coordinates();
296 
297     alt_bn128_ate_G1_precomp result;
298     result.PX = Pcopy.X;
299     result.PY = Pcopy.Y;
300 
301     leave_block("Call to alt_bn128_ate_precompute_G1");
302     return result;
303 }
304 
alt_bn128_ate_precompute_G2(const alt_bn128_G2 & Q)305 alt_bn128_ate_G2_precomp alt_bn128_ate_precompute_G2(const alt_bn128_G2& Q)
306 {
307     enter_block("Call to alt_bn128_ate_precompute_G2");
308 
309     alt_bn128_G2 Qcopy(Q);
310     Qcopy.to_affine_coordinates();
311 
312     alt_bn128_Fq two_inv = (alt_bn128_Fq("2").inverse()); // could add to global params if needed
313 
314     alt_bn128_ate_G2_precomp result;
315     result.QX = Qcopy.X;
316     result.QY = Qcopy.Y;
317 
318     alt_bn128_G2 R;
319     R.X = Qcopy.X;
320     R.Y = Qcopy.Y;
321     R.Z = alt_bn128_Fq2::one();
322 
323     const bigint<alt_bn128_Fr::num_limbs> &loop_count = alt_bn128_ate_loop_count;
324     bool found_one = false;
325     alt_bn128_ate_ell_coeffs c;
326 
327     for (long i = loop_count.max_bits(); i >= 0; --i)
328     {
329         const bool bit = loop_count.test_bit(i);
330         if (!found_one)
331         {
332             /* this skips the MSB itself */
333             found_one |= bit;
334             continue;
335         }
336 
337         doubling_step_for_flipped_miller_loop(two_inv, R, c);
338         result.coeffs.push_back(c);
339 
340         if (bit)
341         {
342             mixed_addition_step_for_flipped_miller_loop(Qcopy, R, c);
343             result.coeffs.push_back(c);
344         }
345     }
346 
347     alt_bn128_G2 Q1 = Qcopy.mul_by_q();
348     assert(Q1.Z == alt_bn128_Fq2::one());
349     alt_bn128_G2 Q2 = Q1.mul_by_q();
350     assert(Q2.Z == alt_bn128_Fq2::one());
351 
352     if (alt_bn128_ate_is_loop_count_neg)
353     {
354         R.Y = - R.Y;
355     }
356     Q2.Y = - Q2.Y;
357 
358     mixed_addition_step_for_flipped_miller_loop(Q1, R, c);
359     result.coeffs.push_back(c);
360 
361     mixed_addition_step_for_flipped_miller_loop(Q2, R, c);
362     result.coeffs.push_back(c);
363 
364     leave_block("Call to alt_bn128_ate_precompute_G2");
365     return result;
366 }
367 
alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp & prec_P,const alt_bn128_ate_G2_precomp & prec_Q)368 alt_bn128_Fq12 alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp &prec_P,
369                                      const alt_bn128_ate_G2_precomp &prec_Q)
370 {
371     enter_block("Call to alt_bn128_ate_miller_loop");
372 
373     alt_bn128_Fq12 f = alt_bn128_Fq12::one();
374 
375     bool found_one = false;
376     size_t idx = 0;
377 
378     const bigint<alt_bn128_Fr::num_limbs> &loop_count = alt_bn128_ate_loop_count;
379     alt_bn128_ate_ell_coeffs c;
380 
381     for (long i = loop_count.max_bits(); i >= 0; --i)
382     {
383         const bool bit = loop_count.test_bit(i);
384         if (!found_one)
385         {
386             /* this skips the MSB itself */
387             found_one |= bit;
388             continue;
389         }
390 
391         /* code below gets executed for all bits (EXCEPT the MSB itself) of
392            alt_bn128_param_p (skipping leading zeros) in MSB to LSB
393            order */
394 
395         c = prec_Q.coeffs[idx++];
396         f = f.squared();
397         f = f.mul_by_024(c.ell_0, prec_P.PY * c.ell_VW, prec_P.PX * c.ell_VV);
398 
399         if (bit)
400         {
401             c = prec_Q.coeffs[idx++];
402             f = f.mul_by_024(c.ell_0, prec_P.PY * c.ell_VW, prec_P.PX * c.ell_VV);
403         }
404 
405     }
406 
407     if (alt_bn128_ate_is_loop_count_neg)
408     {
409     	f = f.inverse();
410     }
411 
412     c = prec_Q.coeffs[idx++];
413     f = f.mul_by_024(c.ell_0,prec_P.PY * c.ell_VW,prec_P.PX * c.ell_VV);
414 
415     c = prec_Q.coeffs[idx++];
416     f = f.mul_by_024(c.ell_0,prec_P.PY * c.ell_VW,prec_P.PX * c.ell_VV);
417 
418     leave_block("Call to alt_bn128_ate_miller_loop");
419     return f;
420 }
421 
alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp & prec_P1,const alt_bn128_ate_G2_precomp & prec_Q1,const alt_bn128_ate_G1_precomp & prec_P2,const alt_bn128_ate_G2_precomp & prec_Q2)422 alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp &prec_P1,
423                                      const alt_bn128_ate_G2_precomp &prec_Q1,
424                                      const alt_bn128_ate_G1_precomp &prec_P2,
425                                      const alt_bn128_ate_G2_precomp &prec_Q2)
426 {
427     enter_block("Call to alt_bn128_ate_double_miller_loop");
428 
429     alt_bn128_Fq12 f = alt_bn128_Fq12::one();
430 
431     bool found_one = false;
432     size_t idx = 0;
433 
434     const bigint<alt_bn128_Fr::num_limbs> &loop_count = alt_bn128_ate_loop_count;
435     for (long i = loop_count.max_bits(); i >= 0; --i)
436     {
437         const bool bit = loop_count.test_bit(i);
438         if (!found_one)
439         {
440             /* this skips the MSB itself */
441             found_one |= bit;
442             continue;
443         }
444 
445         /* code below gets executed for all bits (EXCEPT the MSB itself) of
446            alt_bn128_param_p (skipping leading zeros) in MSB to LSB
447            order */
448 
449         alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx];
450         alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx];
451         ++idx;
452 
453         f = f.squared();
454 
455         f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV);
456         f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV);
457 
458         if (bit)
459         {
460             alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx];
461             alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx];
462             ++idx;
463 
464             f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV);
465             f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV);
466         }
467     }
468 
469     if (alt_bn128_ate_is_loop_count_neg)
470     {
471     	f = f.inverse();
472     }
473 
474     alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx];
475     alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx];
476     ++idx;
477     f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV);
478     f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV);
479 
480     c1 = prec_Q1.coeffs[idx];
481     c2 = prec_Q2.coeffs[idx];
482     ++idx;
483     f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV);
484     f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV);
485 
486     leave_block("Call to alt_bn128_ate_double_miller_loop");
487 
488     return f;
489 }
490 
alt_bn128_ate_pairing(const alt_bn128_G1 & P,const alt_bn128_G2 & Q)491 alt_bn128_Fq12 alt_bn128_ate_pairing(const alt_bn128_G1& P, const alt_bn128_G2 &Q)
492 {
493     enter_block("Call to alt_bn128_ate_pairing");
494     alt_bn128_ate_G1_precomp prec_P = alt_bn128_ate_precompute_G1(P);
495     alt_bn128_ate_G2_precomp prec_Q = alt_bn128_ate_precompute_G2(Q);
496     alt_bn128_Fq12 result = alt_bn128_ate_miller_loop(prec_P, prec_Q);
497     leave_block("Call to alt_bn128_ate_pairing");
498     return result;
499 }
500 
alt_bn128_ate_reduced_pairing(const alt_bn128_G1 & P,const alt_bn128_G2 & Q)501 alt_bn128_GT alt_bn128_ate_reduced_pairing(const alt_bn128_G1 &P, const alt_bn128_G2 &Q)
502 {
503     enter_block("Call to alt_bn128_ate_reduced_pairing");
504     const alt_bn128_Fq12 f = alt_bn128_ate_pairing(P, Q);
505     const alt_bn128_GT result = alt_bn128_final_exponentiation(f);
506     leave_block("Call to alt_bn128_ate_reduced_pairing");
507     return result;
508 }
509 
510 /* choice of pairing */
511 
alt_bn128_precompute_G1(const alt_bn128_G1 & P)512 alt_bn128_G1_precomp alt_bn128_precompute_G1(const alt_bn128_G1& P)
513 {
514     return alt_bn128_ate_precompute_G1(P);
515 }
516 
alt_bn128_precompute_G2(const alt_bn128_G2 & Q)517 alt_bn128_G2_precomp alt_bn128_precompute_G2(const alt_bn128_G2& Q)
518 {
519     return alt_bn128_ate_precompute_G2(Q);
520 }
521 
alt_bn128_miller_loop(const alt_bn128_G1_precomp & prec_P,const alt_bn128_G2_precomp & prec_Q)522 alt_bn128_Fq12 alt_bn128_miller_loop(const alt_bn128_G1_precomp &prec_P,
523                           const alt_bn128_G2_precomp &prec_Q)
524 {
525     return alt_bn128_ate_miller_loop(prec_P, prec_Q);
526 }
527 
alt_bn128_double_miller_loop(const alt_bn128_G1_precomp & prec_P1,const alt_bn128_G2_precomp & prec_Q1,const alt_bn128_G1_precomp & prec_P2,const alt_bn128_G2_precomp & prec_Q2)528 alt_bn128_Fq12 alt_bn128_double_miller_loop(const alt_bn128_G1_precomp &prec_P1,
529                                  const alt_bn128_G2_precomp &prec_Q1,
530                                  const alt_bn128_G1_precomp &prec_P2,
531                                  const alt_bn128_G2_precomp &prec_Q2)
532 {
533     return alt_bn128_ate_double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2);
534 }
535 
alt_bn128_pairing(const alt_bn128_G1 & P,const alt_bn128_G2 & Q)536 alt_bn128_Fq12 alt_bn128_pairing(const alt_bn128_G1& P,
537                       const alt_bn128_G2 &Q)
538 {
539     return alt_bn128_ate_pairing(P, Q);
540 }
541 
alt_bn128_reduced_pairing(const alt_bn128_G1 & P,const alt_bn128_G2 & Q)542 alt_bn128_GT alt_bn128_reduced_pairing(const alt_bn128_G1 &P,
543                              const alt_bn128_G2 &Q)
544 {
545     return alt_bn128_ate_reduced_pairing(P, Q);
546 }
547 } // libff
548