Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
edwards_g1.cpp
Go to the documentation of this file.
1
9
10namespace libff {
11
12#ifdef PROFILE_OP_COUNTS
13long long edwards_G1::add_cnt = 0;
14long long edwards_G1::dbl_cnt = 0;
15#endif
16
17std::vector<size_t> edwards_G1::wnaf_window_table;
19edwards_G1 edwards_G1::G1_zero = {};
20edwards_G1 edwards_G1::G1_one = {};
21bool edwards_G1::initialized = false;
22
24{
25 if (initialized)
26 {
27 this->X = G1_zero.X;
28 this->Y = G1_zero.Y;
29 this->Z = G1_zero.Z;
30 }
31}
32
34{
35 if (this->is_zero())
36 {
37 printf("O\n");
38 }
39 else
40 {
41 edwards_G1 copy(*this);
42 copy.to_affine_coordinates();
43 gmp_printf("(%Nd , %Nd)\n",
44 copy.X.as_bigint().data, edwards_Fq::num_limbs,
45 copy.Y.as_bigint().data, edwards_Fq::num_limbs);
46 }
47}
48
50{
51 if (this->is_zero())
52 {
53 printf("O\n");
54 }
55 else
56 {
57 gmp_printf("(%Nd : %Nd : %Nd)\n",
58 this->X.as_bigint().data, edwards_Fq::num_limbs,
59 this->Y.as_bigint().data, edwards_Fq::num_limbs,
60 this->Z.as_bigint().data, edwards_Fq::num_limbs);
61 }
62}
63
65{
66 if (this->is_zero())
67 {
68 this->X = edwards_Fq::zero();
69 this->Y = edwards_Fq::one();
70 this->Z = edwards_Fq::one();
71 }
72 else
73 {
74 // go from inverted coordinates to projective coordinates
75 edwards_Fq tX = this->Y * this->Z;
76 edwards_Fq tY = this->X * this->Z;
77 edwards_Fq tZ = this->X * this->Y;
78 // go from projective coordinates to affine coordinates
79 edwards_Fq tZ_inv = tZ.inverse();
80 this->X = tX * tZ_inv;
81 this->Y = tY * tZ_inv;
82 this->Z = edwards_Fq::one();
83 }
84}
85
87{
88 if (this->Z.is_zero())
89 {
90 return;
91 }
92
93#ifdef DEBUG
94 const edwards_G1 copy(*this);
95#endif
96
97 edwards_Fq Z_inv = this->Z.inverse();
98 this->X = this->X * Z_inv;
99 this->Y = this->Y * Z_inv;
100 this->Z = edwards_Fq::one();
101
102#ifdef DEBUG
103 assert((*this) == copy);
104#endif
105}
106
108{
109 return (this->is_zero() || this->Z == edwards_Fq::one());
110}
111
113{
114 return (this->Y.is_zero() && this->Z.is_zero());
115}
116
117bool edwards_G1::operator==(const edwards_G1 &other) const
118{
119 if (this->is_zero())
120 {
121 return other.is_zero();
122 }
123
124 if (other.is_zero())
125 {
126 return false;
127 }
128
129 /* now neither is O */
130
131 // X1/Z1 = X2/Z2 <=> X1*Z2 = X2*Z1
132 if ((this->X * other.Z) != (other.X * this->Z))
133 {
134 return false;
135 }
136
137 // Y1/Z1 = Y2/Z2 <=> Y1*Z2 = Y2*Z1
138 if ((this->Y * other.Z) != (other.Y * this->Z))
139 {
140 return false;
141 }
142
143 return true;
144}
145
146bool edwards_G1::operator!=(const edwards_G1& other) const
147{
148 return !(operator==(other));
149}
150
152{
153 // handle special cases having to do with O
154 if (this->is_zero())
155 {
156 return other;
157 }
158
159 if (other.is_zero())
160 {
161 return (*this);
162 }
163
164 return this->add(other);
165}
166
168{
169 return edwards_G1(-(this->X), this->Y, this->Z);
170}
171
172
174{
175 return (*this) + (-other);
176}
177
179{
180#ifdef PROFILE_OP_COUNTS
181 this->add_cnt++;
182#endif
183 // NOTE: does not handle O and pts of order 2,4
184 // http://www.hyperelliptic.org/EFD/g1p/auto-edwards-inverted.html#addition-add-2007-bl
185
186 edwards_Fq A = (this->Z) * (other.Z); // A = Z1*Z2
187 edwards_Fq B = edwards_coeff_d * A.squared(); // B = d*A^2
188 edwards_Fq C = (this->X) * (other.X); // C = X1*X2
189 edwards_Fq D = (this->Y) * (other.Y); // D = Y1*Y2
190 edwards_Fq E = C * D; // E = C*D
191 edwards_Fq H = C - D; // H = C-D
192 edwards_Fq I = (this->X+this->Y)*(other.X+other.Y)-C-D; // I = (X1+Y1)*(X2+Y2)-C-D
193 edwards_Fq X3 = (E+B)*H; // X3 = c*(E+B)*H
194 edwards_Fq Y3 = (E-B)*I; // Y3 = c*(E-B)*I
195 edwards_Fq Z3 = A*H*I; // Z3 = A*H*I
196
197 return edwards_G1(X3, Y3, Z3);
198}
199
201{
202#ifdef PROFILE_OP_COUNTS
203 this->add_cnt++;
204#endif
205 // handle special cases having to do with O
206 if (this->is_zero())
207 {
208 return other;
209 }
210
211 if (other.is_zero())
212 {
213 return *this;
214 }
215
216#ifdef DEBUG
217 assert(other.is_special());
218#endif
219
220 // NOTE: does not handle O and pts of order 2,4
221 // http://www.hyperelliptic.org/EFD/g1p/auto-edwards-inverted.html#addition-madd-2007-lb
222
223 edwards_Fq A = this->Z; // A = Z1
224 edwards_Fq B = edwards_coeff_d * A.squared(); // B = d*A^2
225 edwards_Fq C = (this->X) * (other.X); // C = X1*X2
226 edwards_Fq D = (this->Y) * (other.Y); // D = Y1*Y2
227 edwards_Fq E = C * D; // E = C*D
228 edwards_Fq H = C - D; // H = C-D
229 edwards_Fq I = (this->X+this->Y)*(other.X+other.Y)-C-D; // I = (X1+Y1)*(X2+Y2)-C-D
230 edwards_Fq X3 = (E+B)*H; // X3 = c*(E+B)*H
231 edwards_Fq Y3 = (E-B)*I; // Y3 = c*(E-B)*I
232 edwards_Fq Z3 = A*H*I; // Z3 = A*H*I
233
234 return edwards_G1(X3, Y3, Z3);
235}
236
238{
239#ifdef PROFILE_OP_COUNTS
240 this->dbl_cnt++;
241#endif
242 if (this->is_zero())
243 {
244 return (*this);
245 }
246 else
247 {
248 // NOTE: does not handle O and pts of order 2,4
249 // http://www.hyperelliptic.org/EFD/g1p/auto-edwards-inverted.html#doubling-dbl-2007-bl
250
251 edwards_Fq A = (this->X).squared(); // A = X1^2
252 edwards_Fq B = (this->Y).squared(); // B = Y1^2
253 edwards_Fq C = A+B; // C = A+B
254 edwards_Fq D = A-B; // D = A-B
255 edwards_Fq E = (this->X+this->Y).squared()-C; // E = (X1+Y1)^2-C
256 edwards_Fq X3 = C*D; // X3 = C*D
257 edwards_Fq dZZ = edwards_coeff_d * this->Z.squared();
258 edwards_Fq Y3 = E*(C-dZZ-dZZ); // Y3 = E*(C-2*d*Z1^2)
259 edwards_Fq Z3 = D*E; // Z3 = D*E
260
261 return edwards_G1(X3, Y3, Z3);
262 }
263}
264
266{
267 /* Note that point at infinity is the only special case we must check as
268 inverted representation does no cover points (0, +-c) and (+-c, 0). */
269 if (this->is_zero())
270 {
271 return true;
272 }
273 else
274 {
275 /*
276 a x^2 + y^2 = 1 + d x^2 y^2
277
278 We are using inverted, so equation we need to check is actually
279
280 a (z/x)^2 + (z/y)^2 = 1 + d z^4 / (x^2 * y^2)
281 z^2 (a y^2 + x^2 - dz^2) = x^2 y^2
282 */
283 edwards_Fq X2 = this->X.squared();
284 edwards_Fq Y2 = this->Y.squared();
285 edwards_Fq Z2 = this->Z.squared();
286
287 // for G1 a = 1
288 return (Z2 * (Y2 + X2 - edwards_coeff_d * Z2) == X2 * Y2);
289 }
290}
291
293{
294 return G1_zero;
295}
296
298{
299 return G1_one;
300}
301
306
307std::ostream& operator<<(std::ostream &out, const edwards_G1 &g)
308{
309 edwards_G1 copy(g);
310 copy.to_affine_coordinates();
311#ifdef NO_PT_COMPRESSION
312 out << copy.X << OUTPUT_SEPARATOR << copy.Y;
313#else
314 /* storing LSB of Y */
315 out << copy.X << OUTPUT_SEPARATOR << (copy.Y.as_bigint().data[0] & 1);
316#endif
317
318 return out;
319}
320
321std::istream& operator>>(std::istream &in, edwards_G1 &g)
322{
323 edwards_Fq tX, tY;
324
325#ifdef NO_PT_COMPRESSION
326 in >> tX;
328 in >> tY;
329#else
330 /*
331 a x^2 + y^2 = 1 + d x^2 y^2
332 y = sqrt((1-ax^2)/(1-dx^2))
333 */
334 unsigned char Y_lsb;
335 in >> tX;
336
338 in.read((char*)&Y_lsb, 1);
339 Y_lsb -= '0';
340
341 edwards_Fq tX2 = tX.squared();
342 edwards_Fq tY2 = (edwards_Fq::one() - tX2) * // a = 1 for G1 (not a twist)
344 tY = tY2.sqrt();
345
346 if ((tY.as_bigint().data[0] & 1) != Y_lsb)
347 {
348 tY = -tY;
349 }
350#endif
351
352 // using inverted coordinates
353 g.X = tY;
354 g.Y = tX;
355 g.Z = tX * tY;
356
357#ifdef USE_MIXED_ADDITION
358 g.to_special();
359#endif
360
361 return in;
362}
363
364std::ostream& operator<<(std::ostream& out, const std::vector<edwards_G1> &v)
365{
366 out << v.size() << "\n";
367 for (const edwards_G1& t : v)
368 {
369 out << t << OUTPUT_NEWLINE;
370 }
371
372 return out;
373}
374
375std::istream& operator>>(std::istream& in, std::vector<edwards_G1> &v)
376{
377 v.clear();
378
379 size_t s;
380 in >> s;
381 v.reserve(s);
382 consume_newline(in);
383
384 for (size_t i = 0; i < s; ++i)
385 {
386 edwards_G1 g;
387 in >> g;
388 v.emplace_back(g);
390 }
391
392 return in;
393}
394
395void edwards_G1::batch_to_special_all_non_zeros(std::vector<edwards_G1> &vec)
396{
397 std::vector<edwards_Fq> Z_vec;
398 Z_vec.reserve(vec.size());
399
400 for (auto &el: vec)
401 {
402 Z_vec.emplace_back(el.Z);
403 }
405
407
408 for (size_t i = 0; i < vec.size(); ++i)
409 {
410 vec[i].X = vec[i].X * Z_vec[i];
411 vec[i].Y = vec[i].Y * Z_vec[i];
412 vec[i].Z = one;
413 }
414}
415
416} // libff
bool is_zero() const
Fp_model sqrt() const
Fp_model squared() const
Fp_model inverse() const
bigint< n > as_bigint() const
static Fp_model< n, modulus > random_element()
edwards_G1 add(const edwards_G1 &other) const
void print_coordinates() const
edwards_G1 operator-() const
void to_affine_coordinates()
bool is_well_formed() const
static std::vector< size_t > fixed_base_exp_window_table
static bool initialized
static edwards_G1 one()
bool is_zero() const
static edwards_G1 zero()
edwards_G1 operator+(const edwards_G1 &other) const
static edwards_G1 G1_one
static void batch_to_special_all_non_zeros(std::vector< edwards_G1 > &vec)
static edwards_G1 random_element()
bool is_special() const
bool operator==(const edwards_G1 &other) const
edwards_G1 mixed_add(const edwards_G1 &other) const
void print() const
static edwards_G1 G1_zero
bool operator!=(const edwards_G1 &other) const
edwards_G1 dbl() const
static std::vector< size_t > wnaf_window_table
#define D(var, file, col, who, lev,...)
Definition debug.h:44
#define OUTPUT_NEWLINE
#define OUTPUT_SEPARATOR
void consume_OUTPUT_NEWLINE(std::istream &in)
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)
edwards_Fq edwards_coeff_d
void consume_newline(std::istream &in)
void batch_invert(std::vector< FieldT > &vec)
Definition lib.h:43
char * s