ethereum.prague.vm.precompiled_contracts.bls12_381
BLS12 381 Precompile ^^^^^^^^^^^^^^^^^^^^
.. contents:: Table of Contents :backlinks: none :local:
Introduction
Precompile for BLS12-381 curve operations.
G1_K_DISCOUNT
37 | G1_K_DISCOUNT = [ |
---|---|
38 | 1000, |
39 | 949, |
40 | 848, |
41 | 797, |
42 | 764, |
43 | 750, |
44 | 738, |
45 | 728, |
46 | 719, |
47 | 712, |
48 | 705, |
49 | 698, |
50 | 692, |
51 | 687, |
52 | 682, |
53 | 677, |
54 | 673, |
55 | 669, |
56 | 665, |
57 | 661, |
58 | 658, |
59 | 654, |
60 | 651, |
61 | 648, |
62 | 645, |
63 | 642, |
64 | 640, |
65 | 637, |
66 | 635, |
67 | 632, |
68 | 630, |
69 | 627, |
70 | 625, |
71 | 623, |
72 | 621, |
73 | 619, |
74 | 617, |
75 | 615, |
76 | 613, |
77 | 611, |
78 | 609, |
79 | 608, |
80 | 606, |
81 | 604, |
82 | 603, |
83 | 601, |
84 | 599, |
85 | 598, |
86 | 596, |
87 | 595, |
88 | 593, |
89 | 592, |
90 | 591, |
91 | 589, |
92 | 588, |
93 | 586, |
94 | 585, |
95 | 584, |
96 | 582, |
97 | 581, |
98 | 580, |
99 | 579, |
100 | 577, |
101 | 576, |
102 | 575, |
103 | 574, |
104 | 573, |
105 | 572, |
106 | 570, |
107 | 569, |
108 | 568, |
109 | 567, |
110 | 566, |
111 | 565, |
112 | 564, |
113 | 563, |
114 | 562, |
115 | 561, |
116 | 560, |
117 | 559, |
118 | 558, |
119 | 557, |
120 | 556, |
121 | 555, |
122 | 554, |
123 | 553, |
124 | 552, |
125 | 551, |
126 | 550, |
127 | 549, |
128 | 548, |
129 | 547, |
130 | 547, |
131 | 546, |
132 | 545, |
133 | 544, |
134 | 543, |
135 | 542, |
136 | 541, |
137 | 540, |
138 | 540, |
139 | 539, |
140 | 538, |
141 | 537, |
142 | 536, |
143 | 536, |
144 | 535, |
145 | 534, |
146 | 533, |
147 | 532, |
148 | 532, |
149 | 531, |
150 | 530, |
151 | 529, |
152 | 528, |
153 | 528, |
154 | 527, |
155 | 526, |
156 | 525, |
157 | 525, |
158 | 524, |
159 | 523, |
160 | 522, |
161 | 522, |
162 | 521, |
163 | 520, |
164 | 520, |
165 | 519, |
166 | ] |
G2_K_DISCOUNT
168 | G2_K_DISCOUNT = [ |
---|---|
169 | 1000, |
170 | 1000, |
171 | 923, |
172 | 884, |
173 | 855, |
174 | 832, |
175 | 812, |
176 | 796, |
177 | 782, |
178 | 770, |
179 | 759, |
180 | 749, |
181 | 740, |
182 | 732, |
183 | 724, |
184 | 717, |
185 | 711, |
186 | 704, |
187 | 699, |
188 | 693, |
189 | 688, |
190 | 683, |
191 | 679, |
192 | 674, |
193 | 670, |
194 | 666, |
195 | 663, |
196 | 659, |
197 | 655, |
198 | 652, |
199 | 649, |
200 | 646, |
201 | 643, |
202 | 640, |
203 | 637, |
204 | 634, |
205 | 632, |
206 | 629, |
207 | 627, |
208 | 624, |
209 | 622, |
210 | 620, |
211 | 618, |
212 | 615, |
213 | 613, |
214 | 611, |
215 | 609, |
216 | 607, |
217 | 606, |
218 | 604, |
219 | 602, |
220 | 600, |
221 | 598, |
222 | 597, |
223 | 595, |
224 | 593, |
225 | 592, |
226 | 590, |
227 | 589, |
228 | 587, |
229 | 586, |
230 | 584, |
231 | 583, |
232 | 582, |
233 | 580, |
234 | 579, |
235 | 578, |
236 | 576, |
237 | 575, |
238 | 574, |
239 | 573, |
240 | 571, |
241 | 570, |
242 | 569, |
243 | 568, |
244 | 567, |
245 | 566, |
246 | 565, |
247 | 563, |
248 | 562, |
249 | 561, |
250 | 560, |
251 | 559, |
252 | 558, |
253 | 557, |
254 | 556, |
255 | 555, |
256 | 554, |
257 | 553, |
258 | 552, |
259 | 552, |
260 | 551, |
261 | 550, |
262 | 549, |
263 | 548, |
264 | 547, |
265 | 546, |
266 | 545, |
267 | 545, |
268 | 544, |
269 | 543, |
270 | 542, |
271 | 541, |
272 | 541, |
273 | 540, |
274 | 539, |
275 | 538, |
276 | 537, |
277 | 537, |
278 | 536, |
279 | 535, |
280 | 535, |
281 | 534, |
282 | 533, |
283 | 532, |
284 | 532, |
285 | 531, |
286 | 530, |
287 | 530, |
288 | 529, |
289 | 528, |
290 | 528, |
291 | 527, |
292 | 526, |
293 | 526, |
294 | 525, |
295 | 524, |
296 | 524, |
297 | ] |
G1_MAX_DISCOUNT
299 | G1_MAX_DISCOUNT = 519 |
---|
G2_MAX_DISCOUNT
300 | G2_MAX_DISCOUNT = 524 |
---|
MULTIPLIER
301 | MULTIPLIER = Uint(1000) |
---|
bytes_to_g1
Decode 128 bytes to a G1 point. Does not perform sub-group check.
Parameters
data : The bytes data to decode.
Returns
point : Point3D[FQ] The G1 point.
Raises
InvalidParameter Either a field element is invalid or the point is not on the curve.
def bytes_to_g1(data: Bytes) -> Point3D[FQ]:
307 | """ |
---|---|
308 | Decode 128 bytes to a G1 point. Does not perform sub-group check. |
309 |
|
310 | Parameters |
311 | ---------- |
312 | data : |
313 | The bytes data to decode. |
314 |
|
315 | Returns |
316 | ------- |
317 | point : Point3D[FQ] |
318 | The G1 point. |
319 |
|
320 | Raises |
321 | ------ |
322 | InvalidParameter |
323 | Either a field element is invalid or the point is not on the curve. |
324 | """ |
325 | if len(data) != 128: |
326 | raise InvalidParameter("Input should be 128 bytes long") |
327 | |
328 | x = bytes_to_fq(data[:64]) |
329 | y = bytes_to_fq(data[64:]) |
330 | |
331 | if x >= FQ.field_modulus: |
332 | raise InvalidParameter("x >= field modulus") |
333 | if y >= FQ.field_modulus: |
334 | raise InvalidParameter("y >= field modulus") |
335 | |
336 | z = 1 |
337 | if x == 0 and y == 0: |
338 | z = 0 |
339 | point = FQ(x), FQ(y), FQ(z) |
340 | |
341 | if not is_on_curve(point, b): |
342 | raise InvalidParameter("Point is not on curve") |
343 | |
344 | return point |
g1_to_bytes
Encode a G1 point to 128 bytes.
Parameters
g1_point : The G1 point to encode.
Returns
data : Bytes The encoded data.
def g1_to_bytes(g1_point: Point3D[FQ]) -> Bytes:
350 | """ |
---|---|
351 | Encode a G1 point to 128 bytes. |
352 |
|
353 | Parameters |
354 | ---------- |
355 | g1_point : |
356 | The G1 point to encode. |
357 |
|
358 | Returns |
359 | ------- |
360 | data : Bytes |
361 | The encoded data. |
362 | """ |
363 | g1_normalized = normalize(g1_point) |
364 | x, y = g1_normalized |
365 | return b"".join([int(x).to_bytes(64, "big"), int(y).to_bytes(64, "big")]) |
decode_g1_scalar_pair
Decode 160 bytes to a G1 point and a scalar.
Parameters
data : The bytes data to decode.
Returns
point : Tuple[Point3D[FQ], int] The G1 point and the scalar.
Raises
InvalidParameter If the sub-group check failed.
def decode_g1_scalar_pair(data: Bytes) -> Tuple[Point3D[FQ], int]:
371 | """ |
---|---|
372 | Decode 160 bytes to a G1 point and a scalar. |
373 |
|
374 | Parameters |
375 | ---------- |
376 | data : |
377 | The bytes data to decode. |
378 |
|
379 | Returns |
380 | ------- |
381 | point : Tuple[Point3D[FQ], int] |
382 | The G1 point and the scalar. |
383 |
|
384 | Raises |
385 | ------ |
386 | InvalidParameter |
387 | If the sub-group check failed. |
388 | """ |
389 | if len(data) != 160: |
390 | InvalidParameter("Input should be 160 bytes long") |
391 | |
392 | point = bytes_to_g1(data[:128]) |
393 | if not is_inf(bls12_multiply(point, curve_order)): |
394 | raise InvalidParameter("Sub-group check failed.") |
395 | |
396 | m = int.from_bytes(buffer_read(data, U256(128), U256(32)), "big") |
397 | |
398 | return point, m |
bytes_to_fq
Decode 64 bytes to a FQ element.
Parameters
data : The bytes data to decode.
Returns
fq : FQ The FQ element.
Raises
InvalidParameter If the field element is invalid.
def bytes_to_fq(data: Bytes) -> FQ:
402 | """ |
---|---|
403 | Decode 64 bytes to a FQ element. |
404 |
|
405 | Parameters |
406 | ---------- |
407 | data : |
408 | The bytes data to decode. |
409 |
|
410 | Returns |
411 | ------- |
412 | fq : FQ |
413 | The FQ element. |
414 |
|
415 | Raises |
416 | ------ |
417 | InvalidParameter |
418 | If the field element is invalid. |
419 | """ |
420 | if len(data) != 64: |
421 | raise InvalidParameter("FQ should be 64 bytes long") |
422 | |
423 | c = int.from_bytes(data[:64], "big") |
424 | |
425 | if c >= FQ.field_modulus: |
426 | raise InvalidParameter("Invalid field element") |
427 | |
428 | return FQ(c) |
bytes_to_fq2
Decode 128 bytes to an FQ2 element.
Parameters
data : The bytes data to decode.
Returns
fq2 : FQ2 The FQ2 element.
Raises
InvalidParameter If the field element is invalid.
def bytes_to_fq2(data: Bytes) -> FQ2:
432 | """ |
---|---|
433 | Decode 128 bytes to an FQ2 element. |
434 |
|
435 | Parameters |
436 | ---------- |
437 | data : |
438 | The bytes data to decode. |
439 |
|
440 | Returns |
441 | ------- |
442 | fq2 : FQ2 |
443 | The FQ2 element. |
444 |
|
445 | Raises |
446 | ------ |
447 | InvalidParameter |
448 | If the field element is invalid. |
449 | """ |
450 | if len(data) != 128: |
451 | raise InvalidParameter("FQ2 input should be 128 bytes long") |
452 | c_0 = int.from_bytes(data[:64], "big") |
453 | c_1 = int.from_bytes(data[64:], "big") |
454 | |
455 | if c_0 >= FQ.field_modulus: |
456 | raise InvalidParameter("Invalid field element") |
457 | if c_1 >= FQ.field_modulus: |
458 | raise InvalidParameter("Invalid field element") |
459 | |
460 | return FQ2((c_0, c_1)) |
bytes_to_g2
Decode 256 bytes to a G2 point. Does not perform sub-group check.
Parameters
data : The bytes data to decode.
Returns
point : Point3D[FQ2] The G2 point.
Raises
InvalidParameter Either a field element is invalid or the point is not on the curve.
def bytes_to_g2(data: Bytes) -> Point3D[FQ2]:
466 | """ |
---|---|
467 | Decode 256 bytes to a G2 point. Does not perform sub-group check. |
468 |
|
469 | Parameters |
470 | ---------- |
471 | data : |
472 | The bytes data to decode. |
473 |
|
474 | Returns |
475 | ------- |
476 | point : Point3D[FQ2] |
477 | The G2 point. |
478 |
|
479 | Raises |
480 | ------ |
481 | InvalidParameter |
482 | Either a field element is invalid or the point is not on the curve. |
483 | """ |
484 | if len(data) != 256: |
485 | raise InvalidParameter("G2 should be 256 bytes long") |
486 | |
487 | x = bytes_to_fq2(data[:128]) |
488 | y = bytes_to_fq2(data[128:]) |
489 | |
490 | z = (1, 0) |
491 | if x == FQ2((0, 0)) and y == FQ2((0, 0)): |
492 | z = (0, 0) |
493 | |
494 | point = x, y, FQ2(z) |
495 | |
496 | # Check if the point is on the curve |
497 | if not is_on_curve(point, b2): |
498 | raise InvalidParameter("Point is not on curve") |
499 | |
500 | return point |
FQ2_to_bytes
Encode a FQ2 point to 128 bytes.
Parameters
fq2 : The FQ2 point to encode.
Returns
data : Bytes The encoded data.
def FQ2_to_bytes(fq2: FQ2) -> Bytes:
504 | """ |
---|---|
505 | Encode a FQ2 point to 128 bytes. |
506 |
|
507 | Parameters |
508 | ---------- |
509 | fq2 : |
510 | The FQ2 point to encode. |
511 |
|
512 | Returns |
513 | ------- |
514 | data : Bytes |
515 | The encoded data. |
516 | """ |
517 | coord0, coord1 = fq2.coeffs |
518 | return b"".join( |
519 | [ |
520 | int(coord0).to_bytes(64, "big"), |
521 | int(coord1).to_bytes(64, "big"), |
522 | ] |
523 | ) |
g2_to_bytes
Encode a G2 point to 256 bytes.
Parameters
g2_point : The G2 point to encode.
Returns
data : Bytes The encoded data.
def g2_to_bytes(g2_point: Point3D[FQ2]) -> Bytes:
529 | """ |
---|---|
530 | Encode a G2 point to 256 bytes. |
531 |
|
532 | Parameters |
533 | ---------- |
534 | g2_point : |
535 | The G2 point to encode. |
536 |
|
537 | Returns |
538 | ------- |
539 | data : Bytes |
540 | The encoded data. |
541 | """ |
542 | x_coords, y_coords = normalize(g2_point) |
543 | return b"".join([FQ2_to_bytes(x_coords), FQ2_to_bytes(y_coords)]) |
decode_g2_scalar_pair
Decode 288 bytes to a G2 point and a scalar.
Parameters
data : The bytes data to decode.
Returns
point : Tuple[Point3D[FQ2], int] The G2 point and the scalar.
Raises
InvalidParameter If the sub-group check failed.
def decode_g2_scalar_pair(data: Bytes) -> Tuple[Point3D[FQ2], int]:
549 | """ |
---|---|
550 | Decode 288 bytes to a G2 point and a scalar. |
551 |
|
552 | Parameters |
553 | ---------- |
554 | data : |
555 | The bytes data to decode. |
556 |
|
557 | Returns |
558 | ------- |
559 | point : Tuple[Point3D[FQ2], int] |
560 | The G2 point and the scalar. |
561 |
|
562 | Raises |
563 | ------ |
564 | InvalidParameter |
565 | If the sub-group check failed. |
566 | """ |
567 | if len(data) != 288: |
568 | InvalidParameter("Input should be 288 bytes long") |
569 | |
570 | point = bytes_to_g2(data[:256]) |
571 | |
572 | if not is_inf(bls12_multiply(point, curve_order)): |
573 | raise InvalidParameter("Point failed sub-group check.") |
574 | |
575 | n = int.from_bytes(data[256 : 256 + 32], "big") |
576 | |
577 | return point, n |