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

38
G1_K_DISCOUNT = [
39
    1000,
40
    949,
41
    848,
42
    797,
43
    764,
44
    750,
45
    738,
46
    728,
47
    719,
48
    712,
49
    705,
50
    698,
51
    692,
52
    687,
53
    682,
54
    677,
55
    673,
56
    669,
57
    665,
58
    661,
59
    658,
60
    654,
61
    651,
62
    648,
63
    645,
64
    642,
65
    640,
66
    637,
67
    635,
68
    632,
69
    630,
70
    627,
71
    625,
72
    623,
73
    621,
74
    619,
75
    617,
76
    615,
77
    613,
78
    611,
79
    609,
80
    608,
81
    606,
82
    604,
83
    603,
84
    601,
85
    599,
86
    598,
87
    596,
88
    595,
89
    593,
90
    592,
91
    591,
92
    589,
93
    588,
94
    586,
95
    585,
96
    584,
97
    582,
98
    581,
99
    580,
100
    579,
101
    577,
102
    576,
103
    575,
104
    574,
105
    573,
106
    572,
107
    570,
108
    569,
109
    568,
110
    567,
111
    566,
112
    565,
113
    564,
114
    563,
115
    562,
116
    561,
117
    560,
118
    559,
119
    558,
120
    557,
121
    556,
122
    555,
123
    554,
124
    553,
125
    552,
126
    551,
127
    550,
128
    549,
129
    548,
130
    547,
131
    547,
132
    546,
133
    545,
134
    544,
135
    543,
136
    542,
137
    541,
138
    540,
139
    540,
140
    539,
141
    538,
142
    537,
143
    536,
144
    536,
145
    535,
146
    534,
147
    533,
148
    532,
149
    532,
150
    531,
151
    530,
152
    529,
153
    528,
154
    528,
155
    527,
156
    526,
157
    525,
158
    525,
159
    524,
160
    523,
161
    522,
162
    522,
163
    521,
164
    520,
165
    520,
166
    519,
167
]

G2_K_DISCOUNT

169
G2_K_DISCOUNT = [
170
    1000,
171
    1000,
172
    923,
173
    884,
174
    855,
175
    832,
176
    812,
177
    796,
178
    782,
179
    770,
180
    759,
181
    749,
182
    740,
183
    732,
184
    724,
185
    717,
186
    711,
187
    704,
188
    699,
189
    693,
190
    688,
191
    683,
192
    679,
193
    674,
194
    670,
195
    666,
196
    663,
197
    659,
198
    655,
199
    652,
200
    649,
201
    646,
202
    643,
203
    640,
204
    637,
205
    634,
206
    632,
207
    629,
208
    627,
209
    624,
210
    622,
211
    620,
212
    618,
213
    615,
214
    613,
215
    611,
216
    609,
217
    607,
218
    606,
219
    604,
220
    602,
221
    600,
222
    598,
223
    597,
224
    595,
225
    593,
226
    592,
227
    590,
228
    589,
229
    587,
230
    586,
231
    584,
232
    583,
233
    582,
234
    580,
235
    579,
236
    578,
237
    576,
238
    575,
239
    574,
240
    573,
241
    571,
242
    570,
243
    569,
244
    568,
245
    567,
246
    566,
247
    565,
248
    563,
249
    562,
250
    561,
251
    560,
252
    559,
253
    558,
254
    557,
255
    556,
256
    555,
257
    554,
258
    553,
259
    552,
260
    552,
261
    551,
262
    550,
263
    549,
264
    548,
265
    547,
266
    546,
267
    545,
268
    545,
269
    544,
270
    543,
271
    542,
272
    541,
273
    541,
274
    540,
275
    539,
276
    538,
277
    537,
278
    537,
279
    536,
280
    535,
281
    535,
282
    534,
283
    533,
284
    532,
285
    532,
286
    531,
287
    530,
288
    530,
289
    529,
290
    528,
291
    528,
292
    527,
293
    526,
294
    526,
295
    525,
296
    524,
297
    524,
298
]

G1_MAX_DISCOUNT

300
G1_MAX_DISCOUNT = 519

G2_MAX_DISCOUNT

301
G2_MAX_DISCOUNT = 524

MULTIPLIER

302
MULTIPLIER = Uint(1000)

_bytes_to_g1_cached

Internal cached version of bytes_to_g1 that works with hashable bytes.

309
@lru_cache(maxsize=128)
def _bytes_to_g1_cached(data: bytes, ​​subgroup_check: bool) -> Point3D[FQ]:
314
    """
315
    Internal cached version of `bytes_to_g1` that works with hashable `bytes`.
316
    """
317
    if len(data) != 128:
318
        raise InvalidParameter("Input should be 128 bytes long")
319
320
    x = bytes_to_fq(data[:64])
321
    y = bytes_to_fq(data[64:])
322
323
    if x >= FQ.field_modulus:
324
        raise InvalidParameter("x >= field modulus")
325
    if y >= FQ.field_modulus:
326
        raise InvalidParameter("y >= field modulus")
327
328
    z = 1
329
    if x == 0 and y == 0:
330
        z = 0
331
    point = FQ(x), FQ(y), FQ(z)
332
333
    if not is_on_curve(point, b):
334
        raise InvalidParameter("G1 point is not on curve")
335
336
    if subgroup_check and not is_inf(bls12_multiply(point, curve_order)):
337
        raise InvalidParameter("Subgroup check failed for G1 point.")
338
339
    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]:
