|
5 | 5 |
|
6 | 6 | import pytest |
7 | 7 |
|
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 | +) |
9 | 17 | from ethereum_test_tools import Opcodes as Op |
10 | 18 |
|
11 | 19 | from .conftest import ( |
|
15 | 23 | G2_POINTS_NOT_ON_CURVE, |
16 | 24 | ) |
17 | 25 | 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 |
19 | 27 |
|
20 | 28 | REFERENCE_SPEC_GIT_PATH = ref_spec_2537.git_path |
21 | 29 | REFERENCE_SPEC_VERSION = ref_spec_2537.version |
|
49 | 57 | None, |
50 | 58 | id="inf_pair", |
51 | 59 | ), |
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 | | - ), |
58 | 60 | pytest.param( # e(P, Q) . e(P, −Q) == 1 (inverse pair, factors cancel) |
59 | 61 | Spec.G1 + Spec.G2 + Spec.G1 + (-Spec.G2), |
60 | 62 | Spec.PAIRING_TRUE, |
@@ -133,6 +135,57 @@ def test_valid( |
133 | 135 | ) |
134 | 136 |
|
135 | 137 |
|
| 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 | + |
136 | 189 | @pytest.mark.parametrize( |
137 | 190 | "input_data", |
138 | 191 | # Test vectors from the reference spec (from the cryptography team) |
@@ -180,10 +233,6 @@ def test_valid( |
180 | 233 | Spec.INF_G1 + Spec.P2_NOT_IN_SUBGROUP, |
181 | 234 | id="p2_not_in_subgroup", |
182 | 235 | ), |
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 | | - ), |
187 | 236 | # Points not in the subgroup or not on the curve randomly generated. |
188 | 237 | pytest.param( |
189 | 238 | G1_POINTS_NOT_ON_CURVE[0] + Spec.INF_G2, |
@@ -235,6 +284,57 @@ def test_invalid( |
235 | 284 | ) |
236 | 285 |
|
237 | 286 |
|
| 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 | + |
238 | 338 | @pytest.mark.parametrize( |
239 | 339 | "input_data,expected_output,precompile_gas_modifier", |
240 | 340 | [ |
|
0 commit comments