Skip to content

Commit 29dece9

Browse files
authored
fix(tests): EIP-2537: Make pairing test dynamic to env.gas_limit (#1638)
1 parent c3e5fb6 commit 29dece9

File tree

2 files changed

+120
-14
lines changed

2 files changed

+120
-14
lines changed

tests/prague/eip2537_bls_12_381_precompiles/conftest.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def call_succeeds(
9090
@pytest.fixture
9191
def call_contract_code(
9292
precompile_address: int,
93-
precompile_gas: int,
93+
precompile_gas: int | None,
9494
precompile_gas_modifier: int,
9595
expected_output: bytes | SupportsBytes,
9696
call_succeeds: bool,
@@ -126,12 +126,18 @@ def call_contract_code(
126126
assert call_opcode in [Op.CALL, Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL]
127127
value = [0] if call_opcode in [Op.CALL, Op.CALLCODE] else []
128128

129+
precompile_gas_value_opcode: int | Op
130+
if precompile_gas is None:
131+
precompile_gas_value_opcode = Op.GAS
132+
else:
133+
precompile_gas_value_opcode = precompile_gas + precompile_gas_modifier
134+
129135
code = (
130136
Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE())
131137
+ Op.SSTORE(
132138
call_contract_post_storage.store_next(call_succeeds),
133139
call_opcode(
134-
precompile_gas + precompile_gas_modifier,
140+
precompile_gas_value_opcode,
135141
precompile_address,
136142
*value, # Optional, only used for CALL and CALLCODE.
137143
0,

tests/prague/eip2537_bls_12_381_precompiles/test_bls12_pairing.py

Lines changed: 112 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@
55

66
import pytest
77

8-
from ethereum_test_tools import Alloc, Environment, StateTestFiller, Transaction
8+
from ethereum_test_forks import Fork
9+
from ethereum_test_tools import (
10+
EOA,
11+
Address,
12+
Alloc,
13+
Environment,
14+
StateTestFiller,
15+
Transaction,
16+
)
917
from ethereum_test_tools import Opcodes as Op
1018

1119
from .conftest import (
@@ -15,7 +23,7 @@
1523
G2_POINTS_NOT_ON_CURVE,
1624
)
1725
from .helpers import vectors_from_file
18-
from .spec import PointG1, PointG2, Spec, ref_spec_2537
26+
from .spec import PointG1, PointG2, Spec, pairing_gas, ref_spec_2537
1927

2028
REFERENCE_SPEC_GIT_PATH = ref_spec_2537.git_path
2129
REFERENCE_SPEC_VERSION = ref_spec_2537.version
@@ -49,12 +57,6 @@
4957
None,
5058
id="inf_pair",
5159
),
52-
pytest.param( # 1000 copies of e(inf, inf) == 1
53-
(Spec.INF_G1 + Spec.INF_G2) * 1000,
54-
Spec.PAIRING_TRUE,
55-
None,
56-
id="multi_inf_pair",
57-
),
5860
pytest.param( # e(P, Q) . e(P, −Q) == 1 (inverse pair, factors cancel)
5961
Spec.G1 + Spec.G2 + Spec.G1 + (-Spec.G2),
6062
Spec.PAIRING_TRUE,
@@ -133,6 +135,57 @@ def test_valid(
133135
)
134136

135137

138+
@pytest.mark.slow
139+
@pytest.mark.parametrize("precompile_gas", [None], ids=[""])
140+
@pytest.mark.parametrize("expected_output", [Spec.PAIRING_TRUE], ids=[""])
141+
def test_valid_multi_inf(
142+
state_test: StateTestFiller,
143+
pre: Alloc,
144+
call_contract_address: Address,
145+
sender: EOA,
146+
fork: Fork,
147+
post: dict,
148+
):
149+
"""
150+
Test maximum input given the current environment gas limit for the BLS12_PAIRING
151+
precompile.
152+
"""
153+
intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
154+
memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator()
155+
extra_gas = 100_000
156+
157+
environment_gas_limit = Environment().gas_limit
158+
159+
inf_data = Spec.INF_G1 + Spec.INF_G2
160+
input_data = inf_data
161+
162+
while True:
163+
precompile_gas = pairing_gas(len(input_data + inf_data))
164+
new_tx_gas_limit = (
165+
extra_gas
166+
+ intrinsic_gas_cost_calculator(calldata=input_data + inf_data)
167+
+ memory_expansion_gas_calculator(new_bytes=len(input_data + inf_data))
168+
+ precompile_gas
169+
)
170+
if new_tx_gas_limit > environment_gas_limit:
171+
break
172+
tx_gas_limit = new_tx_gas_limit
173+
input_data += inf_data
174+
175+
tx = Transaction(
176+
gas_limit=tx_gas_limit,
177+
data=input_data,
178+
to=call_contract_address,
179+
sender=sender,
180+
)
181+
state_test(
182+
env=Environment(),
183+
pre=pre,
184+
tx=tx,
185+
post=post,
186+
)
187+
188+
136189
@pytest.mark.parametrize(
137190
"input_data",
138191
# Test vectors from the reference spec (from the cryptography team)
@@ -180,10 +233,6 @@ def test_valid(
180233
Spec.INF_G1 + Spec.P2_NOT_IN_SUBGROUP,
181234
id="p2_not_in_subgroup",
182235
),
183-
pytest.param(
184-
(Spec.INF_G1 + Spec.INF_G2) * 1000 + PointG1(Spec.P, 0) + Spec.INF_G2,
185-
id="long_input_with_invalid_tail",
186-
),
187236
# Points not in the subgroup or not on the curve randomly generated.
188237
pytest.param(
189238
G1_POINTS_NOT_ON_CURVE[0] + Spec.INF_G2,
@@ -235,6 +284,57 @@ def test_invalid(
235284
)
236285

237286

287+
@pytest.mark.slow
288+
@pytest.mark.parametrize("precompile_gas", [None], ids=[""])
289+
@pytest.mark.parametrize("expected_output", [Spec.INVALID], ids=[""])
290+
def test_invalid_multi_inf(
291+
state_test: StateTestFiller,
292+
pre: Alloc,
293+
call_contract_address: Address,
294+
sender: EOA,
295+
fork: Fork,
296+
post: dict,
297+
):
298+
"""
299+
Test maximum input given the current environment gas limit for the BLS12_PAIRING
300+
precompile and an invalid tail.
301+
"""
302+
intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator()
303+
memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator()
304+
extra_gas = 100_000
305+
306+
environment_gas_limit = Environment().gas_limit
307+
308+
inf_data = Spec.INF_G1 + Spec.INF_G2
309+
input_data = PointG1(Spec.P, 0) + Spec.INF_G2
310+
311+
while True:
312+
precompile_gas = pairing_gas(len(input_data + inf_data))
313+
new_tx_gas_limit = (
314+
extra_gas
315+
+ intrinsic_gas_cost_calculator(calldata=input_data + inf_data)
316+
+ memory_expansion_gas_calculator(new_bytes=len(input_data + inf_data))
317+
+ precompile_gas
318+
)
319+
if new_tx_gas_limit > environment_gas_limit:
320+
break
321+
tx_gas_limit = new_tx_gas_limit
322+
input_data = inf_data + input_data
323+
324+
tx = Transaction(
325+
gas_limit=tx_gas_limit,
326+
data=input_data,
327+
to=call_contract_address,
328+
sender=sender,
329+
)
330+
state_test(
331+
env=Environment(),
332+
pre=pre,
333+
tx=tx,
334+
post=post,
335+
)
336+
337+
238338
@pytest.mark.parametrize(
239339
"input_data,expected_output,precompile_gas_modifier",
240340
[

0 commit comments

Comments
 (0)