Skip to content

Commit 619f1cf

Browse files
refactor: update worst stateful opcode scenario
1 parent 333d246 commit 619f1cf

File tree

1 file changed

+34
-89
lines changed

1 file changed

+34
-89
lines changed

tests/benchmark/test_worst_stateful_opcodes.py

Lines changed: 34 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,29 @@
66
"""
77

88
import math
9+
from enum import auto
910

1011
import pytest
1112

13+
from ethereum_test_benchmark.benchmark_code_generator import ExtCallGenerator, JumpLoopGenerator
1214
from ethereum_test_forks import Fork
15+
from ethereum_test_specs import BlockchainTestFiller
16+
from ethereum_test_specs.benchmark import BenchmarkTestFiller
1317
from ethereum_test_tools import (
1418
Account,
1519
Address,
1620
Alloc,
1721
Block,
18-
BlockchainTestFiller,
1922
Bytecode,
2023
Environment,
2124
Hash,
22-
StateTestFiller,
2325
Transaction,
2426
While,
2527
compute_create2_address,
2628
compute_create_address,
2729
)
2830
from ethereum_test_tools.vm.opcode import Opcodes as Op
2931

30-
from .helpers import code_loop_precompile_call
31-
3232
REFERENCE_SPEC_GIT_PATH = "TODO"
3333
REFERENCE_SPEC_VERSION = "TODO"
3434

@@ -47,7 +47,7 @@
4747
],
4848
)
4949
def test_worst_address_state_cold(
50-
blockchain_test: BlockchainTestFiller,
50+
benchmark_test: BenchmarkTestFiller,
5151
pre: Alloc,
5252
fork: Fork,
5353
opcode: Op,
@@ -107,11 +107,10 @@ def test_worst_address_state_cold(
107107
)
108108
blocks.append(Block(txs=[op_tx]))
109109

110-
blockchain_test(
110+
benchmark_test(
111111
pre=pre,
112112
post=post,
113113
blocks=blocks,
114-
exclude_full_post_state_in_output=True,
115114
)
116115

117116

@@ -135,17 +134,12 @@ def test_worst_address_state_cold(
135134
],
136135
)
137136
def test_worst_address_state_warm(
138-
state_test: StateTestFiller,
137+
benchmark_test: BenchmarkTestFiller,
139138
pre: Alloc,
140-
fork: Fork,
141139
opcode: Op,
142140
absent_target: bool,
143-
gas_benchmark_value: int,
144141
):
145142
"""Test running a block with as many stateful opcodes doing warm access for an account."""
146-
max_code_size = fork.max_code_size()
147-
attack_gas_limit = gas_benchmark_value
148-
149143
# Setup
150144
target_addr = Address(100_000)
151145
post = {}
@@ -155,45 +149,29 @@ def test_worst_address_state_warm(
155149
post[target_addr] = Account(balance=100, code=code)
156150

157151
# Execution
158-
prep = Op.MSTORE(0, target_addr)
159-
jumpdest = Op.JUMPDEST
160-
jump_back = Op.JUMP(len(prep))
161-
iter_block = Op.POP(opcode(address=Op.MLOAD(0)))
162-
max_iters_loop = (max_code_size - len(prep) - len(jumpdest) - len(jump_back)) // len(
163-
iter_block
164-
)
165-
op_code = prep + jumpdest + sum([iter_block] * max_iters_loop) + jump_back
166-
if len(op_code) > max_code_size:
167-
# Must never happen, but keep it as a sanity check.
168-
raise ValueError(f"Code size {len(op_code)} exceeds maximum code size {max_code_size}")
169-
op_address = pre.deploy_contract(code=op_code)
170-
tx = Transaction(
171-
to=op_address,
172-
gas_limit=attack_gas_limit,
173-
sender=pre.fund_eoa(),
174-
)
175-
176-
state_test(
152+
setup = Op.MSTORE(0, target_addr)
153+
attack_block = Op.POP(opcode(address=Op.MLOAD(0)))
154+
benchmark_test(
177155
pre=pre,
178156
post=post,
179-
tx=tx,
157+
code_generator=JumpLoopGenerator(setup=setup, attack_block=attack_block),
180158
)
181159

182160

183161
class StorageAction:
184162
"""Enum for storage actions."""
185163

186-
READ = 1
187-
WRITE_SAME_VALUE = 2
188-
WRITE_NEW_VALUE = 3
164+
READ = auto()
165+
WRITE_SAME_VALUE = auto()
166+
WRITE_NEW_VALUE = auto()
189167

190168

191169
class TransactionResult:
192170
"""Enum for the possible transaction outcomes."""
193171

194-
SUCCESS = 1
195-
OUT_OF_GAS = 2
196-
REVERT = 3
172+
SUCCESS = auto()
173+
OUT_OF_GAS = auto()
174+
REVERT = auto()
197175

198176

199177
@pytest.mark.parametrize(
@@ -244,7 +222,7 @@ class TransactionResult:
244222
],
245223
)
246224
def test_worst_storage_access_cold(
247-
blockchain_test: BlockchainTestFiller,
225+
benchmark_test: BenchmarkTestFiller,
248226
pre: Alloc,
249227
fork: Fork,
250228
storage_action: StorageAction,
@@ -256,7 +234,6 @@ def test_worst_storage_access_cold(
256234
"""Test running a block with as many cold storage slot accesses as possible."""
257235
gas_costs = fork.gas_costs()
258236
intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator()
259-
attack_gas_limit = gas_benchmark_value
260237

261238
loop_cost = gas_costs.G_COLD_SLOAD # All accesses are always cold
262239
if storage_action == StorageAction.WRITE_NEW_VALUE:
@@ -305,7 +282,7 @@ def test_worst_storage_access_cold(
305282
)
306283

307284
num_target_slots = (
308-
attack_gas_limit - intrinsic_gas_cost_calc() - prefix_cost - suffix_cost
285+
gas_benchmark_value - intrinsic_gas_cost_calc() - prefix_cost - suffix_cost
309286
) // loop_cost
310287
if tx_result == TransactionResult.OUT_OF_GAS:
311288
# Add an extra slot to make it run out-of-gas
@@ -362,18 +339,16 @@ def test_worst_storage_access_cold(
362339

363340
op_tx = Transaction(
364341
to=contract_address,
365-
gas_limit=attack_gas_limit,
366342
sender=pre.fund_eoa(),
367343
)
368344
blocks.append(Block(txs=[op_tx]))
369345

370-
blockchain_test(
346+
benchmark_test(
371347
pre=pre,
372348
post={},
373349
blocks=blocks,
374-
exclude_full_post_state_in_output=True,
375350
expected_benchmark_gas_used=(
376-
total_gas_used if tx_result != TransactionResult.OUT_OF_GAS else attack_gas_limit
351+
total_gas_used if tx_result != TransactionResult.OUT_OF_GAS else gas_benchmark_value
377352
),
378353
)
379354

@@ -387,15 +362,12 @@ def test_worst_storage_access_cold(
387362
],
388363
)
389364
def test_worst_storage_access_warm(
390-
blockchain_test: BlockchainTestFiller,
365+
benchmark_test: BenchmarkTestFiller,
391366
pre: Alloc,
392367
storage_action: StorageAction,
393368
env: Environment,
394-
gas_benchmark_value: int,
395369
):
396370
"""Test running a block with as many warm storage slot accesses as possible."""
397-
attack_gas_limit = gas_benchmark_value
398-
399371
blocks = []
400372

401373
# The target storage slot for the warm access is storage slot 0.
@@ -438,12 +410,11 @@ def test_worst_storage_access_warm(
438410

439411
op_tx = Transaction(
440412
to=contract_address,
441-
gas_limit=attack_gas_limit,
442413
sender=pre.fund_eoa(),
443414
)
444415
blocks.append(Block(txs=[op_tx]))
445416

446-
blockchain_test(
417+
benchmark_test(
447418
pre=pre,
448419
post={},
449420
blocks=blocks,
@@ -453,7 +424,6 @@ def test_worst_storage_access_warm(
453424
def test_worst_blockhash(
454425
blockchain_test: BlockchainTestFiller,
455426
pre: Alloc,
456-
gas_benchmark_value: int,
457427
):
458428
"""Test running a block with as many blockhash accessing oldest allowed block as possible."""
459429
# Create 256 dummy blocks to fill the blockhash window.
@@ -466,7 +436,6 @@ def test_worst_blockhash(
466436
execution_code_address = pre.deploy_contract(code=execution_code)
467437
op_tx = Transaction(
468438
to=execution_code_address,
469-
gas_limit=gas_benchmark_value,
470439
sender=pre.fund_eoa(),
471440
)
472441
blocks.append(Block(txs=[op_tx]))
@@ -479,35 +448,14 @@ def test_worst_blockhash(
479448

480449

481450
def test_worst_selfbalance(
482-
state_test: StateTestFiller,
451+
benchmark_test: BenchmarkTestFiller,
483452
pre: Alloc,
484-
fork: Fork,
485-
gas_benchmark_value: int,
486453
):
487454
"""Test running a block with as many SELFBALANCE opcodes as possible."""
488-
max_stack_height = fork.max_stack_height()
489-
490-
code_sequence = Op.SELFBALANCE * max_stack_height
491-
target_address = pre.deploy_contract(code=code_sequence)
492-
493-
calldata = Bytecode()
494-
attack_block = Op.POP(Op.STATICCALL(Op.GAS, target_address, 0, 0, 0, 0))
495-
496-
code = code_loop_precompile_call(calldata, attack_block, fork)
497-
assert len(code) <= fork.max_code_size()
498-
499-
code_address = pre.deploy_contract(code=code)
500-
501-
tx = Transaction(
502-
to=code_address,
503-
gas_limit=gas_benchmark_value,
504-
sender=pre.fund_eoa(),
505-
)
506-
507-
state_test(
455+
benchmark_test(
508456
pre=pre,
509457
post={},
510-
tx=tx,
458+
code_generator=ExtCallGenerator(setup=Bytecode(), attack_block=Op.SELFBALANCE),
511459
)
512460

513461

@@ -520,7 +468,7 @@ def test_worst_selfbalance(
520468
],
521469
)
522470
def test_worst_extcodecopy_warm(
523-
state_test: StateTestFiller,
471+
benchmark_test: BenchmarkTestFiller,
524472
pre: Alloc,
525473
copied_size: int,
526474
gas_benchmark_value: int,
@@ -544,7 +492,7 @@ def test_worst_extcodecopy_warm(
544492
sender=pre.fund_eoa(),
545493
)
546494

547-
state_test(
495+
benchmark_test(
548496
pre=pre,
549497
post={},
550498
tx=tx,
@@ -553,7 +501,7 @@ def test_worst_extcodecopy_warm(
553501

554502
@pytest.mark.parametrize("value_bearing", [True, False])
555503
def test_worst_selfdestruct_existing(
556-
blockchain_test: BlockchainTestFiller,
504+
benchmark_test: BenchmarkTestFiller,
557505
fork: Fork,
558506
pre: Alloc,
559507
value_bearing: bool,
@@ -678,21 +626,20 @@ def test_worst_selfdestruct_existing(
678626
post[deployed_contract_address] = Account(nonce=1)
679627
deployed_contract_addresses.append(deployed_contract_address)
680628

681-
blockchain_test(
629+
benchmark_test(
682630
pre=pre,
683631
post=post,
684632
blocks=[
685633
Block(txs=[contracts_deployment_tx]),
686634
Block(txs=[opcode_tx], fee_recipient=fee_recipient),
687635
],
688-
exclude_full_post_state_in_output=True,
689636
expected_benchmark_gas_used=expected_benchmark_gas_used,
690637
)
691638

692639

693640
@pytest.mark.parametrize("value_bearing", [True, False])
694641
def test_worst_selfdestruct_created(
695-
state_test: StateTestFiller,
642+
benchmark_test: BenchmarkTestFiller,
696643
pre: Alloc,
697644
value_bearing: bool,
698645
fork: Fork,
@@ -775,13 +722,11 @@ def test_worst_selfdestruct_created(
775722
)
776723
code_tx = Transaction(
777724
to=code_addr,
778-
gas_limit=gas_benchmark_value,
779725
sender=pre.fund_eoa(),
780726
)
781727

782728
post = {code_addr: Account(storage={0: 42})} # Check for successful execution.
783-
state_test(
784-
env=env,
729+
benchmark_test(
785730
pre=pre,
786731
post=post,
787732
tx=code_tx,
@@ -791,7 +736,7 @@ def test_worst_selfdestruct_created(
791736

792737
@pytest.mark.parametrize("value_bearing", [True, False])
793738
def test_worst_selfdestruct_initcode(
794-
state_test: StateTestFiller,
739+
benchmark_test: BenchmarkTestFiller,
795740
pre: Alloc,
796741
value_bearing: bool,
797742
fork: Fork,
@@ -862,7 +807,7 @@ def test_worst_selfdestruct_initcode(
862807
)
863808

864809
post = {code_addr: Account(storage={0: 42})} # Check for successful execution.
865-
state_test(
810+
benchmark_test(
866811
env=env,
867812
pre=pre,
868813
post=post,

0 commit comments

Comments
 (0)