346
    """
347
    Decode 128 bytes to a G1 point with or without subgroup check.
348
349
    Parameters
350
    ----------
351
    data :
352
        The bytes data to decode.
353
    subgroup_check : bool
354
        Whether to perform a subgroup check on the G1 point.
355
356
    Returns
357
    -------
358
    point : Point3D[FQ]
359
        The G1 point.
360
361
    Raises
362
    ------
363
    InvalidParameter
364
        If a field element is invalid, the point is not on the curve, or the
365
        subgroup check fails.
366
367
    """
368
    # This is needed bc when we slice `Bytes` we get a `bytearray`,
369
    # which is not hashable
370
    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:
376
    """
377
    Encode a G1 point to 128 bytes.
378
379
    Parameters
380
    ----------
381
    g1_point :
382
        The G1 point to encode.
383
384
    Returns
385
    -------
386
    data : Bytes
387
        The encoded data.
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
    if len(data) != 160:
416
        InvalidParameter("Input should be 160 bytes long")
417
418
    point = bytes_to_g1(data[:128], subgroup_check=True)
419
420
    m = int.from_bytes(buffer_read(data, U256(128), U256(32)), "big")
421
422
    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:
426
    """
427
    Decode 64 bytes to a FQ element.
428
429
    Parameters
430
    ----------
431
    data :
432
        The bytes data to decode.
433
434
    Returns
435
    -------
436
    fq : FQ
437
        The FQ element.
438
439
    Raises
440
    ------
441
    InvalidParameter
442
        If the field element is invalid.
443
    """
444
    if len(data) != 64:
445
        raise InvalidParameter("FQ should be 64 bytes long")
446
447
    c = int.from_bytes(data[:64], "big")
448
449
    if c >= FQ.field_modulus:
450
        raise InvalidParameter("Invalid field element")
451
452
    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:
456
    """
457
    Decode 128 bytes to an FQ2 element.
458
459
    Parameters
460
    ----------
461
    data :
462
        The bytes data to decode.
463
464
    Returns
465
    -------
466
    fq2 : FQ2
467
        The FQ2 element.
468
469
    Raises
470
    ------
471
    InvalidParameter
472
        If the field element is invalid.
473
    """
474
    if len(data) != 128:
475
        raise InvalidParameter("FQ2 input should be 128 bytes long")
476
    c_0 = int.from_bytes(data[:64], "big")
477
    c_1 = int.from_bytes(data[64:], "big")
478
479
    if c_0 >= FQ.field_modulus:
480
        raise InvalidParameter("Invalid field element")
481
    if c_1 >= FQ.field_modulus:
482
        raise InvalidParameter("Invalid field element")
483
484
    return FQ2((c_0, c_1))

_bytes_to_g2_cached

Internal cached version of bytes_to_g2 that works with hashable bytes.

491
@lru_cache(maxsize=128)
def _bytes_to_g2_cached(data: bytes, ​​subgroup_check: bool) -> Point3D[FQ2]:
496
    """
497
    Internal cached version of `bytes_to_g2` that works with hashable `bytes`.
498
    """
499
    if len(data) != 256:
500
        raise InvalidParameter("G2 should be 256 bytes long")
501
502
    x = bytes_to_fq2(data[:128])
503
    y = bytes_to_fq2(data[128:])
504
505
    z = (1, 0)
506
    if x == FQ2((0, 0)) and y == FQ2((0, 0)):
507
        z = (0, 0)
508
509
    point = x, y, FQ2(z)
510
511
    if not is_on_curve(point, b2):
512
        raise InvalidParameter("Point is not on curve")
513
514
    if subgroup_check and not is_inf(bls12_multiply(point, curve_order)):
515
        raise InvalidParameter("Subgroup check failed for G2 point.")
516
517
    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]:
524
    """
525
    Decode 256 bytes to a G2 point with or without subgroup check.
526
527
    Parameters
528
    ----------
529
    data :
530
        The bytes data to decode.
531
    subgroup_check : bool
532
        Whether to perform a subgroup check on the G2 point.
533
534
    Returns
535
    -------
536
    point : Point3D[FQ2]
537
        The G2 point.
538
539
    Raises
540
    ------
541
    InvalidParameter
542
        If a field element is invalid, the point is not on the curve, or the
543
        subgroup check fails.
544
    """
545
    # This is needed bc when we slice `Bytes` we get a `bytearray`,
546
    # which is not hashable
547
    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:
551
    """
552
    Encode a FQ2 point to 128 bytes.
553
554
    Parameters
555
    ----------
556
    fq2 :
557
        The FQ2 point to encode.
558
559
    Returns
560
    -------
561
    data : Bytes
562
        The encoded data.
563
    """
564
    coord0, coord1 = fq2.coeffs
565
    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:
571
    """
572
    Encode a G2 point to 256 bytes.
573
574
    Parameters
575
    ----------
576
    g2_point :
577
        The G2 point to encode.
578
579
    Returns
580
    -------
581
    data : Bytes
582
        The encoded data.
583
    """
584
    x_coords, y_coords = normalize(g2_point)
585
    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]:
591
    """
592
    Decode 288 bytes to a G2 point and a scalar.
593
594
    Parameters
595
    ----------
596
    data :
597
        The bytes data to decode.
598
599
    Returns
600
    -------
601
    point : Tuple[Point3D[FQ2], int]
602
        The G2 point and the scalar.
603
604
    Raises
605
    ------
606
    InvalidParameter
607
        If the subgroup check failed.
608
    """
609
    if len(data) != 288:
610
        InvalidParameter("Input should be 288 bytes long")
611
612
    point = bytes_to_g2(data[:256], subgroup_check=True)
613
    n = int.from_bytes(data[256 : 256 + 32], "big")
614
615
    return point, n