Skip to content

Commit 9f50834

Browse files
refactor(benchmark): update worst statefule scenario
1 parent 9f94d47 commit 9f50834

File tree

1 file changed

+38
-93
lines changed

1 file changed

+38
-93
lines changed

tests/benchmark/test_worst_stateful_opcodes.py

Lines changed: 38 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,29 @@
33
"""
44

55
import math
6+
from enum import auto
67

78
import pytest
89

10+
from ethereum_test_benchmark.benchmark_code_generator import ExtCallGenerator, JumpLoopGenerator
911
from ethereum_test_forks import Fork
12+
from ethereum_test_specs import BlockchainTestFiller, StateTestFiller
13+
from ethereum_test_specs.benchmark import BenchmarkTestFiller
1014
from ethereum_test_tools import (
1115
Account,
1216
Address,
1317
Alloc,
1418
Block,
15-
BlockchainTestFiller,
1619
Bytecode,
1720
Environment,
1821
Hash,
19-
StateTestFiller,
2022
Transaction,
2123
While,
2224
compute_create2_address,
2325
compute_create_address,
2426
)
2527
from ethereum_test_vm import Opcodes as Op
2628

27-
from .helpers import code_loop_precompile_call
28-
2929
REFERENCE_SPEC_GIT_PATH = "TODO"
3030
REFERENCE_SPEC_VERSION = "TODO"
3131

@@ -44,7 +44,7 @@
4444
],
4545
)
4646
def test_worst_address_state_cold(
47-
blockchain_test: BlockchainTestFiller,
47+
benchmark_test: BenchmarkTestFiller,
4848
pre: Alloc,
4949
fork: Fork,
5050
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,20 +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,
144-
) -> None:
145-
"""
146-
Test running a block with as many stateful opcodes doing warm access for an
147-
account.
148-
"""
149-
max_code_size = fork.max_code_size()
150-
attack_gas_limit = gas_benchmark_value
151-
141+
):
142+
"""Test running a block with as many stateful opcodes doing warm access for an account."""
152143
# Setup
153144
target_addr = Address(100_000)
154145
post = {}
@@ -158,45 +149,29 @@ def test_worst_address_state_warm(
158149
post[target_addr] = Account(balance=100, code=code)
159150

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

185160

186161
class StorageAction:
187162
"""Enum for storage actions."""
188163

189-
READ = 1
190-
WRITE_SAME_VALUE = 2
191-
WRITE_NEW_VALUE = 3
164+
READ = auto()
165+
WRITE_SAME_VALUE = auto()
166+
WRITE_NEW_VALUE = auto()
192167

193168

194169
class TransactionResult:
195170
"""Enum for the possible transaction outcomes."""
196171

197-
SUCCESS = 1
198-
OUT_OF_GAS = 2
199-
REVERT = 3
172+
SUCCESS = auto()
173+
OUT_OF_GAS = auto()
174+
REVERT = auto()
200175

201176

202177
@pytest.mark.parametrize(
@@ -247,7 +222,7 @@ class TransactionResult:
247222
],
248223
)
249224
def test_worst_storage_access_cold(
250-
blockchain_test: BlockchainTestFiller,
225+
benchmark_test: BenchmarkTestFiller,
251226
pre: Alloc,
252227
fork: Fork,
253228
storage_action: StorageAction,
@@ -261,7 +236,6 @@ def test_worst_storage_access_cold(
261236
"""
262237
gas_costs = fork.gas_costs()
263238
intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator()
264-
attack_gas_limit = gas_benchmark_value
265239

266240
loop_cost = gas_costs.G_COLD_SLOAD # All accesses are always cold
267241
if storage_action == StorageAction.WRITE_NEW_VALUE:
@@ -311,7 +285,7 @@ def test_worst_storage_access_cold(
311285
)
312286

313287
num_target_slots = (
314-
attack_gas_limit - intrinsic_gas_cost_calc() - prefix_cost - suffix_cost
288+
gas_benchmark_value - intrinsic_gas_cost_calc() - prefix_cost - suffix_cost
315289
) // loop_cost
316290
if tx_result == TransactionResult.OUT_OF_GAS:
317291
# Add an extra slot to make it run out-of-gas
@@ -369,18 +343,17 @@ def test_worst_storage_access_cold(
369343

370344
op_tx = Transaction(
371345
to=contract_address,
372-
gas_limit=attack_gas_limit,
346+
gas_limit=gas_benchmark_value,
373347
sender=pre.fund_eoa(),
374348
)
375349
blocks.append(Block(txs=[op_tx]))
376350

377-
blockchain_test(
351+
benchmark_test(
378352
pre=pre,
379353
post={},
380354
blocks=blocks,
381-
exclude_full_post_state_in_output=True,
382355
expected_benchmark_gas_used=(
383-
total_gas_used if tx_result != TransactionResult.OUT_OF_GAS else attack_gas_limit
356+
total_gas_used if tx_result != TransactionResult.OUT_OF_GAS else gas_benchmark_value
384357
),
385358
)
386359

@@ -394,17 +367,13 @@ def test_worst_storage_access_cold(
394367
],
395368
)
396369
def test_worst_storage_access_warm(
397-
blockchain_test: BlockchainTestFiller,
370+
benchmark_test: BenchmarkTestFiller,
398371
pre: Alloc,
399372
storage_action: StorageAction,
400-
env: Environment,
401373
gas_benchmark_value: int,
402-
) -> None:
403-
"""
404-
Test running a block with as many warm storage slot accesses as possible.
405-
"""
406-
attack_gas_limit = gas_benchmark_value
407-
374+
env: Environment,
375+
):
376+
"""Test running a block with as many warm storage slot accesses as possible."""
408377
blocks = []
409378

