ethereum.forks.prague.vm.precompiled_contracts.bls12_381ethereum.forks.osaka.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_cached

Internal cached version of bytes_to_g1 that works with hashable bytes.

308
@lru_cache(maxsize=128)
def _bytes_to_g1_cached(data: bytes, ​​subgroup_check: bool) -> Point3D[FQ]:
313
    """
314
    Internal cached version of `bytes_to_g1` that works with hashable `bytes`.
315
    """
316
    if len(data) != 128:
317
        raise InvalidParameter("Input should be 128 bytes long")
318
319
    x = bytes_to_fq(data[:64])
320
    y = bytes_to_fq(data[64:])
321
322
    if x >= FQ.field_modulus:
323
        raise InvalidParameter("x >= field modulus")
324
    if y >= FQ.field_modulus:
325
        raise InvalidParameter("y >= field modulus")
326
327
    z = 1
328
    if x == 0 and y == 0:
329
        z = 0
330
    point = FQ(x), FQ(y), FQ(z)
331
332
    if not is_on_curve(point, b):
333
        raise InvalidParameter("G1 point is not on curve")
334
335
    if subgroup_check and not is_inf(bls12_multiply(point, curve_order)):
336
        raise InvalidParameter("Subgroup check failed for G1 point.")
337
338
    return point

bytes_to_g1

Decode 128 bytes to a G1 point with or without subgroup check.

Parameters

data : The bytes data to decode. subgroup_check : bool Whether to perform a subgroup check on the G1 point.

Returns

point : Point3D[FQ] The G1 point.

Raises

InvalidParameter If a field element is invalid, the point is not on the curve, or the subgroup check fails.

def bytes_to_g1(data: Bytes, ​​subgroup_check: bool) -> Point3D[FQ]:
345
    """
346
    Decode 128 bytes to a G1 point with or without subgroup check.
347
348
    Parameters
349
    ----------
350
    data :
351
        The bytes data to decode.
352
    subgroup_check : bool
353
        Whether to perform a subgroup check on the G1 point.
354
355
    Returns
356
    -------
357
    point : Point3D[FQ]
358
        The G1 point.
359
360
    Raises
361
    ------
362
    InvalidParameter
363
        If a field element is invalid, the point is not on the curve, or the
364
        subgroup check fails.
365
366
    """
367
    # This is needed bc when we slice `Bytes` we get a `bytearray`,
368
    # which is not hashable
369
    return _bytes_to_g1_cached(bytes(data), subgroup_check)

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:
375
    """
376
    Encode a G1 point to 128 bytes.
377
378
    Parameters
379
    ----------
380
    g1_point :
381
        The G1 point to encode.
382
383
    Returns
384
    -------
385
    data : Bytes
386
        The encoded data.
387
388
    """
389
    g1_normalized = normalize(g1_point)
390
    x, y = g1_normalized
391
    return 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 subgroup check failed.

def decode_g1_scalar_pair(data: Bytes) -> Tuple[Point3D[FQ], int]:
397
    """
398
    Decode 160 bytes to a G1 point and a scalar.
399
400
    Parameters
401
    ----------
402
    data :
403
        The bytes data to decode.
404
405
    Returns
406
    -------
407
    point : Tuple[Point3D[FQ], int]
408
        The G1 point and the scalar.
409
410
    Raises
411
    ------
412
    InvalidParameter
413
        If the subgroup check failed.
414
415
    """
416
    if len(data) != 160:
417
        InvalidParameter("Input should be 160 bytes long")
418
419
    point = bytes_to_g1(data[:128], subgroup_check=True)
420
421
    m = int.from_bytes(buffer_read(data, U256(128), U256(32)), "big")
422
423
    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:
427
    """
428
    Decode 64 bytes to a FQ element.
429
430
    Parameters
431
    ----------
432
    data :
433
        The bytes data to decode.
434
435
    Returns
436
    -------
437
    fq : FQ
438
        The FQ element.
439
440
    Raises
441
    ------
442
    InvalidParameter
443
        If the field element is invalid.
444
445
    """
446
    if len(data) != 64:
447
        raise InvalidParameter("FQ should be 64 bytes long")
448
449
    c = int.from_bytes(data[:64], "big")
450
451
    if c >= FQ.field_modulus:
452
        raise InvalidParameter("Invalid field element")
453
454
    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:
458
    """
459
    Decode 128 bytes to an FQ2 element.
460
461
    Parameters
462
    ----------
463
    data :
464
        The bytes data to decode.
465
466
    Returns
467
    -------
468
    fq2 : FQ2
469
        The FQ2 element.
470
471
    Raises
472
    ------
473
    InvalidParameter
474
        If the field element is invalid.
475
476
    """
