66"""
77
88import math
9+ from enum import auto
910
1011import pytest
1112
13+ from ethereum_test_benchmark .benchmark_code_generator import ExtCallGenerator , JumpLoopGenerator
1214from ethereum_test_forks import Fork
15+ from ethereum_test_specs import BlockchainTestFiller
16+ from ethereum_test_specs .benchmark import BenchmarkTestFiller
1317from 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)
2830from ethereum_test_tools .vm .opcode import Opcodes as Op
2931
30- from .helpers import code_loop_precompile_call
31-
3232REFERENCE_SPEC_GIT_PATH = "TODO"
3333REFERENCE_SPEC_VERSION = "TODO"
3434
4747 ],
4848)
4949def 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)
137136def 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
183161class 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
191169class 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)
246224def 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)
389364def 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(
453424def 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
481450def 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)
522470def 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 ])
555503def 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 ])
694641def 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 ])
793738def 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