410379
# The target storage slot for the warm access is storage slot 0.
@@ -447,12 +416,12 @@ def test_worst_storage_access_warm(
447416

448417
op_tx = Transaction(
449418
to=contract_address,
450-
gas_limit=attack_gas_limit,
419+
gas_limit=gas_benchmark_value,
451420
sender=pre.fund_eoa(),
452421
)
453422
blocks.append(Block(txs=[op_tx]))
454423

455-
blockchain_test(
424+
benchmark_test(
456425
pre=pre,
457426
post={},
458427
blocks=blocks,
@@ -491,35 +460,14 @@ def test_worst_blockhash(
491460

492461

493462
def test_worst_selfbalance(
494-
state_test: StateTestFiller,
463+
benchmark_test: BenchmarkTestFiller,
495464
pre: Alloc,
496-
fork: Fork,
497-
gas_benchmark_value: int,
498-
) -> None:
465+
):
499466
"""Test running a block with as many SELFBALANCE opcodes as possible."""
500-
max_stack_height = fork.max_stack_height()
501-
502-
code_sequence = Op.SELFBALANCE * max_stack_height
503-
target_address = pre.deploy_contract(code=code_sequence)
504-
505-
calldata = Bytecode()
506-
attack_block = Op.POP(Op.STATICCALL(Op.GAS, target_address, 0, 0, 0, 0))
507-
508-
code = code_loop_precompile_call(calldata, attack_block, fork)
509-
assert len(code) <= fork.max_code_size()
510-
511-
code_address = pre.deploy_contract(code=code)
512-
513-
tx = Transaction(
514-
to=code_address,
515-
gas_limit=gas_benchmark_value,
516-
sender=pre.fund_eoa(),
517-
)
518-
519-
state_test(
467+
benchmark_test(
520468
pre=pre,
521469
post={},
522-
tx=tx,
470+
code_generator=ExtCallGenerator(setup=Bytecode(), attack_block=Op.SELFBALANCE),
523471
)
524472

525473

@@ -532,7 +480,7 @@ def test_worst_selfbalance(
532480
],
533481
)
534482
def test_worst_extcodecopy_warm(
535-
state_test: StateTestFiller,
483+
benchmark_test: BenchmarkTestFiller,
536484
pre: Alloc,
537485
copied_size: int,
538486
gas_benchmark_value: int,
@@ -556,7 +504,7 @@ def test_worst_extcodecopy_warm(
556504
sender=pre.fund_eoa(),
557505
)
558506

559-
state_test(
507+
benchmark_test(
560508
pre=pre,
561509
post={},
562510
tx=tx,
@@ -565,7 +513,7 @@ def test_worst_extcodecopy_warm(
565513

566514
@pytest.mark.parametrize("value_bearing", [True, False])
567515
def test_worst_selfdestruct_existing(
568-
blockchain_test: BlockchainTestFiller,
516+
benchmark_test: BenchmarkTestFiller,
569517
fork: Fork,
570518
pre: Alloc,
571519
value_bearing: bool,
@@ -696,14 +644,13 @@ def test_worst_selfdestruct_existing(
696644
post[deployed_contract_address] = Account(nonce=1)
697645
deployed_contract_addresses.append(deployed_contract_address)
698646

699-
blockchain_test(
647+
benchmark_test(
700648
pre=pre,
701649
post=post,
702650
blocks=[
703651
Block(txs=[contracts_deployment_tx]),
704652
Block(txs=[opcode_tx], fee_recipient=fee_recipient),
705653
],
706-
exclude_full_post_state_in_output=True,
707654
expected_benchmark_gas_used=expected_benchmark_gas_used,
708655
)
709656

@@ -800,7 +747,6 @@ def test_worst_selfdestruct_created(
800747
post = {code_addr: Account(storage={0: 42})} # Check for successful
801748
# execution.
802749
state_test(
803-
env=env,
804750
pre=pre,
805751
post=post,
806752
tx=code_tx,
@@ -886,7 +832,6 @@ def test_worst_selfdestruct_initcode(
886832
post = {code_addr: Account(storage={0: 42})} # Check for successful
887833
# execution.
888834
state_test(
889-
env=env,
890835
pre=pre,
891836
post=post,
892837
tx=code_tx,

0 commit comments

Comments
 (0)