477
    if len(data) != 128:
478
        raise InvalidParameter("FQ2 input should be 128 bytes long")
479
    c_0 = int.from_bytes(data[:64], "big")
480
    c_1 = int.from_bytes(data[64:], "big")
481
482
    if c_0 >= FQ.field_modulus:
483
        raise InvalidParameter("Invalid field element")
484
    if c_1 >= FQ.field_modulus:
485
        raise InvalidParameter("Invalid field element")
486
487
    return FQ2((c_0, c_1))

_bytes_to_g2_cached

Internal cached version of bytes_to_g2 that works with hashable bytes.

494
@lru_cache(maxsize=128)
def _bytes_to_g2_cached(data: bytes, ​​subgroup_check: bool) -> Point3D[FQ2]:
499
    """
500
    Internal cached version of `bytes_to_g2` that works with hashable `bytes`.
501
    """
502
    if len(data) != 256:
503
        raise InvalidParameter("G2 should be 256 bytes long")
504
505
    x = bytes_to_fq2(data[:128])
506
    y = bytes_to_fq2(data[128:])
507
508
    z = (1, 0)
509
    if x == FQ2((0, 0)) and y == FQ2((0, 0)):
510
        z = (0, 0)
511
512
    point = x, y, FQ2(z)
513
514
    if not is_on_curve(point, b2):
515
        raise InvalidParameter("Point is not on curve")
516
517
    if subgroup_check and not is_inf(bls12_multiply(point, curve_order)):
518
        raise InvalidParameter("Subgroup check failed for G2 point.")
519
520
    return point

bytes_to_g2

Decode 256 bytes to a G2 point with or without subgroup check.

Parameters

data : The bytes data to decode. subgroup_check : bool Whether to perform a subgroup check on the G2 point.

Returns

point : Point3D[FQ2] The G2 point.

Raises

InvalidParameter If a field element is invalid, the point is not on the curve, or the subgroup check fails.

def bytes_to_g2(data: Bytes, ​​subgroup_check: bool) -> Point3D[FQ2]:
527
    """
528
    Decode 256 bytes to a G2 point with or without subgroup check.
529
530
    Parameters
531
    ----------
532
    data :
533
        The bytes data to decode.
534
    subgroup_check : bool
535
        Whether to perform a subgroup check on the G2 point.
536
537
    Returns
538
    -------
539
    point : Point3D[FQ2]
540
        The G2 point.
541
542
    Raises
543
    ------
544
    InvalidParameter
545
        If a field element is invalid, the point is not on the curve, or the
546
        subgroup check fails.
547
548
    """
549
    # This is needed bc when we slice `Bytes` we get a `bytearray`,
550
    # which is not hashable
551
    return _bytes_to_g2_cached(data, subgroup_check)

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:
555
    """
556
    Encode a FQ2 point to 128 bytes.
557
558
    Parameters
559
    ----------
560
    fq2 :
561
        The FQ2 point to encode.
562
563
    Returns
564
    -------
565
    data : Bytes
566
        The encoded data.
567
568
    """
569
    coord0, coord1 = fq2.coeffs
570
    return int(coord0).to_bytes(64, "big") + int(coord1).to_bytes(64, "big")

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:
576
    """
577
    Encode a G2 point to 256 bytes.
578
579
    Parameters
580
    ----------
581
    g2_point :
582
        The G2 point to encode.
583
584
    Returns
585
    -------
586
    data : Bytes
587
        The encoded data.
588
589
    """
590
    x_coords, y_coords = normalize(g2_point)
591
    return 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 subgroup check failed.

def decode_g2_scalar_pair(data: Bytes) -> Tuple[Point3D[FQ2], int]:
597
    """
598
    Decode 288 bytes to a G2 point and a scalar.
599
600
    Parameters
601
    ----------
602
    data :
603
        The bytes data to decode.
604
605
    Returns
606
    -------
607
    point : Tuple[Point3D[FQ2], int]
608
        The G2 point and the scalar.
609
610
    Raises
611
    ------
612
    InvalidParameter
613
        If the subgroup check failed.
614
615
    """
616
    if len(data) != 288:
617
        InvalidParameter("Input should be 288 bytes long")
618
619
    point = bytes_to_g2(data[:256], subgroup_check=True)
620
    n = int.from_bytes(data[256 : 256 + 32], "big")
621
622
    return point, n