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 ¤t,
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 ¤t,
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