class Spec:
"""
Parameters from the EIP-2537 specifications as defined at
https://eips.ethereum.org/EIPS/eip-2537.
"""
# Addresses
G1ADD = 0x0B
G1MSM = 0x0C
G2ADD = 0x0D
G2MSM = 0x0E
PAIRING = 0x0F
MAP_FP_TO_G1 = 0x10
MAP_FP2_TO_G2 = 0x11
# Gas constants
G1ADD_GAS = 375
G1MUL_GAS = 12_000
G2ADD_GAS = 600
G2MUL_GAS = 22_500
MAP_FP_TO_G1_GAS = 5_500
MAP_FP2_TO_G2_GAS = 23_800
PAIRING_BASE_GAS = 37_700
PAIRING_PER_PAIR_GAS = 32_600
# Other constants
B_COEFFICIENT = 0x04
X = -0xD201000000010000
Q = X**4 - X**2 + 1
P = (X - 1) ** 2 * Q // 3 + X
LEN_PER_PAIR = len(PointG1() + PointG2())
MSM_MULTIPLIER = 1_000
MAX_FP_BIT_SET = 1 << (48 * 8)
# fmt: off
G1MSM_DISCOUNT_TABLE = [
0,
1000, 949, 848, 797, 764, 750, 738, 728, 719, 712, 705, 698, 692, 687,
682, 677, 673, 669, 665, 661, 658, 654, 651, 648, 645, 642, 640, 637,
635, 632, 630, 627, 625, 623, 621, 619, 617, 615, 613, 611, 609, 608,
606, 604, 603, 601, 599, 598, 596, 595, 593, 592, 591, 589, 588, 586,
585, 584, 582, 581, 580, 579, 577, 576, 575, 574, 573, 572, 570, 569,
568, 567, 566, 565, 564, 563, 562, 561, 560, 559, 558, 557, 556, 555,
554, 553, 552, 551, 550, 549, 548, 547, 547, 546, 545, 544, 543, 542,
541, 540, 540, 539, 538, 537, 536, 536, 535, 534, 533, 532, 532, 531,
530, 529, 528, 528, 527, 526, 525, 525, 524, 523, 522, 522, 521, 520,
520, 519
]
G2MSM_DISCOUNT_TABLE = [
0,
1000, 1000, 923, 884, 855, 832, 812, 796, 782, 770, 759, 749, 740, 732,
724, 717, 711, 704, 699, 693, 688, 683, 679, 674, 670, 666, 663, 659,
655, 652, 649, 646, 643, 640, 637, 634, 632, 629, 627, 624, 622, 620,
618, 615, 613, 611, 609, 607, 606, 604, 602, 600, 598, 597, 595, 593,
592, 590, 589, 587, 586, 584, 583, 582, 580, 579, 578, 576, 575, 574,
573, 571, 570, 569, 568, 567, 566, 565, 563, 562, 561, 560, 559, 558,
557, 556, 555, 554, 553, 552, 552, 551, 550, 549, 548, 547, 546, 545,
545, 544, 543, 542, 541, 541, 540, 539, 538, 537, 537, 536, 535, 535,
534, 533, 532, 532, 531, 530, 530, 529, 528, 528, 527, 526, 526, 525,
524, 524
]
# fmt: on
# Test constants from
# https://github.com/ethereum/bls12-381-tests/tree/eip-2537
P1 = PointG1( # random point in G1
0x112B98340EEE2777CC3C14163DEA3EC97977AC3DC5C70DA32E6E87578F44912E902CCEF9EFE28D4A78B8999DFBCA9426,
0x186B28D92356C4DFEC4B5201AD099DBDEDE3781F8998DDF929B4CD7756192185CA7B8F4EF7088F813270AC3D48868A21,
)
G1 = PointG1(
0x17F1D3A73197D7942695638C4FA9AC0FC3688C4F9774B905A14E3A3F171BAC586C55E83FF97A1AEFFB3AF00ADB22C6BB,
0x8B3F481E3AAA0F1A09E30ED741D8AE4FCF5E095D5D00AF600DB18CB2C04B3EDD03CC744A2888AE40CAA232946C5E7E1,
)
# point at infinity in G1
INF_G1 = PointG1(0, 0)
# random point in G2
P2 = PointG2(
(
0x103121A2CEAAE586D240843A398967325F8EB5A93E8FEA99B62B9F88D8556C80DD726A4B30E84A36EEABAF3592937F27,
0x86B990F3DA2AEAC0A36143B7D7C824428215140DB1BB859338764CB58458F081D92664F9053B50B3FBD2E4723121B68,
),
(
0xF9E7BA9A86A8F7624AA2B42DCC8772E1AF4AE115685E60ABC2C9B90242167ACEF3D0BE4050BF935EED7C3B6FC7BA77E,
0xD22C3652D0DC6F0FC9316E14268477C2049EF772E852108D269D9C38DBA1D4802E8DAE479818184C08F9A569D878451,
),
)
G2 = PointG2(
(
0x24AA2B2F08F0A91260805272DC51051C6E47AD4FA403B02B4510B647AE3D1770BAC0326A805BBEFD48056C8C121BDB8,
0x13E02B6052719F607DACD3A088274F65596BD0D09920B61AB5DA61BBDC7F5049334CF11213945D57E5AC7D055D042B7E,
),
(
0xCE5D527727D6E118CC9CDC6DA2E351AADFD9BAA8CBDD3A76D429A695160D12C923AC9CC3BACA289E193548608B82801,
0x606C4A02EA734CC32ACD2B02BC28B99CB3E287E85A763AF267492AB572E99AB3F370D275CEC1DA1AAA9075FF05F79BE,
),
)
# point at infinity in G2
INF_G2 = PointG2((0, 0), (0, 0))
# Other test constants
# point not in subgroup in curve Fp
P1_NOT_IN_SUBGROUP = PointG1(0, 2)
P1_NOT_IN_SUBGROUP_TIMES_2 = PointG1(0, P - 2)
# point not in subgroup in curve Fp2
P2_NOT_IN_SUBGROUP = PointG2(
(1, 1),
(
0x17FAA6201231304F270B858DAD9462089F2A5B83388E4B10773ABC1EEF6D193B9FCE4E8EA2D9D28E3C3A315AA7DE14CA,
0xCC12449BE6AC4E7F367E7242250427C4FB4C39325D3164AD397C1837A90F0EA1A534757DF374DD6569345EB41ED76E,
),
)
P2_NOT_IN_SUBGROUP_TIMES_2 = PointG2(
(
0x919F97860ECC3E933E3477FCAC0E2E4FCC35A6E886E935C97511685232456263DEF6665F143CCCCB44C733333331553,
0x18B4376B50398178FA8D78ED2654B0FFD2A487BE4DBE6B69086E61B283F4E9D58389CCCB8EDC99995718A66666661555,
),
(
0x26898F699C4B07A405AB4183A10B47F923D1C0FDA1018682DD2CCC88968C1B90D44534D6B9270CF57F8DC6D4891678A,
0x3270414330EAD5EC92219A03A24DFA059DBCBE610868BE1851CC13DAC447F60B40D41113FD007D3307B19ADD4B0F061,
),
)
# Pairing precompile results
PAIRING_TRUE = int.to_bytes(1, length=32, byteorder="big")
PAIRING_FALSE = int.to_bytes(0, length=32, byteorder="big")
# Returned on precompile failure
INVALID = b""