Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
alt_bn128_pairing.cpp
Go to the documentation of this file.
1
8#include <cassert>
9
15
16namespace libff {
17
19{
20 return (this->PX == other.PX &&
21 this->PY == other.PY);
22}
23
24std::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
31std::istream& operator>>(std::istream &in, alt_bn128_ate_G1_precomp &prec_P)
32{
33 in >> prec_P.PX;
35 in >> prec_P.PY;
36
37 return in;
38}
39
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
47std::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
53std::istream& operator>>(std::istream &in, alt_bn128_ate_ell_coeffs &c)
54{
55 in >> c.ell_0;
57 in >> c.ell_VW;
59 in >> c.ell_VV;
60
61 return in;
62}
63
65{
66 return (this->QX == other.QX &&
67 this->QY == other.QY &&
68 this->coeffs == other.coeffs);
69}
70
71std::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
82std::istream& operator>>(std::istream& in, alt_bn128_ate_G2_precomp &prec_Q)
83{
84 in >> prec_Q.QX;
86 in >> prec_Q.QY;
88
89 prec_Q.coeffs.clear();
90 size_t s;
91 in >> s;
92
94
95 prec_Q.coeffs.reserve(s);
96
97 for (size_t i = 0; i < s; ++i)
98 {
100 in >> c;
102 prec_Q.coeffs.emplace_back(c);
103 }
104
105 return in;
106}
107
108/* final exponentiations */
109
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
138{
139 enter_block("Call to alt_bn128_exp_by_neg_z");
140
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
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
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;
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
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 */
234
235 leave_block("Call to alt_bn128_final_exponentiation");
236 return result;
237}
238
239/* ate pairing */
240
242 alt_bn128_G2 &current,
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
268 alt_bn128_G2 &current,
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
291{
292 enter_block("Call to alt_bn128_ate_precompute_G1");
293
294 alt_bn128_G1 Pcopy = P;
295 Pcopy.to_affine_coordinates();
296
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
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
315 result.QX = Qcopy.X;
316 result.QY = Qcopy.Y;
317
319 R.X = Qcopy.X;
320 R.Y = Qcopy.Y;
321 R.Z = alt_bn128_Fq2::one();
322
324 bool found_one = false;
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
338 result.coeffs.push_back(c);
339
340 if (bit)
341 {
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
353 {
354 R.Y = - R.Y;
355 }
356 Q2.Y = - Q2.Y;
357
359 result.coeffs.push_back(c);
360
362 result.coeffs.push_back(c);
363
364 leave_block("Call to alt_bn128_ate_precompute_G2");
365 return result;
366}
367
369 const alt_bn128_ate_G2_precomp &prec_Q)
370{
371 enter_block("Call to alt_bn128_ate_miller_loop");
372
374
375 bool found_one = false;
376 size_t idx = 0;
377
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
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
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
430
431 bool found_one = false;
432 size_t idx = 0;
433
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
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
492{
493 enter_block("Call to alt_bn128_ate_pairing");
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
502{
503 enter_block("Call to alt_bn128_ate_reduced_pairing");
506 leave_block("Call to alt_bn128_ate_reduced_pairing");
507 return result;
508}
509
510/* choice of pairing */
511
516
521
523 const alt_bn128_G2_precomp &prec_Q)
524{
525 return alt_bn128_ate_miller_loop(prec_P, prec_Q);
526}
527
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
537 const alt_bn128_G2 &Q)
538{
539 return alt_bn128_ate_pairing(P, Q);
540}
541
547} // libff
Fp12_2over3over2_model Frobenius_map(unsigned long power) const
Fp12_2over3over2_model cyclotomic_exp(const bigint< m > &exponent) const
Fp12_2over3over2_model unitary_inverse() const
Fp12_2over3over2_model inverse() const
Fp12_2over3over2_model cyclotomic_squared() const
static Fp12_2over3over2_model< n, modulus > one()
Fp2_model squared() const
Fp_model inverse() const
alt_bn128_G2 mul_by_q() const
bool test_bit(const std::size_t bitno) const
size_t max_bits() const
Definition bigint.hpp:48
#define D(var, file, col, who, lev,...)
Definition debug.h:44
#define P
Definition dtoa.c:437
#define OUTPUT_NEWLINE
#define OUTPUT_SEPARATOR
const uint64 K
Definition make_512.cpp:78
alt_bn128_Fq12 alt_bn128_pairing(const alt_bn128_G1 &P, const alt_bn128_G2 &Q)
alt_bn128_Fq2 alt_bn128_twist
void consume_OUTPUT_NEWLINE(std::istream &in)
alt_bn128_Fq12 alt_bn128_final_exponentiation_last_chunk(const alt_bn128_Fq12 &elt)
std::istream & operator>>(std::istream &in, alt_bn128_G1 &g)
alt_bn128_GT alt_bn128_reduced_pairing(const alt_bn128_G1 &P, const alt_bn128_G2 &Q)
bigint< alt_bn128_q_limbs > alt_bn128_final_exponent_z
void consume_OUTPUT_SEPARATOR(std::istream &in)
Fp_model< alt_bn128_q_limbs, alt_bn128_modulus_q > alt_bn128_Fq
alt_bn128_GT alt_bn128_ate_reduced_pairing(const alt_bn128_G1 &P, const alt_bn128_G2 &Q)
alt_bn128_Fq12 alt_bn128_miller_loop(const alt_bn128_G1_precomp &prec_P, const alt_bn128_G2_precomp &prec_Q)
alt_bn128_ate_G2_precomp alt_bn128_ate_precompute_G2(const alt_bn128_G2 &Q)
bool alt_bn128_ate_is_loop_count_neg
std::ostream & operator<<(std::ostream &out, const alt_bn128_G1 &g)
void enter_block(const std::string &msg, const bool indent)
bigint< alt_bn128_q_limbs > alt_bn128_ate_loop_count
alt_bn128_G2_precomp alt_bn128_precompute_G2(const alt_bn128_G2 &Q)
void doubling_step_for_flipped_miller_loop(const alt_bn128_Fq two_inv, alt_bn128_G2 &current, alt_bn128_ate_ell_coeffs &c)
bool alt_bn128_final_exponent_is_z_neg
alt_bn128_Fq12 alt_bn128_exp_by_neg_z(const alt_bn128_Fq12 &elt)
alt_bn128_G1_precomp alt_bn128_precompute_G1(const alt_bn128_G1 &P)
Fp12_2over3over2_model< alt_bn128_q_limbs, alt_bn128_modulus_q > alt_bn128_Fq12
alt_bn128_Fq12 alt_bn128_final_exponentiation_first_chunk(const alt_bn128_Fq12 &elt)
alt_bn128_Fq12 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)
alt_bn128_ate_G1_precomp alt_bn128_ate_precompute_G1(const alt_bn128_G1 &P)
alt_bn128_Fq12 alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp &prec_P, const alt_bn128_ate_G2_precomp &prec_Q)
alt_bn128_Fq2 alt_bn128_twist_coeff_b
void leave_block(const std::string &msg, const bool indent)
alt_bn128_GT alt_bn128_final_exponentiation(const alt_bn128_Fq12 &elt)
void consume_newline(std::istream &in)
alt_bn128_Fq12 alt_bn128_ate_pairing(const alt_bn128_G1 &P, const alt_bn128_G2 &Q)
void mixed_addition_step_for_flipped_miller_loop(const alt_bn128_G2 base, alt_bn128_G2 &current, alt_bn128_ate_ell_coeffs &c)
alt_bn128_Fq12 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)
#define T(meth, val, expected)
const int N
Definition quantize.cpp:54
Definition test_zm.cpp:19
Definition lib.h:43
bool operator==(const alt_bn128_ate_G1_precomp &other) const
std::vector< alt_bn128_ate_ell_coeffs > coeffs
bool operator==(const alt_bn128_ate_G2_precomp &other) const
bool operator==(const alt_bn128_ate_ell_coeffs &other) const
#define R
Definition dtoa.c:306
int bit
Definition yubihsm.h:566
char * s