diff --git a/.github/configs/feature.yaml b/.github/configs/feature.yaml index d3d149820ad..7ace6eb192e 100644 --- a/.github/configs/feature.yaml +++ b/.github/configs/feature.yaml @@ -13,7 +13,7 @@ static: solc: 0.8.21 zkevm: evm-type: zkevm - fill-params: --from=Cancun --until=Prague -m zkevm ./tests + fill-params: --from=Cancun --until=Prague --block-gas-limit 36000000 -m zkevm ./tests solc: 0.8.21 feature_only: true eip7692: @@ -21,4 +21,4 @@ eip7692: fill-params: --fork=EOFv1 ./tests/unscheduled solc: 0.8.21 eofwrap: true - feature_only: true \ No newline at end of file + feature_only: true diff --git a/tests/zkevm/test_worst_bytecode.py b/tests/zkevm/test_worst_bytecode.py index 3f35e14c9dc..99dbd7644ba 100644 --- a/tests/zkevm/test_worst_bytecode.py +++ b/tests/zkevm/test_worst_bytecode.py @@ -27,9 +27,6 @@ REFERENCE_SPEC_VERSION = "TODO" MAX_CONTRACT_SIZE = 24 * 1024 # TODO: This could be a fork property -BLOCK_GAS_LIMIT = 36_000_000 # TODO: Parametrize using the (yet to be implemented) block gas limit -# OPCODE_GAS_LIMIT = BLOCK_GAS_LIMIT # TODO: Reduced in order to run the test in a reasonable time -OPCODE_GAS_LIMIT = 100_000 XOR_TABLE_SIZE = 256 XOR_TABLE = [Hash(i).sha256() for i in range(XOR_TABLE_SIZE)] @@ -41,12 +38,20 @@ Op.EXTCODESIZE, ], ) +@pytest.mark.parametrize( + "attack_gas_limit", + [ + Environment().gas_limit, + ], +) +@pytest.mark.slow() @pytest.mark.valid_from("Cancun") def test_worst_bytecode_single_opcode( blockchain_test: BlockchainTestFiller, pre: Alloc, fork: Fork, opcode: Op, + attack_gas_limit: int, ): """ Test a block execution where a single opcode execution maxes out the gas limit, @@ -60,7 +65,9 @@ def test_worst_bytecode_single_opcode( The test is performed in the last block of the test, and the entire block gas limit is consumed by repeated opcode executions. """ - env = Environment(gas_limit=BLOCK_GAS_LIMIT) + # We use 100G gas limit to be able to deploy a large number of contracts in a single block, + # avoiding bloating the number of preparing blocks in the test. + env = Environment(gas_limit=100_000_000_000) # The initcode will take its address as a starting point to the input to the keccak # hash function. @@ -126,19 +133,19 @@ def test_worst_bytecode_single_opcode( ) max_number_of_contract_calls = ( # Base available gas = GAS_LIMIT - intrinsic - (out of loop MSTOREs) - OPCODE_GAS_LIMIT - intrinsic_gas_cost_calc() - gas_costs.G_VERY_LOW * 4 + attack_gas_limit - intrinsic_gas_cost_calc() - gas_costs.G_VERY_LOW * 4 ) // loop_cost total_contracts_to_deploy = max_number_of_contract_calls approximate_gas_per_deployment = 4_970_000 # Obtained from evm tracing - contracts_deployed_per_tx = BLOCK_GAS_LIMIT // approximate_gas_per_deployment + contracts_deployed_per_tx = env.gas_limit // approximate_gas_per_deployment deploy_txs = [] def generate_deploy_tx(contracts_to_deploy: int): return Transaction( to=factory_caller_address, - gas_limit=BLOCK_GAS_LIMIT, + gas_limit=env.gas_limit, gas_price=10**9, # Bump required due to the amount of full blocks data=Hash(contracts_deployed_per_tx), sender=pre.fund_eoa(), @@ -171,8 +178,7 @@ def generate_deploy_tx(contracts_to_deploy: int): + Op.MSTORE(64, initcode.keccak256()) # Main loop + While( - body=Op.POP(Op.EXTCODESIZE(Op.SHA3(32 - 20 - 1, 85))) - + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)), + body=Op.POP(opcode(Op.SHA3(32 - 20 - 1, 85))) + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)), ) ) @@ -185,7 +191,7 @@ def generate_deploy_tx(contracts_to_deploy: int): opcode_address = pre.deploy_contract(code=opcode_code) opcode_tx = Transaction( to=opcode_address, - gas_limit=OPCODE_GAS_LIMIT, + gas_limit=attack_gas_limit, gas_price=10**9, # Bump required due to the amount of full blocks sender=pre.fund_eoa(), ) @@ -198,4 +204,5 @@ def generate_deploy_tx(contracts_to_deploy: int): *[Block(txs=[deploy_tx]) for deploy_tx in deploy_txs], Block(txs=[opcode_tx]), ], + exclude_full_post_state_in_output=True, )