Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
bn128_g2.cpp
Go to the documentation of this file.
1
10
11namespace libff {
12
13#ifdef PROFILE_OP_COUNTS
14long long bn128_G2::add_cnt = 0;
15long long bn128_G2::dbl_cnt = 0;
16#endif
17
18std::vector<size_t> bn128_G2::wnaf_window_table;
20bn128_G2 bn128_G2::G2_zero = {};
21bn128_G2 bn128_G2::G2_one = {};
22bool bn128_G2::initialized = false;
23
24bn::Fp2 bn128_G2::sqrt(const bn::Fp2 &el)
25{
26 size_t v = bn128_Fq2_s;
29 bn::Fp2 x = el * w;
30 bn::Fp2 b = x * w;
31
32#if DEBUG
33 // check if square with Euler's criterion
34 bn::Fp2 check = b;
35 for (size_t i = 0; i < v-1; ++i)
36 {
37 bn::Fp2::square(check, check);
38 }
39
40 assert(check == bn::Fp2(bn::Fp(1), bn::Fp(0)));
41#endif
42
43 // compute square root with Tonelli--Shanks
44 // (does not terminate if not a square!)
45
46 while (b != bn::Fp2(1))
47 {
48 size_t m = 0;
49 bn::Fp2 b2m = b;
50 while (b2m != bn::Fp2(bn::Fp(1), bn::Fp(0)))
51 {
52 // invariant: b2m = b^(2^m) after entering this loop
53 bn::Fp2::square(b2m, b2m);
54 m += 1;
55 }
56
57 int j = v-m-1;
58 w = z;
59 while (j > 0)
60 {
61 bn::Fp2::square(w, w);
62 --j;
63 } // w = z^2^(v-m-1)
64
65 z = w * w;
66 b = b * z;
67 x = x * w;
68 v = m;
69 }
70
71 return x;
72}
73
75{
77 {
78 this->X = G2_zero.X;
79 this->Y = G2_zero.Y;
80 this->Z = G2_zero.Z;
81 }
82}
83
84void bn128_G2::print() const
85{
86 if (this->is_zero())
87 {
88 printf("O\n");
89 }
90 else
91 {
92 bn128_G2 copy(*this);
93 copy.to_affine_coordinates();
94 std::cout << "(" << copy.X.toString(10) << " : " << copy.Y.toString(10) << " : " << copy.Z.toString(10) << ")\n";
95 }
96}
97
99{
100 if (this->is_zero())
101 {
102 printf("O\n");
103 }
104 else
105 {
106 std::cout << "(" << X.toString(10) << " : " << Y.toString(10) << " : " << Z.toString(10) << ")\n";
107 }
108}
109
111{
112 if (this->is_zero())
113 {
114 X = 0;
115 Y = 1;
116 Z = 0;
117 }
118 else
119 {
120 bn::Fp2 r;
121 r = Z;
122 r.inverse();
124 X *= Z;
125 r *= Z;
126 Y *= r;
127 Z = 1;
128 }
129}
130
132{
133 this->to_affine_coordinates();
134}
135
137{
138 return (this->is_zero() || this->Z == 1);
139}
140
142{
143 return Z.isZero();
144}
145
146bool bn128_G2::operator==(const bn128_G2 &other) const
147{
148 if (this->is_zero())
149 {
150 return other.is_zero();
151 }
152
153 if (other.is_zero())
154 {
155 return false;
156 }
157
158 /* now neither is O */
159
160 bn::Fp2 Z1sq, Z2sq, lhs, rhs;
161 bn::Fp2::square(Z1sq, this->Z);
162 bn::Fp2::square(Z2sq, other.Z);
163 bn::Fp2::mul(lhs, Z2sq, this->X);
164 bn::Fp2::mul(rhs, Z1sq, other.X);
165
166 if (lhs != rhs)
167 {
168 return false;
169 }
170
171 bn::Fp2 Z1cubed, Z2cubed;
172 bn::Fp2::mul(Z1cubed, Z1sq, this->Z);
173 bn::Fp2::mul(Z2cubed, Z2sq, other.Z);
174 bn::Fp2::mul(lhs, Z2cubed, this->Y);
175 bn::Fp2::mul(rhs, Z1cubed, other.Y);
176
177 return (lhs == rhs);
178}
179
180bool bn128_G2::operator!=(const bn128_G2& other) const
181{
182 return !(operator==(other));
183}
184
186{
187 // handle special cases having to do with O
188 if (this->is_zero())
189 {
190 return other;
191 }
192
193 if (other.is_zero())
194 {
195 return *this;
196 }
197
198 // no need to handle points of order 2,4
199 // (they cannot exist in a prime-order subgroup)
200
201 // handle double case, and then all the rest
202 if (this->operator==(other))
203 {
204 return this->dbl();
205 }
206 else
207 {
208 return this->add(other);
209 }
210}
211
213{
214 bn128_G2 result(*this);
215 bn::Fp2::neg(result.Y, result.Y);
216 return result;
217}
218
220{
221 return (*this) + (-other);
222}
223
224bn128_G2 bn128_G2::add(const bn128_G2 &other) const
225{
226#ifdef PROFILE_OP_COUNTS
227 this->add_cnt++;
228#endif
229
230 bn::Fp2 this_coord[3], other_coord[3], result_coord[3];
231 this->fill_coord(this_coord);
232 other.fill_coord(other_coord);
233 bn::ecop::ECAdd(result_coord, this_coord, other_coord);
234
235 bn128_G2 result(result_coord);
236 return result;
237}
238
240{
241 if (this->is_zero())
242 {
243 return other;
244 }
245
246 if (other.is_zero())
247 {
248 return *this;
249 }
250
251 // no need to handle points of order 2,4
252 // (they cannot exist in a prime-order subgroup)
253
254#ifdef DEBUG
255 assert(other.is_special());
256#endif
257
258 // check for doubling case
259
260 // using Jacobian coordinates so:
261 // (X1:Y1:Z1) = (X2:Y2:Z2)
262 // iff
263 // X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3
264 // iff
265 // X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3
266
267 // we know that Z2 = 1
268
269 bn::Fp2 Z1Z1;
270 bn::Fp2::square(Z1Z1, this->Z);
271 const bn::Fp2 &U1 = this->X;
272 bn::Fp2 U2;
273 bn::Fp2::mul(U2, other.X, Z1Z1);
274 bn::Fp2 Z1_cubed;
275 bn::Fp2::mul(Z1_cubed, this->Z, Z1Z1);
276
277 const bn::Fp2 &S1 = this->Y;
278 bn::Fp2 S2;
279 bn::Fp2::mul(S2, other.Y, Z1_cubed); // S2 = Y2*Z1*Z1Z1
280
281 if (U1 == U2 && S1 == S2)
282 {
283 // dbl case; nothing of above can be reused
284 return this->dbl();
285 }
286
287#ifdef PROFILE_OP_COUNTS
288 this->add_cnt++;
289#endif
290
291 bn128_G2 result;
292 bn::Fp2 H, HH, I, J, r, V, tmp;
293 // H = U2-X1
294 bn::Fp2::sub(H, U2, this->X);
295 // HH = H^2
296 bn::Fp2::square(HH, H);
297 // I = 4*HH
298 bn::Fp2::add(tmp, HH, HH);
299 bn::Fp2::add(I, tmp, tmp);
300 // J = H*I
301 bn::Fp2::mul(J, H, I);
302 // r = 2*(S2-Y1)
303 bn::Fp2::sub(tmp, S2, this->Y);
304 bn::Fp2::add(r, tmp, tmp);
305 // V = X1*I
306 bn::Fp2::mul(V, this->X, I);
307 // X3 = r^2-J-2*V
308 bn::Fp2::square(result.X, r);
309 bn::Fp2::sub(result.X, result.X, J);
310 bn::Fp2::sub(result.X, result.X, V);
311 bn::Fp2::sub(result.X, result.X, V);
312 // Y3 = r*(V-X3)-2*Y1*J
313 bn::Fp2::sub(tmp, V, result.X);
314 bn::Fp2::mul(result.Y, r, tmp);
315 bn::Fp2::mul(tmp, this->Y, J);
316 bn::Fp2::sub(result.Y, result.Y, tmp);
317 bn::Fp2::sub(result.Y, result.Y, tmp);
318 // Z3 = (Z1+H)^2-Z1Z1-HH
319 bn::Fp2::add(tmp, this->Z, H);
320 bn::Fp2::square(result.Z, tmp);
321 bn::Fp2::sub(result.Z, result.Z, Z1Z1);
322 bn::Fp2::sub(result.Z, result.Z, HH);
323 return result;
324}
325
327{
328#ifdef PROFILE_OP_COUNTS
329 this->dbl_cnt++;
330#endif
331
332 bn::Fp2 this_coord[3], result_coord[3];
333 this->fill_coord(this_coord);
334 bn::ecop::ECDouble(result_coord, this_coord);
335
336 bn128_G2 result(result_coord);
337 return result;
338}
339
341{
342 if (this->is_zero())
343 {
344 return true;
345 }
346 else
347 {
348 /*
349 y^2 = x^3 + b
350
351 We are using Jacobian coordinates, so equation we need to check is actually
352
353 (y/z^3)^2 = (x/z^2)^3 + b
354 y^2 / z^6 = x^3 / z^6 + b
355 y^2 = x^3 + b z^6
356 */
357 bn::Fp2 X2, Y2, Z2;
358 bn::Fp2::square(X2, this->X);
359 bn::Fp2::square(Y2, this->Y);
360 bn::Fp2::square(Z2, this->Z);
361
362 bn::Fp2 X3, Z3, Z6;
363 bn::Fp2::mul(X3, X2, this->X);
364 bn::Fp2::mul(Z3, Z2, this->Z);
365 bn::Fp2::square(Z6, Z3);
366
367 return (Y2 == X3 + bn128_twist_coeff_b * Z6);
368 }
369}
370
372{
373 return G2_zero;
374}
375
377{
378 return G2_one;
379}
380
382{
383 return bn128_Fr::random_element().as_bigint() * G2_one;
384}
385
386std::ostream& operator<<(std::ostream &out, const bn128_G2 &g)
387{
388 bn128_G2 gcopy(g);
389 gcopy.to_affine_coordinates();
390
391 out << (gcopy.is_zero() ? '1' : '0') << OUTPUT_SEPARATOR;
392
393#ifdef NO_PT_COMPRESSION
394 /* no point compression case */
395#ifndef BINARY_OUTPUT
396 out << gcopy.X.a_ << OUTPUT_SEPARATOR << gcopy.X.b_ << OUTPUT_SEPARATOR;
397 out << gcopy.Y.a_ << OUTPUT_SEPARATOR << gcopy.Y.b_;
398#else
399 out.write((char*) &gcopy.X.a_, sizeof(gcopy.X.a_));
400 out.write((char*) &gcopy.X.b_, sizeof(gcopy.X.b_));
401 out.write((char*) &gcopy.Y.a_, sizeof(gcopy.Y.a_));
402 out.write((char*) &gcopy.Y.b_, sizeof(gcopy.Y.b_));
403#endif
404
405#else
406 /* point compression case */
407#ifndef BINARY_OUTPUT
408 out << gcopy.X.a_ << OUTPUT_SEPARATOR << gcopy.X.b_;
409#else
410 out.write((char*) &gcopy.X.a_, sizeof(gcopy.X.a_));
411 out.write((char*) &gcopy.X.b_, sizeof(gcopy.X.b_));
412#endif
413 out << OUTPUT_SEPARATOR << (((unsigned char*)&gcopy.Y.a_)[0] & 1 ? '1' : '0');
414#endif
415
416 return out;
417}
418
419std::istream& operator>>(std::istream &in, bn128_G2 &g)
420{
421 char is_zero;
422 in.read((char*)&is_zero, 1); // this reads is_zero;
423 is_zero -= '0';
425
426#ifdef NO_PT_COMPRESSION
427 /* no point compression case */
428#ifndef BINARY_OUTPUT
429 in >> g.X.a_;
431 in >> g.X.b_;
433 in >> g.Y.a_;
435 in >> g.Y.b_;
436#else
437 in.read((char*) &g.X.a_, sizeof(g.X.a_));
438 in.read((char*) &g.X.b_, sizeof(g.X.b_));
439 in.read((char*) &g.Y.a_, sizeof(g.Y.a_));
440 in.read((char*) &g.Y.b_, sizeof(g.Y.b_));
441#endif
442
443#else
444 /* point compression case */
445 bn::Fp2 tX;
446#ifndef BINARY_OUTPUT
447 in >> tX.a_;
449 in >> tX.b_;
450#else
451 in.read((char*)&tX.a_, sizeof(tX.a_));
452 in.read((char*)&tX.b_, sizeof(tX.b_));
453#endif
455 unsigned char Y_lsb;
456 in.read((char*)&Y_lsb, 1);
457 Y_lsb -= '0';
458
459 // y = +/- sqrt(x^3 + b)
460 if (!is_zero)
461 {
462 g.X = tX;
463 bn::Fp2 tX2, tY2;
464 bn::Fp2::square(tX2, tX);
465 bn::Fp2::mul(tY2, tX2, tX);
467
468 g.Y = bn128_G2::sqrt(tY2);
469 if ((((unsigned char*)&g.Y.a_)[0] & 1) != Y_lsb)
470 {
471 bn::Fp2::neg(g.Y, g.Y);
472 }
473 }
474#endif
475
476 /* finalize */
477 if (!is_zero)
478 {
479 g.Z = bn::Fp2(bn::Fp(1), bn::Fp(0));
480 }
481 else
482 {
483 g = bn128_G2::zero();
484 }
485
486 return in;
487}
488
489void bn128_G2::batch_to_special_all_non_zeros(std::vector<bn128_G2> &vec)
490{
491 std::vector<bn::Fp2> Z_vec;
492 Z_vec.reserve(vec.size());
493
494 for (auto &el: vec)
495 {
496 Z_vec.emplace_back(el.Z);
497 }
499
500 const bn::Fp2 one = 1;
501
502 for (size_t i = 0; i < vec.size(); ++i)
503 {
504 bn::Fp2 Z2, Z3;
505 bn::Fp2::square(Z2, Z_vec[i]);
506 bn::Fp2::mul(Z3, Z2, Z_vec[i]);
507
508 bn::Fp2::mul(vec[i].X, vec[i].X, Z2);
509 bn::Fp2::mul(vec[i].Y, vec[i].Y, Z3);
510 vec[i].Z = one;
511 }
512}
513
514} // libff
const mie::Vuint & r
Definition bn.cpp:28
static Fp_model< n, modulus > random_element()
bn128_G2 mixed_add(const bn128_G2 &other) const
Definition bn128_g2.cpp:239
static bn128_G2 random_element()
Definition bn128_g2.cpp:381
static bn128_G2 G2_zero
Definition bn128_g2.hpp:34
bool is_well_formed() const
Definition bn128_g2.cpp:340
static void batch_to_special_all_non_zeros(std::vector< bn128_G2 > &vec)
Definition bn128_g2.cpp:489
bool is_zero() const
Definition bn128_g2.cpp:141
static std::vector< size_t > fixed_base_exp_window_table
Definition bn128_g2.hpp:33
bn128_G2 dbl() const
Definition bn128_g2.cpp:326
void print_coordinates() const
Definition bn128_g2.cpp:98
bool operator==(const bn128_G2 &other) const
Definition bn128_g2.cpp:146
static bn128_G2 zero()
Definition bn128_g2.cpp:371
bn128_G2 operator-() const
Definition bn128_g2.cpp:212
static bn128_G2 G2_one
Definition bn128_g2.hpp:35
bool is_special() const
Definition bn128_g2.cpp:136
bn128_G2 operator+(const bn128_G2 &other) const
Definition bn128_g2.cpp:185
bool operator!=(const bn128_G2 &other) const
Definition bn128_g2.cpp:180
static std::vector< size_t > wnaf_window_table
Definition bn128_g2.hpp:32
static bool initialized
Definition bn128_g2.hpp:36
void to_affine_coordinates()
Definition bn128_g2.cpp:110
bn128_G2 add(const bn128_G2 &other) const
Definition bn128_g2.cpp:224
void fill_coord(bn::Fp2 coord[3]) const
Definition bn128_g2.hpp:42
static bn128_G2 one()
Definition bn128_g2.cpp:376
void print() const
Definition bn128_g2.cpp:84
Definition zm2.h:18
#define OUTPUT_SEPARATOR
void ECDouble(FF *out, const FF *in)
Definition bn.h:2497
void ECAdd(FF *out, const FF *a, const FF *b)
Definition bn.h:2526
Fp2T< Fp > Fp2
Definition bn.h:2954
bn::Fp2 bn128_twist_coeff_b
size_t bn128_Fq2_s
void bn_batch_invert(std::vector< FieldT > &vec)
std::istream & operator>>(std::istream &in, alt_bn128_G1 &g)
void consume_OUTPUT_SEPARATOR(std::istream &in)
std::ostream & operator<<(std::ostream &out, const alt_bn128_G1 &g)
bn::Fp2 bn128_Fq2_nqr_to_t
mie::Vuint bn128_Fq2_t_minus_1_over_2
T power(const T &x, const S &y)
Definition zm.h:1389
Definition test_zm.cpp:19
Definition lib.h:43
Definition bn.h:348
std::string toString(int base=10) const
Definition bn.h:521
Fp a_
Definition bn.h:350
bool isZero() const
Definition bn.h:364
static void neg(Fp2T &z, const Fp2T &x)
Definition bn.h:400
static void(* square)(Fp2T &z, const Fp2T &x)
Definition bn.h:373
Fp b_
Definition bn.h:350
static void(* sub)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:370
static void(* add)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:368
static void(* mul)(Fp2T &z, const Fp2T &x, const Fp2T &y)
Definition bn.h:372
uint16_t j