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 |