From b73bc368f378e16eb25c3b02292c88adb34b9c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Mon, 15 Sep 2025 20:56:00 +0800 Subject: [PATCH 001/102] refactor(tests): add checklist marker for eip7823 (#2115) * feat(tests): enhance eip7823 coverage * feat(tests): add eip7823 checklist items for coverage * refactor(tests): update modexp upper bounds framework * feat(tests): expand checklist item and enhance test coverage --- osaka/eip7823_modexp_upper_bounds/conftest.py | 186 +++++++++++ .../eip_checklist_external_coverage.txt | 27 ++ .../eip_checklist_not_applicable.txt | 24 ++ osaka/eip7823_modexp_upper_bounds/spec.py | 14 + .../test_modexp_upper_bounds.py | 289 ++++++++++++------ .../eip7702_set_code_tx/test_set_code_txs.py | 2 +- 6 files changed, 452 insertions(+), 90 deletions(-) create mode 100644 osaka/eip7823_modexp_upper_bounds/conftest.py create mode 100644 osaka/eip7823_modexp_upper_bounds/eip_checklist_external_coverage.txt create mode 100644 osaka/eip7823_modexp_upper_bounds/eip_checklist_not_applicable.txt create mode 100644 osaka/eip7823_modexp_upper_bounds/spec.py diff --git a/osaka/eip7823_modexp_upper_bounds/conftest.py b/osaka/eip7823_modexp_upper_bounds/conftest.py new file mode 100644 index 0000000000..56bfb1c937 --- /dev/null +++ b/osaka/eip7823_modexp_upper_bounds/conftest.py @@ -0,0 +1,186 @@ +"""Conftest for EIP-7823 tests.""" + +from typing import Dict + +import pytest + +from ethereum_test_forks import Fork, Osaka +from ethereum_test_tools import Account, Address, Alloc, Storage, Transaction, keccak256 +from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_types import Environment + +from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput +from ..eip7883_modexp_gas_increase.spec import Spec, Spec7883 + + +@pytest.fixture +def call_contract_post_storage() -> Storage: + """ + Storage of the test contract after the transaction is executed. + Note: Fixture `call_contract_code` fills the actual expected storage values. + """ + return Storage() + + +@pytest.fixture +def call_succeeds( + total_gas_used: int, fork: Fork, env: Environment, modexp_input: ModExpInput +) -> bool: + """ + By default, depending on the expected output, we can deduce if the call is expected to succeed + or fail. + """ + # Transaction gas limit exceeded + tx_gas_limit_cap = fork.transaction_gas_limit_cap() or env.gas_limit + if total_gas_used > tx_gas_limit_cap: + return False + + # Input length exceeded + base_length, exp_length, mod_length = modexp_input.get_declared_lengths() + if ( + base_length > Spec.MAX_LENGTH_BYTES + or exp_length > Spec.MAX_LENGTH_BYTES + or mod_length > Spec.MAX_LENGTH_BYTES + ) and fork >= Osaka: + return False + + return True + + +@pytest.fixture +def gas_measure_contract( + pre: Alloc, + fork: Fork, + modexp_expected: bytes, + precompile_gas: int, + call_contract_post_storage: Storage, + call_succeeds: bool, +) -> Address: + """ + Deploys a contract that measures ModExp gas consumption and execution result. + + Always stored: + storage[0]: precompile call success + storage[1]: return data length from precompile + Only if the precompile call succeeds: + storage[2]: gas consumed by precompile + storage[3]: hash of return data from precompile + """ + call_code = Op.CALL( + precompile_gas, + Spec.MODEXP_ADDRESS, + 0, + 0, + Op.CALLDATASIZE(), + 0, + 0, + ) + + gas_costs = fork.gas_costs() + extra_gas = ( + gas_costs.G_WARM_ACCOUNT_ACCESS + + (gas_costs.G_VERY_LOW * (len(Op.CALL.kwargs) - 1)) # type: ignore + + gas_costs.G_BASE # CALLDATASIZE + + gas_costs.G_BASE # GAS + ) + + # Build the gas measurement contract code + # Stack operations: + # [gas_start] + # [gas_start, call_result] + # [gas_start, call_result, gas_end] + # [gas_start, gas_end, call_result] + call_result_measurement = Op.GAS + call_code + Op.GAS + Op.SWAP1 + + # Calculate gas consumed: gas_start - (gas_end + extra_gas) + # Stack Operation: + # [gas_start, gas_end] + # [gas_start, gas_end, extra_gas] + # [gas_start, gas_end + extra_gas] + # [gas_end + extra_gas, gas_start] + # [gas_consumed] + gas_calculation = Op.PUSH2[extra_gas] + Op.ADD + Op.SWAP1 + Op.SUB + + code = ( + Op.CALLDATACOPY(dest_offset=0, offset=0, size=Op.CALLDATASIZE) + + Op.SSTORE(call_contract_post_storage.store_next(call_succeeds), call_result_measurement) + + Op.SSTORE( + call_contract_post_storage.store_next(len(modexp_expected) if call_succeeds else 0), + Op.RETURNDATASIZE(), + ) + ) + + if call_succeeds: + code += Op.SSTORE(call_contract_post_storage.store_next(precompile_gas), gas_calculation) + code += Op.RETURNDATACOPY(dest_offset=0, offset=0, size=Op.RETURNDATASIZE()) + code += Op.SSTORE( + call_contract_post_storage.store_next(keccak256(bytes(modexp_expected))), + Op.SHA3(0, Op.RETURNDATASIZE()), + ) + return pre.deploy_contract(code) + + +@pytest.fixture +def precompile_gas(fork: Fork, modexp_input: ModExpInput) -> int: + """Calculate gas cost for the ModExp precompile and verify it matches expected gas.""" + spec = Spec if fork < Osaka else Spec7883 + try: + calculated_gas = spec.calculate_gas_cost(modexp_input) + return calculated_gas + except Exception: + # Used for `test_modexp_invalid_inputs` we expect the call to not succeed. + # Return is for completeness. + return 500 if fork >= Osaka else 200 + + +@pytest.fixture +def tx( + pre: Alloc, + gas_measure_contract: Address, + modexp_input: ModExpInput, + tx_gas_limit: int, +) -> Transaction: + """Transaction to measure gas consumption of the ModExp precompile.""" + return Transaction( + sender=pre.fund_eoa(), + to=gas_measure_contract, + data=bytes(modexp_input), + gas_limit=tx_gas_limit, + ) + + +@pytest.fixture +def total_gas_used( + fork: Fork, modexp_expected: bytes, modexp_input: ModExpInput, precompile_gas: int +) -> int: + """Transaction gas limit used for the test (Can be overridden in the test).""" + intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() + memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() + extra_gas = 500_000 + + total_gas = ( + extra_gas + + intrinsic_gas_cost_calculator(calldata=bytes(modexp_input)) + + memory_expansion_gas_calculator(new_bytes=len(bytes(modexp_input))) + + precompile_gas + ) + + return total_gas + + +@pytest.fixture +def tx_gas_limit(total_gas_used: int, fork: Fork, env: Environment) -> int: + """Transaction gas limit used for the test (Can be overridden in the test).""" + tx_gas_limit_cap = fork.transaction_gas_limit_cap() or env.gas_limit + return min(tx_gas_limit_cap, total_gas_used) + + +@pytest.fixture +def post( + gas_measure_contract: Address, + call_contract_post_storage: Storage, +) -> Dict[Address, Account]: + """Return expected post state with gas consumption check.""" + return { + gas_measure_contract: Account(storage=call_contract_post_storage), + } diff --git a/osaka/eip7823_modexp_upper_bounds/eip_checklist_external_coverage.txt b/osaka/eip7823_modexp_upper_bounds/eip_checklist_external_coverage.txt new file mode 100644 index 0000000000..213471321d --- /dev/null +++ b/osaka/eip7823_modexp_upper_bounds/eip_checklist_external_coverage.txt @@ -0,0 +1,27 @@ +precompile/test/call_contexts/set_code = Covered in EIP-7702 cases +precompile/test/call_contexts/normal = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/call_contexts/delegate = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/call_contexts/static = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/call_contexts/callcode = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/call_contexts/tx_entry = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/call_contexts/initcode/CREATE = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/call_contexts/initcode/tx = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/call_contexts/set_code = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/inputs/valid = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/inputs/valid/boundary = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/inputs/all_zeros = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/inputs/invalid = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/inputs/invalid/crypto = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/inputs/invalid/corrupted = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/value_transfer/no_fee = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/out_of_bounds/max_plus_one = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/input_lengths/zero = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/input_lengths/dynamic/valid = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/input_lengths/dynamic/too_long = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/gas_usage/dynamic/exact = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/gas_usage/dynamic/oog = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/excessive_gas_usage = Covered in osaka/eip7883_modexp_gas_increase +precompile/test/fork_transition/after/warm = Covered in osaka/eip7883_modexp_gas_increase +gas_cost_changes/test/gas_updates_measurement = Covered in osaka/eip7883_modexp_gas_increase +gas_cost_changes/test/fork_transition/before = Covered in osaka/eip7883_modexp_gas_increase +gas_cost_changes/test/fork_transition/after = Covered in osaka/eip7883_modexp_gas_increase \ No newline at end of file diff --git a/osaka/eip7823_modexp_upper_bounds/eip_checklist_not_applicable.txt b/osaka/eip7823_modexp_upper_bounds/eip_checklist_not_applicable.txt new file mode 100644 index 0000000000..2fe9ebdfdc --- /dev/null +++ b/osaka/eip7823_modexp_upper_bounds/eip_checklist_not_applicable.txt @@ -0,0 +1,24 @@ +precompile/test/value_transfer/fee/under = No value is required +precompile/test/value_transfer/fee/exact = No value is required +precompile/test/value_transfer/fee/over = No value is required +precompile/test/input_lengths/static/correct = The Modexp input length is not static +precompile/test/input_lengths/static/too_short = The Modexp input length is not static +precompile/test/input_lengths/static/too_long = The Modexp input length is not static +precompile/test/input_lengths/dynamic/too_short = there would be no padding for precompile +precompile/test/gas_usage/constant/oog = The Modexp gas cost is dynamic +precompile/test/gas_usage/constant/exact = The Modexp gas cost is dynamic +precompile/test/fork_transition/before/invalid_input = Modexp is not new precompile, it is still valid befork fork activation +precompile/test/fork_transition/before/zero_gas = Modexp is not new precompile, it is still valid befork fork activation +precompile/test/fork_transition/before/cold = Modexp is not new precompile, it is still valid befork fork activation +gas_cost_changes/test/out_of_gas = No Out-of-gas scenario in Modexp +system_contract = EIP does not include a new system contract +opcode = EIP does not introduce a new opcode +removed_precompile = EIP does not remove a precompile +transaction_type = EIP does not introduce a new transaction type +block_header_field = EIP does not add any new block header fields +gas_refunds_changes = EIP does not introduce any gas refund changes +blob_count_changes = EIP does not introduce any blob count changes +execution_layer_request = EIP does not introduce an execution layer request +new_transaction_validity_constraint = EIP does not introduce a new transaction validity constraint +modified_transaction_validity_constraint = EIP does not introduce a modified transaction validity constraint +block_body_field = EIP does not add any new block body fields \ No newline at end of file diff --git a/osaka/eip7823_modexp_upper_bounds/spec.py b/osaka/eip7823_modexp_upper_bounds/spec.py new file mode 100644 index 0000000000..88fddca02a --- /dev/null +++ b/osaka/eip7823_modexp_upper_bounds/spec.py @@ -0,0 +1,14 @@ +"""Defines EIP-7823 specification constants and functions.""" + +from dataclasses import dataclass + + +@dataclass(frozen=True) +class ReferenceSpec: + """Defines the reference spec version and git path.""" + + git_path: str + version: str + + +ref_spec_7823 = ReferenceSpec("EIPS/eip-7823.md", "c8321494fdfbfda52ad46c3515a7ca5dc86b857c") diff --git a/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py b/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py index 6ac1a74270..2f32f1b94d 100644 --- a/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py +++ b/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py @@ -3,121 +3,145 @@ Tests upper bounds of the MODEXP precompile. """ +from typing import Dict + import pytest -from ethereum_test_forks import Fork, Osaka -from ethereum_test_tools import Account, Alloc, Bytes, Environment, StateTestFiller, Transaction +from ethereum_test_checklists import EIPChecklist +from ethereum_test_forks import Fork +from ethereum_test_tools import ( + Account, + Alloc, + Block, + BlockchainTestFiller, + Bytes, + StateTestFiller, + Transaction, + keccak256, +) from ethereum_test_tools.vm.opcode import Opcodes as Op -from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput, ModExpOutput -from ..eip7883_modexp_gas_increase.spec import Spec, Spec7883 - -REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7823.md" -REFERENCE_SPEC_VERSION = "c8321494fdfbfda52ad46c3515a7ca5dc86b857c" +from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput +from ..eip7883_modexp_gas_increase.spec import Spec +from .spec import ref_spec_7823 -MAX_LENGTH_BYTES = 1024 -TX_GAS_LIMIT = 2**24 +REFERENCE_SPEC_GIT_PATH = ref_spec_7823.git_path +REFERENCE_SPEC_VERSION = ref_spec_7823.version -@pytest.fixture -def precompile_gas(fork: Fork, mod_exp_input: ModExpInput) -> int: - """Calculate gas cost for the ModExp precompile and verify it matches expected gas.""" - spec = Spec if fork < Osaka else Spec7883 - calculated_gas = spec.calculate_gas_cost(mod_exp_input) - return calculated_gas - - -@pytest.mark.valid_from("Prague") +@pytest.mark.valid_from("Osaka") @pytest.mark.parametrize( - "mod_exp_input", + "modexp_input,modexp_expected,call_succeeds", [ pytest.param( ModExpInput( - base=b"\0" * (MAX_LENGTH_BYTES + 1), + base=b"\0" * (Spec.MAX_LENGTH_BYTES + 1), exponent=b"\0", modulus=b"\2", ), + Spec.modexp_error, + False, id="excess_length_base", ), pytest.param( ModExpInput( base=b"\0", - exponent=b"\0" * (MAX_LENGTH_BYTES + 1), + exponent=b"\0" * (Spec.MAX_LENGTH_BYTES + 1), modulus=b"\2", ), + Spec.modexp_error, + False, id="excess_length_exponent", ), pytest.param( ModExpInput( base=b"\0", exponent=b"\0", - modulus=b"\0" * (MAX_LENGTH_BYTES) + b"\2", + modulus=b"\0" * (Spec.MAX_LENGTH_BYTES) + b"\2", ), + Spec.modexp_error, + False, id="excess_length_modulus", ), pytest.param( ModExpInput( base=b"", - exponent=b"\0" * (MAX_LENGTH_BYTES + 1), + exponent=b"\0" * (Spec.MAX_LENGTH_BYTES + 1), modulus=b"", ), + Spec.modexp_error, + False, id="exp_1025_base_0_mod_0", ), pytest.param( ModExpInput( base=b"", # Non-zero exponent is cancelled with zero multiplication complexity pre EIP-7823. - exponent=b"\xff" * (MAX_LENGTH_BYTES + 1), + exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1), modulus=b"", ), + Spec.modexp_error, + False, id="expFF_1025_base_0_mod_0", ), pytest.param( ModExpInput( - base=b"\0" * MAX_LENGTH_BYTES, - exponent=b"\xff" * (MAX_LENGTH_BYTES + 1), + base=b"\0" * Spec.MAX_LENGTH_BYTES, + exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1), modulus=b"", ), + Spec.modexp_error, + False, id="expFF_1025_base_1024_mod_0", ), pytest.param( ModExpInput( - base=b"\0" * (MAX_LENGTH_BYTES + 1), - exponent=b"\xff" * (MAX_LENGTH_BYTES + 1), + base=b"\0" * (Spec.MAX_LENGTH_BYTES + 1), + exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1), modulus=b"", ), + Spec.modexp_error, + False, id="expFF_1025_base_1025_mod_0", ), pytest.param( ModExpInput( - base=b"\0" * (MAX_LENGTH_BYTES + 1), + base=b"\0" * (Spec.MAX_LENGTH_BYTES + 1), exponent=b"", modulus=b"", ), + Spec.modexp_error, + False, id="exp_0_base_1025_mod_0", ), pytest.param( ModExpInput( - base=b"\0" * (MAX_LENGTH_BYTES + 1), + base=b"\0" * (Spec.MAX_LENGTH_BYTES + 1), exponent=b"", modulus=b"\2", ), + Spec.modexp_error, + False, id="exp_0_base_1025_mod_1", ), pytest.param( ModExpInput( base=b"", exponent=b"", - modulus=b"\0" * (MAX_LENGTH_BYTES + 1), + modulus=b"\0" * (Spec.MAX_LENGTH_BYTES + 1), ), + Spec.modexp_error, + False, id="exp_0_base_0_mod_1025", ), pytest.param( ModExpInput( base=b"\1", exponent=b"", - modulus=b"\0" * (MAX_LENGTH_BYTES + 1), + modulus=b"\0" * (Spec.MAX_LENGTH_BYTES + 1), ), + Spec.modexp_error, + False, id="exp_0_base_1_mod_1025", ), pytest.param( @@ -127,32 +151,40 @@ def precompile_gas(fork: Fork, mod_exp_input: ModExpInput) -> int: modulus=b"", declared_exponent_length=2**64, ), + Spec.modexp_error, + False, id="exp_2_pow_64_base_0_mod_0", ), # Implementation coverage tests pytest.param( ModExpInput( - base=b"\xff" * (MAX_LENGTH_BYTES + 1), - exponent=b"\xff" * (MAX_LENGTH_BYTES + 1), - modulus=b"\xff" * (MAX_LENGTH_BYTES + 1), + base=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1), + exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1), + modulus=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1), ), + Spec.modexp_error, + False, id="all_exceed_check_ordering", ), pytest.param( ModExpInput( - base=b"\x00" * MAX_LENGTH_BYTES, - exponent=b"\xff" * (MAX_LENGTH_BYTES + 1), - modulus=b"\xff" * (MAX_LENGTH_BYTES + 1), + base=b"\x00" * Spec.MAX_LENGTH_BYTES, + exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1), + modulus=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1), ), + Spec.modexp_error, + False, id="exp_mod_exceed_base_ok", ), pytest.param( ModExpInput( # Bitwise pattern for Nethermind optimization - base=b"\xaa" * (MAX_LENGTH_BYTES + 1), - exponent=b"\x55" * MAX_LENGTH_BYTES, - modulus=b"\xff" * MAX_LENGTH_BYTES, + base=b"\xaa" * (Spec.MAX_LENGTH_BYTES + 1), + exponent=b"\x55" * Spec.MAX_LENGTH_BYTES, + modulus=b"\xff" * Spec.MAX_LENGTH_BYTES, ), + Spec.modexp_error, + False, id="bitwise_pattern_base_exceed", ), pytest.param( @@ -165,76 +197,155 @@ def precompile_gas(fork: Fork, mod_exp_input: ModExpInput) -> int: declared_exponent_length=1, declared_modulus_length=1, ), + Spec.modexp_error, + False, id="near_uint64_max_base", ), pytest.param( ModExpInput( - base=b"\x01" * MAX_LENGTH_BYTES, + base=b"\x01" * Spec.MAX_LENGTH_BYTES, exponent=b"", - modulus=b"\x02" * (MAX_LENGTH_BYTES + 1), + modulus=b"\x02" * (Spec.MAX_LENGTH_BYTES + 1), declared_exponent_length=0, ), + Spec.modexp_error, + False, id="zero_exp_mod_exceed", ), + pytest.param( + ModExpInput( + base=b"\x01" * Spec.MAX_LENGTH_BYTES, + exponent=b"\x00", + modulus=b"\x02", + ), + b"\x01", + True, + id="base_boundary", + ), + pytest.param( + ModExpInput( + base=b"\x01", + exponent=b"\x00" * Spec.MAX_LENGTH_BYTES, + modulus=b"\x02", + ), + b"\x01", + True, + id="exp_boundary", + ), + pytest.param( + ModExpInput( + base=b"\x01", + exponent=b"\x00", + modulus=b"\x02" * Spec.MAX_LENGTH_BYTES, + ), + b"\x01".rjust(Spec.MAX_LENGTH_BYTES, b"\x00"), + True, + id="mod_boundary", + ), + pytest.param( + ModExpInput( + base=b"\x01" * Spec.MAX_LENGTH_BYTES, + exponent=b"\x00", + modulus=b"\x02" * Spec.MAX_LENGTH_BYTES, + ), + b"\x01".rjust(Spec.MAX_LENGTH_BYTES, b"\x00"), + True, + id="base_mod_boundary", + ), ], ) +@EIPChecklist.Precompile.Test.Inputs.MaxValues +@EIPChecklist.Precompile.Test.OutOfBounds.Max def test_modexp_upper_bounds( state_test: StateTestFiller, - mod_exp_input: ModExpInput, + modexp_input: ModExpInput, + modexp_expected: bytes, precompile_gas: int, fork: Fork, + tx: Transaction, + post: Dict, pre: Alloc, ): - """Test the MODEXP precompile.""" - sender = pre.fund_eoa() + """Test the MODEXP precompile input bounds.""" + state_test(pre=pre, tx=tx, post=post) - account = pre.deploy_contract( - # Store all CALLDATA into memory (offset 0) - Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE()) - # Store the returned CALL status (success = 1, fail = 0) into slot 0: - + Op.SSTORE( - 0, - # Setup stack to CALL into ModExp with the CALLDATA and CALL into it (+ pop value) - Op.CALL( - gas=precompile_gas, - address=0x05, - value=0, - args_offset=0, - args_size=Op.CALLDATASIZE(), + +@pytest.mark.parametrize( + "modexp_input,modexp_expected", + [ + pytest.param( + ModExpInput( + base=b"\1" * (Spec.MAX_LENGTH_BYTES + 1), + exponent=b"\0", + modulus=b"\2", ), - ) - # STOP (handy for tracing) - + Op.STOP(), + b"\1", + id="base_1_exp_0_mod_2", + ), + ], +) +@pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True) +def test_modexp_upper_bounds_fork_transition( + blockchain_test: BlockchainTestFiller, + pre: Alloc, + fork: Fork, + precompile_gas: int, + modexp_input: ModExpInput, + modexp_expected: bytes, +): + """Test MODEXP upper bounds enforcement transition from before to after Osaka hard fork.""" + call_code = Op.CALL( + address=Spec.MODEXP_ADDRESS, + args_size=Op.CALLDATASIZE, ) - intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() - intrinsic_gas_cost = intrinsic_gas_cost_calc(calldata=mod_exp_input) - memory_expansion_gas_calc = fork.memory_expansion_gas_calculator() - memory_expansion_gas = memory_expansion_gas_calc(new_bytes=len(bytes(mod_exp_input))) + code = ( + Op.CALLDATACOPY(size=Op.CALLDATASIZE) + + Op.SSTORE( + Op.TIMESTAMP, + call_code, + ) + + Op.RETURNDATACOPY(size=Op.RETURNDATASIZE()) + + Op.SSTORE( + Op.AND(Op.TIMESTAMP, 0xFF), + Op.SHA3(0, Op.RETURNDATASIZE()), + ) + ) - gas_limit = intrinsic_gas_cost + (precompile_gas * 64 // 63) + memory_expansion_gas + 100_000 - expensive = gas_limit > TX_GAS_LIMIT - gas_limit = TX_GAS_LIMIT if expensive else gas_limit - env = Environment(gas_limit=gas_limit) + senders = [pre.fund_eoa() for _ in range(3)] + contracts = [pre.deploy_contract(code) for _ in range(3)] + timestamps = [14_999, 15_000, 15_001] # Before, at, and after transition + expected_results = [True, False, False] - tx = Transaction( - ty=0x0, - to=account, - data=mod_exp_input, - gas_limit=gas_limit, - protected=True, - sender=sender, - ) - base_length, exp_length, mod_length = mod_exp_input.get_declared_lengths() - if ( - base_length <= MAX_LENGTH_BYTES - and exp_length <= MAX_LENGTH_BYTES - and mod_length <= MAX_LENGTH_BYTES - ) or (fork < Osaka and not expensive): - output = ModExpOutput(call_success=True, returned_data="0x01") - else: - output = ModExpOutput(call_success=False, returned_data="0x") + blocks = [ + Block( + timestamp=ts, + txs=[ + Transaction( + to=contract, + data=bytes(modexp_input), + sender=sender, + gas_limit=6_000_000, + ) + ], + ) + for ts, contract, sender in zip(timestamps, contracts, senders, strict=False) + ] - post = {account: Account(storage={0: output.call_success})} + post = { + contract: Account( + storage={ + ts: expected, + ts & 0xFF: keccak256(modexp_expected) + if expected + else keccak256(Spec.modexp_error), + } + ) + for contract, ts, expected in zip(contracts, timestamps, expected_results, strict=False) + } - state_test(env=env, pre=pre, post=post, tx=tx) + blockchain_test( + pre=pre, + blocks=blocks, + post=post, + ) diff --git a/prague/eip7702_set_code_tx/test_set_code_txs.py b/prague/eip7702_set_code_tx/test_set_code_txs.py index c8d382cb9a..cc25e6e57c 100644 --- a/prague/eip7702_set_code_tx/test_set_code_txs.py +++ b/prague/eip7702_set_code_tx/test_set_code_txs.py @@ -2589,7 +2589,7 @@ def test_set_code_to_log( @pytest.mark.with_all_call_opcodes @pytest.mark.with_all_precompiles -@EIPChecklist.Precompile.Test.CallContexts.SetCode(eip=[7951, 7883]) +@EIPChecklist.Precompile.Test.CallContexts.SetCode(eip=[7951, 7883, 7823]) def test_set_code_to_precompile( state_test: StateTestFiller, pre: Alloc, From a3e945150e55159c7486189afa50a36ba281346d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Mon, 15 Sep 2025 21:01:26 +0800 Subject: [PATCH 002/102] refactor(tests): update checklist item for eip7939 (#2097) * feat: update checklist item for clz * feat: add new checklist items * refactor: update checklist items for eip7939 * refactor: update checklist not applicable itemss * feat(checklist): Add checklist warnings * feat(checklist): ad coverage and reentry notes to eip7939 checklist * fix linting issue * refactor(checklist): remove duplicate ban check items --------- Co-authored-by: Mario Vega --- ethereum_test_checklists/eip_checklist.py | 5 +++++ ethereum_test_checklists/eip_checklist.pyi | 1 + pytest_plugins/filler/eip_checklist.py | 17 +++-------------- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/ethereum_test_checklists/eip_checklist.py b/ethereum_test_checklists/eip_checklist.py index 2fd01ea834..9a3b0b26cd 100644 --- a/ethereum_test_checklists/eip_checklist.py +++ b/ethereum_test_checklists/eip_checklist.py @@ -386,6 +386,11 @@ class OutOfGasMemory(ChecklistItem): pass + class ExtraGas(ChecklistItem): + """Extra gas usage tests.""" + + pass + class OrderOfOperations(ChecklistItem): """Order of operations tests.""" diff --git a/ethereum_test_checklists/eip_checklist.pyi b/ethereum_test_checklists/eip_checklist.pyi index 54c2b707da..d12d7f8a92 100644 --- a/ethereum_test_checklists/eip_checklist.pyi +++ b/ethereum_test_checklists/eip_checklist.pyi @@ -138,6 +138,7 @@ class EIPChecklist: Invalid: _CallableChecklistItem class GasUsage(_CallableChecklistItem): + ExtraGas: _CallableChecklistItem MemoryExpansion: _CallableChecklistItem Normal: _CallableChecklistItem OutOfGasExecution: _CallableChecklistItem diff --git a/pytest_plugins/filler/eip_checklist.py b/pytest_plugins/filler/eip_checklist.py index 4405347d34..2387aa178c 100644 --- a/pytest_plugins/filler/eip_checklist.py +++ b/pytest_plugins/filler/eip_checklist.py @@ -118,7 +118,7 @@ def __str__(self) -> str: status = "❓" else: status = "✅" - tests = ", ".join(sorted(map(resolve_test_link, self.tests))) + tests = ", ".join(sorted(self.tests)) elif self.not_applicable: status = "N/A" tests = self.not_applicable_reason @@ -160,17 +160,6 @@ def resolve_id(item_id: str) -> Set[str]: return covered_ids -def resolve_test_link(test_id: str) -> str: - """Resolve a test ID to a test link.""" - # test_id example: tests/fork/eip1234_some_eip/test_file.py::test_function[test_param1-...] - # Relative path: ../../../../tests/fork/eip1234_some_eip/test_file/test_function/ - pattern = r"(.*)\.py::(\w+)" - match = re.match(pattern, test_id) - if not match: - return test_id - return f"[{test_id}](../../../../{match.group(1)}/{match.group(2)}/)" - - ALL_CHECKLIST_WARNINGS: Dict[str, Type["ChecklistWarning"]] = {} @@ -222,8 +211,7 @@ def from_items(cls, all_items: Dict[str, EIPItem]) -> ChecklistWarning | None: for item in conflicting_items: details.append( f"| {item.id} | {item.description} | " - + f"{item.not_applicable_reason} | " - + f"{', '.join(sorted(map(resolve_test_link, item.tests)))} |" + + f"{item.not_applicable_reason} | {', '.join(sorted(item.tests))} |" ) return cls(details=details) @@ -245,6 +233,7 @@ def add_covered_test(self, checklist_id: str, node_id: str) -> None: def covered_items(self) -> int: """Return the number of covered items.""" return sum(1 for item in self.items.values() if item.covered and not item.not_applicable) + return sum(1 for item in self.items.values() if item.covered and not item.not_applicable) @property def total_items(self) -> int: From 73aec73251eaeefd1417937bc6ac1f24574a4bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Mon, 15 Sep 2025 21:01:26 +0800 Subject: [PATCH 003/102] refactor(tests): update checklist item for eip7939 (#2097) * feat: update checklist item for clz * feat: add new checklist items * refactor: update checklist items for eip7939 * refactor: update checklist not applicable itemss * feat(checklist): Add checklist warnings * feat(checklist): ad coverage and reentry notes to eip7939 checklist * fix linting issue * refactor(checklist): remove duplicate ban check items --------- Co-authored-by: Mario Vega --- .../eip_checklist_external_coverage.txt | 2 ++ .../eip_checklist_not_applicable.txt | 29 +++++++++++++++++++ .../test_count_leading_zeros.py | 17 +++++++++++ 3 files changed, 48 insertions(+) create mode 100644 osaka/eip7939_count_leading_zeros/eip_checklist_external_coverage.txt create mode 100644 osaka/eip7939_count_leading_zeros/eip_checklist_not_applicable.txt diff --git a/osaka/eip7939_count_leading_zeros/eip_checklist_external_coverage.txt b/osaka/eip7939_count_leading_zeros/eip_checklist_external_coverage.txt new file mode 100644 index 0000000000..f0b87011f0 --- /dev/null +++ b/osaka/eip7939_count_leading_zeros/eip_checklist_external_coverage.txt @@ -0,0 +1,2 @@ +general/code_coverage/eels = Please check https://app.codecov.io/gh/ethereum/execution-specs/pull/1388/blob/src/ethereum/osaka/vm/instructions/bitwise.py#L243 for relevant test coverage +general/code_coverage/test_coverage = Please run the test with `--cov` flag for final coverage \ No newline at end of file diff --git a/osaka/eip7939_count_leading_zeros/eip_checklist_not_applicable.txt b/osaka/eip7939_count_leading_zeros/eip_checklist_not_applicable.txt new file mode 100644 index 0000000000..f8a1d0e744 --- /dev/null +++ b/osaka/eip7939_count_leading_zeros/eip_checklist_not_applicable.txt @@ -0,0 +1,29 @@ +system_contract = EIP does not introduce a new system contract +precompile = EIP does not introduce a new precompile +removed_precompile = EIP does not remove a precompile +transaction_type = EIP does not introduce a new transaction type +block_header_field = EIP does not add any new block header fields +block_body_field = EIP does not add any new block body fields +gas_cost_changes = EIP does not modify existing gas costs, only introduces new opcode with fixed cost +gas_refunds_changes = EIP does not introduce any gas refund changes +blob_count_changes = EIP does not introduce any blob count changes +execution_layer_request = EIP does not introduce an execution layer request +new_transaction_validity_constraint = EIP does not introduce a new transaction validity constraint +modified_transaction_validity_constraint = EIP does not introduce a modified transaction validity constraint +opcode/test/mem_exp = CLZ does not read/write to memory component +opcode/test/stack_overflow = CLZ takes one args and pushes one args to stack, not increasing stack element, hence no overflow issue +opcode/test/stack_complex_operations/data_portion_variables = there is no data portion for CLZ +opcode/test/execution_context/delegatecall/code = CLZ does not modify code +opcode/test/execution_context/tx_context = CLZ does not change behavior depending on transaction property +opcode/test/execution_context/block_context = CLZ does not change behavior depending on block property +opcode/test/execution_context/initcode/reentry = CLZ is not a stateful opcode +opcode/test/gas_usage/memory_expansion = no memory read/write for CLZ +opcode/test/gas_usage/out_of_gas_memory = no memory read/write for CLZ +opcode/test/gas_usage/order_of_operations = the order will not affect result of CLZ +opcode/test/return_data = although we could verify the return buffer is not affected, but it is more like testing memory write operation, as CLZ does not write to memory directly +opcode/test/terminating = not such opcode +opcode/test/terminating/rollback = CLZ is not a terminating opcode, so no rollback behavior +opcode/test/out_of_bounds = takes one element from stack, no specific boundary +opcode/test/exceptional_abort = underflow is the only exceptional abort scenario and it is included already +opcode/test/data_portion = no data portion +opcode/test/contract_creation = no contract created in execution \ No newline at end of file diff --git a/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py b/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py index 4f9c0efa52..6ade4a1eda 100644 --- a/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py +++ b/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py @@ -6,6 +6,7 @@ import pytest from ethereum_test_base_types import Storage +from ethereum_test_checklists import EIPChecklist from ethereum_test_forks import Fork from ethereum_test_tools import ( Account, @@ -144,6 +145,9 @@ def test_clz_gas_cost(state_test: StateTestFiller, pre: Alloc, fork: Fork): state_test(pre=pre, post=post, tx=tx) +@EIPChecklist.Opcode.Test.GasUsage.Normal() +@EIPChecklist.Opcode.Test.GasUsage.OutOfGasExecution() +@EIPChecklist.Opcode.Test.GasUsage.ExtraGas() @pytest.mark.valid_from("Osaka") @pytest.mark.parametrize("bits", [0, 64, 128, 255]) @pytest.mark.parametrize("gas_cost_delta", [-2, -1, 0, 1, 2]) @@ -178,6 +182,8 @@ def test_clz_gas_cost_boundary( state_test(pre=pre, post=post, tx=tx) +@EIPChecklist.Opcode.Test.StackUnderflow() +@EIPChecklist.Opcode.Test.StackComplexOperations.StackHeights.Zero() @pytest.mark.valid_from("Osaka") def test_clz_stack_underflow(state_test: StateTestFiller, pre: Alloc): """Test CLZ opcode with empty stack (should revert due to stack underflow).""" @@ -202,6 +208,8 @@ def test_clz_stack_underflow(state_test: StateTestFiller, pre: Alloc): state_test(pre=pre, post=post, tx=tx) +@EIPChecklist.Opcode.Test.StackComplexOperations.StackHeights.Odd() +@EIPChecklist.Opcode.Test.StackComplexOperations.StackHeights.Even() @pytest.mark.valid_from("Osaka") def test_clz_stack_not_overflow(state_test: StateTestFiller, pre: Alloc, fork: Fork): """Test CLZ opcode never causes stack overflow.""" @@ -260,6 +268,8 @@ def test_clz_push_operation_same_value(state_test: StateTestFiller, pre: Alloc): state_test(pre=pre, post=post, tx=tx) +@EIPChecklist.Opcode.Test.ForkTransition.Invalid() +@EIPChecklist.Opcode.Test.ForkTransition.At() @pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True) def test_clz_fork_transition(blockchain_test: BlockchainTestFiller, pre: Alloc): """Test CLZ opcode behavior at fork transition.""" @@ -386,6 +396,7 @@ def test_clz_jump_operation( auth_account_start_balance = 0 +@EIPChecklist.Opcode.Test.ExecutionContext.SetCode() @pytest.mark.valid_from("Osaka") def test_clz_from_set_code( state_test: StateTestFiller, @@ -530,6 +541,7 @@ def test_clz_with_memory_operation(state_test: StateTestFiller, pre: Alloc, bits state_test(pre=pre, post=post, tx=tx) +@EIPChecklist.Opcode.Test.ExecutionContext.Initcode.Behavior.Tx() @pytest.mark.valid_from("Osaka") def test_clz_initcode_context(state_test: StateTestFiller, pre: Alloc): """Test CLZ opcode behavior when creating a contract.""" @@ -559,6 +571,7 @@ def test_clz_initcode_context(state_test: StateTestFiller, pre: Alloc): state_test(pre=pre, post=post, tx=tx) +@EIPChecklist.Opcode.Test.ExecutionContext.Initcode.Behavior.Opcode() @pytest.mark.valid_from("Osaka") @pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2]) def test_clz_initcode_create(state_test: StateTestFiller, pre: Alloc, opcode: Op): @@ -609,6 +622,10 @@ class CallingContext: no_context = 3 # STATICCALL +@EIPChecklist.Opcode.Test.ExecutionContext.Call() +@EIPChecklist.Opcode.Test.ExecutionContext.Delegatecall() +@EIPChecklist.Opcode.Test.ExecutionContext.Callcode() +@EIPChecklist.Opcode.Test.ExecutionContext.Staticcall() @pytest.mark.valid_from("Osaka") @pytest.mark.parametrize( "opcode,context", From df055e5c71f9926cafc19c4986dc5b7b4718d399 Mon Sep 17 00:00:00 2001 From: spencer Date: Mon, 15 Sep 2025 14:14:10 +0100 Subject: [PATCH 004/102] chore(cli): besu blob tx exception mapper update (#2145) --- ethereum_clis/clis/besu.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ethereum_clis/clis/besu.py b/ethereum_clis/clis/besu.py index b30b205757..4ddf8a9f37 100644 --- a/ethereum_clis/clis/besu.py +++ b/ethereum_clis/clis/besu.py @@ -289,10 +289,10 @@ class BesuExceptionMapper(ExceptionMapper): TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM: ( r"transaction invalid Transaction gas limit must be at most \d+" ), - TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED: ( - r"Blob transaction has too many blobs: \d+" - ), TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED: ( - r"Invalid Blob Count: \d+" + r"Blob transaction 0x[0-9a-f]+ exceeds block blob gas limit: \d+ > \d+" + ), + TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED: ( + r"Blob transaction has too many blobs: \d+|Invalid Blob Count: \d+" ), } From f87ee56530c454bd14bd04072c5720e13c4ad8da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Tue, 16 Sep 2025 17:32:56 +0800 Subject: [PATCH 005/102] refactor(tests): add checklist marker for eip7825 (#2107) * chore: add max quotient for gas refund logic * refactor: update the eip checklist items * feat: label eip checklist and add new cases * refactor: update fork transition case * fix typo * refactor: update external coverage * refactor: update ref spec and comment --- ethereum_test_checklists/eip_checklist.pyi | 17 ++++++++++++++++- ethereum_test_forks/base_fork.py | 6 ++++++ ethereum_test_forks/forks/forks.py | 10 ++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/ethereum_test_checklists/eip_checklist.pyi b/ethereum_test_checklists/eip_checklist.pyi index d12d7f8a92..2a0f37d22d 100644 --- a/ethereum_test_checklists/eip_checklist.pyi +++ b/ethereum_test_checklists/eip_checklist.pyi @@ -1,7 +1,7 @@ """ Type stubs for EIP checklist - auto-generated. -DO NOT EDIT MANUALLY - This file is generated by `uv run generate-checklist-stubs` +DO NOT EDIT MANUALLY - This file is generated by `uv run generate_checklist_stubs` """ from typing import Any, Callable, TypeVar, overload @@ -89,6 +89,21 @@ class EIPChecklist: SecondClient: _CallableChecklistItem TestCoverage: _CallableChecklistItem + class ModifiedTransactionValidityConstraint(_CallableChecklistItem): + class Test(_CallableChecklistItem): + class ForkTransition(_CallableChecklistItem): + AcceptedAfterFork: _CallableChecklistItem + AcceptedBeforeFork: _CallableChecklistItem + RejectedAfterFork: _CallableChecklistItem + RejectedBeforeFork: _CallableChecklistItem + + class NewTransactionValidityConstraint(_CallableChecklistItem): + class Test(_CallableChecklistItem): + class ForkTransition(_CallableChecklistItem): + AcceptedAfterFork: _CallableChecklistItem + AcceptedBeforeFork: _CallableChecklistItem + RejectedAfterFork: _CallableChecklistItem + class Opcode(_CallableChecklistItem): class Test(_CallableChecklistItem): ExceptionalAbort: _CallableChecklistItem diff --git a/ethereum_test_forks/base_fork.py b/ethereum_test_forks/base_fork.py index 2ce7a89705..292c893dec 100644 --- a/ethereum_test_forks/base_fork.py +++ b/ethereum_test_forks/base_fork.py @@ -333,6 +333,12 @@ def base_fee_elasticity_multiplier(cls, block_number: int = 0, timestamp: int = """Return the base fee elasticity multiplier at a given fork.""" pass + @classmethod + @abstractmethod + def max_refund_quotient(cls) -> int: + """Return the max refund quotient at a given fork.""" + pass + @classmethod @abstractmethod def transaction_data_floor_cost_calculator( diff --git a/ethereum_test_forks/forks/forks.py b/ethereum_test_forks/forks/forks.py index b032354811..fdf519d246 100644 --- a/ethereum_test_forks/forks/forks.py +++ b/ethereum_test_forks/forks/forks.py @@ -605,6 +605,11 @@ def create_opcodes( (Opcodes.CREATE, EVMCodeType.LEGACY), ] + @classmethod + def max_refund_quotient(cls) -> int: + """Return the max refund quotient at Genesis.""" + return 2 + @classmethod def max_request_type(cls, block_number: int = 0, timestamp: int = 0) -> int: """At genesis, no request type is supported, signaled by -1.""" @@ -913,6 +918,11 @@ def valid_opcodes( """Return list of Opcodes that are valid to work on this fork.""" return [Opcodes.BASEFEE] + super(London, cls).valid_opcodes() + @classmethod + def max_refund_quotient(cls) -> int: + """Return the max refund quotient at London.""" + return 5 + @classmethod def base_fee_max_change_denominator(cls, block_number: int = 0, timestamp: int = 0) -> int: """Return the base fee max change denominator at London.""" From c1bd3e2bc55613373c1a13266696d192909e5e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Tue, 16 Sep 2025 17:32:56 +0800 Subject: [PATCH 006/102] refactor(tests): add checklist marker for eip7825 (#2107) * chore: add max quotient for gas refund logic * refactor: update the eip checklist items * feat: label eip checklist and add new cases * refactor: update fork transition case * fix typo * refactor: update external coverage * refactor: update ref spec and comment --- .../eip_checklist_external_coverage.txt | 2 + .../eip_checklist_not_applicable.txt | 12 +++ .../eip7825_transaction_gas_limit_cap/spec.py | 2 +- .../test_tx_gas_limit.py | 65 +++++++++++++++- .../test_tx_gas_limit_transition_fork.py | 74 ++++++++++++------- 5 files changed, 125 insertions(+), 30 deletions(-) create mode 100644 osaka/eip7825_transaction_gas_limit_cap/eip_checklist_external_coverage.txt create mode 100644 osaka/eip7825_transaction_gas_limit_cap/eip_checklist_not_applicable.txt diff --git a/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_external_coverage.txt b/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_external_coverage.txt new file mode 100644 index 0000000000..f0b87011f0 --- /dev/null +++ b/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_external_coverage.txt @@ -0,0 +1,2 @@ +general/code_coverage/eels = Please check https://app.codecov.io/gh/ethereum/execution-specs/pull/1388/blob/src/ethereum/osaka/vm/instructions/bitwise.py#L243 for relevant test coverage +general/code_coverage/test_coverage = Please run the test with `--cov` flag for final coverage \ No newline at end of file diff --git a/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_not_applicable.txt b/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_not_applicable.txt new file mode 100644 index 0000000000..8f1d2d066c --- /dev/null +++ b/osaka/eip7825_transaction_gas_limit_cap/eip_checklist_not_applicable.txt @@ -0,0 +1,12 @@ +system_contract = EIP does not introduce a new system contract +opcode = EIP does not introduce a new opcode +precompile = EIP does not introduce a new precompile +removed_precompile = EIP does not remove a precompile +transaction_type = EIP does not introduce a new transaction type +block_header_field = EIP does not add any new block header fields +block_body_field = EIP does not add any new block body fields +gas_cost_changes = EIP does not modify existing gas costs, only introduces new opcode with fixed cost +gas_refunds_changes = EIP does not introduce any gas refund changes +blob_count_changes = EIP does not introduce any blob count changes +execution_layer_request = EIP does not introduce an execution layer request +new_transaction_validity_constraint = EIP does not introduce a new transaction validity constraint diff --git a/osaka/eip7825_transaction_gas_limit_cap/spec.py b/osaka/eip7825_transaction_gas_limit_cap/spec.py index 05f459f1bc..58a93203a4 100644 --- a/osaka/eip7825_transaction_gas_limit_cap/spec.py +++ b/osaka/eip7825_transaction_gas_limit_cap/spec.py @@ -12,7 +12,7 @@ class ReferenceSpec: # EIP-7825 reference specification -ref_spec_7825 = ReferenceSpec("EIPS/eip-7825.md", "47cbfed315988c0bd4d10002c110ae402504cd94") +ref_spec_7825 = ReferenceSpec("EIPS/eip-7825.md", "1ed95cbac750539c2aac67c8cbbcc2d77974231c") @dataclass(frozen=True) diff --git a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py index c20efa7a3a..3c694b3c10 100644 --- a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py +++ b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py @@ -16,6 +16,7 @@ AuthorizationTuple, Block, BlockchainTestFiller, + Bytecode, Environment, Hash, StateTestFiller, @@ -53,7 +54,7 @@ def tx_gas_limit_cap_tests(fork: Fork) -> List[ParameterSet]: id="tx_gas_limit_cap_exceeds_maximum", marks=pytest.mark.exception_test, ), - pytest.param(fork_tx_gas_limit_cap, None, id="tx_gas_limit_cap_none"), + pytest.param(fork_tx_gas_limit_cap, None, id="tx_gas_limit_cap_over"), ] @@ -201,6 +202,68 @@ def test_tx_gas_larger_than_block_gas_limit( blockchain_test(pre=pre, post={}, blocks=[block]) +@pytest.mark.parametrize( + "exceed_gas_refund_limit", + [ + pytest.param(True), + pytest.param(False), + ], +) +@pytest.mark.valid_from("Osaka") +def test_maximum_gas_refund( + state_test: StateTestFiller, + pre: Alloc, + fork: Fork, + exceed_gas_refund_limit: bool, +): + """Test the maximum gas refund behavior according to EIP-3529.""" + gas_costs = fork.gas_costs() + tx_gas_limit_cap = fork.transaction_gas_limit_cap() + assert tx_gas_limit_cap is not None, "Fork does not have a transaction gas limit cap" + max_refund_quotient = fork.max_refund_quotient() + + storage = Storage() + + # Base Operation: SSTORE(slot, 0) + iteration_cost = gas_costs.G_STORAGE_RESET + gas_costs.G_BASE + gas_costs.G_VERY_LOW + gas_refund = gas_costs.R_STORAGE_CLEAR + + # EIP-3529: Reduction in refunds + storage_count = tx_gas_limit_cap // iteration_cost + gas_used = storage_count * iteration_cost + + maximum_gas_refund = gas_used // max_refund_quotient + gas_refund_count = maximum_gas_refund // gas_refund + + # Base case: operations that fit within the refund limit + iteration_count = min(storage_count, gas_refund_count + int(exceed_gas_refund_limit)) + + assert iteration_cost * iteration_count <= tx_gas_limit_cap, ( + "Iteration cost exceeds tx gas limit cap" + ) + + opcode = sum( + (Op.SSTORE(storage.store_next(0), Op.PUSH0) for _ in range(iteration_count)), + Bytecode(), + ) + assert len(opcode) <= fork.max_code_size(), "code size exceeds max code size" + + contract = pre.deploy_contract( + code=opcode, + storage={Hash(i): Hash(1) for i in range(iteration_count)}, + ) + + tx = Transaction( + to=contract, + sender=pre.fund_eoa(), + gas_limit=tx_gas_limit_cap, + ) + + post = {contract: Account(storage=storage)} + + state_test(pre=pre, post=post, tx=tx) + + @pytest.fixture def total_cost_floor_per_token(fork: Fork): """Total cost floor per token.""" diff --git a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py index 6519014695..9d7bd449bd 100644 --- a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py +++ b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py @@ -5,6 +5,7 @@ import pytest +from ethereum_test_checklists import EIPChecklist from ethereum_test_forks import Fork from ethereum_test_tools import ( Account, @@ -22,12 +23,23 @@ REFERENCE_SPEC_VERSION = ref_spec_7825.version +@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.AcceptedBeforeFork() +@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.RejectedBeforeFork() +@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.AcceptedAfterFork() +@EIPChecklist.ModifiedTransactionValidityConstraint.Test.ForkTransition.RejectedAfterFork() @pytest.mark.valid_at_transition_to("Osaka", subsequent_forks=True) -@pytest.mark.exception_test +@pytest.mark.parametrize( + "transaction_at_cap", + [ + pytest.param(True, id="at_cap"), + pytest.param(False, marks=pytest.mark.exception_test, id="above_cap"), + ], +) def test_transaction_gas_limit_cap_at_transition( blockchain_test: BlockchainTestFiller, pre: Alloc, fork: Fork, + transaction_at_cap: bool, ): """ Test transaction gas limit cap behavior at the Osaka transition. @@ -35,60 +47,61 @@ def test_transaction_gas_limit_cap_at_transition( Before timestamp 15000: No gas limit cap (transactions with gas > 2^24 are valid) At/after timestamp 15000: Gas limit cap of 2^24 is enforced """ - sender = pre.fund_eoa() contract_address = pre.deploy_contract( - code=Op.SSTORE(0, Op.ADD(Op.SLOAD(0), 1)) + Op.STOP, + code=Op.SSTORE(Op.TIMESTAMP, Op.ADD(Op.SLOAD(Op.TIMESTAMP), 1)) + Op.STOP, ) - pre_cap = fork.transaction_gas_limit_cap() - post_cap = fork.transaction_gas_limit_cap(timestamp=15_000) - assert post_cap is not None, "Post cap should not be None" + # Get the gas limit cap at fork activation + tx_gas_cap = fork.transaction_gas_limit_cap(timestamp=15_000) + assert tx_gas_cap is not None, "Gas limit cap should not be None after fork activation" - pre_cap = pre_cap if pre_cap else post_cap + 1 + # Test boundary: cap + 1 should fail after fork activation + above_cap = tx_gas_cap + 1 - assert post_cap <= pre_cap, ( - "Post cap should be less than or equal to pre cap, test needs update" + # Before fork activation: both cap and above_cap transactions should succeed + at_cap_tx_before_fork = Transaction( + ty=0, # Legacy transaction + to=contract_address, + gas_limit=tx_gas_cap, + sender=pre.fund_eoa(), ) - # Transaction with gas limit above the cap before transition - high_gas_tx = Transaction( + above_cap_tx_before_fork = Transaction( ty=0, # Legacy transaction to=contract_address, - gas_limit=pre_cap, - data=b"", - value=0, - sender=sender, + gas_limit=above_cap, + sender=pre.fund_eoa(), ) post_cap_tx_error = TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM - # Transaction with gas limit at the cap - cap_gas_tx = Transaction( + # After fork activation: test at cap vs above cap + transition_tx = Transaction( ty=0, # Legacy transaction to=contract_address, - gas_limit=post_cap + 1, - data=b"", - value=0, - sender=sender, - error=post_cap_tx_error, + gas_limit=tx_gas_cap if transaction_at_cap else above_cap, + sender=pre.fund_eoa(), + error=None if transaction_at_cap else post_cap_tx_error, ) blocks = [] - # Before transition (timestamp < 15000): high gas transaction should succeed + # Before transition (timestamp < 15000): both cap and above_cap transactions should succeed blocks.append( Block( timestamp=14_999, - txs=[high_gas_tx], + txs=[above_cap_tx_before_fork, at_cap_tx_before_fork], ) ) - # At transition (timestamp = 15000): high gas transaction should fail + # At transition (timestamp = 15000): + # - transaction at cap should succeed + # - transaction above cap (cap + 1) should fail blocks.append( Block( timestamp=15_000, - txs=[cap_gas_tx], # Only transaction at the cap succeeds - exception=post_cap_tx_error, + txs=[transition_tx], + exception=post_cap_tx_error if not transaction_at_cap else None, ) ) @@ -96,7 +109,12 @@ def test_transaction_gas_limit_cap_at_transition( post = { contract_address: Account( storage={ - 0: 1, # Set by first transaction (before transition) + # Set by both transactions in first block (before transition): + 14_999: 2, + # After transition: + # - Set by transaction at cap (should succeed) + # - Not set by transaction above cap (should fail) + 15_000: 1 if transaction_at_cap else 0, } ) } From 623b3f62b9ebfe1c6d89671622fe9c1d547f1e31 Mon Sep 17 00:00:00 2001 From: spencer Date: Tue, 16 Sep 2025 11:05:58 +0100 Subject: [PATCH 007/102] chore(consume): update sync timeout for consume sync. (#2158) --- .../consume/simulators/simulator_logic/test_via_sync.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py index adbbbb0f8a..c3ab8e202e 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py @@ -442,7 +442,7 @@ def test_blockchain_via_sync( last_forkchoice_time = time.time() forkchoice_interval = 2.0 # Send forkchoice updates every 2 seconds - while time.time() - sync_start_time < 10: # 10 second timeout + while time.time() - sync_start_time < 60: # 60 second timeout # Send periodic forkchoice updates to keep sync alive if time.time() - last_forkchoice_time >= forkchoice_interval: try: From 0782b6e91e7a0a89742e2cf93b55f7dc05b2deea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Tue, 16 Sep 2025 19:59:58 +0800 Subject: [PATCH 008/102] refactor(tests): add checklist marker for eip7883 (#2098) * refactor: add checklist marker for eip7883 * doc: update eip checklist template * refactor: update modexp test and add checklist marker * chore: update checklist rules * refactor: enhance modexp checklist descriptions for clarity * refactor: update coverage table and check gas usage * fix rebase issue * chore: remove outdated entry from modexp checklist * refactor: expand modexp checklist with external coverage entries * refactor: adjust gas usage assertion for only Osaka fork * refactor: overwrite id and add comment --- osaka/eip7883_modexp_gas_increase/conftest.py | 8 +- .../eip_checklist_external_coverage.txt | 3 + .../eip_checklist_not_applicable.txt | 24 ++ .../test_modexp_thresholds.py | 323 ++++++++++++++---- .../test_modexp_thresholds_transition.py | 18 +- 5 files changed, 304 insertions(+), 72 deletions(-) create mode 100644 osaka/eip7883_modexp_gas_increase/eip_checklist_external_coverage.txt create mode 100644 osaka/eip7883_modexp_gas_increase/eip_checklist_not_applicable.txt diff --git a/osaka/eip7883_modexp_gas_increase/conftest.py b/osaka/eip7883_modexp_gas_increase/conftest.py index 2d75c80d99..f69d6b3eb3 100644 --- a/osaka/eip7883_modexp_gas_increase/conftest.py +++ b/osaka/eip7883_modexp_gas_increase/conftest.py @@ -119,8 +119,14 @@ def gas_measure_contract( assert call_opcode in [Op.CALL, Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL] value = [0] if call_opcode in [Op.CALL, Op.CALLCODE] else [] + gas_used = ( + precompile_gas + precompile_gas_modifier + if precompile_gas_modifier != float("inf") + else Environment().gas_limit + ) + call_code = call_opcode( - precompile_gas + precompile_gas_modifier, + gas_used, Spec.MODEXP_ADDRESS, *value, 0, diff --git a/osaka/eip7883_modexp_gas_increase/eip_checklist_external_coverage.txt b/osaka/eip7883_modexp_gas_increase/eip_checklist_external_coverage.txt new file mode 100644 index 0000000000..b2d3db4ab8 --- /dev/null +++ b/osaka/eip7883_modexp_gas_increase/eip_checklist_external_coverage.txt @@ -0,0 +1,3 @@ +precompile/test/call_contexts/set_code = Covered in EIP-7702 cases +precompile/test/inputs/max_values = Covered in osaka/eip7823_modexp_upper_bounds +precompile/test/out_of_bounds/max = Covered in osaka/eip7823_modexp_upper_bounds \ No newline at end of file diff --git a/osaka/eip7883_modexp_gas_increase/eip_checklist_not_applicable.txt b/osaka/eip7883_modexp_gas_increase/eip_checklist_not_applicable.txt new file mode 100644 index 0000000000..63a41d5689 --- /dev/null +++ b/osaka/eip7883_modexp_gas_increase/eip_checklist_not_applicable.txt @@ -0,0 +1,24 @@ +precompile/test/value_transfer/fee/under = No value is required +precompile/test/value_transfer/fee/exact = No value is required +precompile/test/value_transfer/fee/over = No value is required +precompile/test/input_lengths/static/correct = The Modexp input length is not static +precompile/test/input_lengths/static/too_short = The Modexp input length is not static +precompile/test/input_lengths/static/too_long = The Modexp input length is not static +precompile/test/input_lengths/dynamic/too_short = there would be no padding for precompile +precompile/test/gas_usage/constant/oog = The Modexp gas cost is dynamic +precompile/test/gas_usage/constant/exact = The Modexp gas cost is dynamic +precompile/test/fork_transition/before/invalid_input = Modexp is not new precompile, it is still valid befork fork activation +precompile/test/fork_transition/before/zero_gas = Modexp is not new precompile, it is still valid befork fork activation +precompile/test/fork_transition/before/cold = Modexp is not new precompile, it is still valid befork fork activation +gas_cost_changes/test/out_of_gas = No Out-of-gas scenario in Modexp +system_contract = EIP does not include a new system contract +opcode = EIP does not introduce a new opcode +removed_precompile = EIP does not remove a precompile +transaction_type = EIP does not introduce a new transaction type +block_header_field = EIP does not add any new block header fields +gas_refunds_changes = EIP does not introduce any gas refund changes +blob_count_changes = EIP does not introduce any blob count changes +execution_layer_request = EIP does not introduce an execution layer request +new_transaction_validity_constraint = EIP does not introduce a new transaction validity constraint +modified_transaction_validity_constraint = EIP does not introduce a modified transaction validity constraint +block_body_field = EIP does not add any new block body fields diff --git a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py index 4b12e98c51..b0bf716667 100644 --- a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py +++ b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py @@ -8,8 +8,17 @@ import pytest from ethereum_test_checklists import EIPChecklist -from ethereum_test_tools import Alloc, StateTestFiller, Transaction +from ethereum_test_forks import Fork, Osaka +from ethereum_test_tools import ( + Alloc, + Environment, + StateTestFiller, + Storage, + Transaction, + keccak256, +) from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_types.helpers import compute_create_address from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput from .helpers import vectors_from_file @@ -24,6 +33,9 @@ vectors_from_file("vectors.json"), ids=lambda v: v.name, ) +@EIPChecklist.Precompile.Test.Inputs.Valid() +@EIPChecklist.Precompile.Test.InputLengths.Dynamic.Valid() +@EIPChecklist.GasCostChanges.Test.GasUpdatesMeasurement() @pytest.mark.valid_from("Berlin") def test_vectors_from_eip( state_test: StateTestFiller, @@ -44,6 +56,7 @@ def test_vectors_from_eip( vectors_from_file("legacy.json"), ids=lambda v: v.name, ) +@EIPChecklist.Precompile.Test.Inputs.Invalid() @pytest.mark.valid_from("Berlin") def test_vectors_from_legacy_tests( state_test: StateTestFiller, @@ -83,6 +96,7 @@ def test_vectors_from_legacy_tests( [ pytest.param(bytes(), False), ], + ids=[""], ) @EIPChecklist.Precompile.Test.Inputs.AllZeros @pytest.mark.valid_from("Berlin") @@ -145,6 +159,10 @@ def test_modexp_invalid_inputs( ), ], ) +@EIPChecklist.Precompile.Test.OutOfBounds.MaxPlusOne() +@EIPChecklist.Precompile.Test.Inputs.Invalid.Corrupted() +@EIPChecklist.Precompile.Test.Inputs.Invalid() +@EIPChecklist.Precompile.Test.InputLengths.Dynamic.TooLong() @pytest.mark.valid_from("Osaka") def test_modexp_boundary_inputs( state_test: StateTestFiller, @@ -175,10 +193,10 @@ def test_modexp_boundary_inputs( pytest.param(Spec.modexp_input, Spec.modexp_expected, id="base-heavy"), ], ) -@EIPChecklist.Precompile.Test.CallContexts.Static -@EIPChecklist.Precompile.Test.CallContexts.Delegate -@EIPChecklist.Precompile.Test.CallContexts.Callcode -@EIPChecklist.Precompile.Test.CallContexts.Normal +@EIPChecklist.Precompile.Test.CallContexts.Static() +@EIPChecklist.Precompile.Test.CallContexts.Delegate() +@EIPChecklist.Precompile.Test.CallContexts.Callcode() +@EIPChecklist.Precompile.Test.CallContexts.Normal() @pytest.mark.valid_from("Berlin") def test_modexp_call_operations( state_test: StateTestFiller, @@ -218,11 +236,17 @@ def test_modexp_call_operations( False, id="insufficient_gas", ), + pytest.param( + Spec.modexp_input, + Spec.modexp_expected, + float("inf"), + True, + id="excessive_gas", + ), ], ) -@EIPChecklist.Precompile.Test.ValueTransfer.Fee.Over -@EIPChecklist.Precompile.Test.ValueTransfer.Fee.Exact -@EIPChecklist.Precompile.Test.ValueTransfer.Fee.Under +@EIPChecklist.Precompile.Test.GasUsage.Dynamic() +@EIPChecklist.Precompile.Test.ExcessiveGasUsage() @pytest.mark.valid_from("Berlin") def test_modexp_gas_usage_contract_wrapper( state_test: StateTestFiller, @@ -235,12 +259,13 @@ def test_modexp_gas_usage_contract_wrapper( @pytest.mark.parametrize( - "modexp_input,modexp_expected,precompile_gas_modifier,call_succeeds", + "modexp_input,modexp_expected,precompile_gas_modifier,call_values,call_succeeds", [ pytest.param( Spec.modexp_input, Spec.modexp_expected, 1, + 0, True, id="extra_gas", ), @@ -248,18 +273,30 @@ def test_modexp_gas_usage_contract_wrapper( Spec.modexp_input, Spec.modexp_expected, 0, + 0, True, id="exact_gas", ), + pytest.param( + Spec.modexp_input, + Spec.modexp_expected, + 0, + 1000, + True, + id="extra_value", + ), pytest.param( Spec.modexp_input, Spec.modexp_error, -1, + 0, False, id="insufficient_gas", ), ], ) +@EIPChecklist.Precompile.Test.CallContexts.TxEntry() +@EIPChecklist.Precompile.Test.ValueTransfer.NoFee() @pytest.mark.valid_from("Berlin") def test_modexp_used_in_transaction_entry_points( state_test: StateTestFiller, @@ -267,6 +304,7 @@ def test_modexp_used_in_transaction_entry_points( tx: Transaction, modexp_input: bytes, tx_gas_limit: int, + call_values: int, ): """Test ModExp using in transaction entry points with different precompile gas modifiers.""" tx = Transaction( @@ -274,10 +312,149 @@ def test_modexp_used_in_transaction_entry_points( sender=pre.fund_eoa(), data=bytes(modexp_input), gas_limit=tx_gas_limit, + value=call_values, ) state_test(pre=pre, tx=tx, post={}) +@pytest.mark.parametrize( + "modexp_input,modexp_expected", + [ + pytest.param( + Spec.modexp_input, + Spec.modexp_expected, + id="valid_input", + ) + ], +) +@EIPChecklist.Precompile.Test.CallContexts.Initcode() +@pytest.mark.valid_from("Berlin") +def test_contract_creation_transaction( + state_test: StateTestFiller, + pre: Alloc, + post: dict, + tx: Transaction, + modexp_input: bytes, + modexp_expected: bytes, +): + """Test the contract creation for the ModExp precompile.""" + sender = pre.fund_eoa() + + storage = Storage() + + contract_address = compute_create_address(address=sender, nonce=0) + contract_bytecode = ( + Op.CODECOPY(0, Op.SUB(Op.CODESIZE, len(bytes(modexp_input))), len(bytes(modexp_input))) + + Op.CALL( + gas=1_000_000, + address=Spec.MODEXP_ADDRESS, + value=0, + args_offset=0, + args_size=len(bytes(modexp_input)), + ret_offset=0, + ret_size=len(bytes(modexp_expected)), + ) + + Op.SSTORE(storage.store_next(True), Op.DUP1()) + + Op.SSTORE( + storage.store_next(keccak256(bytes(modexp_expected))), Op.SHA3(0, Op.RETURNDATASIZE()) + ) + + Op.SSTORE(storage.store_next(len(bytes(modexp_expected))), Op.RETURNDATASIZE()) + + Op.STOP + ) + + tx = Transaction( + sender=sender, + gas_limit=1_000_000, + to=None, + value=0, + data=contract_bytecode + bytes(modexp_input), + ) + + post = { + contract_address: { + "storage": storage, + } + } + + state_test(env=Environment(), pre=pre, post=post, tx=tx) + + +@pytest.mark.parametrize( + "modexp_input,modexp_expected", + [ + pytest.param( + Spec.modexp_input, + Spec.modexp_expected, + id="valid_input", + ), + ], +) +@pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2]) +@EIPChecklist.Precompile.Test.CallContexts.Initcode.CREATE() +@pytest.mark.valid_from("Berlin") +def test_contract_initcode( + state_test: StateTestFiller, + pre: Alloc, + post: dict, + tx: Transaction, + modexp_input: bytes, + modexp_expected: bytes, + opcode: Op, +): + """Test ModExp behavior from contract creation.""" + sender = pre.fund_eoa() + + storage = Storage() + + call_modexp_bytecode = ( + Op.CODECOPY(0, Op.SUB(Op.CODESIZE, len(bytes(modexp_input))), len(bytes(modexp_input))) + + Op.CALL( + gas=200_000, + address=Spec.MODEXP_ADDRESS, + value=0, + args_offset=0, + args_size=len(bytes(modexp_input)), + ret_offset=0, + ret_size=len(bytes(modexp_expected)), + ) + + Op.SSTORE(storage.store_next(True), Op.DUP1()) + + Op.SSTORE( + storage.store_next(keccak256(bytes(modexp_expected))), Op.SHA3(0, Op.RETURNDATASIZE()) + ) + + Op.SSTORE(storage.store_next(len(bytes(modexp_expected))), Op.RETURNDATASIZE()) + + Op.STOP + ) + full_initcode = call_modexp_bytecode + bytes(modexp_input) + total_bytecode_length = len(call_modexp_bytecode) + len(bytes(modexp_input)) + + create_contract = ( + Op.CALLDATACOPY(offset=0, size=total_bytecode_length) + + opcode(offset=0, size=total_bytecode_length) + + Op.STOP + ) + + factory_contract_address = pre.deploy_contract(code=create_contract) + contract_address = compute_create_address( + address=factory_contract_address, nonce=1, initcode=full_initcode, opcode=opcode + ) + + tx = Transaction( + sender=sender, + gas_limit=200_000, + to=factory_contract_address, + value=0, + data=call_modexp_bytecode + bytes(modexp_input), + ) + + post = { + contract_address: { + "storage": storage, + } + } + + state_test(env=Environment(), pre=pre, post=post, tx=tx) + + def create_modexp_variable_gas_test_cases(): """ Create test cases for ModExp variable gas cost testing. @@ -286,79 +463,79 @@ def create_modexp_variable_gas_test_cases(): List of pytest.param objects for the test cases """ - # Test case definitions: (base, exponent, modulus, expected_result, test_id) + # Test case definitions: (base, exponent, modulus, expected_result, gas_usage, test_id) test_cases = [ - ("", "", "", "", "Z0"), - ("01" * 32, "00" * 32, "", "", "Z1"), - ("01" * 1024, "00" * 32, "", "", "Z2"), - ("01" * 32, "00" * 1024, "", "", "Z3"), - ("01" * 32, "00" * 1023 + "01", "", "", "Z4"), - ("", "", "01" * 32, "00" * 31 + "01", "Z5"), - ("", "01" * 32, "01" * 32, "00" * 32, "Z6"), - ("", "00" * 31 + "01", "01" * 1024, "00" * 1024, "Z7"), - ("01" * 16, "00" * 16, "02" * 16, "00" * 15 + "01", "S0"), - ("01" * 16, "00" * 15 + "03", "02" * 16, "01" * 16, "S1"), - ("01" * 32, "FF" * 32, "02" * 32, "01" * 32, "S2"), - ("01" * 16, "00" * 40, "02" * 16, "00" * 15 + "01", "S3"), - ("01" * 16, "00" * 39 + "01", "02" * 16, "01" * 16, "S4"), - ("01" * 24, "00", "02" * 8, "00" * 7 + "01", "S5"), - ("01" * 8, "01", "02" * 24, "00" * 16 + "01" * 8, "S6"), - ("01" * 40, "00" * 16, "02" * 40, "00" * 39 + "01", "L0"), - ("01" * 40, "FF" * 32, "02" * 40, "01" * 40, "L1"), - ("01" * 40, "00" * 40, "02" * 40, "00" * 39 + "01", "L2"), - ("01" * 40, "00" * 39 + "01", "02" * 40, "01" * 40, "L3"), - ("01" * 48, "01", "02" * 16, "01" * 16, "L4"), - ("01" * 16, "00" * 40, "02" * 48, "00" * 47 + "01", "L5"), + ("", "", "", "", 500, "Z0"), + ("01" * 32, "00" * 32, "", "", 500, "Z1"), + ("01" * 1024, "00" * 32, "", "", 32768, "Z2"), + ("01" * 32, "00" * 1024, "", "", 253952, "Z3"), + ("01" * 32, "00" * 1023 + "01", "", "", 253952, "Z4"), + ("", "", "01" * 32, "00" * 31 + "01", 500, "Z5"), + ("", "01" * 32, "01" * 32, "00" * 32, 3968, "Z6"), + ("", "00" * 31 + "01", "01" * 1024, "00" * 1024, 32768, "Z7"), + ("01" * 16, "00" * 16, "02" * 16, "00" * 15 + "01", 500, "S0"), + ("01" * 16, "00" * 15 + "03", "02" * 16, "01" * 16, 500, "S1"), + ("01" * 32, "FF" * 32, "02" * 32, "01" * 32, 4080, "S2"), + ("01" * 16, "00" * 40, "02" * 16, "00" * 15 + "01", 2048, "S3"), + ("01" * 16, "00" * 39 + "01", "02" * 16, "01" * 16, 2048, "S4"), + ("01" * 24, "00", "02" * 8, "00" * 7 + "01", 500, "S5"), + ("01" * 8, "01", "02" * 24, "00" * 16 + "01" * 8, 500, "S6"), + ("01" * 40, "00" * 16, "02" * 40, "00" * 39 + "01", 500, "L0"), + ("01" * 40, "FF" * 32, "02" * 40, "01" * 40, 12750, "L1"), + ("01" * 40, "00" * 40, "02" * 40, "00" * 39 + "01", 6400, "L2"), + ("01" * 40, "00" * 39 + "01", "02" * 40, "01" * 40, 6400, "L3"), + ("01" * 48, "01", "02" * 16, "01" * 16, 500, "L4"), + ("01" * 16, "00" * 40, "02" * 48, "00" * 47 + "01", 9216, "L5"), # Critical 32-byte boundary cases - ("01" * 31, "01", "02" * 33, "00" * 2 + "01" * 31, "B1"), - ("01" * 33, "01", "02" * 31, "00" * 29 + "01" * 2, "B2"), - ("01" * 33, "01", "02" * 33, "01" * 33, "B4"), + ("01" * 31, "01", "02" * 33, "00" * 2 + "01" * 31, 500, "B1"), + ("01" * 33, "01", "02" * 31, "00" * 29 + "01" * 2, 500, "B2"), + ("01" * 33, "01", "02" * 33, "01" * 33, 500, "B4"), # Zero value edge cases - ("00" * 32, "00" * 32, "01" * 32, "00" * 31 + "01", "Z8"), - ("01" * 32, "00" * 32, "00" * 32, "00" * 32, "Z9"), - ("00" * 32, "01" * 32, "02" * 32, "00" * 32, "Z10"), - ("00" * 32, "00" * 33, "01" * 32, "00" * 31 + "01", "Z11"), - ("00" * 32, "00" * 1024, "01" * 32, "00" * 31 + "01", "Z12"), - ("00" * 1024, "00" * 32, "01" * 32, "00" * 31 + "01", "Z13"), - ("01" * 32, "00" * 1024, "00" * 32, "00" * 32, "Z14"), - ("01" * 32, "00" * 31 + "01", "00" * 1024, "00" * 1024, "Z15"), + ("00" * 32, "00" * 32, "01" * 32, "00" * 31 + "01", 500, "Z8"), + ("01" * 32, "00" * 32, "00" * 32, "00" * 32, 500, "Z9"), + ("00" * 32, "01" * 32, "02" * 32, "00" * 32, 3968, "Z10"), + ("00" * 32, "00" * 33, "01" * 32, "00" * 31 + "01", 500, "Z11"), + ("00" * 32, "00" * 1024, "01" * 32, "00" * 31 + "01", 253952, "Z12"), + ("00" * 1024, "00" * 32, "01" * 32, "00" * 31 + "01", 32768, "Z13"), + ("01" * 32, "00" * 1024, "00" * 32, "00" * 32, 253952, "Z14"), + ("01" * 32, "00" * 31 + "01", "00" * 1024, "00" * 1024, 32768, "Z15"), # Maximum value stress tests - ("FF" * 64, "FF" * 64, "FF" * 64, "00" * 64, "M1"), - ("FF" * 32, "01", "FF" * 32, "00" * 32, "M2"), - ("01", "FF" * 64, "FF" * 64, "00" * 63 + "01", "M3"), + ("FF" * 64, "FF" * 64, "FF" * 64, "00" * 64, 98176, "M1"), + ("FF" * 32, "01", "FF" * 32, "00" * 32, 500, "M2"), + ("01", "FF" * 64, "FF" * 64, "00" * 63 + "01", 98176, "M3"), # Tiny maximum values - ("FF", "FE", "FD", "47", "T2"), + ("FF", "FE", "FD", "47", 500, "T2"), # Bit pattern cases - ("01" * 32, "80" * 32, "02" * 32, "01" * 32, "P2"), - ("01" * 33, "00" * 31 + "80" + "00", "02" * 33, "01" * 33, "P3"), + ("01" * 32, "80" * 32, "02" * 32, "01" * 32, 4080, "P2"), + ("01" * 33, "00" * 31 + "80" + "00", "02" * 33, "01" * 33, 1150, "P3"), # Asymmetric length cases - ("01", "00" * 64, "02" * 64, "00" * 63 + "01", "A1"), - ("01" * 64, "01", "02", "01", "A2"), - ("01" * 64, "00" * 64, "02", "01", "A3"), + ("01", "00" * 64, "02" * 64, "00" * 63 + "01", 65536, "A1"), + ("01" * 64, "01", "02", "01", 500, "A2"), + ("01" * 64, "00" * 64, "02", "01", 65536, "A3"), # Word boundary case - ("01" * 8, "01", "02" * 8, "0101010101010101", "W2"), + ("01" * 8, "01", "02" * 8, "0101010101010101", 500, "W2"), # Exponent edge cases - ("01" * 16, "00" * 32 + "01", "02" * 16, "01" * 16, "E1"), - ("01" * 16, "80" + "00" * 31, "02" * 16, "01" * 16, "E2"), - ("01" * 16, "00" * 31 + "80", "02" * 16, "01" * 16, "E3"), - ("01" * 16, "7F" + "FF" * 31, "02" * 16, "01" * 16, "E4"), + ("01" * 16, "00" * 32 + "01", "02" * 16, "01" * 16, 500, "E1"), + ("01" * 16, "80" + "00" * 31, "02" * 16, "01" * 16, 4080, "E2"), + ("01" * 16, "00" * 31 + "80", "02" * 16, "01" * 16, 500, "E3"), + ("01" * 16, "7F" + "FF" * 31, "02" * 16, "01" * 16, 4064, "E4"), # Implementation coverage cases # IC1: Bit shift vs multiplication at 33-byte boundary - ("FF" * 33, "01", "FF" * 33, "00" * 33, "IC1"), + ("FF" * 33, "01", "FF" * 33, "00" * 33, 500, "IC1"), # IC3: Ceiling division at 7 bytes - ("01" * 7, "01", "02" * 7, "01" * 7, "IC3"), + ("01" * 7, "01", "02" * 7, "01" * 7, 500, "IC3"), # IC4: Ceiling division at 9 bytes - ("01" * 9, "01", "02" * 9, "01" * 9, "IC4"), + ("01" * 9, "01", "02" * 9, "01" * 9, 500, "IC4"), # IC5: Bit counting in middle of exponent - ("01", "00" * 15 + "80" + "00" * 16, "02", "01", "IC5"), + ("01", "00" * 15 + "80" + "00" * 16, "02", "01", 2160, "IC5"), # IC6: Native library even byte optimization - ("01" * 31 + "00", "01", "01" * 31 + "00", "00" * 32, "IC6"), + ("01" * 31 + "00", "01", "01" * 31 + "00", "00" * 32, 500, "IC6"), # IC7: Vector optimization 128-bit boundary - ("00" * 15 + "01" * 17, "01", "00" * 15 + "01" * 17, "00" * 32, "IC7"), + ("00" * 15 + "01" * 17, "01", "00" * 15 + "01" * 17, "00" * 32, 500, "IC7"), # IC9: Zero modulus with large inputs - ("FF" * 32, "FF" * 32, "", "", "IC9"), + ("FF" * 32, "FF" * 32, "", "", None, "IC9"), # N/A case # IC10: Power-of-2 boundary with high bit - ("01" * 32, "80" + "00" * 31, "02" * 32, "01" * 32, "IC10"), + ("01" * 32, "80" + "00" * 31, "02" * 32, "01" * 32, 4080, "IC10"), ] # Gas calculation parameters: @@ -387,7 +564,7 @@ def create_modexp_variable_gas_test_cases(): # │ Z0 │ - │ - │ - │ - │ 500 │ Zero case – empty inputs │ # │ Z1 │ S │ - │ A │ True │ 500 │ Non-zero base, zero exp, empty modulus │ # │ Z2 │ L │ - │ A │ False │ 32768 │ Large base (1024B), zero exp, empty modulus │ - # │ Z3 │ S │ - │ C │ False │253936 │ Base, large zero exp (1024B), empty modulus │ + # │ Z3 │ S │ - │ C │ False |253952 │ Base, large zero exp (1024B), empty modulus │ # │ Z4 │ S │ - │ D │ False │253952 │ Base, large exp (last byte=1), empty modulus │ # │ Z5 │ S │ < │ A │ True │ 500 │ Empty base/exp, non-zero modulus only │ # │ Z6 │ S │ < │ B │ False │ 3968 │ Empty base, non-zero exp and modulus │ @@ -412,9 +589,9 @@ def create_modexp_variable_gas_test_cases(): # │ Z9 │ S │ = │ A │ True │ 500 │ Zero modulus special case │ # │ Z10 │ S │ = │ B │ False │ 3968 │ Zero base, large exponent │ # │ Z11 │ S │ = │ C │ True │ 500 │ Zero base, 33B zero exp, non-zero modulus │ - # │ Z12 │ S │ = │ C │ False │253936 │ Zero base, large zero exp, non-zero modulus │ + # │ Z12 │ S │ = │ C │ False |253952 │ Zero base, large zero exp, non-zero modulus │ # │ Z13 │ L │ > │ A │ False │ 32768 │ Large zero base, zero exp, non-zero modulus │ - # │ Z14 │ S │ = │ C │ False │253936 │ Base, large zero exp, zero modulus │ + # │ Z14 │ S │ = │ C │ False |253952 │ Base, large zero exp, zero modulus │ # │ Z15 │ L │ < │ B │ False │ 32768 │ Base, small exp, large zero modulus │ # │ Z16 │ L │ < │ C │ False │520060928│ Zero base, zero exp, large modulus (gas cap) | # │ M1 │ L │ = │ D │ False │ 98176 │ Maximum values stress test │ @@ -440,26 +617,34 @@ def create_modexp_variable_gas_test_cases(): # │ IC9 │ S │ = │ B │ N/A │ N/A │ Zero modulus handling │ # │ IC10│ S │ = │ B │ False │ 4080 │ Power-of-2 boundary with high bit │ # └─────┴──────┴─────┴──────┴───────┴─────────┴───────────────────────────────────────────────┘ - for base, exponent, modulus, expected_result, test_id in test_cases: + for base, exponent, modulus, expected_result, gas_usage, test_id in test_cases: yield pytest.param( ModExpInput(base=base, exponent=exponent, modulus=modulus), bytes.fromhex(expected_result), + gas_usage, id=test_id, ) @pytest.mark.parametrize( - "modexp_input,modexp_expected", + "modexp_input,modexp_expected,gas_usage", create_modexp_variable_gas_test_cases(), ) +@EIPChecklist.Precompile.Test.InputLengths.Zero() +@EIPChecklist.GasCostChanges.Test.GasUpdatesMeasurement() @pytest.mark.valid_from("Berlin") def test_modexp_variable_gas_cost( state_test: StateTestFiller, + precompile_gas: int, + gas_usage: int, pre: Alloc, tx: Transaction, + fork: Fork, post: Dict, ): """Test ModExp variable gas cost.""" + if fork >= Osaka: # Check that gas used defined in table is accurate + assert (gas_usage is None) or (precompile_gas >= gas_usage), "inconsistent gas usage" state_test(pre=pre, tx=tx, post=post) diff --git a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py index a5a10c866a..7b3315b73c 100644 --- a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py +++ b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py @@ -2,8 +2,9 @@ import pytest +from ethereum_test_checklists import EIPChecklist from ethereum_test_forks import Fork -from ethereum_test_tools import Account, Alloc, Block, BlockchainTestFiller, Transaction +from ethereum_test_tools import Account, Alloc, Block, BlockchainTestFiller, Transaction, keccak256 from ethereum_test_tools.vm.opcode import Opcodes as Op from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput @@ -20,7 +21,13 @@ [ pytest.param(Spec.modexp_input, Spec.modexp_expected, 200, 1200), ], + ids=[""], ) +@EIPChecklist.GasCostChanges.Test.ForkTransition.Before() +@EIPChecklist.GasCostChanges.Test.ForkTransition.After() +@EIPChecklist.Precompile.Test.ForkTransition.After.Warm() +@EIPChecklist.GasCostChanges.Test.ForkTransition.Before() +@EIPChecklist.GasCostChanges.Test.ForkTransition.After() def test_modexp_fork_transition( blockchain_test: BlockchainTestFiller, pre: Alloc, @@ -29,6 +36,7 @@ def test_modexp_fork_transition( gas_new: int, tx_gas_limit: int, modexp_input: ModExpInput, + modexp_expected: bytes, ): """Test ModExp gas cost transition from EIP-7883 before and after the Osaka hard fork.""" call_code = Op.CALL( @@ -57,6 +65,12 @@ def test_modexp_fork_transition( + Op.SSTORE # [] ) + # Verification the precompile call result + code += Op.RETURNDATACOPY(dest_offset=0, offset=0, size=Op.RETURNDATASIZE()) + Op.SSTORE( + Op.AND(Op.TIMESTAMP, 0xFF), + Op.SHA3(0, Op.RETURNDATASIZE()), + ) + senders = [pre.fund_eoa() for _ in range(3)] contracts = [pre.deploy_contract(code) for _ in range(3)] timestamps = [14_999, 15_000, 15_001] @@ -78,7 +92,7 @@ def test_modexp_fork_transition( ] post = { - contract: Account(storage={ts: gas}) + contract: Account(storage={ts: gas, ts & 0xFF: keccak256(bytes(modexp_expected))}) for contract, ts, gas in zip(contracts, timestamps, gas_values, strict=False) } From a6fce3a5e87ca25d5362fe0b8f235546144c8dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:06:02 +0800 Subject: [PATCH 009/102] feat(tests): add invalid p256verify cases (#2149) --- benchmark/test_worst_compute.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/benchmark/test_worst_compute.py b/benchmark/test_worst_compute.py index 90ce819a7e..ba5d074e66 100644 --- a/benchmark/test_worst_compute.py +++ b/benchmark/test_worst_compute.py @@ -1680,6 +1680,28 @@ def test_worst_modexp( id="p256verify", marks=[pytest.mark.eip_checklist("precompile/test/excessive_gas_usage", eip=[7951])], ), + pytest.param( + p256verify_spec.Spec.P256VERIFY, + [ + "235060CAFE19A407880C272BC3E73600E3A12294F56143ED61929C2FF4525ABB", + "182E5CBDF96ACCB859E8EEA1850DE5FF6E430A19D1D9A680ECD5946BBEA8A32B", + "76DDFAE6797FA6777CAAB9FA10E75F52E70A4E6CEB117B3C5B2F445D850BD64C", + "3828736CDFC4C8696008F71999260329AD8B12287846FEDCEDE3BA1205B12729", + "3E5141734E971A8D55015068D9B3666760F4608A49B11F92E500ACEA647978C7", + ], + id="p256verify_wrong_endianness", + ), + pytest.param( + p256verify_spec.Spec.P256VERIFY, + [ + "BB5A52F42F9C9261ED4361F59422A1E30036E7C32B270C8807A419FECA605023", + "000000000000000000000000000000004319055358E8617B0C46353D039CDAAB", + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E", + "0AD99500288D466940031D72A9F5445A4D43784640855BF0A69874D2DE5FE103", + "C5011E6EF2C42DCD50D5D3D29F99AE6EBA2C80C9244F4C5422F0979FF0C3BA5E", + ], + id="p256verify_modular_comp_x_coordinate_exceeds_n", + ), ], ) def test_worst_precompile_fixed_cost( From 3fa00f230716ab2362801d50a8cb681e0d4da720 Mon Sep 17 00:00:00 2001 From: spencer Date: Tue, 16 Sep 2025 16:04:55 +0100 Subject: [PATCH 010/102] fix(tests): fix shanghai to cancun transition test genesis file (#2161) --- .../test_excess_blob_gas_fork_transition.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py b/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py index d2231f4a0f..1d11234da0 100644 --- a/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py +++ b/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py @@ -47,7 +47,11 @@ def block_gas_limit(fork: Fork) -> int: # noqa: D103 @pytest.fixture -def genesis_environment(block_gas_limit: int, block_base_fee_per_gas: int) -> Environment: # noqa: D103 +def genesis_environment(block_gas_limit: int, block_base_fee_per_gas: int) -> Environment: + """ + Genesis environment that enables existing transition tests to be used of BPO forks. + Compatible with all fork transitions. + """ return Environment( base_fee_per_gas=(block_base_fee_per_gas * BASE_FEE_MAX_CHANGE_DENOMINATOR) // 7, gas_limit=block_gas_limit, @@ -320,7 +324,7 @@ def post( # noqa: D103 @pytest.mark.exception_test def test_invalid_pre_fork_block_with_blob_fields( blockchain_test: BlockchainTestFiller, - env: Environment, + genesis_environment: Environment, pre: Alloc, pre_fork_blocks: List[Block], excess_blob_gas_present: bool, @@ -349,7 +353,7 @@ def test_invalid_pre_fork_block_with_blob_fields( engine_api_error_code=EngineAPIError.InvalidParams, ) ], - genesis_environment=env, + genesis_environment=genesis_environment, ) @@ -365,7 +369,7 @@ def test_invalid_pre_fork_block_with_blob_fields( @pytest.mark.exception_test def test_invalid_post_fork_block_without_blob_fields( blockchain_test: BlockchainTestFiller, - env: Environment, + genesis_environment: Environment, pre: Alloc, pre_fork_blocks: List[Block], excess_blob_gas_missing: bool, @@ -395,7 +399,7 @@ def test_invalid_post_fork_block_without_blob_fields( engine_api_error_code=EngineAPIError.InvalidParams, ) ], - genesis_environment=env, + genesis_environment=genesis_environment, ) @@ -419,7 +423,7 @@ def test_invalid_post_fork_block_without_blob_fields( ) def test_fork_transition_excess_blob_gas_at_blob_genesis( blockchain_test: BlockchainTestFiller, - env: Environment, + genesis_environment: Environment, pre: Alloc, pre_fork_blocks: List[Block], post_fork_blocks: List[Block], @@ -435,7 +439,7 @@ def test_fork_transition_excess_blob_gas_at_blob_genesis( pre=pre, post=post, blocks=pre_fork_blocks + post_fork_blocks, - genesis_environment=env, + genesis_environment=genesis_environment, ) From 0b4c505f7fb917e0313ab1abcdca65da9dd2d5e3 Mon Sep 17 00:00:00 2001 From: spencer Date: Tue, 16 Sep 2025 16:14:04 +0100 Subject: [PATCH 011/102] chore(consume): fix consume rlp for python 3.11 (#2162) --- .../consume/simulators/simulator_logic/test_via_rlp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py index f2a7363700..936819385b 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py @@ -63,7 +63,7 @@ def test_via_rlp( ) raise AssertionError( "blockHash mismatch in last block - field mismatches:" - f"\n{'\n'.join(mismatches)}" + "\n" + "\n".join(mismatches) ) except Exception as e: raise AssertionError( From b58b9e0169a87c88bda920eae1217b28c07caa32 Mon Sep 17 00:00:00 2001 From: Sam Wilson <57262657+SamWilsn@users.noreply.github.com> Date: Wed, 17 Sep 2025 03:07:29 -0400 Subject: [PATCH 012/102] chore(tests): group mem-heavy tests together in xdist (#2153) --- .../eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py | 1 + osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py | 3 +++ prague/eip7702_set_code_tx/test_set_code_txs.py | 7 +++++++ prague/eip7702_set_code_tx/test_set_code_txs_2.py | 3 +++ shanghai/eip3855_push0/test_push0.py | 2 ++ shanghai/eip3860_initcode/test_initcode.py | 2 ++ shanghai/eip4895_withdrawals/test_withdrawals.py | 2 ++ 7 files changed, 20 insertions(+) diff --git a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py index 3c694b3c10..8d06306865 100644 --- a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py +++ b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py @@ -271,6 +271,7 @@ def total_cost_floor_per_token(fork: Fork): return gas_costs.G_TX_DATA_FLOOR_TOKEN_COST +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.parametrize( "exceed_tx_gas_limit,correct_intrinsic_cost_in_transaction_gas_limit", [ diff --git a/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py b/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py index fc90e59bde..575c8c002c 100644 --- a/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py +++ b/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py @@ -381,6 +381,7 @@ def _exact_size_transactions_impl( return transactions, final_gas +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.parametrize( "delta", [ @@ -440,6 +441,7 @@ def test_block_at_rlp_size_limit_boundary( ) +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.with_all_typed_transactions @pytest.mark.verify_sync def test_block_rlp_size_at_limit_with_all_typed_transactions( @@ -479,6 +481,7 @@ def test_block_rlp_size_at_limit_with_all_typed_transactions( ) +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.verify_sync def test_block_at_rlp_limit_with_logs( blockchain_test: BlockchainTestFiller, diff --git a/prague/eip7702_set_code_tx/test_set_code_txs.py b/prague/eip7702_set_code_tx/test_set_code_txs.py index cc25e6e57c..aa94f2fe60 100644 --- a/prague/eip7702_set_code_tx/test_set_code_txs.py +++ b/prague/eip7702_set_code_tx/test_set_code_txs.py @@ -1812,6 +1812,7 @@ def test_set_code_to_self_destructing_account_deployed_in_same_tx( ) +@pytest.mark.xdist_group(name="bigmem") def test_set_code_multiple_first_valid_authorization_tuples_same_signer( state_test: StateTestFiller, pre: Alloc, @@ -1859,6 +1860,7 @@ def test_set_code_multiple_first_valid_authorization_tuples_same_signer( ) +@pytest.mark.xdist_group(name="bigmem") def test_set_code_multiple_valid_authorization_tuples_same_signer_increasing_nonce( state_test: StateTestFiller, pre: Alloc, @@ -1906,6 +1908,7 @@ def test_set_code_multiple_valid_authorization_tuples_same_signer_increasing_non ) +@pytest.mark.xdist_group(name="bigmem") def test_set_code_multiple_valid_authorization_tuples_same_signer_increasing_nonce_self_sponsored( state_test: StateTestFiller, pre: Alloc, @@ -2001,6 +2004,7 @@ def test_set_code_multiple_valid_authorization_tuples_first_invalid_same_signer( ) +@pytest.mark.xdist_group(name="bigmem") def test_set_code_all_invalid_authorization_tuples( state_test: StateTestFiller, pre: Alloc, @@ -2040,6 +2044,7 @@ def test_set_code_all_invalid_authorization_tuples( ) +@pytest.mark.xdist_group(name="bigmem") def test_set_code_using_chain_specific_id( state_test: StateTestFiller, pre: Alloc, @@ -2088,6 +2093,7 @@ def test_set_code_using_chain_specific_id( SECP256K1N_OVER_2 = SECP256K1N // 2 +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.parametrize( "v,r,s", [ @@ -2148,6 +2154,7 @@ def test_set_code_using_valid_synthetic_signatures( ) +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.parametrize( "v,r,s", [ diff --git a/prague/eip7702_set_code_tx/test_set_code_txs_2.py b/prague/eip7702_set_code_tx/test_set_code_txs_2.py index 1b7348f5ba..20023e713c 100644 --- a/prague/eip7702_set_code_tx/test_set_code_txs_2.py +++ b/prague/eip7702_set_code_tx/test_set_code_txs_2.py @@ -1441,6 +1441,7 @@ class DelegationTo(Enum): RESET = 3 +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.valid_from("Prague") @pytest.mark.parametrize( "first_delegation", [DelegationTo.CONTRACT_A, DelegationTo.CONTRACT_B, DelegationTo.RESET] @@ -1536,6 +1537,7 @@ def test_double_auth( ) +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.valid_from("Prague") def test_pointer_resets_an_empty_code_account_with_storage( blockchain_test: BlockchainTestFiller, @@ -1754,6 +1756,7 @@ def test_set_code_type_tx_pre_fork( @pytest.mark.valid_from("Prague") +@pytest.mark.xdist_group(name="bigmem") def test_delegation_replacement_call_previous_contract( state_test: StateTestFiller, pre: Alloc, diff --git a/shanghai/eip3855_push0/test_push0.py b/shanghai/eip3855_push0/test_push0.py index 410cbb18bc..9633582377 100644 --- a/shanghai/eip3855_push0/test_push0.py +++ b/shanghai/eip3855_push0/test_push0.py @@ -29,6 +29,7 @@ pytestmark = pytest.mark.valid_from("Shanghai") +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.parametrize( "contract_code,expected_storage", [ @@ -120,6 +121,7 @@ def push0_contract_caller( ) return pre.deploy_contract(call_code) + @pytest.mark.xdist_group(name="bigmem") @pytest.mark.parametrize( "call_opcode", [ diff --git a/shanghai/eip3860_initcode/test_initcode.py b/shanghai/eip3860_initcode/test_initcode.py index fa52ca0816..9f3d24fb5c 100644 --- a/shanghai/eip3860_initcode/test_initcode.py +++ b/shanghai/eip3860_initcode/test_initcode.py @@ -117,6 +117,7 @@ """ +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.parametrize( "initcode", [ @@ -481,6 +482,7 @@ def create2_word_cost(self, opcode: Op, fork: Fork, initcode: Initcode) -> int: gas_costs = fork.gas_costs() return ceiling_division(len(initcode), 32) * gas_costs.G_KECCAK_256_WORD + @pytest.mark.xdist_group(name="bigmem") def test_create_opcode_initcode( self, state_test: StateTestFiller, diff --git a/shanghai/eip4895_withdrawals/test_withdrawals.py b/shanghai/eip4895_withdrawals/test_withdrawals.py index fc9305a83e..5280dd1e4f 100644 --- a/shanghai/eip4895_withdrawals/test_withdrawals.py +++ b/shanghai/eip4895_withdrawals/test_withdrawals.py @@ -651,6 +651,7 @@ def test_zero_amount( ) +@pytest.mark.xdist_group(name="bigmem") def test_large_amount( blockchain_test: BlockchainTestFiller, pre: Alloc, @@ -690,6 +691,7 @@ def test_large_amount( blockchain_test(pre=pre, post=post, blocks=blocks) +@pytest.mark.xdist_group(name="bigmem") @pytest.mark.parametrize("amount", [0, 1]) @pytest.mark.with_all_precompiles def test_withdrawing_to_precompiles( From 6f7c43f834c4ca2ce1c8f22b92e8df5f2ffe4a2b Mon Sep 17 00:00:00 2001 From: spencer Date: Wed, 17 Sep 2025 08:15:37 +0100 Subject: [PATCH 013/102] chore(cli): fix reth eip-7825 tx gas limit cap exceptions (#2164) --- ethereum_clis/clis/reth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum_clis/clis/reth.py b/ethereum_clis/clis/reth.py index 6eae2b7fe4..4a3c0bcdca 100644 --- a/ethereum_clis/clis/reth.py +++ b/ethereum_clis/clis/reth.py @@ -58,7 +58,7 @@ class RethExceptionMapper(ExceptionMapper): r"transaction gas limit \w+ is more than blocks available gas \w+" ), TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM: ( - r"transaction gas limit \(\d+\) is greater than the cap \(\d+\)" + r"transaction 0x[a-fA-F0-9]+ gas limit \d+ exceeds maximum \d+" ), BlockException.SYSTEM_CONTRACT_CALL_FAILED: r"failed to apply .* requests contract call", BlockException.INCORRECT_BLOB_GAS_USED: ( From 8aa5da4b830ce7d29473d402a9c8f78c9b7cadee Mon Sep 17 00:00:00 2001 From: felipe Date: Wed, 17 Sep 2025 03:56:36 -0600 Subject: [PATCH 014/102] feat(tests): Enforce EIP-7928 ordering rules (#2138) * fix(tests): Validate order for BAL coming from t8n The specs are currently correctly written, but we were not validating all of the ordering according to EIP-7928: - Addresses: lexicographic (bytewise). - Storage keys: lexicographic within each account. - Block access indices: ascending within each change list. This change validates the order of the BAL before we even begin to compare against our expectation. We also now validate that the expectations we define are subsequences within the BAL (expected order). - refactor: Explicit check for the fields we care about up front for `model_fields_set` - refactor: awkward comparison method should just be a validation method (_validate_change_lists) * chore: Unit test BAL ordering validation checks * chore: Add note to CHANGELOG * fix: ``Number`` -> ``HexNumber`` for BAL types - This becomes an issue when JSON-serializing the BAL object and then re-filling from the fixture. We should use `HexNumber` for any Number fields as this correctly serializes to JSON as hex representation. * chore: move release note up to unreleased * refactor: apply changes from comments on PR #2138 --- .../block_access_list/__init__.py | 337 +++++++++++++----- .../block_access_list/modifiers.py | 18 +- .../tests/test_block_access_lists.py | 332 ++++++++++++++++- 3 files changed, 578 insertions(+), 109 deletions(-) diff --git a/ethereum_test_types/block_access_list/__init__.py b/ethereum_test_types/block_access_list/__init__.py index 753aaa44e7..c1d4354ae2 100644 --- a/ethereum_test_types/block_access_list/__init__.py +++ b/ethereum_test_types/block_access_list/__init__.py @@ -6,7 +6,7 @@ """ from functools import cached_property -from typing import Any, Callable, ClassVar, Dict, List +from typing import Any, Callable, ClassVar, Dict, List, Union import ethereum_rlp as eth_rlp from pydantic import Field, PrivateAttr @@ -17,13 +17,18 @@ CamelModel, EthereumTestRootModel, HexNumber, - Number, RLPSerializable, StorageKey, ) from ethereum_test_base_types.serialization import to_serializable_element +class BlockAccessListValidationError(Exception): + """Custom exception for Block Access List validation errors.""" + + pass + + def compose( *modifiers: Callable[["BlockAccessList"], "BlockAccessList"], ) -> Callable[["BlockAccessList"], "BlockAccessList"]: @@ -41,8 +46,11 @@ def composed(bal: BlockAccessList) -> BlockAccessList: class BalNonceChange(CamelModel, RLPSerializable): """Represents a nonce change in the block access list.""" - tx_index: Number = Field(..., description="Transaction index where the change occurred") - post_nonce: Number = Field(..., description="Nonce value after the transaction") + tx_index: HexNumber = Field( + HexNumber(1), + description="Transaction index where the change occurred", + ) + post_nonce: HexNumber = Field(..., description="Nonce value after the transaction") rlp_fields: ClassVar[List[str]] = ["tx_index", "post_nonce"] @@ -50,7 +58,10 @@ class BalNonceChange(CamelModel, RLPSerializable): class BalBalanceChange(CamelModel, RLPSerializable): """Represents a balance change in the block access list.""" - tx_index: Number = Field(..., description="Transaction index where the change occurred") + tx_index: HexNumber = Field( + HexNumber(1), + description="Transaction index where the change occurred", + ) post_balance: HexNumber = Field(..., description="Balance after the transaction") rlp_fields: ClassVar[List[str]] = ["tx_index", "post_balance"] @@ -59,7 +70,10 @@ class BalBalanceChange(CamelModel, RLPSerializable): class BalCodeChange(CamelModel, RLPSerializable): """Represents a code change in the block access list.""" - tx_index: Number = Field(..., description="Transaction index where the change occurred") + tx_index: HexNumber = Field( + HexNumber(1), + description="Transaction index where the change occurred", + ) new_code: Bytes = Field(..., description="New code bytes") rlp_fields: ClassVar[List[str]] = ["tx_index", "new_code"] @@ -68,7 +82,10 @@ class BalCodeChange(CamelModel, RLPSerializable): class BalStorageChange(CamelModel, RLPSerializable): """Represents a change to a specific storage slot.""" - tx_index: Number = Field(..., description="Transaction index where the change occurred") + tx_index: HexNumber = Field( + HexNumber(1), + description="Transaction index where the change occurred", + ) post_value: StorageKey = Field(..., description="Value after the transaction") rlp_fields: ClassVar[List[str]] = ["tx_index", "post_value"] @@ -115,6 +132,13 @@ class BalAccountChange(CamelModel, RLPSerializable): ] +BlockAccessListChangeLists = Union[ + List[BalNonceChange], + List[BalBalanceChange], + List[BalCodeChange], +] + + class BlockAccessList(EthereumTestRootModel[List[BalAccountChange]]): """ Block Access List for t8n tool communication and fixtures. @@ -256,6 +280,11 @@ def verify_against(self, actual_bal: "BlockAccessList") -> None: """ Verify that the actual BAL from the client matches this expected BAL. + Validation steps: + 1. Validate actual BAL conforms to EIP-7928 ordering requirements + 2. Verify address expectations - presence or explicit absence + 3. Verify expected changes within accounts match actual changes + Args: actual_bal: The BlockAccessList model from the client @@ -263,23 +292,104 @@ def verify_against(self, actual_bal: "BlockAccessList") -> None: Exception: If verification fails """ - actual_accounts_by_addr = {acc.address: acc for acc in actual_bal.root} + # validate the actual BAL structure follows EIP-7928 ordering + self._validate_bal_ordering(actual_bal) + actual_accounts_by_addr = {acc.address: acc for acc in actual_bal.root} for address, expectation in self.account_expectations.items(): if expectation is None: # check explicit exclusion of address when set to `None` if address in actual_accounts_by_addr: - raise Exception(f"Address {address} should not be in BAL but was found") + raise BlockAccessListValidationError( + f"Address {address} should not be in BAL but was found" + ) else: - # Address should be in BAL with expected values + # check address is present and validate changes if address not in actual_accounts_by_addr: - raise Exception(f"Expected address {address} not found in actual BAL") + raise BlockAccessListValidationError( + f"Expected address {address} not found in actual BAL" + ) actual_account = actual_accounts_by_addr[address] try: self._compare_account_expectations(expectation, actual_account) except AssertionError as e: - raise Exception(f"Account {address}: {str(e)}") from e + raise BlockAccessListValidationError(f"Account {address}: {str(e)}") from e + + @staticmethod + def _validate_bal_ordering(bal: "BlockAccessList") -> None: + """ + Validate that the actual BAL follows EIP-7928 ordering requirements. + + Per EIP-7928: + - Addresses must be in lexicographic (bytewise) order + - Storage keys must be in lexicographic order within each account + - Block access indices must be in ascending order within each change list + + Args: + bal: The BlockAccessList to validate + + Raises: + Exception: If BAL doesn't follow EIP-7928 ordering + + """ + addresses = [acc.address for acc in bal.root] + + # Check addresses are in lexicographic order + sorted_addresses = sorted(addresses, key=lambda x: bytes(x)) + if addresses != sorted_addresses: + raise BlockAccessListValidationError( + f"BAL addresses not in lexicographic order per EIP-7928. " + f"Got: {[str(a) for a in addresses]}, " + f"Expected: {[str(a) for a in sorted_addresses]}" + ) + + # Check ordering within each account + for account in bal.root: + # Check storage slots are in lexicographic order + if account.storage_changes: + slots = [s.slot for s in account.storage_changes] + sorted_slots = sorted(slots, key=lambda x: bytes(x)) + if slots != sorted_slots: + raise BlockAccessListValidationError( + f"Account {account.address}: Storage slots not in lexicographic order. " + f"Got: {slots}, Expected: {sorted_slots}" + ) + + # Check tx indices within each storage slot are in ascending order + for slot_change in account.storage_changes: + if slot_change.slot_changes: + tx_indices = [c.tx_index for c in slot_change.slot_changes] + if tx_indices != sorted(tx_indices): + raise BlockAccessListValidationError( + f"Account {account.address}, Slot {slot_change.slot}: " + f"tx_indices not in ascending order. Got: {tx_indices}" + ) + + # Check storage reads are in lexicographic order + if account.storage_reads: + sorted_reads = sorted(account.storage_reads, key=lambda x: bytes(x)) + if account.storage_reads != sorted_reads: + raise BlockAccessListValidationError( + f"Account {account.address}: Storage reads not in " + f"lexicographic order. Got: {account.storage_reads}, " + f"Expected: {sorted_reads}" + ) + + # Check tx indices in other change lists + changes_to_check: List[tuple[str, Union[BlockAccessListChangeLists]]] = [ + ("nonce_changes", account.nonce_changes), + ("balance_changes", account.balance_changes), + ("code_changes", account.code_changes), + ] + for field_name, changes in changes_to_check: + if changes: + tx_indices = [c.tx_index for c in changes] + if tx_indices != sorted(tx_indices): + raise BlockAccessListValidationError( + f"Account {account.address}: {field_name} tx_indices " + f"not in ascending order. Got: {tx_indices}" + ) def _compare_account_expectations( self, expected: BalAccountExpectation, actual: BalAccountChange @@ -290,68 +400,110 @@ def _compare_account_expectations( Only validates fields that were explicitly set in the expected model, using model_fields_set to determine what was intentionally specified. """ + change_fields = { + "nonce_changes", + "balance_changes", + "code_changes", + "storage_changes", + } + bal_fields = change_fields | {"storage_reads"} + # Only check fields that were explicitly set in the expected model - for field_name in expected.model_fields_set: + for field_name in expected.model_fields_set.intersection(bal_fields): expected_value = getattr(expected, field_name) actual_value = getattr(actual, field_name) # empty list explicitly set (no changes expected) if not expected_value: if actual_value: - raise AssertionError( + raise BlockAccessListValidationError( f"Expected {field_name} to be empty but found: {actual_value}" ) continue if field_name == "storage_reads": - # Convert to comparable format (both are lists of 32-byte values) - expected_set = {bytes(v) if hasattr(v, "__bytes__") else v for v in expected_value} - actual_set = {bytes(v) if hasattr(v, "__bytes__") else v for v in actual_value} - if expected_set != actual_set: - missing = expected_set - actual_set - extra = actual_set - expected_set - msg = "Storage reads mismatch." - if missing: - missing_str = [ - v.hex() if isinstance(v, bytes) else str(v) for v in missing - ] - msg += f" Missing: {missing_str}." - if extra: - extra_str = [v.hex() if isinstance(v, bytes) else str(v) for v in extra] - msg += f" Extra: {extra_str}." - raise AssertionError(msg) - - elif isinstance(expected_value, list): - # For lists of changes, use the model_dump approach for comparison - expected_data = [ - item.model_dump() if hasattr(item, "model_dump") else item - for item in expected_value - ] - actual_data = [ - item.model_dump() if hasattr(item, "model_dump") else item - for item in actual_value + # EIP-7928: Storage reads must be in lexicographic order + # check as subsequence + expected_reads = [ + bytes(v) if hasattr(v, "__bytes__") else v for v in expected_value ] - - if not self._compare_change_lists(field_name, expected_data, actual_data): - # The comparison method will raise with details - pass + actual_reads = [bytes(v) if hasattr(v, "__bytes__") else v for v in actual_value] + + # Check that expected reads form a subsequence of actual reads + actual_idx = 0 + for exp_read in expected_reads: + found = False + while actual_idx < len(actual_reads): + if actual_reads[actual_idx] == exp_read: + found = True + actual_idx += 1 + break + actual_idx += 1 + + if not found: + exp_str = exp_read.hex() if isinstance(exp_read, bytes) else str(exp_read) + actual_str = [ + r.hex() if isinstance(r, bytes) else str(r) for r in actual_reads + ] + raise BlockAccessListValidationError( + f"Storage read {exp_str} not found or not in correct order. " + f"Actual reads: {actual_str}" + ) + + elif field_name in change_fields: + # For lists of changes, convert Pydantic models to dicts for + # comparison + expected_data = [item.model_dump() for item in expected_value] + actual_data = [item.model_dump() for item in actual_value] + self._validate_change_lists(field_name, expected_data, actual_data) @staticmethod - def _compare_change_lists(field_name: str, expected: List, actual: List) -> bool: - """Compare lists of change objects using set operations for better error messages.""" + def _validate_change_lists(field_name: str, expected: List, actual: List) -> None: + """ + Validate that expected change lists form a subsequence of actual changes. + + Note: Ordering validation per EIP-7928 is already done in _validate_bal_ordering. + This method only checks that expected items appear in the actual list as a subsequence. + + Raises: + AssertionError: If expected changes are not found or not in correct order + + """ if field_name == "storage_changes": # Storage changes are nested (slot -> changes) + expected_slots = [slot["slot"] for slot in expected] + actual_slots = [slot["slot"] for slot in actual] + + # Check expected slots form a subsequence (ordering already validated) + actual_idx = 0 + for exp_slot in expected_slots: + found = False + while actual_idx < len(actual_slots): + if actual_slots[actual_idx] == exp_slot: + found = True + break + actual_idx += 1 + + if not found: + raise BlockAccessListValidationError( + f"Expected storage slot {exp_slot} not found or not in " + f"correct order. Actual slots: {actual_slots}" + ) + + # check changes within each slot expected_by_slot = {slot["slot"]: slot["slot_changes"] for slot in expected} actual_by_slot = {slot["slot"]: slot["slot_changes"] for slot in actual} - missing_slots = set(expected_by_slot.keys()) - set(actual_by_slot.keys()) - if missing_slots: - raise AssertionError(f"Missing storage slots: {missing_slots}") - for slot, exp_changes in expected_by_slot.items(): - act_changes = actual_by_slot.get(slot, []) - # Handle Hash/bytes for post_value comparison - exp_set = { + if slot not in actual_by_slot: + raise BlockAccessListValidationError( + f"Expected storage slot {slot} not found in actual" + ) + + act_changes = actual_by_slot[slot] + + # Check that expected changes form a subsequence + exp_tuples = [ ( c["tx_index"], bytes(c["post_value"]) @@ -359,8 +511,8 @@ def _compare_change_lists(field_name: str, expected: List, actual: List) -> bool else c["post_value"], ) for c in exp_changes - } - act_set = { + ] + act_tuples = [ ( c["tx_index"], bytes(c["post_value"]) @@ -368,45 +520,58 @@ def _compare_change_lists(field_name: str, expected: List, actual: List) -> bool else c["post_value"], ) for c in act_changes - } - - if exp_set != act_set: - missing = exp_set - act_set - extra = act_set - exp_set - msg = f"Slot {slot} changes mismatch." - if missing: - msg += f" Missing: {missing}." - if extra: - msg += f" Extra: {extra}." - raise AssertionError(msg) + ] + + act_idx = 0 + for exp_tuple in exp_tuples: + found = False + while act_idx < len(act_tuples): + if act_tuples[act_idx] == exp_tuple: + found = True + act_idx += 1 + break + act_idx += 1 + + if not found: + raise BlockAccessListValidationError( + f"Slot {slot}: Expected change {exp_tuple} not found " + f"or not in correct order. Actual changes: {act_tuples}" + ) + else: - # Create comparable tuples for each change type + # Create tuples for comparison (ordering already validated) if field_name == "nonce_changes": - expected_set = {(c["tx_index"], c["post_nonce"]) for c in expected} - actual_set = {(c["tx_index"], c["post_nonce"]) for c in actual} + expected_tuples = [(c["tx_index"], c["post_nonce"]) for c in expected] + actual_tuples = [(c["tx_index"], c["post_nonce"]) for c in actual] item_type = "nonce" elif field_name == "balance_changes": - expected_set = {(c["tx_index"], int(c["post_balance"])) for c in expected} - actual_set = {(c["tx_index"], int(c["post_balance"])) for c in actual} + expected_tuples = [(c["tx_index"], int(c["post_balance"])) for c in expected] + actual_tuples = [(c["tx_index"], int(c["post_balance"])) for c in actual] item_type = "balance" elif field_name == "code_changes": - expected_set = {(c["tx_index"], bytes(c["new_code"])) for c in expected} - actual_set = {(c["tx_index"], bytes(c["new_code"])) for c in actual} + expected_tuples = [(c["tx_index"], bytes(c["new_code"])) for c in expected] + actual_tuples = [(c["tx_index"], bytes(c["new_code"])) for c in actual] item_type = "code" else: - raise ValueError("Unexpected type") - - if expected_set != actual_set: - missing = expected_set - actual_set - extra = actual_set - expected_set - msg = f"{item_type.capitalize()} changes mismatch." - if missing: - msg += f" Missing: {missing}." - if extra: - msg += f" Extra: {extra}." - raise AssertionError(msg) - - return True + # sanity check + raise ValueError(f"Unexpected field type: {field_name}") + + # Check that expected forms a subsequence of actual + actual_idx = 0 + for exp_tuple in expected_tuples: + found = False + while actual_idx < len(actual_tuples): + if actual_tuples[actual_idx] == exp_tuple: + found = True + actual_idx += 1 + break + actual_idx += 1 + + if not found: + raise BlockAccessListValidationError( + f"{item_type.capitalize()} change {exp_tuple} not found " + f"or not in correct order. Actual changes: {actual_tuples}" + ) __all__ = [ diff --git a/ethereum_test_types/block_access_list/modifiers.py b/ethereum_test_types/block_access_list/modifiers.py index 718ed50814..57bd1a8f89 100644 --- a/ethereum_test_types/block_access_list/modifiers.py +++ b/ethereum_test_types/block_access_list/modifiers.py @@ -8,7 +8,7 @@ from typing import Callable, List -from ethereum_test_base_types import Address, Number +from ethereum_test_base_types import Address, HexNumber from .. import BalCodeChange from . import ( @@ -244,26 +244,26 @@ def transform(bal: BlockAccessList) -> BlockAccessList: if new_account.nonce_changes: for nonce_change in new_account.nonce_changes: if nonce_change.tx_index == tx1: - nonce_change.tx_index = Number(tx2) + nonce_change.tx_index = HexNumber(tx2) elif nonce_change.tx_index == tx2: - nonce_change.tx_index = Number(tx1) + nonce_change.tx_index = HexNumber(tx1) # Swap in balance changes if new_account.balance_changes: for balance_change in new_account.balance_changes: if balance_change.tx_index == tx1: - balance_change.tx_index = Number(tx2) + balance_change.tx_index = HexNumber(tx2) elif balance_change.tx_index == tx2: - balance_change.tx_index = Number(tx1) + balance_change.tx_index = HexNumber(tx1) # Swap in storage changes (nested structure) if new_account.storage_changes: for storage_slot in new_account.storage_changes: for storage_change in storage_slot.slot_changes: if storage_change.tx_index == tx1: - storage_change.tx_index = Number(tx2) + storage_change.tx_index = HexNumber(tx2) elif storage_change.tx_index == tx2: - storage_change.tx_index = Number(tx1) + storage_change.tx_index = HexNumber(tx1) # Note: storage_reads is just a list of StorageKey, no tx_index to swap @@ -271,9 +271,9 @@ def transform(bal: BlockAccessList) -> BlockAccessList: if new_account.code_changes: for code_change in new_account.code_changes: if code_change.tx_index == tx1: - code_change.tx_index = Number(tx2) + code_change.tx_index = HexNumber(tx2) elif code_change.tx_index == tx2: - code_change.tx_index = Number(tx1) + code_change.tx_index = HexNumber(tx1) new_root.append(new_account) diff --git a/ethereum_test_types/tests/test_block_access_lists.py b/ethereum_test_types/tests/test_block_access_lists.py index 852894bc25..707df0a9c3 100644 --- a/ethereum_test_types/tests/test_block_access_lists.py +++ b/ethereum_test_types/tests/test_block_access_lists.py @@ -2,23 +2,25 @@ import pytest -from ethereum_test_base_types import Address +from ethereum_test_base_types import Address, StorageKey from ethereum_test_types.block_access_list import ( BalAccountChange, BalAccountExpectation, BalBalanceChange, + BalCodeChange, BalNonceChange, BalStorageChange, BalStorageSlot, BlockAccessList, BlockAccessListExpectation, + BlockAccessListValidationError, ) def test_address_exclusion_validation_passes(): """Test that address exclusion works when address is not in BAL.""" - alice = Address("0x000000000000000000000000000000000000000a") - bob = Address("0x000000000000000000000000000000000000000b") + alice = Address(0xA) + bob = Address(0xB) actual_bal = BlockAccessList( [ @@ -41,8 +43,8 @@ def test_address_exclusion_validation_passes(): def test_address_exclusion_validation_raises_when_address_is_present(): """Test that validation fails when excluded address is in BAL.""" - alice = Address("0x000000000000000000000000000000000000000a") - bob = Address("0x000000000000000000000000000000000000000b") + alice = Address(0xA) + bob = Address(0xB) actual_bal = BlockAccessList( [ @@ -62,13 +64,13 @@ def test_address_exclusion_validation_raises_when_address_is_present(): account_expectations={bob: None}, ) - with pytest.raises(Exception, match="should not be in BAL but was found"): + with pytest.raises(BlockAccessListValidationError, match="should not be in BAL but was found"): expectation.verify_against(actual_bal) def test_empty_list_validation(): """Test that empty list validates correctly.""" - alice = Address("0x000000000000000000000000000000000000000a") + alice = Address(0xA) actual_bal = BlockAccessList( [ @@ -94,7 +96,7 @@ def test_empty_list_validation(): def test_empty_list_validation_fails(): """Test that validation fails when expecting empty but field has values.""" - alice = Address("0x000000000000000000000000000000000000000a") + alice = Address(0xA) actual_bal = BlockAccessList( [ @@ -112,13 +114,16 @@ def test_empty_list_validation_fails(): } ) - with pytest.raises(Exception, match="Expected balance_changes to be empty"): + with pytest.raises( + BlockAccessListValidationError, + match="Expected balance_changes to be empty", + ): expectation.verify_against(actual_bal) def test_partial_validation(): """Test that unset fields are not validated.""" - alice = Address("0x000000000000000000000000000000000000000a") + alice = Address(0xA) # Actual BAL has multiple types of changes actual_bal = BlockAccessList( @@ -147,7 +152,7 @@ def test_partial_validation(): def test_storage_changes_validation(): """Test storage changes validation.""" - contract = Address("0x000000000000000000000000000000000000000c") + contract = Address(0xC) # Actual BAL with storage changes actual_bal = BlockAccessList( @@ -183,8 +188,8 @@ def test_storage_changes_validation(): def test_missing_expected_address(): """Test that validation fails when expected address is missing.""" - alice = Address("0x000000000000000000000000000000000000000a") - bob = Address("0x000000000000000000000000000000000000000b") + alice = Address(0xA) + bob = Address(0xB) actual_bal = BlockAccessList( [ @@ -204,5 +209,304 @@ def test_missing_expected_address(): } ) - with pytest.raises(Exception, match="Expected address .* not found in actual BAL"): + with pytest.raises( + BlockAccessListValidationError, match="Expected address .* not found in actual BAL" + ): expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize( + "addresses,error_message", + [ + ( + [ + Address(0xB), + Address(0xA), # should come first + ], + "BAL addresses not in lexicographic order per EIP-7928", + ), + ( + [ + Address(0x1), + Address(0x3), + Address(0x2), + ], + "BAL addresses not in lexicographic order per EIP-7928", + ), + ], +) +def test_actual_bal_address_ordering_validation(addresses, error_message): + """Test that actual BAL must have addresses in lexicographic order.""" + # Create BAL with addresses in the given order + actual_bal = BlockAccessList( + [BalAccountChange(address=addr, nonce_changes=[]) for addr in addresses] + ) + + expectation = BlockAccessListExpectation(account_expectations={}) + + with pytest.raises(BlockAccessListValidationError, match=error_message): + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize( + "storage_slots,error_message", + [ + ( + [StorageKey(0x02), StorageKey(0x01)], # 0x02 before 0x01 + "Storage slots not in lexicographic order", + ), + ( + [StorageKey(0x01), StorageKey(0x03), StorageKey(0x02)], + "Storage slots not in lexicographic order", + ), + ], +) +def test_actual_bal_storage_slot_ordering(storage_slots, error_message): + """Test that actual BAL must have storage slots in lexicographic order.""" + addr = Address(0xA) + + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=addr, + storage_changes=[ + BalStorageSlot(slot=slot, slot_changes=[]) for slot in storage_slots + ], + ) + ] + ) + + expectation = BlockAccessListExpectation(account_expectations={}) + + with pytest.raises(BlockAccessListValidationError, match=error_message): + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize( + "storage_reads,error_message", + [ + ([StorageKey(0x02), StorageKey(0x01)], "Storage reads not in lexicographic order"), + ( + [StorageKey(0x01), StorageKey(0x03), StorageKey(0x02)], + "Storage reads not in lexicographic order", + ), + ], +) +def test_actual_bal_storage_reads_ordering(storage_reads, error_message): + """Test that actual BAL must have storage reads in lexicographic order.""" + addr = Address(0xA) + + actual_bal = BlockAccessList([BalAccountChange(address=addr, storage_reads=storage_reads)]) + + expectation = BlockAccessListExpectation(account_expectations={}) + + with pytest.raises(BlockAccessListValidationError, match=error_message): + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize( + "field_name", + ["nonce_changes", "balance_changes", "code_changes"], +) +def test_actual_bal_tx_indices_ordering(field_name): + """Test that actual BAL must have tx indices in ascending order.""" + addr = Address(0xA) + + tx_indices = [2, 3, 1] # out of order + + changes = [] + if field_name == "nonce_changes": + changes = [BalNonceChange(tx_index=idx, post_nonce=1) for idx in tx_indices] + elif field_name == "balance_changes": + changes = [BalBalanceChange(tx_index=idx, post_balance=100) for idx in tx_indices] + elif field_name == "code_changes": + changes = [BalCodeChange(tx_index=idx, new_code=b"code") for idx in tx_indices] + + actual_bal = BlockAccessList([BalAccountChange(address=addr, **{field_name: changes})]) + + expectation = BlockAccessListExpectation(account_expectations={}) + + with pytest.raises( + BlockAccessListValidationError, + match="tx_indices not in ascending order", + ): + expectation.verify_against(actual_bal) + + +def test_expected_addresses_auto_sorted(): + """ + Test that expected addresses are automatically sorted before comparison. + + The BAL *Expectation address order should not matter for the dict. + We DO, however, validate that the actual BAL (from t8n) is sorted correctly. + """ + alice = Address(0xA) + bob = Address(0xB) + charlie = Address(0xC) + + actual_bal = BlockAccessList( + [ + BalAccountChange(address=alice, nonce_changes=[]), + BalAccountChange(address=bob, nonce_changes=[]), + BalAccountChange(address=charlie, nonce_changes=[]), + ] + ) + + # expectation order should not matter for the dict though we DO validate + # that the _actual_ BAL (from t8n) is sorted correctly + expectation = BlockAccessListExpectation( + account_expectations={ + charlie: BalAccountExpectation(nonce_changes=[]), + alice: BalAccountExpectation(nonce_changes=[]), + bob: BalAccountExpectation(nonce_changes=[]), + } + ) + + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize( + "expected_slots,should_pass", + [ + # Correct order - should pass + ([StorageKey(0x01), StorageKey(0x02), StorageKey(0x03)], True), + # Partial subset in correct order - should pass + ([StorageKey(0x01), StorageKey(0x03)], True), + # Out of order - should fail + ([StorageKey(0x01), StorageKey(0x03), StorageKey(0x02)], False), + # Wrong order from start - should fail + ([StorageKey(0x02), StorageKey(0x01)], False), + ], +) +def test_expected_storage_slots_ordering(expected_slots, should_pass): + """Test that expected storage slots must be defined in correct order.""" + addr = Address(0xA) + + # Actual BAL with storage slots in correct order + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=addr, + storage_changes=[ + BalStorageSlot(slot=StorageKey(0x01), slot_changes=[]), + BalStorageSlot(slot=StorageKey(0x02), slot_changes=[]), + BalStorageSlot(slot=StorageKey(0x03), slot_changes=[]), + ], + ) + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + addr: BalAccountExpectation( + storage_changes=[ + BalStorageSlot(slot=slot, slot_changes=[]) for slot in expected_slots + ], + ), + } + ) + + if should_pass: + expectation.verify_against(actual_bal) + else: + with pytest.raises( + BlockAccessListValidationError, + match="not found or not in correct order", + ): + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize( + "expected_reads,should_pass", + [ + # Correct order - should pass + ([StorageKey(0x01), StorageKey(0x02), StorageKey(0x03)], True), + # Partial subset in correct order - should pass + ([StorageKey(0x02), StorageKey(0x03)], True), + # Out of order - should fail + ([StorageKey(0x03), StorageKey(0x02)], False), + # Wrong order with all elements - should fail + ([StorageKey(0x01), StorageKey(0x03), StorageKey(0x02)], False), + ], +) +def test_expected_storage_reads_ordering(expected_reads, should_pass): + """Test that expected storage reads must be defined in correct order.""" + addr = Address(0xA) + + # Actual BAL with storage reads in correct order + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=addr, + storage_reads=[StorageKey(0x01), StorageKey(0x02), StorageKey(0x03)], + ) + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + addr: BalAccountExpectation(storage_reads=expected_reads), + } + ) + + if should_pass: + expectation.verify_against(actual_bal) + else: + with pytest.raises( + BlockAccessListValidationError, + match="not found or not in correct order", + ): + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize( + "expected_tx_indices,should_pass", + [ + # Correct order - should pass + ([1, 2, 3], True), + # Partial subset in correct order - should pass + ([1, 3], True), + # Single element - should pass + ([2], True), + # Out of order - should fail + ([2, 1], False), + # Wrong order with all elements - should fail + ([1, 3, 2], False), + ], +) +def test_expected_tx_indices_ordering(expected_tx_indices, should_pass): + """Test that expected tx indices must be defined in correct order.""" + addr = Address(0xA) + + # actual BAL with tx indices in correct order + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=addr, + nonce_changes=[ + BalNonceChange(tx_index=1, post_nonce=1), + BalNonceChange(tx_index=2, post_nonce=2), + BalNonceChange(tx_index=3, post_nonce=3), + ], + ) + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + addr: BalAccountExpectation( + nonce_changes=[ + BalNonceChange(tx_index=idx, post_nonce=idx) for idx in expected_tx_indices + ], + ), + } + ) + + if should_pass: + expectation.verify_against(actual_bal) + else: + with pytest.raises( + BlockAccessListValidationError, + match="not found or not in correct order", + ): + expectation.verify_against(actual_bal) From 415236b643ef224f6dc922c55ea1ea309e533836 Mon Sep 17 00:00:00 2001 From: felix Date: Wed, 17 Sep 2025 15:03:03 +0000 Subject: [PATCH 015/102] chore(consume): increase fcu retries to 30 (at 1 second each) (#2168) * erigon requested increase of retries * do not wait after failure in last attempt --- .../simulator_logic/test_via_engine.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py index 26e95719c5..a4f8a62117 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py @@ -18,6 +18,9 @@ logger = get_logger(__name__) +MAX_RETRIES = 30 +DELAY_BETWEEN_RETRIES_IN_SEC = 1 + class LoggedError(Exception): """Exception that uses the logger to log the failure.""" @@ -44,8 +47,7 @@ def test_blockchain_via_engine( # Send a initial forkchoice update with timing_data.time("Initial forkchoice update"): logger.info("Sending initial forkchoice update to genesis block...") - delay = 0.5 - for attempt in range(3): + for attempt in range(1, MAX_RETRIES + 1): forkchoice_response = engine_rpc.forkchoice_updated( forkchoice_state=ForkchoiceState( head_block_hash=fixture.genesis.block_hash, @@ -54,16 +56,16 @@ def test_blockchain_via_engine( version=fixture.payloads[0].forkchoice_updated_version, ) status = forkchoice_response.payload_status.status - logger.info(f"Initial forkchoice update response attempt {attempt + 1}: {status}") + logger.info(f"Initial forkchoice update response attempt {attempt}: {status}") if status != PayloadStatusEnum.SYNCING: break - if attempt < 2: - time.sleep(delay) - delay *= 2 + + if attempt < MAX_RETRIES: + time.sleep(DELAY_BETWEEN_RETRIES_IN_SEC) if forkchoice_response.payload_status.status != PayloadStatusEnum.VALID: logger.error( - f"Client failed to initialize properly after 3 attempts, " + f"Client failed to initialize properly after {MAX_RETRIES} attempts, " f"final status: {forkchoice_response.payload_status.status}" ) raise LoggedError( From 9190bf1c960e1d10993789ae4bc34979538b706a Mon Sep 17 00:00:00 2001 From: felipe Date: Wed, 17 Sep 2025 14:12:22 -0600 Subject: [PATCH 016/102] feat(tests): Add flexibility to expected absent scenarios for BALs (#2124) * fix(tests): Validate order for BAL coming from t8n The specs are currently correctly written, but we were not validating all of the ordering according to EIP-7928: - Addresses: lexicographic (bytewise). - Storage keys: lexicographic within each account. - Block access indices: ascending within each change list. This change validates the order of the BAL before we even begin to compare against our expectation. We also now validate that the expectations we define are subsequences within the BAL (expected order). - refactor: Explicit check for the fields we care about up front for `model_fields_set` - refactor: awkward comparison method should just be a validation method (_validate_change_lists) * chore: Unit test BAL ordering validation checks * chore: Add note to CHANGELOG * chore: move release note up to unreleased * feat(tests): Add flexibility to expected absent scenarios for BALs - We should have flexibility in defining the absence cases we expect for block-level access lists. This allows us to define absence validators for any case we might want to validate against. I don't expect these to grow very much but this does provide some flexibility. * feat: Validate all validators use @validate_call appropriately * chore: changelog note for #2124 * fix: no need to raise from any parsing errors; raise general case * feat: add sanity checks to modifiers; abstract common logic --- .../block_access_list/__init__.py | 12 + .../block_access_list/absence_validators.py | 140 +++++++ .../block_access_list/modifiers.py | 268 ++++++-------- .../tests/test_block_access_lists.py | 349 ++++++++++++++++++ .../simulator_logic/test_via_rlp.py | 4 +- 5 files changed, 626 insertions(+), 147 deletions(-) create mode 100644 ethereum_test_types/block_access_list/absence_validators.py diff --git a/ethereum_test_types/block_access_list/__init__.py b/ethereum_test_types/block_access_list/__init__.py index c1d4354ae2..f099859b84 100644 --- a/ethereum_test_types/block_access_list/__init__.py +++ b/ethereum_test_types/block_access_list/__init__.py @@ -196,6 +196,9 @@ class BalAccountExpectation(CamelModel): storage_reads: List[StorageKey] = Field( default_factory=list, description="List of expected read storage slots" ) + should_not_exist: List["AbsenceValidator"] = Field( + default_factory=list, description="List of validators checking for forbidden conditions" + ) class BlockAccessListExpectation(CamelModel): @@ -400,6 +403,11 @@ def _compare_account_expectations( Only validates fields that were explicitly set in the expected model, using model_fields_set to determine what was intentionally specified. """ + # Run absence validators first + if "should_not_exist" in expected.model_fields_set: + for validator in expected.should_not_exist: + validator(actual) + change_fields = { "nonce_changes", "balance_changes", @@ -574,8 +582,12 @@ def _validate_change_lists(field_name: str, expected: List, actual: List) -> Non ) +AbsenceValidator = Callable[[BalAccountChange], None] + + __all__ = [ # Core models + "AbsenceValidator", "BlockAccessList", "BlockAccessListExpectation", "BalAccountExpectation", diff --git a/ethereum_test_types/block_access_list/absence_validators.py b/ethereum_test_types/block_access_list/absence_validators.py new file mode 100644 index 0000000000..532f06a42c --- /dev/null +++ b/ethereum_test_types/block_access_list/absence_validators.py @@ -0,0 +1,140 @@ +""" +Absence validator functions for BAL testing. + +This module provides validator functions that check for the absence of specific +changes in Block Access Lists. These validators are used with the +``should_not_exist`` field in BalAccountExpectation to ensure certain changes +do *not* occur. + +All validator functions must be decorated with +``@validate_call(validate_return=True)`` to ensure proper type validation. +This is enforced via tests. +""" + +from typing import Set + +from pydantic import validate_call + +from ethereum_test_base_types import Number, StorageKey + +from . import AbsenceValidator, BalAccountChange + + +@validate_call(validate_return=True) +def no_nonce_changes(tx_indices: Set[Number] | None = None) -> AbsenceValidator: + """ + Forbid nonce changes at specified transaction indices or all indices if None. + + Args: + tx_indices: Set of transaction indices to check. If None, + checks all transactions. + + """ + + def check(account: BalAccountChange) -> None: + for nonce_change in account.nonce_changes: + if tx_indices is None or nonce_change.tx_index in tx_indices: + raise AssertionError( + f"Unexpected nonce change found at tx {nonce_change.tx_index}" + ) + + return check + + +@validate_call(validate_return=True) +def no_balance_changes(tx_indices: Set[Number] | None = None) -> AbsenceValidator: + """ + Forbid balance changes at specified transaction indices or all indices + if None. + + Args: + tx_indices: Set of transaction indices to check. If None, + checks all transactions. + + """ + + def check(account: BalAccountChange) -> None: + for balance_change in account.balance_changes: + if tx_indices is None or balance_change.tx_index in tx_indices: + raise AssertionError( + f"Unexpected balance change found at tx {balance_change.tx_index}" + ) + + return check + + +@validate_call(validate_return=True) +def no_storage_changes( + slots: Set[StorageKey] | None = None, + tx_indices: Set[Number] | None = None, +) -> AbsenceValidator: + """ + Forbid storage changes at specified slots and/or transaction indices. + + Args: + slots: Set of storage slots to check. If None, checks all slots. + tx_indices: Set of transaction indices to check. If None, + checks all transactions. + + """ + + def check(account: BalAccountChange) -> None: + for storage_slot in account.storage_changes: + if slots is None or storage_slot.slot in slots: + for slot_change in storage_slot.slot_changes: + if tx_indices is None or slot_change.tx_index in tx_indices: + raise AssertionError( + "Unexpected storage change found at slot " + f"{storage_slot.slot} in tx " + f"{slot_change.tx_index}" + ) + + return check + + +@validate_call(validate_return=True) +def no_storage_reads(slots: Set[StorageKey] | None = None) -> AbsenceValidator: + """ + Forbid storage reads at specified slots or all slots if None. + + Args: + slots: Set of storage slots to check. If None, checks all slots. + + """ + + def check(account: BalAccountChange) -> None: + for read_slot in account.storage_reads: + if slots is None or read_slot in slots: + raise AssertionError(f"Unexpected storage read found at slot {read_slot}") + + return check + + +@validate_call(validate_return=True) +def no_code_changes(tx_indices: Set[Number] | None = None) -> AbsenceValidator: + """ + Forbid code changes at specified transaction indices or all indices + if None. + + Args: + tx_indices: Set of transaction indices to check. If None, + checks all transactions. + + """ + + def check(account: BalAccountChange) -> None: + for code_change in account.code_changes: + if tx_indices is None or code_change.tx_index in tx_indices: + raise AssertionError(f"Unexpected code change found at tx {code_change.tx_index}") + + return check + + +__all__ = [ + "AbsenceValidator", + "no_nonce_changes", + "no_balance_changes", + "no_storage_changes", + "no_storage_reads", + "no_code_changes", +] diff --git a/ethereum_test_types/block_access_list/modifiers.py b/ethereum_test_types/block_access_list/modifiers.py index 57bd1a8f89..b33f2b067c 100644 --- a/ethereum_test_types/block_access_list/modifiers.py +++ b/ethereum_test_types/block_access_list/modifiers.py @@ -6,7 +6,7 @@ combined to create complex modifications. """ -from typing import Callable, List +from typing import Any, Callable, List, Optional from ethereum_test_base_types import Address, HexNumber @@ -20,222 +20,178 @@ ) -def remove_accounts(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: - """Remove entire account entries from the BAL.""" - - def transform(bal: BlockAccessList) -> BlockAccessList: - new_root = [] - for account_change in bal.root: - if account_change.address not in addresses: - new_root.append(account_change) - return BlockAccessList(root=new_root) - - return transform - - -def remove_nonces(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: - """Remove nonce changes from specified accounts.""" +def _remove_field_from_accounts( + addresses: tuple[Address, ...], field_name: str +) -> Callable[[BlockAccessList], BlockAccessList]: + """Abstracted helper to remove a field from specified accounts.""" + len_addresses = len(addresses) + found_addresses = set() def transform(bal: BlockAccessList) -> BlockAccessList: + nonlocal found_addresses new_root = [] for account_change in bal.root: if account_change.address in addresses: - # Create a copy without nonce changes + found_addresses.add(account_change.address) new_account = account_change.model_copy(deep=True) - new_account.nonce_changes = [] + # clear the specified field + setattr(new_account, field_name, []) new_root.append(new_account) else: new_root.append(account_change) + + if len(found_addresses) != len_addresses: + # sanity check that we found all addresses specified + missing = set(addresses) - found_addresses + raise ValueError(f"Some specified addresses were not found in the BAL: {missing}") + return BlockAccessList(root=new_root) return transform -def remove_balances(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: - """Remove balance changes from specified accounts.""" +def _modify_field_value( + address: Address, + tx_index: int, + field_name: str, + change_class: type, + new_value: Any, + value_field: str = "post_value", + nested: bool = False, + slot: Optional[int] = None, +) -> Callable[[BlockAccessList], BlockAccessList]: + """Abstracted helper to modify a field value for a specific account and transaction.""" + found_address = False def transform(bal: BlockAccessList) -> BlockAccessList: + nonlocal found_address new_root = [] for account_change in bal.root: - if account_change.address in addresses: - # Create a copy without balance changes + if account_change.address == address: + found_address = True new_account = account_change.model_copy(deep=True) - new_account.balance_changes = [] + changes = getattr(new_account, field_name) + + if changes: + if nested and slot is not None: + # nested structure (storage) + for storage_slot in changes: + if storage_slot.slot == slot: + for j, change in enumerate(storage_slot.slot_changes): + if change.tx_index == tx_index: + kwargs = {"tx_index": tx_index, value_field: new_value} + storage_slot.slot_changes[j] = change_class(**kwargs) + break + break + else: + # flat structure (nonce, balance, code) + for i, change in enumerate(changes): + if change.tx_index == tx_index: + kwargs = {"tx_index": tx_index, value_field: new_value} + changes[i] = change_class(**kwargs) + break + new_root.append(new_account) else: new_root.append(account_change) + + if not found_address: + # sanity check that we actually found the address + raise ValueError(f"Address {address} not found in BAL to modify {field_name}") + return BlockAccessList(root=new_root) return transform -def remove_storage(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: - """Remove storage changes from specified accounts.""" +def remove_accounts(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: + """Remove entire account entries from the BAL.""" def transform(bal: BlockAccessList) -> BlockAccessList: new_root = [] for account_change in bal.root: - if account_change.address in addresses: - # Create a copy without storage changes - new_account = account_change.model_copy(deep=True) - new_account.storage_changes = [] - new_root.append(new_account) - else: + if account_change.address not in addresses: new_root.append(account_change) return BlockAccessList(root=new_root) return transform -def remove_storage_reads(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: - """Remove storage reads from specified accounts.""" +def remove_nonces(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: + """Remove nonce changes from specified accounts.""" + return _remove_field_from_accounts(addresses, "nonce_changes") - def transform(bal: BlockAccessList) -> BlockAccessList: - new_root = [] - for account_change in bal.root: - if account_change.address in addresses: - # Create a copy without storage reads - new_account = account_change.model_copy(deep=True) - new_account.storage_reads = [] - new_root.append(new_account) - else: - new_root.append(account_change) - return BlockAccessList(root=new_root) - return transform +def remove_balances(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: + """Remove balance changes from specified accounts.""" + return _remove_field_from_accounts(addresses, "balance_changes") -def remove_code(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: - """Remove code changes from specified accounts.""" +def remove_storage(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: + """Remove storage changes from specified accounts.""" + return _remove_field_from_accounts(addresses, "storage_changes") - def transform(bal: BlockAccessList) -> BlockAccessList: - new_root = [] - for account_change in bal.root: - if account_change.address in addresses: - # Create a copy without code changes - new_account = account_change.model_copy(deep=True) - new_account.code_changes = [] - new_root.append(new_account) - else: - new_root.append(account_change) - return BlockAccessList(root=new_root) - return transform +def remove_storage_reads(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: + """Remove storage reads from specified accounts.""" + return _remove_field_from_accounts(addresses, "storage_reads") + + +def remove_code(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: + """Remove code changes from specified accounts.""" + return _remove_field_from_accounts(addresses, "code_changes") def modify_nonce( address: Address, tx_index: int, nonce: int ) -> Callable[[BlockAccessList], BlockAccessList]: """Set an incorrect nonce value for a specific account and transaction.""" - - def transform(bal: BlockAccessList) -> BlockAccessList: - new_root = [] - for account_change in bal.root: - if account_change.address == address: - new_account = account_change.model_copy(deep=True) - # Find and modify the specific nonce change - for i, nonce_change in enumerate(new_account.nonce_changes or []): - if nonce_change.tx_index == tx_index: - new_account.nonce_changes[i] = BalNonceChange( - tx_index=tx_index, post_nonce=nonce - ) - break - new_root.append(new_account) - else: - new_root.append(account_change) - return BlockAccessList(root=new_root) - - return transform + return _modify_field_value( + address, tx_index, "nonce_changes", BalNonceChange, nonce, "post_nonce" + ) def modify_balance( address: Address, tx_index: int, balance: int ) -> Callable[[BlockAccessList], BlockAccessList]: """Set an incorrect balance value for a specific account and transaction.""" - - def transform(bal: BlockAccessList) -> BlockAccessList: - new_root = [] - for account_change in bal.root: - if account_change.address == address: - new_account = account_change.model_copy(deep=True) - # Find and modify the specific balance change - if new_account.balance_changes: - for i, balance_change in enumerate(new_account.balance_changes): - if balance_change.tx_index == tx_index: - # Create new balance change with wrong value - new_account.balance_changes[i] = BalBalanceChange( - tx_index=tx_index, post_balance=balance - ) - break - new_root.append(new_account) - else: - new_root.append(account_change) - return BlockAccessList(root=new_root) - - return transform + return _modify_field_value( + address, tx_index, "balance_changes", BalBalanceChange, balance, "post_balance" + ) def modify_storage( address: Address, tx_index: int, slot: int, value: int ) -> Callable[[BlockAccessList], BlockAccessList]: """Set an incorrect storage value for a specific account, transaction, and slot.""" - - def transform(bal: BlockAccessList) -> BlockAccessList: - new_root = [] - for account_change in bal.root: - if account_change.address == address: - new_account = account_change.model_copy(deep=True) - # Find and modify the specific storage change (nested structure) - if new_account.storage_changes: - for storage_slot in new_account.storage_changes: - if storage_slot.slot == slot: - for j, change in enumerate(storage_slot.slot_changes): - if change.tx_index == tx_index: - # Create new storage change with wrong value - storage_slot.slot_changes[j] = BalStorageChange( - tx_index=tx_index, post_value=value - ) - break - break - new_root.append(new_account) - else: - new_root.append(account_change) - return BlockAccessList(root=new_root) - - return transform + return _modify_field_value( + address, + tx_index, + "storage_changes", + BalStorageChange, + value, + "post_value", + nested=True, + slot=slot, + ) def modify_code( address: Address, tx_index: int, code: bytes ) -> Callable[[BlockAccessList], BlockAccessList]: """Set an incorrect code value for a specific account and transaction.""" - - def transform(bal: BlockAccessList) -> BlockAccessList: - new_root = [] - for account_change in bal.root: - if account_change.address == address: - new_account = account_change.model_copy(deep=True) - # Find and modify the specific code change - if new_account.code_changes: - for i, code_change in enumerate(new_account.code_changes): - if code_change.tx_index == tx_index: - # Create new code change with wrong value - new_account.code_changes[i] = BalCodeChange( - tx_index=tx_index, post_code=code - ) - break - new_root.append(new_account) - else: - new_root.append(account_change) - return BlockAccessList(root=new_root) - - return transform + return _modify_field_value(address, tx_index, "code_changes", BalCodeChange, code, "post_code") def swap_tx_indices(tx1: int, tx2: int) -> Callable[[BlockAccessList], BlockAccessList]: """Swap transaction indices throughout the BAL, modifying tx ordering.""" + nonce_indices = {tx1: False, tx2: False} + balance_indices = nonce_indices.copy() + storage_indices = nonce_indices.copy() + code_indices = nonce_indices.copy() def transform(bal: BlockAccessList) -> BlockAccessList: + nonlocal nonce_indices, balance_indices, storage_indices, code_indices new_root = [] for account_change in bal.root: new_account = account_change.model_copy(deep=True) @@ -244,16 +200,20 @@ def transform(bal: BlockAccessList) -> BlockAccessList: if new_account.nonce_changes: for nonce_change in new_account.nonce_changes: if nonce_change.tx_index == tx1: + nonce_indices[tx1] = True nonce_change.tx_index = HexNumber(tx2) elif nonce_change.tx_index == tx2: + nonce_indices[tx2] = True nonce_change.tx_index = HexNumber(tx1) # Swap in balance changes if new_account.balance_changes: for balance_change in new_account.balance_changes: if balance_change.tx_index == tx1: + balance_indices[tx1] = True balance_change.tx_index = HexNumber(tx2) elif balance_change.tx_index == tx2: + balance_indices[tx2] = True balance_change.tx_index = HexNumber(tx1) # Swap in storage changes (nested structure) @@ -261,8 +221,10 @@ def transform(bal: BlockAccessList) -> BlockAccessList: for storage_slot in new_account.storage_changes: for storage_change in storage_slot.slot_changes: if storage_change.tx_index == tx1: + balance_indices[tx1] = True storage_change.tx_index = HexNumber(tx2) elif storage_change.tx_index == tx2: + balance_indices[tx2] = True storage_change.tx_index = HexNumber(tx1) # Note: storage_reads is just a list of StorageKey, no tx_index to swap @@ -271,8 +233,10 @@ def transform(bal: BlockAccessList) -> BlockAccessList: if new_account.code_changes: for code_change in new_account.code_changes: if code_change.tx_index == tx1: + code_indices[tx1] = True code_change.tx_index = HexNumber(tx2) elif code_change.tx_index == tx2: + code_indices[tx2] = True code_change.tx_index = HexNumber(tx1) new_root.append(new_account) @@ -297,14 +261,22 @@ def transform(bal: BlockAccessList) -> BlockAccessList: def duplicate_account(address: Address) -> Callable[[BlockAccessList], BlockAccessList]: """Duplicate an account entry in the BAL.""" + address_present = False def transform(bal: BlockAccessList) -> BlockAccessList: + nonlocal address_present new_root = [] for account_change in bal.root: new_root.append(account_change) if account_change.address == address: # Add duplicate immediately after new_root.append(account_change.model_copy(deep=True)) + address_present = True + + if not address_present: + # sanity check that we actually duplicate + raise ValueError(f"Address {address} not found in BAL to duplicate") + return BlockAccessList(root=new_root) return transform @@ -344,7 +316,7 @@ def transform(bal: BlockAccessList) -> BlockAccessList: def clear_all() -> Callable[[BlockAccessList], BlockAccessList]: """Return an empty BAL.""" - def transform(bal: BlockAccessList) -> BlockAccessList: + def transform(_bal: BlockAccessList) -> BlockAccessList: return BlockAccessList(root=[]) return transform @@ -352,12 +324,18 @@ def transform(bal: BlockAccessList) -> BlockAccessList: def keep_only(*addresses: Address) -> Callable[[BlockAccessList], BlockAccessList]: """Keep only the specified accounts, removing all others.""" + len_addresses = len(addresses) def transform(bal: BlockAccessList) -> BlockAccessList: new_root = [] for account_change in bal.root: if account_change.address in addresses: new_root.append(account_change) + + if len(new_root) != len_addresses: + # sanity check that we found all specified addresses + raise ValueError("Some specified addresses were not found in the BAL") + return BlockAccessList(root=new_root) return transform diff --git a/ethereum_test_types/tests/test_block_access_lists.py b/ethereum_test_types/tests/test_block_access_lists.py index 707df0a9c3..4406d413b8 100644 --- a/ethereum_test_types/tests/test_block_access_lists.py +++ b/ethereum_test_types/tests/test_block_access_lists.py @@ -14,6 +14,14 @@ BlockAccessList, BlockAccessListExpectation, BlockAccessListValidationError, + absence_validators, +) +from ethereum_test_types.block_access_list.absence_validators import ( + no_balance_changes, + no_code_changes, + no_nonce_changes, + no_storage_changes, + no_storage_reads, ) @@ -510,3 +518,344 @@ def test_expected_tx_indices_ordering(expected_tx_indices, should_pass): match="not found or not in correct order", ): expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize("has_change_should_raise", [True, False]) +def test_absence_validator_nonce_changes(has_change_should_raise): + """Test nonce_changes_at_tx validator with present/absent changes.""" + alice = Address(0xA) + + nonce_changes = [BalNonceChange(tx_index=1, post_nonce=1)] + if has_change_should_raise: + # add nonce change at tx 2 which should trigger failure + nonce_changes.append(BalNonceChange(tx_index=2, post_nonce=2)) + + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=alice, + nonce_changes=nonce_changes, + ), + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + # no nonce changes at tx 2 + alice: BalAccountExpectation(should_not_exist=[no_nonce_changes({2})]) + } + ) + + if has_change_should_raise: + with pytest.raises(Exception, match="Unexpected nonce change found at tx 0x2"): + expectation.verify_against(actual_bal) + else: + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize("has_change_should_raise", [True, False]) +def test_absence_validator_balance_changes(has_change_should_raise): + """Test balance_changes_at_tx validator with present/absent changes.""" + alice = Address(0xA) + + balance_changes = [BalBalanceChange(tx_index=1, post_balance=100)] + if has_change_should_raise: + # add balance change at tx 2 which should trigger failure + balance_changes.append(BalBalanceChange(tx_index=2, post_balance=200)) + + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=alice, + balance_changes=balance_changes, + ), + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + should_not_exist=[no_balance_changes({2})], + ), + } + ) + + if has_change_should_raise: + with pytest.raises( + Exception, + match="Unexpected balance change found at tx 0x2", + ): + expectation.verify_against(actual_bal) + else: + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize("has_change_should_raise", [True, False]) +def test_absence_validator_storage_changes(has_change_should_raise): + """Test storage_changes_at_slots validator with present/absent changes.""" + contract = Address(0xC) + + storage_changes = [ + BalStorageSlot( + slot=0x01, + slot_changes=[BalStorageChange(tx_index=1, post_value=0x99)], + ) + ] + if has_change_should_raise: + storage_changes.append( + BalStorageSlot( + slot=0x42, + slot_changes=[BalStorageChange(tx_index=1, post_value=0xBEEF)], + ) + ) + + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=contract, + storage_changes=storage_changes, + ), + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + # no storage changes at slot 0x42 + contract: BalAccountExpectation(should_not_exist=[no_storage_changes(slots={0x42})]), + } + ) + + if has_change_should_raise: + with pytest.raises(Exception, match="Unexpected storage change found at slot"): + expectation.verify_against(actual_bal) + else: + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize("has_read_should_raise", [True, False]) +def test_absence_validator_storage_reads(has_read_should_raise): + """Test storage_reads_at_slots validator with present/absent reads.""" + contract = Address(0xC) + + # Create actual BAL with or without storage read at slot 0x42 + storage_reads = [StorageKey(0x01)] + if has_read_should_raise: + storage_reads.append(StorageKey(0x42)) + + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=contract, + storage_reads=storage_reads, + ), + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + # no storage reads at slot 0x42 + contract: BalAccountExpectation(should_not_exist=[no_storage_reads({0x42})]), + } + ) + + if has_read_should_raise: + with pytest.raises(Exception, match="Unexpected storage read found at slot"): + expectation.verify_against(actual_bal) + else: + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize("has_change_should_raise", [True, False]) +def test_absence_validator_code_changes(has_change_should_raise): + """Test code_changes_at_tx validator with present/absent changes.""" + alice = Address(0xA) + + code_changes = [BalCodeChange(tx_index=1, new_code=b"\x00")] + if has_change_should_raise: + # add code change at tx 2 which should trigger failure + code_changes.append(BalCodeChange(tx_index=2, new_code=b"\x60\x00")) + + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=alice, + code_changes=code_changes, + ), + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + # no code changes at tx 2 + alice: BalAccountExpectation(should_not_exist=[no_code_changes({2})]), + } + ) + + if has_change_should_raise: + with pytest.raises(Exception, match="Unexpected code change found at tx 0x2"): + expectation.verify_against(actual_bal) + else: + expectation.verify_against(actual_bal) + + +def test_multiple_absence_validators(): + """Test multiple absence validators working together.""" + contract = Address(0xC) + + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=contract, + nonce_changes=[], + balance_changes=[], + storage_changes=[ + BalStorageSlot( + slot=0x01, + slot_changes=[BalStorageChange(tx_index=1, post_value=0x99)], + ) + ], + storage_reads=[StorageKey(0x01)], + code_changes=[], + ), + ] + ) + + # Test that multiple validators all pass + expectation = BlockAccessListExpectation( + account_expectations={ + contract: BalAccountExpectation( + storage_changes=[ + BalStorageSlot( + slot=0x01, + slot_changes=[BalStorageChange(tx_index=1, post_value=0x99)], + ) + ], + should_not_exist=[ + no_nonce_changes({1, 2}), # No nonce changes at tx 1 or 2 + no_balance_changes({1, 2}), # No balance changes at tx 1 or 2 + no_storage_changes(slots={0x42, 0x43}), # These slots not changed + no_storage_reads({0x42, 0x43}), # These slots not read + no_code_changes({1, 2}), # No code changes at tx 1 or 2 + ], + ), + } + ) + + expectation.verify_against(actual_bal) + + +def test_absence_validator_with_multiple_tx_indices(): + """Test absence validators with multiple transaction indices.""" + alice = Address(0xA) + + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=alice, + nonce_changes=[ + # nonce changes at tx 1 and 3 + BalNonceChange(tx_index=1, post_nonce=1), + BalNonceChange(tx_index=3, post_nonce=2), + ], + ), + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[ + BalNonceChange(tx_index=1, post_nonce=1), + BalNonceChange(tx_index=3, post_nonce=2), + ], + should_not_exist=[ + # should not be changes at tx 2 and 4 + no_nonce_changes({2, 4}), + ], + ), + } + ) + + expectation.verify_against(actual_bal) + + expectation_fail = BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + should_not_exist=[ + # wrongly forbid change at txs 1 and 2 (1 exists, so should fail) + no_nonce_changes({1, 2}), + ], + ), + } + ) + + with pytest.raises(Exception, match="Unexpected nonce change found at tx 0x1"): + expectation_fail.verify_against(actual_bal) + + +@pytest.mark.parametrize( + "validator_func,field_name,changes,error_pattern", + [ + ( + no_nonce_changes(), + "nonce_changes", + [BalNonceChange(tx_index=1, post_nonce=1)], + "Unexpected nonce change found at tx", + ), + ( + no_balance_changes(), + "balance_changes", + [BalBalanceChange(tx_index=2, post_balance=100)], + "Unexpected balance change found at tx", + ), + ( + no_code_changes(), + "code_changes", + [BalCodeChange(tx_index=3, new_code=b"\x60\x00")], + "Unexpected code change found at tx", + ), + ( + no_storage_reads(), + "storage_reads", + [StorageKey(0x42)], + "Unexpected storage read found at slot", + ), + ( + no_storage_changes(), + "storage_changes", + [ + BalStorageSlot( + slot=0x01, slot_changes=[BalStorageChange(tx_index=1, post_value=99)] + ) + ], + "Unexpected storage change found at slot", + ), + ], +) +def test_absence_validator_forbids_all(validator_func, field_name, changes, error_pattern): + """Test that validators without specific indices/slots forbid ALL changes.""" + addr = Address(0xA) + + actual_bal = BlockAccessList([BalAccountChange(address=addr, **{field_name: changes})]) + + expectation = BlockAccessListExpectation( + account_expectations={ + addr: BalAccountExpectation(should_not_exist=[validator_func]), + } + ) + + with pytest.raises(Exception, match=error_pattern): + expectation.verify_against(actual_bal) + + +def test_all_absence_validators_use_validate_call(): + """Test that all exported absence validators use @validate_call decorator.""" + validator_names = [name for name in absence_validators.__all__ if name != "AbsenceValidator"] + + for name in validator_names: + func = getattr(absence_validators, name) + + assert hasattr(func, "__wrapped__"), ( + f"{name} is not decorated with `@validate_call`. " + "All validators must use `@validate_call(validate_return=True)`." + ) diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py index 936819385b..4c63eba5b7 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py @@ -65,8 +65,8 @@ def test_via_rlp( "blockHash mismatch in last block - field mismatches:" "\n" + "\n".join(mismatches) ) - except Exception as e: + except Exception: raise AssertionError( f"blockHash mismatch in last block: got `{block['hash']}`, " f"expected `{fixture.last_block_hash}`" - ) from e + ) from None From 108af8c8d3008d41b8ed52fb8df7abb4c137d5e5 Mon Sep 17 00:00:00 2001 From: felix Date: Thu, 18 Sep 2025 08:52:10 +0000 Subject: [PATCH 017/102] chore(tooling): enforce ruff rule c420 (#2146) * enforce c420 * enforce ruff rule c420 * Update tests/prague/eip7702_set_code_tx/test_gas.py Co-authored-by: danceratopz * Update tests/cancun/eip1153_tstore/test_tstorage.py Co-authored-by: danceratopz * Update tests/cancun/eip1153_tstore/test_tstorage.py Co-authored-by: danceratopz * Update tests/cancun/eip1153_tstore/test_tstorage.py Co-authored-by: danceratopz --------- Co-authored-by: danceratopz --- cancun/eip1153_tstore/test_tstorage.py | 14 +++++++------- cancun/eip4788_beacon_root/spec.py | 2 +- cancun/eip4844_blobs/test_blobhash_opcode.py | 2 +- .../test_point_evaluation_precompile.py | 2 +- prague/eip7702_set_code_tx/test_gas.py | 2 +- prague/eip7702_set_code_tx/test_set_code_txs.py | 8 ++++---- prague/eip7702_set_code_tx/test_set_code_txs_2.py | 2 +- .../eip3540_eof_v1/test_execution_function.py | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cancun/eip1153_tstore/test_tstorage.py b/cancun/eip1153_tstore/test_tstorage.py index 0b84b63857..990cd804e3 100644 --- a/cancun/eip1153_tstore/test_tstorage.py +++ b/cancun/eip1153_tstore/test_tstorage.py @@ -45,7 +45,7 @@ def test_transient_storage_unset_values(state_test: StateTestFiller, pre: Alloc) code_address = pre.deploy_contract( code=code, # type: ignore - storage={slot: 1 for slot in slots_under_test}, + storage=dict.fromkeys(slots_under_test, 1), ) tx = Transaction( @@ -54,7 +54,7 @@ def test_transient_storage_unset_values(state_test: StateTestFiller, pre: Alloc) gas_limit=1_000_000, ) - post = {code_address: Account(storage={slot: 0 for slot in slots_under_test})} + post = {code_address: Account(storage=dict.fromkeys(slots_under_test, 0))} state_test( env=env, @@ -79,7 +79,7 @@ def test_tload_after_tstore(state_test: StateTestFiller, pre: Alloc): ) code_address = pre.deploy_contract( code=code, # type: ignore - storage={slot: 0xFF for slot in slots_under_test}, + storage=dict.fromkeys(slots_under_test, 0xFF), ) tx = Transaction( @@ -114,7 +114,7 @@ def test_tload_after_sstore(state_test: StateTestFiller, pre: Alloc): ) code_address = pre.deploy_contract( code=code, # type: ignore - storage={slot: 1 for slot in slots_under_test}, + storage=dict.fromkeys(slots_under_test, 1), ) tx = Transaction( @@ -127,7 +127,7 @@ def test_tload_after_sstore(state_test: StateTestFiller, pre: Alloc): code_address: Account( code=code, storage={slot - 1: 0xFF for slot in slots_under_test} - | {slot: 0 for slot in slots_under_test}, + | dict.fromkeys(slots_under_test, 0), ) } @@ -157,7 +157,7 @@ def test_tload_after_tstore_is_zero(state_test: StateTestFiller, pre: Alloc): code_address = pre.deploy_contract( code=code, # type: ignore - storage={slot: 0xFFFF for slot in slots_to_write + slots_to_read}, + storage=dict.fromkeys(slots_to_write + slots_to_read, 0xFFFF), ) tx = Transaction( @@ -168,7 +168,7 @@ def test_tload_after_tstore_is_zero(state_test: StateTestFiller, pre: Alloc): post = { code_address: Account( - storage={slot: 0 for slot in slots_to_read} | {slot: 0xFFFF for slot in slots_to_write} + storage=dict.fromkeys(slots_to_read, 0) | dict.fromkeys(slots_to_write, 0xFFFF) ) } diff --git a/cancun/eip4788_beacon_root/spec.py b/cancun/eip4788_beacon_root/spec.py index 9a4c4ba99f..4cbd2975de 100644 --- a/cancun/eip4788_beacon_root/spec.py +++ b/cancun/eip4788_beacon_root/spec.py @@ -58,7 +58,7 @@ def expected_storage( - validity of the timestamp input used within the call. """ # By default assume the call is unsuccessful and all keys are zero - storage = Storage({k: 0 for k in range(4)}) # type: ignore + storage = Storage(dict.fromkeys(range(4), 0)) # type: ignore if valid_call and valid_input: # beacon root contract call is successful storage[0] = 1 diff --git a/cancun/eip4844_blobs/test_blobhash_opcode.py b/cancun/eip4844_blobs/test_blobhash_opcode.py index b33d5540c8..b22883be03 100644 --- a/cancun/eip4844_blobs/test_blobhash_opcode.py +++ b/cancun/eip4844_blobs/test_blobhash_opcode.py @@ -387,7 +387,7 @@ def blob_tx(address: Address, tx_type: int): storage={i: random_blob_hashes[i] for i in range(max_blobs_per_tx)} ) if address in (addresses[1], addresses[3]) - else Account(storage={i: 0 for i in range(max_blobs_per_tx)}) + else Account(storage=dict.fromkeys(range(max_blobs_per_tx), 0)) for address in addresses } blockchain_test( diff --git a/cancun/eip4844_blobs/test_point_evaluation_precompile.py b/cancun/eip4844_blobs/test_point_evaluation_precompile.py index cf218a5dea..a878976526 100644 --- a/cancun/eip4844_blobs/test_point_evaluation_precompile.py +++ b/cancun/eip4844_blobs/test_point_evaluation_precompile.py @@ -700,7 +700,7 @@ def test_precompile_during_fork( post = { precompile_caller_address: Account( - storage={b: 1 for b in range(1, len(PRE_FORK_BLOCK_RANGE) + 1)}, + storage=dict.fromkeys(range(1, len(PRE_FORK_BLOCK_RANGE) + 1), 1), # Only the call in the last block's tx fails; storage 0 by default. ), Address(Spec.POINT_EVALUATION_PRECOMPILE_ADDRESS): Account( diff --git a/prague/eip7702_set_code_tx/test_gas.py b/prague/eip7702_set_code_tx/test_gas.py index f37e43a523..af634fc29d 100644 --- a/prague/eip7702_set_code_tx/test_gas.py +++ b/prague/eip7702_set_code_tx/test_gas.py @@ -959,7 +959,7 @@ def test_account_warming( callee_code += Op.STOP callee_address = pre.deploy_contract( callee_code, - storage={check_address: 0xDEADBEEF for check_address in addresses_to_check}, + storage=dict.fromkeys(addresses_to_check, 0xDEADBEEF), ) tx = Transaction( diff --git a/prague/eip7702_set_code_tx/test_set_code_txs.py b/prague/eip7702_set_code_tx/test_set_code_txs.py index aa94f2fe60..090fea22fb 100644 --- a/prague/eip7702_set_code_tx/test_set_code_txs.py +++ b/prague/eip7702_set_code_tx/test_set_code_txs.py @@ -128,7 +128,7 @@ def test_self_sponsored_set_code( pre=pre, tx=tx, post={ - set_code_to_address: Account(storage={k: 0 for k in storage}), + set_code_to_address: Account(storage=dict.fromkeys(storage, 0)), sender: Account( nonce=2, code=Spec.delegation_designation(set_code_to_address), @@ -208,7 +208,7 @@ def test_set_code_to_sstore( tx=tx, post={ set_code_to_address: Account( - storage={k: 0 for k in storage}, + storage=dict.fromkeys(storage, 0), ), auth_signer: Account( nonce=2 if self_sponsored else 1, @@ -799,8 +799,8 @@ def test_set_code_call_set_code( pre=pre, tx=tx, post={ - set_code_to_address_1: Account(storage={k: 0 for k in storage_1}), - set_code_to_address_2: Account(storage={k: 0 for k in storage_2}), + set_code_to_address_1: Account(storage=dict.fromkeys(storage_1, 0)), + set_code_to_address_2: Account(storage=dict.fromkeys(storage_2, 0)), auth_signer_1: Account( nonce=1, code=Spec.delegation_designation(set_code_to_address_1), diff --git a/prague/eip7702_set_code_tx/test_set_code_txs_2.py b/prague/eip7702_set_code_tx/test_set_code_txs_2.py index 20023e713c..c7733c238f 100644 --- a/prague/eip7702_set_code_tx/test_set_code_txs_2.py +++ b/prague/eip7702_set_code_tx/test_set_code_txs_2.py @@ -1745,7 +1745,7 @@ def test_set_code_type_tx_pre_fork( pre=pre, tx=tx, post={ - set_code_to_address: Account(storage={k: 0 for k in storage}), + set_code_to_address: Account(storage=dict.fromkeys(storage, 0)), sender: Account( nonce=0, code="", diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py index 212d86f502..33d6fe41c5 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py @@ -419,7 +419,7 @@ def test_eof_functions_contract_call_within_deep_nested( sender=sender, ) post = { - callee_address: Account(storage={i: 1 for i in range(MAX_CODE_SECTIONS)}), + callee_address: Account(storage=dict.fromkeys(range(MAX_CODE_SECTIONS), 1)), nested_callee_address: Account( storage={ 0: 1, From 295d6b3e427c0ba16652159b5a0e7c5cdf1d48a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Thu, 18 Sep 2025 21:23:15 +0800 Subject: [PATCH 018/102] refactor(benchmark): update expected gas usage rule for flexibility (#2155) * refactor: update expected gas usage rule for flexibility * docs(benchmarks): clarify gas usage check flexibility * feat(tests): introduce skip_gas_used_validation flag for flexible gas checks * docs(benchmarks): update gas usage check to use skip_gas_used_validation flag --- ethereum_test_specs/base.py | 2 ++ ethereum_test_specs/blockchain.py | 12 +++++++----- ethereum_test_specs/state.py | 13 +++++++------ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ethereum_test_specs/base.py b/ethereum_test_specs/base.py index 45da6fde83..a82c0d9456 100644 --- a/ethereum_test_specs/base.py +++ b/ethereum_test_specs/base.py @@ -73,6 +73,7 @@ class BaseTest(BaseModel): _gas_optimization_max_gas_limit: int | None = PrivateAttr(None) expected_benchmark_gas_used: int | None = None + skip_gas_used_validation: bool = False spec_types: ClassVar[Dict[str, Type["BaseTest"]]] = {} @@ -117,6 +118,7 @@ def from_test( tag=base_test.tag, t8n_dump_dir=base_test.t8n_dump_dir, expected_benchmark_gas_used=base_test.expected_benchmark_gas_used, + skip_gas_used_validation=base_test.skip_gas_used_validation, **kwargs, ) new_instance._request = base_test._request diff --git a/ethereum_test_specs/blockchain.py b/ethereum_test_specs/blockchain.py index 2848a40f38..3fb37a2688 100644 --- a/ethereum_test_specs/blockchain.py +++ b/ethereum_test_specs/blockchain.py @@ -580,11 +580,13 @@ def generate_block_data( "expected_benchmark_gas_used is not set" ) gas_used = int(transition_tool_output.result.gas_used) - assert gas_used == expected_benchmark_gas_used, ( - f"gas_used ({gas_used}) does not match expected_benchmark_gas_used " - f"({expected_benchmark_gas_used})" - f", difference: {gas_used - expected_benchmark_gas_used}" - ) + + if not self.skip_gas_used_validation: + assert gas_used == expected_benchmark_gas_used, ( + f"gas_used ({gas_used}) does not match expected_benchmark_gas_used " + f"({expected_benchmark_gas_used})" + f", difference: {gas_used - expected_benchmark_gas_used}" + ) requests_list: List[Bytes] | None = None if fork.header_requests_required(header.number, header.timestamp): diff --git a/ethereum_test_specs/state.py b/ethereum_test_specs/state.py index f840b8db1b..d45e385d4f 100644 --- a/ethereum_test_specs/state.py +++ b/ethereum_test_specs/state.py @@ -366,15 +366,16 @@ def make_state_test_fixture( if self._operation_mode == OpMode.BENCHMARKING: expected_benchmark_gas_used = self.expected_benchmark_gas_used - gas_used = int(transition_tool_output.result.gas_used) assert expected_benchmark_gas_used is not None, ( "expected_benchmark_gas_used is not set" ) - assert gas_used == expected_benchmark_gas_used, ( - f"gas_used ({gas_used}) does not match expected_benchmark_gas_used " - f"({expected_benchmark_gas_used})" - f", difference: {gas_used - expected_benchmark_gas_used}" - ) + gas_used = int(transition_tool_output.result.gas_used) + if not self.skip_gas_used_validation: + assert gas_used == expected_benchmark_gas_used, ( + f"gas_used ({gas_used}) does not match expected_benchmark_gas_used " + f"({expected_benchmark_gas_used})" + f", difference: {gas_used - expected_benchmark_gas_used}" + ) return StateFixture( env=FixtureEnvironment(**env.model_dump(exclude_none=True)), From 417eb449f32335be26ee8b01219528fe7967d830 Mon Sep 17 00:00:00 2001 From: spencer Date: Thu, 18 Sep 2025 16:57:37 +0100 Subject: [PATCH 019/102] chore(tests): fix peerdas transition test. (#2172) --- osaka/eip7594_peerdas/test_max_blob_per_tx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osaka/eip7594_peerdas/test_max_blob_per_tx.py b/osaka/eip7594_peerdas/test_max_blob_per_tx.py index 52c6eb2fde..c9d0114738 100644 --- a/osaka/eip7594_peerdas/test_max_blob_per_tx.py +++ b/osaka/eip7594_peerdas/test_max_blob_per_tx.py @@ -177,7 +177,7 @@ def test_max_blobs_per_tx_fork_transition( exception=[expected_exception], ) post_fork_block = Block( - txs=[tx.with_nonce(2).with_error(expected_exception)], + txs=[tx.with_nonce(1).with_error(expected_exception)], timestamp=FORK_TIMESTAMP + 1, exception=[expected_exception], ) From ea083d61f68640fb503a9d0e957297098d25e2bf Mon Sep 17 00:00:00 2001 From: felipe Date: Fri, 19 Sep 2025 02:57:51 -0600 Subject: [PATCH 020/102] fix: use `engine_newPayloadV5` for Glamsterdam (#2170) * fix: use engine_newPayloadV5 for Amsterdam * fix: update exception mapper for geth * fix: We should update BAL hash in fixture for invalid tests * Clean up extraneous BAL exceptions * refactor: use fork check for BAL in engine payload --- .../test_block_access_lists_invalid.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py index f86b7af401..7041a3bbcf 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py @@ -72,7 +72,7 @@ def test_bal_invalid_missing_nonce( blocks=[ Block( txs=[tx], - exception=BlockException.INCORRECT_BLOCK_FORMAT, + exception=BlockException.INVALID_BLOCK_ACCESS_LIST, expected_block_access_list=BlockAccessListExpectation( account_expectations={ sender: BalAccountExpectation( @@ -111,7 +111,7 @@ def test_bal_invalid_nonce_value( blocks=[ Block( txs=[tx], - exception=BlockException.INCORRECT_BLOCK_FORMAT, + exception=BlockException.INVALID_BLOCK_ACCESS_LIST, expected_block_access_list=BlockAccessListExpectation( account_expectations={ sender: BalAccountExpectation( @@ -155,7 +155,7 @@ def test_bal_invalid_storage_value( blocks=[ Block( txs=[tx], - exception=BlockException.INCORRECT_BLOCK_FORMAT, + exception=BlockException.INVALID_BLOCK_ACCESS_LIST, expected_block_access_list=BlockAccessListExpectation( account_expectations={ contract: BalAccountExpectation( @@ -219,7 +219,7 @@ def test_bal_invalid_tx_order( blocks=[ Block( txs=[tx1, tx2], - exception=BlockException.INCORRECT_BLOCK_FORMAT, + exception=BlockException.INVALID_BLOCK_ACCESS_LIST, expected_block_access_list=BlockAccessListExpectation( account_expectations={ sender1: BalAccountExpectation( @@ -269,7 +269,7 @@ def test_bal_invalid_account( blocks=[ Block( txs=[tx], - exception=BlockException.INCORRECT_BLOCK_FORMAT, + exception=BlockException.INVALID_BAL_EXTRA_ACCOUNT, expected_block_access_list=BlockAccessListExpectation( account_expectations={ sender: BalAccountExpectation( @@ -412,7 +412,7 @@ def test_bal_invalid_complex_corruption( blocks=[ Block( txs=[tx1, tx2], - exception=BlockException.INCORRECT_BLOCK_FORMAT, + exception=BlockException.INVALID_BLOCK_ACCESS_LIST, expected_block_access_list=BlockAccessListExpectation( account_expectations={ sender: BalAccountExpectation( @@ -474,7 +474,7 @@ def test_bal_invalid_missing_account( blocks=[ Block( txs=[tx], - exception=BlockException.INCORRECT_BLOCK_FORMAT, + exception=BlockException.INVALID_BAL_MISSING_ACCOUNT, expected_block_access_list=BlockAccessListExpectation( account_expectations={ sender: BalAccountExpectation( @@ -516,7 +516,7 @@ def test_bal_invalid_balance_value( blocks=[ Block( txs=[tx], - exception=BlockException.INCORRECT_BLOCK_FORMAT, + exception=BlockException.INVALID_BLOCK_ACCESS_LIST, expected_block_access_list=BlockAccessListExpectation( account_expectations={ receiver: BalAccountExpectation( From 7fbdfbb83b51480f10ace17581e6bdc0947d89fd Mon Sep 17 00:00:00 2001 From: felipe Date: Fri, 19 Sep 2025 02:57:51 -0600 Subject: [PATCH 021/102] fix: use `engine_newPayloadV5` for Glamsterdam (#2170) * fix: use engine_newPayloadV5 for Amsterdam * fix: update exception mapper for geth * fix: We should update BAL hash in fixture for invalid tests * Clean up extraneous BAL exceptions * refactor: use fork check for BAL in engine payload --- ethereum_clis/clis/geth.py | 4 ++++ ethereum_test_exceptions/exceptions/block.py | 17 +++++++++++++ ethereum_test_fixtures/blockchain.py | 9 +++++++ ethereum_test_forks/base_fork.py | 11 +++++++++ ethereum_test_forks/forks/forks.py | 24 +++++++++++++++++++ ethereum_test_specs/blockchain.py | 15 +++++++----- .../block_access_list/__init__.py | 12 ++-------- 7 files changed, 76 insertions(+), 16 deletions(-) diff --git a/ethereum_clis/clis/geth.py b/ethereum_clis/clis/geth.py index a104410923..bf80527080 100644 --- a/ethereum_clis/clis/geth.py +++ b/ethereum_clis/clis/geth.py @@ -71,6 +71,7 @@ class GethExceptionMapper(ExceptionMapper): TransactionException.TYPE_4_TX_PRE_FORK: ("transaction type not supported"), TransactionException.INITCODE_SIZE_EXCEEDED: "max initcode size exceeded", TransactionException.NONCE_MISMATCH_TOO_LOW: "nonce too low", + TransactionException.NONCE_MISMATCH_TOO_HIGH: "nonce too high", BlockException.INVALID_DEPOSIT_EVENT_LAYOUT: "unable to parse deposit data", BlockException.INCORRECT_BLOB_GAS_USED: "blob gas used mismatch", BlockException.INCORRECT_EXCESS_BLOB_GAS: "invalid excessBlobGas", @@ -79,6 +80,9 @@ class GethExceptionMapper(ExceptionMapper): BlockException.SYSTEM_CONTRACT_CALL_FAILED: "system call failed to execute:", BlockException.INVALID_BLOCK_HASH: "blockhash mismatch", BlockException.RLP_BLOCK_LIMIT_EXCEEDED: "block RLP-encoded size exceeds maximum", + BlockException.INVALID_BAL_EXTRA_ACCOUNT: "BAL change not reported in computed", + BlockException.INVALID_BAL_MISSING_ACCOUNT: "additional mutations compared to BAL", + BlockException.INVALID_BLOCK_ACCESS_LIST: "unequal", } mapping_regex: ClassVar[Dict[ExceptionBase, str]] = { TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED: ( diff --git a/ethereum_test_exceptions/exceptions/block.py b/ethereum_test_exceptions/exceptions/block.py index 033da0bb37..4053b1938e 100644 --- a/ethereum_test_exceptions/exceptions/block.py +++ b/ethereum_test_exceptions/exceptions/block.py @@ -216,3 +216,20 @@ class BlockException(ExceptionBase): Transaction emits a `DepositEvent` in the deposit contract (EIP-6110), but the layout of the event does not match the required layout. """ + # --- Block-Level Access Lists (EIP-7928) --- # + INVALID_BLOCK_ACCESS_LIST = auto() + """ + Block's access list is invalid. + """ + INVALID_BAL_HASH = auto() + """ + Block header's BAL hash does not match the computed BAL hash. + """ + INVALID_BAL_EXTRA_ACCOUNT = auto() + """ + Block BAL contains an account change that is not present in the computed BAL. + """ + INVALID_BAL_MISSING_ACCOUNT = auto() + """ + Block BAL is missing an account change that is present in the computed BAL. + """ diff --git a/ethereum_test_fixtures/blockchain.py b/ethereum_test_fixtures/blockchain.py index c773b2af3b..74d60f16bb 100644 --- a/ethereum_test_fixtures/blockchain.py +++ b/ethereum_test_fixtures/blockchain.py @@ -301,10 +301,12 @@ def from_fixture_header( Hash, List[Bytes], ] +EngineNewPayloadV5Parameters = EngineNewPayloadV4Parameters # Important: We check EngineNewPayloadV3Parameters first as it has more fields, and pydantic # has a weird behavior when the smaller tuple is checked first. EngineNewPayloadParameters = Union[ + EngineNewPayloadV5Parameters, EngineNewPayloadV4Parameters, EngineNewPayloadV3Parameters, EngineNewPayloadV1Parameters, @@ -354,6 +356,13 @@ def from_fixture_header( ) assert new_payload_version is not None, "Invalid header for engine_newPayload" + + if fork.engine_execution_payload_block_access_list(header.number, header.timestamp): + if block_access_list is None: + raise ValueError( + f"`block_access_list` is required in engine `ExecutionPayload` for >={fork}." + ) + execution_payload = FixtureExecutionPayload.from_fixture_header( header=header, transactions=transactions, diff --git a/ethereum_test_forks/base_fork.py b/ethereum_test_forks/base_fork.py index 292c893dec..74840c55e1 100644 --- a/ethereum_test_forks/base_fork.py +++ b/ethereum_test_forks/base_fork.py @@ -553,6 +553,17 @@ def engine_new_payload_target_blobs_per_block( """ pass + @classmethod + @abstractmethod + def engine_execution_payload_block_access_list( + cls, block_number: int = 0, timestamp: int = 0 + ) -> bool: + """ + Return `True` if the engine api version requires execution payload to include a + `block_access_list`. + """ + pass + @classmethod @abstractmethod def engine_payload_attribute_target_blobs_per_block( diff --git a/ethereum_test_forks/forks/forks.py b/ethereum_test_forks/forks/forks.py index fdf519d246..9fba9f3794 100644 --- a/ethereum_test_forks/forks/forks.py +++ b/ethereum_test_forks/forks/forks.py @@ -347,6 +347,13 @@ def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) """At genesis, payloads do not have requests.""" return False + @classmethod + def engine_execution_payload_block_access_list( + cls, block_number: int = 0, timestamp: int = 0 + ) -> bool: + """At genesis, payloads do not have block access list.""" + return False + @classmethod def engine_new_payload_target_blobs_per_block( cls, @@ -1836,6 +1843,23 @@ def is_deployed(cls) -> bool: """Return True if this fork is deployed.""" return False + @classmethod + def engine_new_payload_version( + cls, block_number: int = 0, timestamp: int = 0 + ) -> Optional[int]: + """From Amsterdam, new payload calls must use version 5.""" + return 5 + + @classmethod + def engine_execution_payload_block_access_list( + cls, block_number: int = 0, timestamp: int = 0 + ) -> bool: + """ + From Amsterdam, engine execution payload includes `block_access_list` as + a parameter. + """ + return True + class EOFv1(Prague, solc_name="cancun"): """EOF fork.""" diff --git a/ethereum_test_specs/blockchain.py b/ethereum_test_specs/blockchain.py index 3fb37a2688..796a34ce4d 100644 --- a/ethereum_test_specs/blockchain.py +++ b/ethereum_test_specs/blockchain.py @@ -629,12 +629,15 @@ def generate_block_data( header.fork = fork # Deleted during `apply` because `exclude=True` # Process block access list - apply transformer if present for invalid tests - bal = transition_tool_output.result.block_access_list - if block.expected_block_access_list is not None and bal is not None: - # Use to_fixture_bal to validate and potentially transform the BAL - bal = block.expected_block_access_list.to_fixture_bal(bal) - # Don't update the header hash - leave it as the hash of the correct BAL - # This creates a mismatch that should cause the block to be rejected + t8n_bal = transition_tool_output.result.block_access_list + bal = t8n_bal + if block.expected_block_access_list is not None and t8n_bal is not None: + block.expected_block_access_list.verify_against(t8n_bal) + + bal = block.expected_block_access_list.modify_if_invalid_test(t8n_bal) + if bal != t8n_bal: + # If the BAL was modified, update the header hash + header.block_access_list_hash = Hash(bal.rlp.keccak256()) built_block = BuiltBlock( header=header, diff --git a/ethereum_test_types/block_access_list/__init__.py b/ethereum_test_types/block_access_list/__init__.py index f099859b84..3eb2e12cc8 100644 --- a/ethereum_test_types/block_access_list/__init__.py +++ b/ethereum_test_types/block_access_list/__init__.py @@ -256,12 +256,9 @@ def modify( new_instance._modifier = compose(*modifiers) return new_instance - def to_fixture_bal(self, t8n_bal: "BlockAccessList") -> "BlockAccessList": + def modify_if_invalid_test(self, t8n_bal: "BlockAccessList") -> "BlockAccessList": """ - Convert t8n BAL to fixture BAL, optionally applying transformations. - - 1. First validates expectations are met (if any) - 2. Then applies modifier if specified (for invalid tests) + Apply the modifier to the given BAL if this is an invalid test case. Args: t8n_bal: The BlockAccessList from t8n tool @@ -270,13 +267,8 @@ def to_fixture_bal(self, t8n_bal: "BlockAccessList") -> "BlockAccessList": The potentially transformed BlockAccessList for the fixture """ - if self.account_expectations: - self.verify_against(t8n_bal) - - # Apply modifier if present (for invalid tests) if self._modifier: return self._modifier(t8n_bal) - return t8n_bal def verify_against(self, actual_bal: "BlockAccessList") -> None: From e80afdd10462d58356a30ffaefc659afb6022ab2 Mon Sep 17 00:00:00 2001 From: felix Date: Fri, 19 Sep 2025 10:57:09 +0000 Subject: [PATCH 022/102] chore(all): rename shadowed modules to enable ruff a005 (#2133) --- .../test_block_access_lists.py | 2 +- benchmark/helpers.py | 2 +- benchmark/test_worst_bytecode.py | 2 +- benchmark/test_worst_compute.py | 4 ++-- benchmark/test_worst_memory.py | 2 +- benchmark/test_worst_opcode.py | 4 ++-- benchmark/test_worst_stateful_opcodes.py | 2 +- .../eip2929_gas_cost_increases/test_precompile_warming.py | 2 +- byzantium/eip198_modexp_precompile/test_modexp.py | 2 +- cancun/eip1153_tstore/test_basic_tload.py | 2 +- cancun/eip1153_tstore/test_tload_calls.py | 4 ++-- cancun/eip1153_tstore/test_tload_reentrancy.py | 6 +++--- cancun/eip1153_tstore/test_tstorage_clear_after_tx.py | 2 +- cancun/eip1153_tstore/test_tstore_reentrancy.py | 6 +++--- cancun/eip4788_beacon_root/test_beacon_root_contract.py | 2 +- cancun/eip4844_blobs/test_point_evaluation_precompile.py | 2 +- .../eip4844_blobs/test_point_evaluation_precompile_gas.py | 2 +- .../test_dynamic_create2_selfdestruct_collision.py | 2 +- .../test_reentrancy_selfdestruct_revert.py | 2 +- cancun/eip6780_selfdestruct/test_selfdestruct.py | 4 ++-- frontier/opcodes/test_all_opcodes.py | 4 ++-- frontier/opcodes/test_call.py | 4 ++-- frontier/opcodes/test_call_and_callcode_gas_calculation.py | 2 +- frontier/opcodes/test_calldatacopy.py | 2 +- frontier/opcodes/test_calldataload.py | 2 +- frontier/opcodes/test_calldatasize.py | 2 +- frontier/opcodes/test_push.py | 2 +- frontier/precompiles/test_precompiles.py | 2 +- frontier/scenarios/common.py | 2 +- frontier/scenarios/programs/all_frontier_opcodes.py | 2 +- frontier/scenarios/programs/context_calls.py | 2 +- frontier/scenarios/programs/invalid_opcodes.py | 2 +- frontier/scenarios/programs/static_violation.py | 2 +- frontier/scenarios/scenarios/call_combinations.py | 5 ++--- frontier/scenarios/scenarios/create_combinations.py | 7 +++---- frontier/scenarios/scenarios/revert_combinations.py | 6 +++--- frontier/scenarios/test_scenarios.py | 4 ++-- homestead/coverage/test_coverage.py | 4 ++-- istanbul/eip1344_chainid/test_chainid.py | 2 +- istanbul/eip152_blake2/conftest.py | 4 ++-- istanbul/eip152_blake2/test_blake2.py | 2 +- osaka/eip7594_peerdas/test_get_blobs.py | 2 +- osaka/eip7823_modexp_upper_bounds/conftest.py | 2 +- .../test_modexp_upper_bounds.py | 2 +- .../eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py | 2 +- .../test_tx_gas_limit_transition_fork.py | 2 +- osaka/eip7883_modexp_gas_increase/conftest.py | 2 +- .../eip7883_modexp_gas_increase/test_modexp_thresholds.py | 2 +- .../test_modexp_thresholds_transition.py | 2 +- osaka/eip7934_block_rlp_limit/conftest.py | 2 +- .../test_count_leading_zeros.py | 2 +- paris/security/test_selfdestruct_balance_bug.py | 2 +- prague/eip7702_set_code_tx/test_calls.py | 2 +- prague/eip7702_set_code_tx/test_set_code_txs_2.py | 4 ++-- shanghai/eip3651_warm_coinbase/test_warm_coinbase.py | 2 +- shanghai/eip3855_push0/test_push0.py | 2 +- shanghai/eip3860_initcode/helpers.py | 2 +- shanghai/eip3860_initcode/test_initcode.py | 2 +- shanghai/eip3860_initcode/test_with_eof.py | 2 +- shanghai/eip4895_withdrawals/test_withdrawals.py | 2 +- unscheduled/eip7692_eof_v1/eip3540_eof_v1/opcodes.py | 2 +- .../eip3540_eof_v1/test_container_validation.py | 2 +- .../eip7692_eof_v1/eip3540_eof_v1/test_execution.py | 2 +- .../eip3540_eof_v1/test_execution_function.py | 2 +- .../eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py | 2 +- .../eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py | 2 +- .../eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py | 2 +- .../eip4750_functions/test_code_validation.py | 2 +- .../eip7692_eof_v1/eip5450_stack/test_code_validation.py | 4 ++-- unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py | 2 +- .../eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py | 2 +- .../eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py | 2 +- .../eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py | 2 +- .../eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py | 2 +- .../eip6206_jumpf/test_nonreturning_validation.py | 2 +- .../eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py | 2 +- .../eip663_dupn_swapn_exchange/test_exchange.py | 2 +- .../eip663_dupn_swapn_exchange/test_swapn.py | 2 +- .../eip7069_extcall/test_address_space_extension.py | 2 +- .../eip7692_eof_v1/eip7069_extcall/test_calldata.py | 2 +- unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py | 5 ++--- unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py | 2 +- .../eip7692_eof_v1/eip7069_extcall/test_returndataload.py | 2 +- .../eip7480_data_section/test_code_validation.py | 2 +- .../eip7480_data_section/test_data_opcodes.py | 2 +- .../eip7480_data_section/test_datacopy_memory_expansion.py | 2 +- .../eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py | 4 ++-- .../eip7620_eof_create/test_eofcreate_failures.py | 2 +- unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py | 2 +- .../eip7620_eof_create/test_legacy_eof_creates.py | 4 ++-- .../eip7692_eof_v1/eip7620_eof_create/test_memory.py | 2 +- .../eip7692_eof_v1/eip7620_eof_create/test_returncode.py | 2 +- .../eip7620_eof_create/test_subcontainer_validation.py | 2 +- .../eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py | 2 +- .../eip7692_eof_v1/eip7873_tx_create/test_txcreate.py | 4 ++-- .../eip7873_tx_create/test_txcreate_failures.py | 4 ++-- .../eip7873_tx_create/test_txcreate_validates.py | 4 ++-- unscheduled/eip7692_eof_v1/gas_test.py | 2 +- 98 files changed, 124 insertions(+), 127 deletions(-) diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py index c01cdf698d..128f8276f8 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py @@ -11,7 +11,6 @@ Transaction, compute_create_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.block_access_list import ( BalAccountExpectation, BalBalanceChange, @@ -21,6 +20,7 @@ BalStorageSlot, BlockAccessListExpectation, ) +from ethereum_test_vm import Opcodes as Op from .spec import ref_spec_7928 diff --git a/benchmark/helpers.py b/benchmark/helpers.py index 833a5dd1ec..ca3e070572 100644 --- a/benchmark/helpers.py +++ b/benchmark/helpers.py @@ -2,7 +2,7 @@ from ethereum_test_forks import Fork from ethereum_test_tools import Bytecode -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op def code_loop_precompile_call(calldata: Bytecode, attack_block: Bytecode, fork: Fork): diff --git a/benchmark/test_worst_bytecode.py b/benchmark/test_worst_bytecode.py index 67b1eca89a..9c38e010bb 100644 --- a/benchmark/test_worst_bytecode.py +++ b/benchmark/test_worst_bytecode.py @@ -23,8 +23,8 @@ While, compute_create2_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.helpers import compute_create_address +from ethereum_test_vm import Opcodes as Op from .helpers import code_loop_precompile_call diff --git a/benchmark/test_worst_compute.py b/benchmark/test_worst_compute.py index ba5d074e66..9bfdee1648 100644 --- a/benchmark/test_worst_compute.py +++ b/benchmark/test_worst_compute.py @@ -27,9 +27,9 @@ Transaction, add_kzg_version, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types import TransactionType -from ethereum_test_vm.opcode import Opcode +from ethereum_test_vm import Opcode +from ethereum_test_vm import Opcodes as Op from ..byzantium.eip198_modexp_precompile.test_modexp import ModExpInput from ..cancun.eip4844_blobs.spec import Spec as BlobsSpec diff --git a/benchmark/test_worst_memory.py b/benchmark/test_worst_memory.py index 4a1797097a..8952c05a45 100644 --- a/benchmark/test_worst_memory.py +++ b/benchmark/test_worst_memory.py @@ -15,7 +15,7 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .helpers import code_loop_precompile_call diff --git a/benchmark/test_worst_opcode.py b/benchmark/test_worst_opcode.py index f41321fb89..e4e6e3bcf1 100644 --- a/benchmark/test_worst_opcode.py +++ b/benchmark/test_worst_opcode.py @@ -14,8 +14,8 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op -from ethereum_test_vm.opcode import Opcode +from ethereum_test_vm import Opcode +from ethereum_test_vm import Opcodes as Op from .helpers import code_loop_precompile_call diff --git a/benchmark/test_worst_stateful_opcodes.py b/benchmark/test_worst_stateful_opcodes.py index 8146175ae7..f68783e61c 100644 --- a/benchmark/test_worst_stateful_opcodes.py +++ b/benchmark/test_worst_stateful_opcodes.py @@ -25,7 +25,7 @@ compute_create2_address, compute_create_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .helpers import code_loop_precompile_call diff --git a/berlin/eip2929_gas_cost_increases/test_precompile_warming.py b/berlin/eip2929_gas_cost_increases/test_precompile_warming.py index 41fda5771d..696f68b2d5 100644 --- a/berlin/eip2929_gas_cost_increases/test_precompile_warming.py +++ b/berlin/eip2929_gas_cost_increases/test_precompile_warming.py @@ -21,7 +21,7 @@ BlockchainTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "EIPS/eip-2929.md" REFERENCE_SPEC_VERSION = "0e11417265a623adb680c527b15d0cb6701b870b" diff --git a/byzantium/eip198_modexp_precompile/test_modexp.py b/byzantium/eip198_modexp_precompile/test_modexp.py index 98c6a07058..859a73b8e1 100644 --- a/byzantium/eip198_modexp_precompile/test_modexp.py +++ b/byzantium/eip198_modexp_precompile/test_modexp.py @@ -15,7 +15,7 @@ Transaction, compute_create_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .helpers import ModExpInput, ModExpOutput diff --git a/cancun/eip1153_tstore/test_basic_tload.py b/cancun/eip1153_tstore/test_basic_tload.py index 0f93f0f6d0..0b797913a8 100644 --- a/cancun/eip1153_tstore/test_basic_tload.py +++ b/cancun/eip1153_tstore/test_basic_tload.py @@ -8,7 +8,7 @@ import pytest from ethereum_test_tools import Account, Address, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .spec import Spec, ref_spec_1153 diff --git a/cancun/eip1153_tstore/test_tload_calls.py b/cancun/eip1153_tstore/test_tload_calls.py index 6d3492624d..27837bc797 100644 --- a/cancun/eip1153_tstore/test_tload_calls.py +++ b/cancun/eip1153_tstore/test_tload_calls.py @@ -6,8 +6,8 @@ import pytest from ethereum_test_tools import Account, Address, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Bytecode -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1153.md" REFERENCE_SPEC_VERSION = "1eb863b534a5a3e19e9c196ab2a7f3db4bb9da17" diff --git a/cancun/eip1153_tstore/test_tload_reentrancy.py b/cancun/eip1153_tstore/test_tload_reentrancy.py index 3a8a52092b..4d66ea5115 100644 --- a/cancun/eip1153_tstore/test_tload_reentrancy.py +++ b/cancun/eip1153_tstore/test_tload_reentrancy.py @@ -18,9 +18,9 @@ Switch, Transaction, ) -from ethereum_test_tools.vm.opcode import Bytecode -from ethereum_test_tools.vm.opcode import Macros as Om -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Macros as Om +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1153.md" REFERENCE_SPEC_VERSION = "1eb863b534a5a3e19e9c196ab2a7f3db4bb9da17" diff --git a/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py b/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py index 725941db67..8cf988bd76 100644 --- a/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py +++ b/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py @@ -17,8 +17,8 @@ Initcode, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container +from ethereum_test_vm import Opcodes as Op from .spec import ref_spec_1153 diff --git a/cancun/eip1153_tstore/test_tstore_reentrancy.py b/cancun/eip1153_tstore/test_tstore_reentrancy.py index b371ea9314..30d200b4fb 100644 --- a/cancun/eip1153_tstore/test_tstore_reentrancy.py +++ b/cancun/eip1153_tstore/test_tstore_reentrancy.py @@ -18,9 +18,9 @@ Switch, Transaction, ) -from ethereum_test_tools.vm.opcode import Bytecode -from ethereum_test_tools.vm.opcode import Macros as Om -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Macros as Om +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1153.md" REFERENCE_SPEC_VERSION = "1eb863b534a5a3e19e9c196ab2a7f3db4bb9da17" diff --git a/cancun/eip4788_beacon_root/test_beacon_root_contract.py b/cancun/eip4788_beacon_root/test_beacon_root_contract.py index d9e6f57a70..69db3d19ab 100644 --- a/cancun/eip4788_beacon_root/test_beacon_root_contract.py +++ b/cancun/eip4788_beacon_root/test_beacon_root_contract.py @@ -35,7 +35,7 @@ Transaction, Withdrawal, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .spec import Spec, ref_spec_4788 diff --git a/cancun/eip4844_blobs/test_point_evaluation_precompile.py b/cancun/eip4844_blobs/test_point_evaluation_precompile.py index a878976526..44257dc67d 100644 --- a/cancun/eip4844_blobs/test_point_evaluation_precompile.py +++ b/cancun/eip4844_blobs/test_point_evaluation_precompile.py @@ -53,7 +53,7 @@ TransactionReceipt, call_return_code, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .common import INF_POINT, Z_Y_VALID_ENDIANNESS, Z from .spec import Spec, ref_spec_4844 diff --git a/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py b/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py index 22ff6476c0..02a80eb3de 100644 --- a/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py +++ b/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py @@ -20,7 +20,7 @@ Transaction, ceiling_division, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .common import INF_POINT, Z from .spec import Spec, ref_spec_4844 diff --git a/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py b/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py index 3c40ad69d6..ea59c47f2c 100644 --- a/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py +++ b/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py @@ -21,7 +21,7 @@ Transaction, compute_create2_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "EIPS/eip-6780.md" REFERENCE_SPEC_VERSION = "1b6a0e94cc47e859b9866e570391cf37dc55059a" diff --git a/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py b/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py index 40cc682480..9a851c6b26 100644 --- a/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py +++ b/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py @@ -18,7 +18,7 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "EIPS/eip-6780.md" REFERENCE_SPEC_VERSION = "1b6a0e94cc47e859b9866e570391cf37dc55059a" diff --git a/cancun/eip6780_selfdestruct/test_selfdestruct.py b/cancun/eip6780_selfdestruct/test_selfdestruct.py index c38220fe00..b839626162 100644 --- a/cancun/eip6780_selfdestruct/test_selfdestruct.py +++ b/cancun/eip6780_selfdestruct/test_selfdestruct.py @@ -18,6 +18,7 @@ Block, BlockchainTestFiller, Bytecode, + Conditional, Hash, Initcode, StateTestFiller, @@ -25,8 +26,7 @@ Transaction, compute_create_address, ) -from ethereum_test_tools.code.generators import Conditional -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "EIPS/eip-6780.md" REFERENCE_SPEC_VERSION = "1b6a0e94cc47e859b9866e570391cf37dc55059a" diff --git a/frontier/opcodes/test_all_opcodes.py b/frontier/opcodes/test_all_opcodes.py index d8679d252c..458c332dd3 100644 --- a/frontier/opcodes/test_all_opcodes.py +++ b/frontier/opcodes/test_all_opcodes.py @@ -17,8 +17,8 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcode, UndefinedOpcodes -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcode, UndefinedOpcodes +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "N/A" REFERENCE_SPEC_VERSION = "N/A" diff --git a/frontier/opcodes/test_call.py b/frontier/opcodes/test_call.py index ad13a4d73a..e7feb662db 100644 --- a/frontier/opcodes/test_call.py +++ b/frontier/opcodes/test_call.py @@ -6,12 +6,12 @@ from ethereum_test_tools import ( Account, Alloc, + CodeGasMeasure, Environment, StateTestFiller, Transaction, ) -from ethereum_test_tools.code.generators import CodeGasMeasure -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op # TODO: There's an issue with gas definitions on forks previous to Berlin, remove this when fixed. diff --git a/frontier/opcodes/test_call_and_callcode_gas_calculation.py b/frontier/opcodes/test_call_and_callcode_gas_calculation.py index 73e9c9f3cc..740253dbb5 100644 --- a/frontier/opcodes/test_call_and_callcode_gas_calculation.py +++ b/frontier/opcodes/test_call_and_callcode_gas_calculation.py @@ -37,7 +37,7 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op """ PUSH opcode cost is 3, GAS opcode cost is 2. diff --git a/frontier/opcodes/test_calldatacopy.py b/frontier/opcodes/test_calldatacopy.py index 44ab406a45..90bd3c68ce 100644 --- a/frontier/opcodes/test_calldatacopy.py +++ b/frontier/opcodes/test_calldatacopy.py @@ -4,7 +4,7 @@ from ethereum_test_forks import Byzantium, Fork from ethereum_test_tools import Account, Alloc, Bytecode, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op @pytest.mark.ported_from( diff --git a/frontier/opcodes/test_calldataload.py b/frontier/opcodes/test_calldataload.py index ca135e51a0..41f03f1284 100644 --- a/frontier/opcodes/test_calldataload.py +++ b/frontier/opcodes/test_calldataload.py @@ -5,7 +5,7 @@ from ethereum_test_forks import Byzantium, Fork from ethereum_test_tools import Account, Alloc, StateTestFiller, Transaction from ethereum_test_tools import Macros as Om -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op @pytest.mark.ported_from( diff --git a/frontier/opcodes/test_calldatasize.py b/frontier/opcodes/test_calldatasize.py index 38a2f9415a..d06a7330da 100644 --- a/frontier/opcodes/test_calldatasize.py +++ b/frontier/opcodes/test_calldatasize.py @@ -5,7 +5,7 @@ from ethereum_test_forks import Byzantium, Fork from ethereum_test_tools import Account, Alloc, StateTestFiller, Transaction from ethereum_test_tools import Macros as Om -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op @pytest.mark.ported_from( diff --git a/frontier/opcodes/test_push.py b/frontier/opcodes/test_push.py index 65cb213d6d..a97abaa982 100644 --- a/frontier/opcodes/test_push.py +++ b/frontier/opcodes/test_push.py @@ -8,7 +8,7 @@ from ethereum_test_forks import Fork, Frontier, Homestead from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction from ethereum_test_tools import Opcodes as Op -from ethereum_test_vm.bytecode import Bytecode +from ethereum_test_vm import Bytecode def get_input_for_push_opcode(opcode: Op) -> bytes: diff --git a/frontier/precompiles/test_precompiles.py b/frontier/precompiles/test_precompiles.py index 280b732353..24ef1b0045 100644 --- a/frontier/precompiles/test_precompiles.py +++ b/frontier/precompiles/test_precompiles.py @@ -13,7 +13,7 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op def precompile_addresses(fork: Fork) -> Iterator[Tuple[Address, bool]]: diff --git a/frontier/scenarios/common.py b/frontier/scenarios/common.py index ce9170c035..7142ca685e 100644 --- a/frontier/scenarios/common.py +++ b/frontier/scenarios/common.py @@ -6,7 +6,7 @@ from ethereum_test_forks import Fork, Frontier from ethereum_test_tools import Address, Alloc, Bytecode, Conditional -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op class ScenarioExpectOpcode(Enum): diff --git a/frontier/scenarios/programs/all_frontier_opcodes.py b/frontier/scenarios/programs/all_frontier_opcodes.py index 1120fbf4da..83978c7509 100644 --- a/frontier/scenarios/programs/all_frontier_opcodes.py +++ b/frontier/scenarios/programs/all_frontier_opcodes.py @@ -4,7 +4,7 @@ from ethereum_test_forks import Fork from ethereum_test_tools import Alloc, Bytecode, Conditional -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from ..common import ProgramResult, ScenarioTestProgram diff --git a/frontier/scenarios/programs/context_calls.py b/frontier/scenarios/programs/context_calls.py index bcf0a1ba4f..0693d18110 100644 --- a/frontier/scenarios/programs/context_calls.py +++ b/frontier/scenarios/programs/context_calls.py @@ -4,7 +4,7 @@ from ethereum_test_forks import Byzantium, Cancun, Constantinople, Fork, Istanbul, London, Shanghai from ethereum_test_tools import Alloc, Bytecode -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from ..common import ( ProgramResult, diff --git a/frontier/scenarios/programs/invalid_opcodes.py b/frontier/scenarios/programs/invalid_opcodes.py index 82c396ff58..0157dba7b2 100644 --- a/frontier/scenarios/programs/invalid_opcodes.py +++ b/frontier/scenarios/programs/invalid_opcodes.py @@ -4,7 +4,7 @@ from ethereum_test_forks import Fork from ethereum_test_tools import Alloc, Bytecode -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from ..common import ProgramResult, ScenarioTestProgram, make_invalid_opcode_contract diff --git a/frontier/scenarios/programs/static_violation.py b/frontier/scenarios/programs/static_violation.py index 950eed293e..42146f2c4b 100644 --- a/frontier/scenarios/programs/static_violation.py +++ b/frontier/scenarios/programs/static_violation.py @@ -4,7 +4,7 @@ from ethereum_test_forks import Cancun, Fork from ethereum_test_tools import Alloc, Bytecode -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from ..common import ProgramResult, ScenarioTestProgram diff --git a/frontier/scenarios/scenarios/call_combinations.py b/frontier/scenarios/scenarios/call_combinations.py index 1049218f27..e8e091307c 100644 --- a/frontier/scenarios/scenarios/call_combinations.py +++ b/frontier/scenarios/scenarios/call_combinations.py @@ -4,9 +4,8 @@ from typing import List from ethereum_test_tools import Address, Alloc -from ethereum_test_tools.vm.opcode import Opcode -from ethereum_test_tools.vm.opcode import Opcodes as Op -from ethereum_test_vm import EVMCodeType +from ethereum_test_vm import EVMCodeType, Opcode +from ethereum_test_vm import Opcodes as Op from ..common import Scenario, ScenarioEnvironment, ScenarioGeneratorInput diff --git a/frontier/scenarios/scenarios/create_combinations.py b/frontier/scenarios/scenarios/create_combinations.py index 8c43dcb88c..d560391324 100644 --- a/frontier/scenarios/scenarios/create_combinations.py +++ b/frontier/scenarios/scenarios/create_combinations.py @@ -4,11 +4,10 @@ from typing import List from ethereum_test_tools import Alloc, Bytecode -from ethereum_test_tools.vm.opcode import Macros as Om -from ethereum_test_tools.vm.opcode import Opcode -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types import compute_create_address -from ethereum_test_vm import EVMCodeType +from ethereum_test_vm import EVMCodeType, Opcode +from ethereum_test_vm import Macros as Om +from ethereum_test_vm import Opcodes as Op from ..common import Scenario, ScenarioEnvironment, ScenarioGeneratorInput diff --git a/frontier/scenarios/scenarios/revert_combinations.py b/frontier/scenarios/scenarios/revert_combinations.py index 1734428523..668fe83455 100644 --- a/frontier/scenarios/scenarios/revert_combinations.py +++ b/frontier/scenarios/scenarios/revert_combinations.py @@ -2,9 +2,9 @@ from typing import List -from ethereum_test_tools.vm.opcode import Macro, Opcode -from ethereum_test_tools.vm.opcode import Macros as Om -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Macro, Opcode +from ethereum_test_vm import Macros as Om +from ethereum_test_vm import Opcodes as Op from ..common import Scenario, ScenarioEnvironment, ScenarioGeneratorInput diff --git a/frontier/scenarios/test_scenarios.py b/frontier/scenarios/test_scenarios.py index 4fd73509ce..585aa6aab7 100644 --- a/frontier/scenarios/test_scenarios.py +++ b/frontier/scenarios/test_scenarios.py @@ -18,7 +18,7 @@ Storage, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .common import ( ExecutionEnvironment, @@ -117,7 +117,7 @@ def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List ) @pytest.mark.valid_from("Frontier") @pytest.mark.parametrize( - # select program to debug ("program_id", "scenario_name") + # select program to debug ("program_id","scenario_name") # program="" select all programs # scenario_name="" select all scenarios # Example: [ScenarioDebug(program_id=ProgramSstoreSload().id, scenario_name="scenario_CALL_CALL")], # noqa: E501 diff --git a/homestead/coverage/test_coverage.py b/homestead/coverage/test_coverage.py index b7240c38a3..b0120d113f 100644 --- a/homestead/coverage/test_coverage.py +++ b/homestead/coverage/test_coverage.py @@ -4,7 +4,7 @@ from ethereum_test_forks import Cancun, Fork from ethereum_test_tools import Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "N/A" REFERENCE_SPEC_VERSION = "N/A" @@ -18,7 +18,7 @@ def test_coverage( ): """ Cover gaps that result from transforming Yul code into - `ethereum_test_tools.vm.opcode.Opcodes` bytecode. + our Python opcode wrapper bytecode. E.g. Yul tends to optimize stack items by using `SWAP1` and `DUP1` opcodes, which are not regularly used in python code. diff --git a/istanbul/eip1344_chainid/test_chainid.py b/istanbul/eip1344_chainid/test_chainid.py index 0fb3b7fbaf..72c670268c 100644 --- a/istanbul/eip1344_chainid/test_chainid.py +++ b/istanbul/eip1344_chainid/test_chainid.py @@ -6,7 +6,7 @@ import pytest from ethereum_test_tools import Account, Alloc, ChainConfig, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "EIPS/eip-1344.md" REFERENCE_SPEC_VERSION = "02e46aebc80e6e5006ab4d2daa41876139f9a9e2" diff --git a/istanbul/eip152_blake2/conftest.py b/istanbul/eip152_blake2/conftest.py index c21a352ced..ed544ec291 100644 --- a/istanbul/eip152_blake2/conftest.py +++ b/istanbul/eip152_blake2/conftest.py @@ -2,8 +2,8 @@ import pytest -from ethereum_test_tools.vm.opcode import Opcodes as Op -from ethereum_test_vm.bytecode import Bytecode +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from .spec import Spec diff --git a/istanbul/eip152_blake2/test_blake2.py b/istanbul/eip152_blake2/test_blake2.py index 0fb8660781..dab5c9e6ba 100644 --- a/istanbul/eip152_blake2/test_blake2.py +++ b/istanbul/eip152_blake2/test_blake2.py @@ -16,7 +16,7 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .common import Blake2bInput, ExpectedOutput from .spec import SpecTestVectors, ref_spec_152 diff --git a/osaka/eip7594_peerdas/test_get_blobs.py b/osaka/eip7594_peerdas/test_get_blobs.py index 5e8e9a350f..2d349fd93b 100644 --- a/osaka/eip7594_peerdas/test_get_blobs.py +++ b/osaka/eip7594_peerdas/test_get_blobs.py @@ -19,7 +19,7 @@ Transaction, TransactionException, ) -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger from .spec import ref_spec_7594 diff --git a/osaka/eip7823_modexp_upper_bounds/conftest.py b/osaka/eip7823_modexp_upper_bounds/conftest.py index 56bfb1c937..9a89e91db3 100644 --- a/osaka/eip7823_modexp_upper_bounds/conftest.py +++ b/osaka/eip7823_modexp_upper_bounds/conftest.py @@ -6,8 +6,8 @@ from ethereum_test_forks import Fork, Osaka from ethereum_test_tools import Account, Address, Alloc, Storage, Transaction, keccak256 -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types import Environment +from ethereum_test_vm import Opcodes as Op from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput from ..eip7883_modexp_gas_increase.spec import Spec, Spec7883 diff --git a/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py b/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py index 2f32f1b94d..fca1e18127 100644 --- a/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py +++ b/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py @@ -19,7 +19,7 @@ Transaction, keccak256, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput from ..eip7883_modexp_gas_increase.spec import Spec diff --git a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py index 8d06306865..254cf62dec 100644 --- a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py +++ b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py @@ -26,7 +26,7 @@ add_kzg_version, ) from ethereum_test_tools.utility.pytest import ParameterSet -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .spec import Spec, ref_spec_7825 diff --git a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py index 9d7bd449bd..eb992e8ded 100644 --- a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py +++ b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py @@ -15,7 +15,7 @@ Transaction, TransactionException, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .spec import ref_spec_7825 diff --git a/osaka/eip7883_modexp_gas_increase/conftest.py b/osaka/eip7883_modexp_gas_increase/conftest.py index f69d6b3eb3..1a68553154 100644 --- a/osaka/eip7883_modexp_gas_increase/conftest.py +++ b/osaka/eip7883_modexp_gas_increase/conftest.py @@ -15,7 +15,7 @@ Transaction, keccak256, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput from .spec import Spec, Spec7883 diff --git a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py index b0bf716667..4132bbfdf6 100644 --- a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py +++ b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py @@ -17,8 +17,8 @@ Transaction, keccak256, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.helpers import compute_create_address +from ethereum_test_vm import Opcodes as Op from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput from .helpers import vectors_from_file diff --git a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py index 7b3315b73c..5c4499ace6 100644 --- a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py +++ b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py @@ -5,7 +5,7 @@ from ethereum_test_checklists import EIPChecklist from ethereum_test_forks import Fork from ethereum_test_tools import Account, Alloc, Block, BlockchainTestFiller, Transaction, keccak256 -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from ...byzantium.eip198_modexp_precompile.helpers import ModExpInput from .spec import Spec, ref_spec_7883 diff --git a/osaka/eip7934_block_rlp_limit/conftest.py b/osaka/eip7934_block_rlp_limit/conftest.py index 651ae98488..c3ee0fccd8 100644 --- a/osaka/eip7934_block_rlp_limit/conftest.py +++ b/osaka/eip7934_block_rlp_limit/conftest.py @@ -6,8 +6,8 @@ Address, Alloc, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types import Environment +from ethereum_test_vm import Opcodes as Op @pytest.fixture diff --git a/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py b/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py index 6ade4a1eda..04cb4f2a26 100644 --- a/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py +++ b/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py @@ -21,7 +21,7 @@ Transaction, compute_create_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from ...prague.eip7702_set_code_tx.spec import Spec as Spec7702 from .spec import Spec, ref_spec_7939 diff --git a/paris/security/test_selfdestruct_balance_bug.py b/paris/security/test_selfdestruct_balance_bug.py index 9df539ac8e..1122d2f460 100644 --- a/paris/security/test_selfdestruct_balance_bug.py +++ b/paris/security/test_selfdestruct_balance_bug.py @@ -23,7 +23,7 @@ Transaction, compute_create_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op @pytest.mark.valid_from("Constantinople") diff --git a/prague/eip7702_set_code_tx/test_calls.py b/prague/eip7702_set_code_tx/test_calls.py index 4bd038293c..54de197656 100644 --- a/prague/eip7702_set_code_tx/test_calls.py +++ b/prague/eip7702_set_code_tx/test_calls.py @@ -13,7 +13,7 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op pytestmark = pytest.mark.valid_from("Prague") REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7702.md" diff --git a/prague/eip7702_set_code_tx/test_set_code_txs_2.py b/prague/eip7702_set_code_tx/test_set_code_txs_2.py index c7733c238f..e6a622246e 100644 --- a/prague/eip7702_set_code_tx/test_set_code_txs_2.py +++ b/prague/eip7702_set_code_tx/test_set_code_txs_2.py @@ -14,6 +14,7 @@ BlockchainTestFiller, Bytes, Case, + CodeGasMeasure, Conditional, Environment, Hash, @@ -24,10 +25,9 @@ TransactionException, compute_create_address, ) -from ethereum_test_tools.code.generators import CodeGasMeasure -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_vm import Macros +from ethereum_test_vm import Opcodes as Op from .spec import Spec, ref_spec_7702 diff --git a/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py b/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py index 0e924a28f6..b49b8569fd 100644 --- a/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py +++ b/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py @@ -19,7 +19,7 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .spec import ref_spec_3651 diff --git a/shanghai/eip3855_push0/test_push0.py b/shanghai/eip3855_push0/test_push0.py index 9633582377..c490d0d8fa 100644 --- a/shanghai/eip3855_push0/test_push0.py +++ b/shanghai/eip3855_push0/test_push0.py @@ -19,7 +19,7 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .spec import ref_spec_3855 diff --git a/shanghai/eip3860_initcode/helpers.py b/shanghai/eip3860_initcode/helpers.py index b97e9faf41..0719355caf 100644 --- a/shanghai/eip3860_initcode/helpers.py +++ b/shanghai/eip3860_initcode/helpers.py @@ -1,7 +1,7 @@ """Helpers for the EIP-3860 initcode tests.""" from ethereum_test_tools import Initcode -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op INITCODE_RESULTING_DEPLOYED_CODE = Op.STOP diff --git a/shanghai/eip3860_initcode/test_initcode.py b/shanghai/eip3860_initcode/test_initcode.py index 9f3d24fb5c..1b52b29b03 100644 --- a/shanghai/eip3860_initcode/test_initcode.py +++ b/shanghai/eip3860_initcode/test_initcode.py @@ -28,7 +28,7 @@ ceiling_division, compute_create_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .helpers import INITCODE_RESULTING_DEPLOYED_CODE, get_create_id, get_initcode_name from .spec import Spec, ref_spec_3860 diff --git a/shanghai/eip3860_initcode/test_with_eof.py b/shanghai/eip3860_initcode/test_with_eof.py index ddf9132cc9..433ba31d9f 100644 --- a/shanghai/eip3860_initcode/test_with_eof.py +++ b/shanghai/eip3860_initcode/test_with_eof.py @@ -14,8 +14,8 @@ Transaction, compute_create_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE, MAX_INITCODE_SIZE +from ethereum_test_vm import Opcodes as Op from .spec import ref_spec_3860 diff --git a/shanghai/eip4895_withdrawals/test_withdrawals.py b/shanghai/eip4895_withdrawals/test_withdrawals.py index 5280dd1e4f..44bbbeb902 100644 --- a/shanghai/eip4895_withdrawals/test_withdrawals.py +++ b/shanghai/eip4895_withdrawals/test_withdrawals.py @@ -23,7 +23,7 @@ TransactionException, Withdrawal, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op from .spec import ref_spec_4895 diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/opcodes.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/opcodes.py index 4d273ec5ac..9f5e816191 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/opcodes.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/opcodes.py @@ -2,7 +2,7 @@ from typing import List -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op V1_EOF_OPCODES: List[Op] = [ # new eof ops diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py index ce669cad84..7e0875da28 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py @@ -5,7 +5,6 @@ import pytest from ethereum_test_tools import EOFException, EOFTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import ( AutoSection, Container, @@ -19,6 +18,7 @@ MAX_CODE_SECTIONS, MAX_STACK_INCREASE_LIMIT, ) +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution.py index 676610b9de..609ebb643c 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution.py @@ -4,8 +4,8 @@ from ethereum_test_base_types import Storage from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py index 33d6fe41c5..9d36525d65 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py @@ -5,9 +5,9 @@ import pytest from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import MAX_CODE_SECTIONS, MAX_RETURN_STACK_HEIGHT +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py index 96fdef127f..0a2e407cc5 100644 --- a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py +++ b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py @@ -3,10 +3,10 @@ import pytest from ethereum_test_tools import Account, EOFException, EOFStateTestFiller, EOFTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .helpers import JumpDirection, slot_code_worked, value_code_worked diff --git a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py index f4739cf508..3fa0e7f3f6 100644 --- a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py +++ b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py @@ -12,10 +12,10 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .helpers import ( diff --git a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py index 1fbbd28deb..7fe59d8ffa 100644 --- a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py +++ b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py @@ -3,9 +3,9 @@ import pytest from ethereum_test_tools import Account, EOFException, EOFStateTestFiller, EOFTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .helpers import JumpDirection, slot_code_worked, slot_conditional_result, value_code_worked diff --git a/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py b/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py index c781249137..c705d19758 100644 --- a/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py +++ b/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py @@ -5,7 +5,6 @@ import pytest from ethereum_test_tools import EOFException, EOFTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.constants import MAX_RUNTIME_STACK_HEIGHT from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import ( @@ -13,6 +12,7 @@ MAX_CODE_SECTIONS, MAX_STACK_INCREASE_LIMIT, ) +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py b/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py index 424c584582..ed58e09c06 100644 --- a/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py +++ b/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py @@ -8,10 +8,10 @@ from ethereum_test_exceptions.exceptions import EOFException from ethereum_test_tools import Account, EOFStateTestFiller, EOFTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import MAX_STACK_INCREASE_LIMIT, NON_RETURNING_SECTION -from ethereum_test_vm.bytecode import Bytecode +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from ..eip3540_eof_v1.test_all_opcodes_in_container import valid_eof_opcodes diff --git a/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py b/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py index a4586a3787..d72f12eb14 100644 --- a/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py +++ b/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py @@ -4,7 +4,6 @@ from ethereum_test_exceptions import EOFException from ethereum_test_tools import Account, EOFStateTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.constants import MAX_RUNTIME_STACK_HEIGHT from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import ( @@ -12,6 +11,7 @@ MAX_STACK_INCREASE_LIMIT, NON_RETURNING_SECTION, ) +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py index 56b2a5fc7c..c8c21022b9 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py @@ -5,10 +5,10 @@ from ethereum_test_base_types import Storage from ethereum_test_specs import StateTestFiller from ethereum_test_tools import Account, Environment, EOFException, EOFStateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types import Alloc from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import NON_RETURNING_SECTION +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .helpers import ( diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py index ade091a3f8..0831a8c9c2 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py @@ -4,9 +4,9 @@ from ethereum_test_specs import EOFTestFiller from ethereum_test_tools import Account, EOFException, EOFStateTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.constants import MAX_RUNTIME_STACK_HEIGHT from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .helpers import slot_code_worked, value_code_worked diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py index 80e2e61ef2..dcfd397430 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py @@ -3,9 +3,9 @@ import pytest from ethereum_test_tools import Account, EOFException, EOFStateTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import NON_RETURNING_SECTION +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .helpers import slot_code_worked, value_code_worked diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py index 6abc91cf9e..67a057df89 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py @@ -3,9 +3,9 @@ import pytest from ethereum_test_tools import EOFException, EOFTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.constants import MAX_RUNTIME_STACK_HEIGHT from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py index 4ecf0a5831..c5bc912994 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py @@ -3,9 +3,9 @@ import pytest from ethereum_test_tools import EOFException, EOFTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import NON_RETURNING_SECTION, Container, ContainerKind, Section from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py index 997e89808f..4285d6c8e0 100644 --- a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py +++ b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py @@ -15,9 +15,9 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import MAX_STACK_INCREASE_LIMIT +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION diff --git a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py index 0c7c490485..74e40d83f1 100644 --- a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py +++ b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py @@ -15,8 +15,8 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION diff --git a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py index 47e8c6bfaf..dedbd76771 100644 --- a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py +++ b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py @@ -15,9 +15,9 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import MAX_STACK_INCREASE_LIMIT +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py index 66dd853fac..feee36e6b2 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py @@ -5,8 +5,8 @@ import pytest from ethereum_test_tools import Account, Address, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .helpers import value_exceptional_abort_canary diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py index a5bdc1958f..2bc3f36e83 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py @@ -6,8 +6,8 @@ import pytest from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py index 66ebac993a..a6e6f0a393 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py @@ -15,11 +15,10 @@ Storage, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.helpers import compute_eofcreate_address -from ethereum_test_vm.bytecode import Bytecode -from ethereum_test_vm.evm_types import EVMCodeType +from ethereum_test_vm import Bytecode, EVMCodeType +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .spec import ( diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py index bd42af22e3..e7b6ffa923 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py @@ -8,8 +8,8 @@ from ethereum_test_base_types import Address from ethereum_test_forks import Fork from ethereum_test_tools import Alloc, Environment, StateTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from ..gas_test import gas_test diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py index 37b0363c0a..53400fd80f 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py @@ -8,8 +8,8 @@ import pytest from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Storage, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION diff --git a/unscheduled/eip7692_eof_v1/eip7480_data_section/test_code_validation.py b/unscheduled/eip7692_eof_v1/eip7480_data_section/test_code_validation.py index 0189f632d4..23df4e4336 100644 --- a/unscheduled/eip7692_eof_v1/eip7480_data_section/test_code_validation.py +++ b/unscheduled/eip7692_eof_v1/eip7480_data_section/test_code_validation.py @@ -3,9 +3,9 @@ import pytest from ethereum_test_tools import EOFException, EOFTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import MAX_INITCODE_SIZE +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py b/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py index 238cfe7cc8..234ea530a7 100644 --- a/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py +++ b/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py @@ -4,8 +4,8 @@ from ethereum_test_specs import EOFStateTestFiller from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py b/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py index a57fd99910..4c4e58d7bb 100644 --- a/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py +++ b/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py @@ -15,8 +15,8 @@ Storage, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py index 460ed2b5d3..3f4780368a 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py @@ -14,9 +14,9 @@ Transaction, compute_eofcreate_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section -from ethereum_test_vm.bytecode import Bytecode +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from ..eip7069_extcall.spec import EXTCALL_SUCCESS diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py index 8a40c601c8..68f50eec3e 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py @@ -11,9 +11,9 @@ Transaction, compute_eofcreate_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE, MAX_INITCODE_SIZE +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from ..eip7069_extcall.spec import EXTCALL_FAILURE, EXTCALL_REVERT, LEGACY_CALL_FAILURE diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py index e010dd40ee..f7cb2519a1 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py @@ -4,8 +4,8 @@ from ethereum_test_forks import Fork from ethereum_test_tools import Alloc, Environment, StateTestFiller, compute_eofcreate_address -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from ..gas_test import gas_test diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py index ebd607293f..390b1ce089 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py @@ -11,10 +11,10 @@ Transaction, ) from ethereum_test_tools import Initcode as LegacyInitcode -from ethereum_test_tools.vm.opcode import Opcodes -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container from ethereum_test_types.helpers import compute_create_address +from ethereum_test_vm import Opcodes +from ethereum_test_vm import Opcodes as Op from ....prague.eip7702_set_code_tx.spec import Spec from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py index 8b0bb756a6..67748507e6 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py @@ -4,9 +4,9 @@ from ethereum_test_base_types import Account, Storage from ethereum_test_tools import Alloc, Environment, StateTestFiller, compute_eofcreate_address -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types import Transaction from ethereum_test_types.eof.v1 import Container, Section +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .helpers import ( diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py index 788933fcf9..3b50714dec 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py @@ -5,10 +5,10 @@ from ethereum_test_base_types import Account from ethereum_test_specs import StateTestFiller from ethereum_test_tools import Alloc, EOFException, EOFTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types import Environment, Transaction, compute_eofcreate_address from ethereum_test_types.eof.v1 import Container, ContainerKind, Section from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .helpers import ( diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py index acd6f0a67d..045e3dbbd3 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py @@ -3,10 +3,10 @@ import pytest from ethereum_test_tools import Account, EOFException, EOFStateTestFiller, EOFTestFiller -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, ContainerKind, Section from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE, MAX_INITCODE_SIZE from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from .helpers import slot_code_worked, value_code_worked diff --git a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py index 87ad9fa1e3..7d21916f29 100644 --- a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py +++ b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py @@ -10,7 +10,7 @@ StateTestFiller, Transaction, ) -from ethereum_test_tools.code.generators import Initcode as LegacyInitcode +from ethereum_test_tools import Initcode as LegacyInitcode from ethereum_test_types import TransactionReceipt from ethereum_test_types.eof.v1 import Container diff --git a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py index bd7dd21295..4d3b571f23 100644 --- a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py +++ b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py @@ -13,9 +13,9 @@ Transaction, compute_eofcreate_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section -from ethereum_test_vm.bytecode import Bytecode +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from ..eip7069_extcall.spec import EXTCALL_SUCCESS, LEGACY_CALL_SUCCESS diff --git a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py index 035861ae40..d44588aaed 100644 --- a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py +++ b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py @@ -14,10 +14,10 @@ Transaction, compute_eofcreate_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_types.eof.v1.constants import MAX_BYTECODE_SIZE, MAX_INITCODE_SIZE -from ethereum_test_vm.bytecode import Bytecode +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from .. import EOF_FORK_NAME from ..eip7069_extcall.spec import EXTCALL_FAILURE, EXTCALL_REVERT, LEGACY_CALL_FAILURE diff --git a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py index dfa07b48d4..3dd9dc8965 100644 --- a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py +++ b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py @@ -17,9 +17,9 @@ Transaction, compute_eofcreate_address, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section -from ethereum_test_vm.bytecode import Bytecode +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op from ....prague.eip7702_set_code_tx.spec import Spec from .. import EOF_FORK_NAME diff --git a/unscheduled/eip7692_eof_v1/gas_test.py b/unscheduled/eip7692_eof_v1/gas_test.py index d0425caf79..b2520dcbc8 100644 --- a/unscheduled/eip7692_eof_v1/gas_test.py +++ b/unscheduled/eip7692_eof_v1/gas_test.py @@ -4,9 +4,9 @@ from ethereum_test_base_types.base_types import Address from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types.eof.v1 import Container, Section from ethereum_test_vm import Bytecode, EVMCodeType +from ethereum_test_vm import Opcodes as Op from .eip7069_extcall.spec import ( LEGACY_CALL_FAILURE, From 933f8ead60ae506960453e6dbc1837c3bc6ba7eb Mon Sep 17 00:00:00 2001 From: felix Date: Fri, 19 Sep 2025 10:57:09 +0000 Subject: [PATCH 023/102] chore(all): rename shadowed modules to enable ruff a005 (#2133) --- cli/eest/make/templates/blockchain_test.py.j2 | 2 +- cli/eest/make/templates/state_test.py.j2 | 2 +- cli/eofwrap.py | 2 +- cli/evm_bytes.py | 3 +-- cli/gentest/request_manager.py | 2 +- cli/gentest/test_context_providers.py | 2 +- cli/gentest/test_providers.py | 2 +- .../pytest_ini_files/pytest-consume.ini | 2 +- .../pytest-execute-eth-config.ini | 2 +- .../pytest_ini_files/pytest-execute.ini | 2 +- .../pytest_ini_files/pytest-fill.ini | 2 +- ethereum_clis/__init__.py | 14 ++++++------- ethereum_clis/{types.py => cli_types.py} | 2 +- ethereum_clis/clis/besu.py | 2 +- ethereum_clis/clis/execution_specs.py | 2 +- ethereum_clis/ethereum_cli.py | 2 +- .../tests/test_transition_tools_support.py | 2 +- ethereum_clis/transition_tool.py | 6 +++--- ethereum_test_base_types/__init__.py | 2 +- .../{json.py => base_types_json.py} | 0 .../tests/test_base_types.py | 2 +- .../exceptions/__init__.py | 4 ++-- .../{types.py => exceptions_types.py} | 0 ethereum_test_execution/blob_transaction.py | 4 ++-- ethereum_test_rpc/__init__.py | 2 +- ethereum_test_rpc/rpc.py | 4 ++-- ethereum_test_rpc/{types.py => rpc_types.py} | 0 ethereum_test_specs/state.py | 2 +- ethereum_test_tools/__init__.py | 2 +- ethereum_test_tools/tests/test_code.py | 2 +- .../{code => tools_code}/__init__.py | 0 .../{code => tools_code}/generators.py | 0 .../{code => tools_code}/yul.py | 0 ethereum_test_tools/vm/__init__.py | 13 ------------ ethereum_test_tools/vm/opcode.py | 21 ------------------- ethereum_test_types/blob_types.py | 2 +- ethereum_test_types/transaction_types.py | 2 +- ethereum_test_vm/__init__.py | 2 +- ethereum_test_vm/helpers.py | 2 +- ethereum_test_vm/{opcode.py => opcodes.py} | 0 ethereum_test_vm/tests/test_vm.py | 6 +++--- .../simulator_logic/test_via_engine.py | 4 ++-- .../simulator_logic/test_via_sync.py | 4 ++-- .../{logging => custom_logging}/__init__.py | 2 +- .../plugin_logging.py} | 0 .../tests/__init__.py | 0 .../tests/test_logging.py | 4 ++-- .../execute/eth_config/eth_config.py | 4 ++-- .../execute/eth_config/execute_eth_config.py | 4 ++-- .../eth_config/{types.py => execute_types.py} | 0 .../tests/test_execute_eth_config.py | 2 +- .../execute/eth_config/tests/test_genesis.py | 2 +- pytest_plugins/execute/pre_alloc.py | 2 +- .../execute/rpc/chain_builder_eth_rpc.py | 2 +- pytest_plugins/filler/static_filler.py | 2 +- .../filler/tests/test_prealloc_group.py | 4 ++-- pytest_plugins/forks/forks.py | 2 +- pytest_plugins/pytest_hive/pytest_hive.py | 2 +- 58 files changed, 65 insertions(+), 100 deletions(-) rename ethereum_clis/{types.py => cli_types.py} (99%) rename ethereum_test_base_types/{json.py => base_types_json.py} (100%) rename ethereum_test_exceptions/exceptions/{types.py => exceptions_types.py} (100%) rename ethereum_test_rpc/{types.py => rpc_types.py} (100%) rename ethereum_test_tools/{code => tools_code}/__init__.py (100%) rename ethereum_test_tools/{code => tools_code}/generators.py (100%) rename ethereum_test_tools/{code => tools_code}/yul.py (100%) delete mode 100644 ethereum_test_tools/vm/__init__.py delete mode 100644 ethereum_test_tools/vm/opcode.py rename ethereum_test_vm/{opcode.py => opcodes.py} (100%) rename pytest_plugins/{logging => custom_logging}/__init__.py (93%) rename pytest_plugins/{logging/logging.py => custom_logging/plugin_logging.py} (100%) rename pytest_plugins/{logging => custom_logging}/tests/__init__.py (100%) rename pytest_plugins/{logging => custom_logging}/tests/test_logging.py (98%) rename pytest_plugins/execute/eth_config/{types.py => execute_types.py} (100%) diff --git a/cli/eest/make/templates/blockchain_test.py.j2 b/cli/eest/make/templates/blockchain_test.py.j2 index beb6bdd4d8..7cb2c14aad 100644 --- a/cli/eest/make/templates/blockchain_test.py.j2 +++ b/cli/eest/make/templates/blockchain_test.py.j2 @@ -14,7 +14,7 @@ from ethereum_test_tools import ( Environment, Transaction, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "DUMMY/eip-DUMMY.md" REFERENCE_SPEC_VERSION = "DUMMY_VERSION" diff --git a/cli/eest/make/templates/state_test.py.j2 b/cli/eest/make/templates/state_test.py.j2 index 35d845ca27..ad5c12a7a6 100644 --- a/cli/eest/make/templates/state_test.py.j2 +++ b/cli/eest/make/templates/state_test.py.j2 @@ -7,7 +7,7 @@ import pytest from ethereum_test_forks import Fork from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction -from ethereum_test_tools.vm.opcode import Opcodes as Op +from ethereum_test_vm import Opcodes as Op REFERENCE_SPEC_GIT_PATH = "DUMMY/eip-DUMMY.md" REFERENCE_SPEC_VERSION = "DUMMY_VERSION" diff --git a/cli/eofwrap.py b/cli/eofwrap.py index 479eb045fd..c23a695a43 100644 --- a/cli/eofwrap.py +++ b/cli/eofwrap.py @@ -33,7 +33,7 @@ from ethereum_test_types import Transaction from ethereum_test_types.block_types import Environment from ethereum_test_types.eof.v1 import Container -from ethereum_test_vm.bytecode import Bytecode +from ethereum_test_vm import Bytecode from .evm_bytes import OpcodeWithOperands, process_evm_bytes diff --git a/cli/evm_bytes.py b/cli/evm_bytes.py index cfe3c6283f..1b847ed97f 100644 --- a/cli/evm_bytes.py +++ b/cli/evm_bytes.py @@ -6,9 +6,8 @@ import click from ethereum_test_base_types import ZeroPaddedHexNumber -from ethereum_test_vm import Macro +from ethereum_test_vm import Bytecode, Macro from ethereum_test_vm import Opcodes as Op -from ethereum_test_vm.bytecode import Bytecode OPCODES_WITH_EMPTY_LINES_AFTER = { Op.STOP, diff --git a/cli/gentest/request_manager.py b/cli/gentest/request_manager.py index ab9ccc80d8..e4eac7e11d 100644 --- a/cli/gentest/request_manager.py +++ b/cli/gentest/request_manager.py @@ -15,7 +15,7 @@ from config import EnvConfig from ethereum_test_base_types import Hash from ethereum_test_rpc import BlockNumberType, DebugRPC, EthRPC -from ethereum_test_rpc.types import TransactionByHashResponse +from ethereum_test_rpc.rpc_types import TransactionByHashResponse from ethereum_test_types import Environment diff --git a/cli/gentest/test_context_providers.py b/cli/gentest/test_context_providers.py index 54b913cf86..f0cb5c3e02 100644 --- a/cli/gentest/test_context_providers.py +++ b/cli/gentest/test_context_providers.py @@ -19,7 +19,7 @@ from pydantic import BaseModel from ethereum_test_base_types import Account, Hash -from ethereum_test_rpc.types import TransactionByHashResponse +from ethereum_test_rpc.rpc_types import TransactionByHashResponse from ethereum_test_tools import Environment, Transaction from .request_manager import RPCRequest diff --git a/cli/gentest/test_providers.py b/cli/gentest/test_providers.py index 75a44fbe89..dc29d306ee 100644 --- a/cli/gentest/test_providers.py +++ b/cli/gentest/test_providers.py @@ -17,7 +17,7 @@ from pydantic import BaseModel from ethereum_test_base_types import Account, Address, ZeroPaddedHexNumber -from ethereum_test_rpc.types import TransactionByHashResponse +from ethereum_test_rpc.rpc_types import TransactionByHashResponse from ethereum_test_types import Environment diff --git a/cli/pytest_commands/pytest_ini_files/pytest-consume.ini b/cli/pytest_commands/pytest_ini_files/pytest-consume.ini index b6efe7a551..e8e005aaa1 100644 --- a/cli/pytest_commands/pytest_ini_files/pytest-consume.ini +++ b/cli/pytest_commands/pytest_ini_files/pytest-consume.ini @@ -8,6 +8,6 @@ addopts = -p pytest_plugins.concurrency # disable pytest built-in logging entirely `-p no:logging` -p no:logging - -p pytest_plugins.logging.logging + -p pytest_plugins.custom_logging.plugin_logging -p pytest_plugins.consume.consume -p pytest_plugins.help.help \ No newline at end of file diff --git a/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini b/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini index 439116dab5..9b098a5efc 100644 --- a/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini +++ b/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini @@ -6,7 +6,7 @@ python_files = *.py addopts = -p pytest_plugins.execute.eth_config.eth_config -p pytest_plugins.help.help - -p pytest_plugins.logging.logging + -p pytest_plugins.custom_logging.plugin_logging -m "not eip_version_check" --tb short --dist loadscope diff --git a/cli/pytest_commands/pytest_ini_files/pytest-execute.ini b/cli/pytest_commands/pytest_ini_files/pytest-execute.ini index 8e476ead0c..9797d1f892 100644 --- a/cli/pytest_commands/pytest_ini_files/pytest-execute.ini +++ b/cli/pytest_commands/pytest_ini_files/pytest-execute.ini @@ -16,7 +16,7 @@ addopts = -p pytest_plugins.execute.rpc.remote -p pytest_plugins.forks.forks -p pytest_plugins.help.help - -p pytest_plugins.logging.logging + -p pytest_plugins.custom_logging.plugin_logging --tb short --dist loadscope --ignore tests/cancun/eip4844_blobs/point_evaluation_vectors/ diff --git a/cli/pytest_commands/pytest_ini_files/pytest-fill.ini b/cli/pytest_commands/pytest_ini_files/pytest-fill.ini index d59472d7c6..018db69c28 100644 --- a/cli/pytest_commands/pytest_ini_files/pytest-fill.ini +++ b/cli/pytest_commands/pytest_ini_files/pytest-fill.ini @@ -17,7 +17,7 @@ addopts = -p pytest_plugins.forks.forks -p pytest_plugins.eels_resolver -p pytest_plugins.help.help - -p pytest_plugins.logging.logging + -p pytest_plugins.custom_logging.plugin_logging --tb short --ignore tests/cancun/eip4844_blobs/point_evaluation_vectors/ # these customizations require the pytest-custom-report plugin diff --git a/ethereum_clis/__init__.py b/ethereum_clis/__init__.py index f555cae91e..9b2850b724 100644 --- a/ethereum_clis/__init__.py +++ b/ethereum_clis/__init__.py @@ -1,5 +1,12 @@ """Library of Python wrappers for the different implementations of transition tools.""" +from .cli_types import ( + BlockExceptionWithMessage, + Result, + Traces, + TransactionExceptionWithMessage, + TransitionToolOutput, +) from .clis.besu import BesuTransitionTool from .clis.ethereumjs import EthereumJSTransitionTool from .clis.evmone import EvmoneExceptionMapper, EvmOneTransitionTool @@ -10,13 +17,6 @@ from .ethereum_cli import CLINotFoundInPathError, UnknownCLIError from .fixture_consumer_tool import FixtureConsumerTool from .transition_tool import TransitionTool -from .types import ( - BlockExceptionWithMessage, - Result, - Traces, - TransactionExceptionWithMessage, - TransitionToolOutput, -) TransitionTool.set_default_tool(ExecutionSpecsTransitionTool) FixtureConsumerTool.set_default_tool(GethFixtureConsumer) diff --git a/ethereum_clis/types.py b/ethereum_clis/cli_types.py similarity index 99% rename from ethereum_clis/types.py rename to ethereum_clis/cli_types.py index 0d55c63eb2..b6c9b48bad 100644 --- a/ethereum_clis/types.py +++ b/ethereum_clis/cli_types.py @@ -29,7 +29,7 @@ Transaction, TransactionReceipt, ) -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger logger = get_logger(__name__) diff --git a/ethereum_clis/clis/besu.py b/ethereum_clis/clis/besu.py index 4ddf8a9f37..833248909f 100644 --- a/ethereum_clis/clis/besu.py +++ b/ethereum_clis/clis/besu.py @@ -19,8 +19,8 @@ ) from ethereum_test_forks import Fork +from ..cli_types import TransitionToolOutput from ..transition_tool import TransitionTool, dump_files_to_directory, model_dump_config -from ..types import TransitionToolOutput class BesuTransitionTool(TransitionTool): diff --git a/ethereum_clis/clis/execution_specs.py b/ethereum_clis/clis/execution_specs.py index 3012acc12d..31b5dd2e43 100644 --- a/ethereum_clis/clis/execution_specs.py +++ b/ethereum_clis/clis/execution_specs.py @@ -19,7 +19,7 @@ TransactionException, ) from ethereum_test_forks import Fork -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger from ..transition_tool import TransitionTool diff --git a/ethereum_clis/ethereum_cli.py b/ethereum_clis/ethereum_cli.py index d08d11b529..7ea060fcc7 100644 --- a/ethereum_clis/ethereum_cli.py +++ b/ethereum_clis/ethereum_cli.py @@ -8,7 +8,7 @@ from re import Pattern from typing import Any, List, Optional, Type -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger logger = get_logger(__name__) diff --git a/ethereum_clis/tests/test_transition_tools_support.py b/ethereum_clis/tests/test_transition_tools_support.py index 3c6fd625c1..953af15744 100644 --- a/ethereum_clis/tests/test_transition_tools_support.py +++ b/ethereum_clis/tests/test_transition_tools_support.py @@ -31,8 +31,8 @@ Withdrawal, add_kzg_version, ) -from ethereum_test_tools.vm.opcode import Opcodes as Op from ethereum_test_types import Alloc +from ethereum_test_vm import Opcodes as Op BLOB_COMMITMENT_VERSION_KZG = 1 diff --git a/ethereum_clis/transition_tool.py b/ethereum_clis/transition_tool.py index 58d66424dc..c3fa04ec27 100644 --- a/ethereum_clis/transition_tool.py +++ b/ethereum_clis/transition_tool.py @@ -24,9 +24,7 @@ from ethereum_test_forks.helpers import get_development_forks, get_forks from ethereum_test_types import Alloc, Environment, Transaction -from .ethereum_cli import EthereumCLI -from .file_utils import dump_files_to_directory, write_json_file -from .types import ( +from .cli_types import ( Traces, TransactionReceipt, TransactionTraces, @@ -35,6 +33,8 @@ TransitionToolOutput, TransitionToolRequest, ) +from .ethereum_cli import EthereumCLI +from .file_utils import dump_files_to_directory, write_json_file model_dump_config: Mapping = {"by_alias": True, "exclude_none": True} diff --git a/ethereum_test_base_types/__init__.py b/ethereum_test_base_types/__init__.py index 3bb8c6a370..6562a2e848 100644 --- a/ethereum_test_base_types/__init__.py +++ b/ethereum_test_base_types/__init__.py @@ -18,6 +18,7 @@ Wei, ZeroPaddedHexNumber, ) +from .base_types_json import to_json from .composite_types import ( AccessList, Account, @@ -38,7 +39,6 @@ TestPrivateKey2, ) from .conversions import to_bytes, to_hex -from .json import to_json from .pydantic import CamelModel, EthereumTestBaseModel, EthereumTestRootModel from .reference_spec import ReferenceSpec from .serialization import RLPSerializable, SignableRLPSerializable diff --git a/ethereum_test_base_types/json.py b/ethereum_test_base_types/base_types_json.py similarity index 100% rename from ethereum_test_base_types/json.py rename to ethereum_test_base_types/base_types_json.py diff --git a/ethereum_test_base_types/tests/test_base_types.py b/ethereum_test_base_types/tests/test_base_types.py index c53ff13898..a521cbb971 100644 --- a/ethereum_test_base_types/tests/test_base_types.py +++ b/ethereum_test_base_types/tests/test_base_types.py @@ -5,8 +5,8 @@ import pytest from ..base_types import Address, Hash, Wei +from ..base_types_json import to_json from ..composite_types import AccessList -from ..json import to_json @pytest.mark.parametrize( diff --git a/ethereum_test_exceptions/exceptions/__init__.py b/ethereum_test_exceptions/exceptions/__init__.py index 3587b249a1..8434e5f331 100644 --- a/ethereum_test_exceptions/exceptions/__init__.py +++ b/ethereum_test_exceptions/exceptions/__init__.py @@ -3,14 +3,14 @@ from .base import ExceptionBase, UndefinedException, from_pipe_str, to_pipe_str from .block import BlockException from .eof import EOFException -from .transaction import TransactionException -from .types import ( +from .exceptions_types import ( BlockExceptionInstanceOrList, EOFExceptionInstanceOrList, ExceptionBoundTypeVar, ExceptionInstanceOrList, TransactionExceptionInstanceOrList, ) +from .transaction import TransactionException __all__ = [ "ExceptionBase", diff --git a/ethereum_test_exceptions/exceptions/types.py b/ethereum_test_exceptions/exceptions/exceptions_types.py similarity index 100% rename from ethereum_test_exceptions/exceptions/types.py rename to ethereum_test_exceptions/exceptions/exceptions_types.py diff --git a/ethereum_test_execution/blob_transaction.py b/ethereum_test_execution/blob_transaction.py index 8be0a25b44..6c7f6a90d0 100644 --- a/ethereum_test_execution/blob_transaction.py +++ b/ethereum_test_execution/blob_transaction.py @@ -9,10 +9,10 @@ from ethereum_test_base_types.base_types import Bytes from ethereum_test_forks import Fork from ethereum_test_rpc import BlobAndProofV1, BlobAndProofV2, EngineRPC, EthRPC -from ethereum_test_rpc.types import GetBlobsResponse +from ethereum_test_rpc.rpc_types import GetBlobsResponse from ethereum_test_types import NetworkWrappedTransaction, Transaction from ethereum_test_types.transaction_types import TransactionTestMetadata -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger from .base import BaseExecute diff --git a/ethereum_test_rpc/__init__.py b/ethereum_test_rpc/__init__.py index 5e5438a2ca..85e533d89b 100644 --- a/ethereum_test_rpc/__init__.py +++ b/ethereum_test_rpc/__init__.py @@ -9,7 +9,7 @@ NetRPC, SendTransactionExceptionError, ) -from .types import ( +from .rpc_types import ( BlobAndProofV1, BlobAndProofV2, EthConfigResponse, diff --git a/ethereum_test_rpc/rpc.py b/ethereum_test_rpc/rpc.py index 61aa05c650..1f289b628f 100644 --- a/ethereum_test_rpc/rpc.py +++ b/ethereum_test_rpc/rpc.py @@ -11,9 +11,9 @@ from ethereum_test_base_types import Address, Bytes, Hash, to_json from ethereum_test_types import Transaction -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger -from .types import ( +from .rpc_types import ( EthConfigResponse, ForkchoiceState, ForkchoiceUpdateResponse, diff --git a/ethereum_test_rpc/types.py b/ethereum_test_rpc/rpc_types.py similarity index 100% rename from ethereum_test_rpc/types.py rename to ethereum_test_rpc/rpc_types.py diff --git a/ethereum_test_specs/state.py b/ethereum_test_specs/state.py index d45e385d4f..b368b41298 100644 --- a/ethereum_test_specs/state.py +++ b/ethereum_test_specs/state.py @@ -35,7 +35,7 @@ Environment, Transaction, ) -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger from .base import BaseTest, OpMode from .blockchain import Block, BlockchainTest, Header diff --git a/ethereum_test_tools/__init__.py b/ethereum_test_tools/__init__.py index 18fa9543ec..bb0b026ef9 100644 --- a/ethereum_test_tools/__init__.py +++ b/ethereum_test_tools/__init__.py @@ -82,7 +82,7 @@ call_return_code, ) -from .code import ( +from .tools_code import ( CalldataCase, Case, CodeGasMeasure, diff --git a/ethereum_test_tools/tests/test_code.py b/ethereum_test_tools/tests/test_code.py index 48465367dd..40d4782142 100644 --- a/ethereum_test_tools/tests/test_code.py +++ b/ethereum_test_tools/tests/test_code.py @@ -22,7 +22,7 @@ from ethereum_test_vm import UndefinedOpcodes from pytest_plugins.solc.solc import SOLC_EXPECTED_MIN_VERSION -from ..code import CalldataCase, Case, Conditional, Initcode, Switch +from ..tools_code import CalldataCase, Case, Conditional, Initcode, Switch @pytest.fixture(params=get_deployed_forks()) diff --git a/ethereum_test_tools/code/__init__.py b/ethereum_test_tools/tools_code/__init__.py similarity index 100% rename from ethereum_test_tools/code/__init__.py rename to ethereum_test_tools/tools_code/__init__.py diff --git a/ethereum_test_tools/code/generators.py b/ethereum_test_tools/tools_code/generators.py similarity index 100% rename from ethereum_test_tools/code/generators.py rename to ethereum_test_tools/tools_code/generators.py diff --git a/ethereum_test_tools/code/yul.py b/ethereum_test_tools/tools_code/yul.py similarity index 100% rename from ethereum_test_tools/code/yul.py rename to ethereum_test_tools/tools_code/yul.py diff --git a/ethereum_test_tools/vm/__init__.py b/ethereum_test_tools/vm/__init__.py deleted file mode 100644 index 6bd0c74648..0000000000 --- a/ethereum_test_tools/vm/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Mirror module to import `ethereum_test_vm`.""" - -from .opcode import Bytecode, Macro, Macros, Opcode, OpcodeCallArg, Opcodes, UndefinedOpcodes - -__all__ = ( - "Bytecode", - "Macro", - "Macros", - "Opcode", - "OpcodeCallArg", - "Opcodes", - "UndefinedOpcodes", -) diff --git a/ethereum_test_tools/vm/opcode.py b/ethereum_test_tools/vm/opcode.py deleted file mode 100644 index fc5ed0c8ef..0000000000 --- a/ethereum_test_tools/vm/opcode.py +++ /dev/null @@ -1,21 +0,0 @@ -"""Import shortcuts for the ethereum_test_vm package.""" - -from ethereum_test_vm import ( - Bytecode, - Macro, - Macros, - Opcode, - OpcodeCallArg, - Opcodes, - UndefinedOpcodes, -) - -__all__ = ( - "Bytecode", - "Macro", - "Macros", - "Opcode", - "OpcodeCallArg", - "Opcodes", - "UndefinedOpcodes", -) diff --git a/ethereum_test_types/blob_types.py b/ethereum_test_types/blob_types.py index ca7e13afc3..3adc860c86 100644 --- a/ethereum_test_types/blob_types.py +++ b/ethereum_test_types/blob_types.py @@ -14,7 +14,7 @@ from ethereum_test_base_types.base_types import Bytes, Hash from ethereum_test_base_types.pydantic import CamelModel from ethereum_test_forks import Fork -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger CACHED_BLOBS_DIRECTORY: Path = ( Path(platformdirs.user_cache_dir("ethereum-execution-spec-tests")) / "cached_blobs" diff --git a/ethereum_test_types/transaction_types.py b/ethereum_test_types/transaction_types.py index 9b3c0966d2..4ffe706bb0 100644 --- a/ethereum_test_types/transaction_types.py +++ b/ethereum_test_types/transaction_types.py @@ -33,7 +33,7 @@ TestPrivateKey, ) from ethereum_test_exceptions import TransactionException -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger from .account_types import EOA from .blob_types import Blob diff --git a/ethereum_test_vm/__init__.py b/ethereum_test_vm/__init__.py index 34972a73a4..cd84471f20 100644 --- a/ethereum_test_vm/__init__.py +++ b/ethereum_test_vm/__init__.py @@ -3,7 +3,7 @@ from .bytecode import Bytecode from .evm_types import EVMCodeType from .helpers import call_return_code -from .opcode import Macro, Macros, Opcode, OpcodeCallArg, Opcodes, UndefinedOpcodes +from .opcodes import Macro, Macros, Opcode, OpcodeCallArg, Opcodes, UndefinedOpcodes __all__ = ( "Bytecode", diff --git a/ethereum_test_vm/helpers.py b/ethereum_test_vm/helpers.py index 7460975f63..2b7a723d5b 100644 --- a/ethereum_test_vm/helpers.py +++ b/ethereum_test_vm/helpers.py @@ -1,6 +1,6 @@ """Helper functions for the EVM.""" -from .opcode import Opcodes as Op +from .opcodes import Opcodes as Op def call_return_code(opcode: Op, success: bool, *, revert: bool = False) -> int: diff --git a/ethereum_test_vm/opcode.py b/ethereum_test_vm/opcodes.py similarity index 100% rename from ethereum_test_vm/opcode.py rename to ethereum_test_vm/opcodes.py diff --git a/ethereum_test_vm/tests/test_vm.py b/ethereum_test_vm/tests/test_vm.py index f9da93d84e..be9d7edd5d 100644 --- a/ethereum_test_vm/tests/test_vm.py +++ b/ethereum_test_vm/tests/test_vm.py @@ -4,9 +4,9 @@ from ethereum_test_base_types import Address -from ..opcode import Bytecode -from ..opcode import Macros as Om -from ..opcode import Opcodes as Op +from ..opcodes import Bytecode +from ..opcodes import Macros as Om +from ..opcodes import Opcodes as Op @pytest.mark.parametrize( diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py index a4f8a62117..1d54d0586c 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py @@ -10,9 +10,9 @@ from ethereum_test_exceptions import UndefinedException from ethereum_test_fixtures import BlockchainEngineFixture from ethereum_test_rpc import EngineRPC, EthRPC -from ethereum_test_rpc.types import ForkchoiceState, JSONRPCError, PayloadStatusEnum +from ethereum_test_rpc.rpc_types import ForkchoiceState, JSONRPCError, PayloadStatusEnum -from ....logging import get_logger +from ....custom_logging import get_logger from ..helpers.exceptions import GenesisBlockMismatchExceptionError from ..helpers.timing import TimingData diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py index c3ab8e202e..cf30667c92 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py @@ -18,13 +18,13 @@ from ethereum_test_exceptions import UndefinedException from ethereum_test_fixtures import BlockchainEngineSyncFixture from ethereum_test_rpc import AdminRPC, EngineRPC, EthRPC, NetRPC -from ethereum_test_rpc.types import ( +from ethereum_test_rpc.rpc_types import ( ForkchoiceState, JSONRPCError, PayloadStatusEnum, ) -from ....logging import get_logger +from ....custom_logging import get_logger from ..helpers.exceptions import GenesisBlockMismatchExceptionError from ..helpers.timing import TimingData diff --git a/pytest_plugins/logging/__init__.py b/pytest_plugins/custom_logging/__init__.py similarity index 93% rename from pytest_plugins/logging/__init__.py rename to pytest_plugins/custom_logging/__init__.py index 7c2d7fe3e6..a03e1b28ad 100644 --- a/pytest_plugins/logging/__init__.py +++ b/pytest_plugins/custom_logging/__init__.py @@ -1,6 +1,6 @@ """Import the logging module content to make it available from pytest_plugins.logging.""" -from .logging import ( +from .plugin_logging import ( FAIL_LEVEL, VERBOSE_LEVEL, ColorFormatter, diff --git a/pytest_plugins/logging/logging.py b/pytest_plugins/custom_logging/plugin_logging.py similarity index 100% rename from pytest_plugins/logging/logging.py rename to pytest_plugins/custom_logging/plugin_logging.py diff --git a/pytest_plugins/logging/tests/__init__.py b/pytest_plugins/custom_logging/tests/__init__.py similarity index 100% rename from pytest_plugins/logging/tests/__init__.py rename to pytest_plugins/custom_logging/tests/__init__.py diff --git a/pytest_plugins/logging/tests/test_logging.py b/pytest_plugins/custom_logging/tests/test_logging.py similarity index 98% rename from pytest_plugins/logging/tests/test_logging.py rename to pytest_plugins/custom_logging/tests/test_logging.py index dad7b82b9d..9437f2e6cb 100644 --- a/pytest_plugins/logging/tests/test_logging.py +++ b/pytest_plugins/custom_logging/tests/test_logging.py @@ -12,7 +12,7 @@ from pathlib import Path from unittest.mock import MagicMock, patch -from ..logging import ( +from ..plugin_logging import ( FAIL_LEVEL, VERBOSE_LEVEL, ColorFormatter, @@ -194,7 +194,7 @@ class TestPytestIntegration: def test_pytest_configure(self, monkeypatch, tmpdir): """Test that pytest_configure sets up logging correctly.""" - from pytest_plugins.logging.logging import pytest_configure + from pytest_plugins.custom_logging.plugin_logging import pytest_configure # Create logs directory if it doesn't exist log_dir = Path("logs") diff --git a/pytest_plugins/execute/eth_config/eth_config.py b/pytest_plugins/execute/eth_config/eth_config.py index 1e7da09cb3..cb8d30a029 100644 --- a/pytest_plugins/execute/eth_config/eth_config.py +++ b/pytest_plugins/execute/eth_config/eth_config.py @@ -10,9 +10,9 @@ import requests from ethereum_test_rpc import EthRPC -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger -from .types import Genesis, NetworkConfigFile +from .execute_types import Genesis, NetworkConfigFile CURRENT_FILE = Path(realpath(__file__)) CURRENT_FOLDER = CURRENT_FILE.parent diff --git a/pytest_plugins/execute/eth_config/execute_eth_config.py b/pytest_plugins/execute/eth_config/execute_eth_config.py index 194bce8f75..af43ec0b1e 100644 --- a/pytest_plugins/execute/eth_config/execute_eth_config.py +++ b/pytest_plugins/execute/eth_config/execute_eth_config.py @@ -8,9 +8,9 @@ import pytest from ethereum_test_rpc import EthConfigResponse, EthRPC -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger -from .types import NetworkConfig +from .execute_types import NetworkConfig logger = get_logger(__name__) diff --git a/pytest_plugins/execute/eth_config/types.py b/pytest_plugins/execute/eth_config/execute_types.py similarity index 100% rename from pytest_plugins/execute/eth_config/types.py rename to pytest_plugins/execute/eth_config/execute_types.py diff --git a/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py b/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py index 8feebb8371..bb147b8241 100644 --- a/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py +++ b/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py @@ -10,7 +10,7 @@ from ethereum_test_base_types import ForkHash from ethereum_test_rpc import EthConfigResponse -from ..types import NetworkConfig, NetworkConfigFile +from ..execute_types import NetworkConfig, NetworkConfigFile EXPECTED_CANCUN = json.loads(""" { diff --git a/pytest_plugins/execute/eth_config/tests/test_genesis.py b/pytest_plugins/execute/eth_config/tests/test_genesis.py index 46fbadba5c..dcf02ecc65 100644 --- a/pytest_plugins/execute/eth_config/tests/test_genesis.py +++ b/pytest_plugins/execute/eth_config/tests/test_genesis.py @@ -28,7 +28,7 @@ ForkConfigBlobSchedule, ) -from ..types import ForkActivationTimes, Genesis, NetworkConfig +from ..execute_types import ForkActivationTimes, Genesis, NetworkConfig CURRENT_FILE = Path(realpath(__file__)) CURRENT_FOLDER = CURRENT_FILE.parent diff --git a/pytest_plugins/execute/pre_alloc.py b/pytest_plugins/execute/pre_alloc.py index 8ee83b3f0a..40ab87f803 100644 --- a/pytest_plugins/execute/pre_alloc.py +++ b/pytest_plugins/execute/pre_alloc.py @@ -23,7 +23,7 @@ ) from ethereum_test_forks import Fork from ethereum_test_rpc import EthRPC -from ethereum_test_rpc.types import TransactionByHashResponse +from ethereum_test_rpc.rpc_types import TransactionByHashResponse from ethereum_test_tools import ( EOA, Account, diff --git a/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py b/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py index ac78b29968..017eb40fbc 100644 --- a/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py +++ b/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py @@ -11,7 +11,7 @@ from ethereum_test_forks import Fork from ethereum_test_rpc import EngineRPC from ethereum_test_rpc import EthRPC as BaseEthRPC -from ethereum_test_rpc.types import ( +from ethereum_test_rpc.rpc_types import ( ForkchoiceState, PayloadAttributes, PayloadStatusEnum, diff --git a/pytest_plugins/filler/static_filler.py b/pytest_plugins/filler/static_filler.py index 33271d3172..9e240a75ea 100644 --- a/pytest_plugins/filler/static_filler.py +++ b/pytest_plugins/filler/static_filler.py @@ -19,7 +19,7 @@ from ethereum_test_fixtures import BaseFixture, LabeledFixtureFormat from ethereum_test_forks import Fork, get_closest_fork from ethereum_test_specs import BaseStaticTest, BaseTest -from ethereum_test_tools.code.yul import Yul +from ethereum_test_tools.tools_code.yul import Yul from ..forks.forks import ValidityMarker from ..shared.helpers import labeled_format_parameter_set diff --git a/pytest_plugins/filler/tests/test_prealloc_group.py b/pytest_plugins/filler/tests/test_prealloc_group.py index dfceb93dcc..86ccc9c3b6 100644 --- a/pytest_plugins/filler/tests/test_prealloc_group.py +++ b/pytest_plugins/filler/tests/test_prealloc_group.py @@ -232,7 +232,7 @@ class StateTest(FormattedTest): # noqa: D101 StateTestFiller, Transaction ) - from ethereum_test_tools.vm.opcode import Opcodes as Op + from ethereum_test_vm import Opcodes as Op @pytest.mark.valid_from("Istanbul") def test_chainid(state_test: StateTestFiller, pre: Alloc): @@ -269,7 +269,7 @@ class BlockchainTest(FormattedTest): # noqa: D101 Environment, Transaction ) - from ethereum_test_tools.vm.opcode import Opcodes as Op + from ethereum_test_vm import Opcodes as Op @pytest.mark.valid_from("Istanbul") def test_chainid_blockchain(blockchain_test: BlockchainTestFiller, pre: Alloc): diff --git a/pytest_plugins/forks/forks.py b/pytest_plugins/forks/forks.py index 6291951fec..6fa07821f8 100644 --- a/pytest_plugins/forks/forks.py +++ b/pytest_plugins/forks/forks.py @@ -25,7 +25,7 @@ get_transition_forks, transition_fork_to, ) -from pytest_plugins.logging import get_logger +from pytest_plugins.custom_logging import get_logger logger = get_logger(__name__) diff --git a/pytest_plugins/pytest_hive/pytest_hive.py b/pytest_plugins/pytest_hive/pytest_hive.py index fb29cf3345..b8e0fd0cb9 100644 --- a/pytest_plugins/pytest_hive/pytest_hive.py +++ b/pytest_plugins/pytest_hive/pytest_hive.py @@ -41,7 +41,7 @@ from hive.simulation import Simulation from hive.testing import HiveTest, HiveTestResult, HiveTestSuite -from ..logging import get_logger +from ..custom_logging import get_logger from .hive_info import ClientFile, HiveInfo logger = get_logger(__name__) From cdec88254dc29ec3c39dda6c0d8e5ab8ecfbc716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 22 Sep 2025 16:45:14 +0200 Subject: [PATCH 024/102] feat(tests): add correct P256 precompile tests for invalid point (#2179) Add test cases for the `p256_verify` precompile from EIP-7951 where the input point representing the public key is from different curve or simply some random bytes. The other parameters of the input: h, r, s are computed in a way that the signature verification succeeds in case the curve check is missing in the implementation. The previous test cases "invalid_curve_attack" added in #2082 are ineffective: the signature verification fails even without the curve check because the final check `R.x == r` fails. --- .../test_p256verify.py | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index 8c4f1cd5ef..9a82ca4a9b 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -188,6 +188,138 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact + Y(0x85EC5A4AF40176B63189069AEFFCB229C96D3E046E0283ED2F9DAC21B15AD3C), id="invalid_curve_attack_composite_order", ), + pytest.param( + # Invalid curve attack: Composite order curve with b = -Spec.B + # Random point which satisfies y² = x³ - 3x - Spec.B (mod p) + # Without the curve check in the implementation, the signature checks out. + H(0xC223E1538C4D7B5BBD3EF932736826FD64F4E8B5C80250D9E07A728689D13C38) + + R(0x0C7CB59EF6BE7539397CC979AD9A87A3B73A0DD268BBA4990A3378C6391512D5) + + S(0xF8C943685BCFE7864C0F8485CACD732D3A9F167531CAF26B67A3CB10B641F92C) + + X(0xF1F2ADE681DB5699741B1F9FF080E9A08DCFF48F48A5048C4D90EC89440C3EFB) + + Y(0xBFFE372E7BBDBD60E4DF885E17A37878461AE13B6491E7863020305962F2C6B6), + id="invalid_curve_attack_bneg_1", + ), + pytest.param( + # Invalid curve attack: Composite order curve with b = -Spec.B + # Random point which satisfies y² = x³ - 3x - Spec.B (mod p) + # Without the curve check in the implementation, the signature checks out. + H(0x982D25BF8E0E81FF41AC3C8033604C78ED5EF17C6EDDA977072EAB6821A7AD0A) + + R(0x7C1996FA0EC911E4739AE7340B5345823272F494DFA32034A4FE5642C3DB91F2) + + S(0x1E4D6CCF1AFB675D18BD27274770C8B84028D272D1D2641E70B30E1DF17AF3DC) + + X(0xC9124B6AB12F08790A2712AEC74A1B71FA997CA7DE1E9117BC18D07DCBFE7C91) + + Y(0xADD1E9DF40A47ADD6B2191C05D0C1B4AF1BAEEAA0C0A97E7B3D06FFAE543D096), + id="invalid_curve_attack_bneg_2", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0) + + R(0xD21697149F598FEAE9A750DCA86AE6D5EFA654680BA748D2DF7053115101C129) + + S(0xEF3FD943AD1F126B3EBA1A5900D79886755DB6DAFCB6B0117D86364340CE36CC) + + X(0x687216395BD2F58E5A6D91964AE67E766DF2A2FB8E623795A5852507927C70C2) + + Y(0xF40E19B93BEB5C0678EDE25AB3654E08C0C6EF6A143CEC9865F3A447C6EB84E3), + id="invalid_curve_attack_h0_random1", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0) + + R(0x52E47C5D6AAB66AB6A18A694359EB86FDD40F10E79EF5493C5469EC88BA03334) + + S(0x7584C5BF3CA2869C7E383B1603A935EEB79D990B7F7152E055EC562E87FD715E) + + X(0x0000000000000002000000000000000000000000000000000000000000000000) + + Y(0x000000000000000000000000000000000000000000000000FE00000000000000), + id="invalid_curve_attack_h0_random2", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0) + + R(0x81333B13B13F362253BD536D17563A72EB575F1993F55ED40E633E503F60B864) + + S(0xE2208C4045F5241ECCF08F825399224C4B78595A10433EC33799DCAD7B0E1F4A) + + X(0xCE9C1088B4BCC71223A187410BB05819A6D32D2F1A1024B83557E51833AB23DC) + + Y(0x00FB64209538D1143A88E8B91D2DA46095AF852D7DD494BE6AF26C29D545F856), + id="invalid_curve_attack_h0_random3", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0) + + R(0x3C593B5857D1D0EB83923D73E76A7A53EF191BB210267D8C0BE17A4E34AB2E73) + + S(0xD022359310067882F713AFBECECE71CB80E4857368F46AB0346362DB033ED298) + + X(0x358DF65C0D732CCAB431D4CAB7F98E9F9279BD71D64635FAB21EA87EF254C5D1) + + Y(0x82909FF2E230433D000000000000000000000000000000000000000000000000), + id="invalid_curve_attack_h0_random4", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0) + + R(0x425CFFCA652791CABFC81B1E4B7712DBA196599FABCE16978E06E6AF486B1FEC) + + S(0x58B864B5A41CD17524E4773EC353C9590D792F601DA075AD9B3F40E8E7070E8A) + + X(0x00000000000000000000000000000000000000000000000000007FFFFFFFFFFF) + + Y(0xFFFF000000000000000000000000000000000000000000000000000000000000), + id="invalid_curve_attack_h0_random5", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0x2DA0A74BE3122AEAEF5704D0EB27881FBFB918B4A5252B660935263D0569BA92) + + R(0x5543729CBCFD99EE6C3B422D7F245903E7177B3A6A4E3C20C0DC5F5E109795AE) + + S(0x96403D5BB253EBD7DEF44BCBC062FCD4EA5E358B19B67C13E625EFDF6B977597) + + X(0x996CADC001622FB5E363B421A08854096569397B3BDCB8C3DEC907392F7CC59B) + + Y(0xD34A4E0F08C6FC549F7FAFFBCAF610D7F6C467B7B27072720E81079FB6595B52), + id="invalid_curve_attack_random6", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0x1F9D9B26DB42380C85F075174DDAF158F9DE4CD10C3104190D7AF96938DD8ECD) + + R(0x159946DBC4F1DE68CD4096862A5B10E5986ACB32229D6E68884DC83DAB70A307) + + S(0x63D80724A4074421F7DD255630794E3AEBE635B756D72B24652AAC07D01B289C) + + X(0x9CA2F39CC3536861000000000000000000000000000000000000000000000000) + + Y(0x000000000000B100000000000000000000000000000000000000000000000000), + id="invalid_curve_attack_random7", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0xD380DA9251F1FB809ED48C70DC8F81E91C471F0E81BC95E7611C653278A5B6B4) + + R(0xFF197EB72A9E531B17B872525247E6564B786CC014ED28B6849CE7D8C976BDF2) + + S(0x7B0B2EFF9BB5409052B35FD3FF81DCE77D95A1F75C46989817045120DA5C3C9C) + + X(0xBA7695481956A6269DD646ADDD4AFE6D9763637D76AD780299E51201384A8403) + + Y(0xA62443DD4AFE6D9763637D76AD780299E51201384AE4FEDD3CDAC9F461600D53), + id="invalid_curve_attack_random8", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0x4B082B60497ED87FFE570612D521E73A2CD6C832744EF8E4E2E329E30D3D5879) + + R(0x6665A88CB3FF30D339A1975FD46CF5EF480A68A093AB778550073D3528C3B609) + + S(0xAEAADDB235E4AC6097356DB96161E27849EA8EDF1E971F74EB51E19A1CC950A1) + + X(0x0000000000000002000000000000000000000000000000000000000000000000) + + Y(0x000000000000000000000000000000000000000000000000FE00000000000000), + id="invalid_curve_attack_random9", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0x6CC2B605CFBDB22B9E7B55EFE8C1DA0F1C5A0EC1AA8D82EEDFB5EA70E9846E88) + + R(0x3C593B5857D1D0EB83923D73E76A7A53EF191BB210267D8C0BE17A4E34AB2E73) + + S(0xD022359310067882F713AFBECECE71CB80E4857368F46AB0346362DB033ED298) + + X(0x358DF65C0D732CCAB431D4CAB7F98E9F9279BD71D64635FAB21EA87EF254C5D1) + + Y(0x82909FF2E230433D000000000000000000000000000000000000000000000000), + id="invalid_curve_attack_random10", + ), + pytest.param( + # Invalid curve attack: random point bytes. + # Without the curve check in the implementation, the signature checks out. + H(0x810C1D53EA96A700C93F6AF1C183197B040EA6FEAE10564877A1C78EC6074FF1) + + R(0x34D0F0C8E14D39002B5DEA00808957963E849503DDFD626323433047D696C7C4) + + S(0x6A7FE39C046304317F799FB900877073F2AE3C798DD4414795551A833ABCBA85) + + X(0x0000000000F90000000067923073C067015B601D94F262F0E82B9DA2D33A6A32) + + Y(0xFC3D71CB490CF346ED31DC37405FB0069F4A7ED188381DC049ABAB66E9F80080), + id="invalid_curve_attack_random_11", + ), ], ) @pytest.mark.parametrize("expected_output", [Spec.INVALID_RETURN_VALUE], ids=[""]) From eea26c27ef986029fd0b8fd9b7042455c10f5b8a Mon Sep 17 00:00:00 2001 From: Sam Wilson <57262657+SamWilsn@users.noreply.github.com> Date: Mon, 22 Sep 2025 19:02:53 -0400 Subject: [PATCH 025/102] chore: unused arguments (#2166) Co-authored-by: danceratopz --- cli/gen_index.py | 15 +-------------- cli/gentest/tests/test_cli.py | 1 + cli/pytest_commands/check_eip_versions.py | 2 ++ cli/pytest_commands/checklist.py | 2 ++ cli/pytest_commands/consume.py | 8 ++++++-- cli/pytest_commands/fill.py | 4 ++++ cli/show_pre_alloc_group_stats.py | 4 ++-- cli/tests/test_pytest_execute_command.py | 2 +- ethereum_clis/tests/test_execution_specs.py | 18 ++---------------- ethereum_clis/tests/test_transition_tool.py | 2 ++ .../tests/test_reference_spec.py | 2 ++ .../test_checklist_template_consistency.py | 2 +- ethereum_test_forks/forks/forks.py | 11 +++++++++++ ethereum_test_forks/helpers.py | 3 +-- ethereum_test_forks/transition_base_fork.py | 2 ++ .../block_access_list/modifiers.py | 3 ++- ethereum_test_types/tests/test_transactions.py | 1 - pytest_plugins/consume/consume.py | 1 - .../simulator_logic/test_via_sync.py | 4 +--- .../consume/simulators/sync/conftest.py | 3 ++- .../consume/simulators/timing_data.py | 2 ++ .../consume/tests/test_consume_args.py | 2 ++ .../custom_logging/plugin_logging.py | 8 +++++++- pytest_plugins/eels_resolver.py | 2 ++ pytest_plugins/execute/execute.py | 4 ++++ pytest_plugins/execute/execute_recover.py | 2 ++ pytest_plugins/filler/filler.py | 12 +++++++++--- pytest_plugins/filler/static_filler.py | 2 +- pytest_plugins/forks/forks.py | 2 ++ pytest_plugins/pytest_hive/pytest_hive.py | 6 ++++++ pytest_plugins/shared/execute_fill.py | 1 + pytest_plugins/solc/solc.py | 2 ++ .../spec_version_checker.py | 2 ++ 33 files changed, 87 insertions(+), 50 deletions(-) diff --git a/cli/gen_index.py b/cli/gen_index.py index 753b137136..a19e239431 100644 --- a/cli/gen_index.py +++ b/cli/gen_index.py @@ -53,15 +53,6 @@ def count_json_files_exclude_index(start_path: Path) -> int: required=True, help="The input directory", ) -@click.option( - "--disable-infer-format", - "-d", - "disable_infer_format", - is_flag=True, - default=False, - expose_value=True, - help="Don't try to guess the fixture format from the json file's path.", -) @click.option( "--quiet", "-q", @@ -80,15 +71,12 @@ def count_json_files_exclude_index(start_path: Path) -> int: expose_value=True, help="Force re-generation of the index file, even if it already exists.", ) -def generate_fixtures_index_cli( - input_dir: str, quiet_mode: bool, force_flag: bool, disable_infer_format: bool -): +def generate_fixtures_index_cli(input_dir: str, quiet_mode: bool, force_flag: bool): """CLI wrapper to an index of all the fixtures in the specified directory.""" generate_fixtures_index( Path(input_dir), quiet_mode=quiet_mode, force_flag=force_flag, - disable_infer_format=disable_infer_format, ) @@ -96,7 +84,6 @@ def generate_fixtures_index( input_path: Path, quiet_mode: bool = False, force_flag: bool = False, - disable_infer_format: bool = False, ): """ Generate an index file (index.json) of all the fixtures in the specified diff --git a/cli/gentest/tests/test_cli.py b/cli/gentest/tests/test_cli.py index 27ff66489b..c8d9a869c6 100644 --- a/cli/gentest/tests/test_cli.py +++ b/cli/gentest/tests/test_cli.py @@ -106,6 +106,7 @@ def test_tx_type(pytester, tmp_path, monkeypatch, tx_type, transaction_hash, def tx = transactions_by_type[tx_type] def get_mock_context(self: StateTestProvider) -> dict: + del self return tx monkeypatch.setattr(StateTestProvider, "get_context", get_mock_context) diff --git a/cli/pytest_commands/check_eip_versions.py b/cli/pytest_commands/check_eip_versions.py index 46e0875b3d..32b714b64e 100644 --- a/cli/pytest_commands/check_eip_versions.py +++ b/cli/pytest_commands/check_eip_versions.py @@ -14,6 +14,8 @@ @common_pytest_options def check_eip_versions(pytest_args: List[str], **kwargs) -> None: """Run pytest with the `spec_version_checker` plugin.""" + del kwargs + command = PytestCommand( config_file="pytest-check-eip-versions.ini", argument_processors=[HelpFlagsProcessor("check-eip-versions")], diff --git a/cli/pytest_commands/checklist.py b/cli/pytest_commands/checklist.py index 2114853636..d87b2a14a8 100644 --- a/cli/pytest_commands/checklist.py +++ b/cli/pytest_commands/checklist.py @@ -41,6 +41,8 @@ def checklist(output: str, eip: tuple, **kwargs) -> None: uv run checklist --output ./my-checklists """ + del kwargs + # Add output directory to pytest args args = ["--checklist-output", output] diff --git a/cli/pytest_commands/consume.py b/cli/pytest_commands/consume.py index bf4d662000..cc9b202038 100644 --- a/cli/pytest_commands/consume.py +++ b/cli/pytest_commands/consume.py @@ -36,7 +36,7 @@ def create_consume_command( ) -def get_command_logic_test_paths(command_name: str, is_hive: bool) -> List[Path]: +def get_command_logic_test_paths(command_name: str) -> List[Path]: """Determine the command paths based on the command name and hive flag.""" base_path = Path("pytest_plugins/consume") if command_name in ["engine", "rlp"]: @@ -66,7 +66,7 @@ def consume_command(is_hive: bool = False) -> Callable[[Callable[..., Any]], cli def decorator(func: Callable[..., Any]) -> click.Command: command_name = func.__name__ command_help = func.__doc__ - command_logic_test_paths = get_command_logic_test_paths(command_name, is_hive) + command_logic_test_paths = get_command_logic_test_paths(command_name) @consume.command( name=command_name, @@ -76,6 +76,8 @@ def decorator(func: Callable[..., Any]) -> click.Command: @common_pytest_options @functools.wraps(func) def command(pytest_args: List[str], **kwargs) -> None: + del kwargs + consume_cmd = create_consume_command( command_logic_test_paths=command_logic_test_paths, is_hive=is_hive, @@ -118,5 +120,7 @@ def sync() -> None: @common_pytest_options def cache(pytest_args: List[str], **kwargs) -> None: """Consume command to cache test fixtures.""" + del kwargs + cache_cmd = create_consume_command(command_logic_test_paths=[], is_hive=False) cache_cmd.execute(list(pytest_args)) diff --git a/cli/pytest_commands/fill.py b/cli/pytest_commands/fill.py index 9b98628f67..452a6f1d27 100644 --- a/cli/pytest_commands/fill.py +++ b/cli/pytest_commands/fill.py @@ -213,6 +213,8 @@ def create_executions(self, pytest_args: List[str]) -> List[PytestExecution]: @common_pytest_options def fill(pytest_args: List[str], **kwargs) -> None: """Entry point for the fill command.""" + del kwargs + command = FillCommand() command.execute(list(pytest_args)) @@ -225,6 +227,8 @@ def fill(pytest_args: List[str], **kwargs) -> None: @common_pytest_options def phil(pytest_args: List[str], **kwargs) -> None: """Friendly alias for the fill command.""" + del kwargs + command = PhilCommand() command.execute(list(pytest_args)) diff --git a/cli/show_pre_alloc_group_stats.py b/cli/show_pre_alloc_group_stats.py index a5d10183e1..c7cf51cedf 100644 --- a/cli/show_pre_alloc_group_stats.py +++ b/cli/show_pre_alloc_group_stats.py @@ -100,7 +100,7 @@ def calculate_size_distribution( return group_distribution, test_distribution -def analyze_pre_alloc_folder(folder: Path, verbose: int = 0) -> Dict: +def analyze_pre_alloc_folder(folder: Path) -> Dict: """Analyze pre-allocation folder and return statistics.""" pre_alloc_groups = PreAllocGroups.from_folder(folder, lazy_load=False) @@ -480,7 +480,7 @@ def main(pre_alloc_folder: Path, verbose: int): console = Console() try: - stats = analyze_pre_alloc_folder(pre_alloc_folder, verbose=verbose) + stats = analyze_pre_alloc_folder(pre_alloc_folder) display_stats(stats, console, verbose=verbose) except FileNotFoundError: console.print(f"[red]Error: Folder not found: {pre_alloc_folder}[/red]") diff --git a/cli/tests/test_pytest_execute_command.py b/cli/tests/test_pytest_execute_command.py index a8faae6518..d6df1d5c0c 100644 --- a/cli/tests/test_pytest_execute_command.py +++ b/cli/tests/test_pytest_execute_command.py @@ -28,7 +28,7 @@ def test_execute_help_shows_subcommand_docstrings(runner): assert "Recover funds from test executions" in result.output -def test_execute_subcommands_have_help_text(runner): +def test_execute_subcommands_have_help_text(): """Test that execute sub-commands have proper help text defined.""" from ..pytest_commands.execute import hive, recover, remote diff --git a/ethereum_clis/tests/test_execution_specs.py b/ethereum_clis/tests/test_execution_specs.py index 410c58a831..964820dd8a 100644 --- a/ethereum_clis/tests/test_execution_specs.py +++ b/ethereum_clis/tests/test_execution_specs.py @@ -12,7 +12,7 @@ from ethereum_clis import ExecutionSpecsTransitionTool, TransitionTool from ethereum_test_base_types import to_json -from ethereum_test_forks import Berlin, Fork, Istanbul, London +from ethereum_test_forks import Berlin from ethereum_test_types import Alloc, Environment, Transaction FIXTURES_ROOT = Path(os.path.join("src", "ethereum_clis", "tests", "fixtures")) @@ -34,9 +34,8 @@ def monkeypatch_path_for_entry_points(monkeypatch): monkeypatch.setenv("PATH", f"{bin_dir}:{os.environ['PATH']}") -@pytest.mark.parametrize("fork", [London, Istanbul]) @pytest.mark.parametrize( - "alloc,base_fee,expected_hash", + "alloc,expected_hash", [ ( { @@ -47,7 +46,6 @@ def monkeypatch_path_for_entry_points(monkeypatch): "storage": {}, }, }, - 7, bytes.fromhex("51e7c7508e76dca0"), ), ( @@ -56,7 +54,6 @@ def monkeypatch_path_for_entry_points(monkeypatch): "balance": "0x0BA1A9CE0BA1A9CE", }, }, - None, bytes.fromhex("51e7c7508e76dca0"), ), ( @@ -68,7 +65,6 @@ def monkeypatch_path_for_entry_points(monkeypatch): "storage": {}, }, }, - None, bytes.fromhex("37c2dedbdea6b3af"), ), ( @@ -80,25 +76,15 @@ def monkeypatch_path_for_entry_points(monkeypatch): }, }, }, - None, bytes.fromhex("096122e88929baec"), ), ], ) def test_calc_state_root( - default_t8n: TransitionTool, - fork: Fork, alloc: Dict, - base_fee: int | None, expected_hash: bytes, ) -> None: """Test calculation of the state root against expected hash.""" - - class TestEnv: - base_fee: int | None - - env = TestEnv() - env.base_fee = base_fee assert Alloc(alloc).state_root().startswith(expected_hash) diff --git a/ethereum_clis/tests/test_transition_tool.py b/ethereum_clis/tests/test_transition_tool.py index 40884de027..01c2c1bb10 100644 --- a/ethereum_clis/tests/test_transition_tool.py +++ b/ethereum_clis/tests/test_transition_tool.py @@ -67,9 +67,11 @@ def __init__(self, stdout): self.returncode = 0 def mock_which(self): + del self return which_result def mock_run(args, **kwargs): + del args, kwargs return MockCompletedProcess(read_result.encode()) monkeypatch.setattr(shutil, "which", mock_which) diff --git a/ethereum_test_base_types/tests/test_reference_spec.py b/ethereum_test_base_types/tests/test_reference_spec.py index c7aedbc5fb..bd94814d07 100644 --- a/ethereum_test_base_types/tests/test_reference_spec.py +++ b/ethereum_test_base_types/tests/test_reference_spec.py @@ -63,6 +63,8 @@ def test_git_reference_spec(monkeypatch): """Test Git reference spec.""" def mock_get(self, headers=None): + del self, headers + class Response: content = ( '{"content": "' diff --git a/ethereum_test_checklists/tests/test_checklist_template_consistency.py b/ethereum_test_checklists/tests/test_checklist_template_consistency.py index 1e99199cde..69be5f2157 100644 --- a/ethereum_test_checklists/tests/test_checklist_template_consistency.py +++ b/ethereum_test_checklists/tests/test_checklist_template_consistency.py @@ -32,7 +32,7 @@ def extract_markdown_ids(markdown_content: str) -> Set[str]: return ids -def get_all_checklist_ids(obj, current_path="") -> Set[str]: +def get_all_checklist_ids(obj) -> Set[str]: """Recursively extract all checklist IDs from EIPChecklist and its children.""" ids = set() diff --git a/ethereum_test_forks/forks/forks.py b/ethereum_test_forks/forks/forks.py index 9fba9f3794..c40484a34d 100644 --- a/ethereum_test_forks/forks/forks.py +++ b/ethereum_test_forks/forks/forks.py @@ -153,6 +153,8 @@ def calldata_gas_calculator( gas_costs = cls.gas_costs(block_number, timestamp) def fn(*, data: BytesConvertible, floor: bool = False) -> int: + del floor + cost = 0 for b in Bytes(data): if b == 0: @@ -201,6 +203,7 @@ def transaction_data_floor_cost_calculator( """At frontier, the transaction data floor cost is a constant zero.""" def fn(*, data: BytesConvertible) -> int: + del data return 0 return fn @@ -221,6 +224,8 @@ def fn( authorization_list_or_count: Sized | int | None = None, return_cost_deducted_prior_execution: bool = False, ) -> int: + del return_cost_deducted_prior_execution + assert access_list is None, f"Access list is not supported in {cls.name()}" assert authorization_list_or_count is None, ( f"Authorizations are not supported in {cls.name()}" @@ -694,6 +699,8 @@ def fn( authorization_list_or_count: Sized | int | None = None, return_cost_deducted_prior_execution: bool = False, ) -> int: + del return_cost_deducted_prior_execution + intrinsic_cost: int = super_fn( calldata=calldata, contract_creation=contract_creation, @@ -885,6 +892,8 @@ def fn( authorization_list_or_count: Sized | int | None = None, return_cost_deducted_prior_execution: bool = False, ) -> int: + del return_cost_deducted_prior_execution + intrinsic_cost: int = super_fn( calldata=calldata, contract_creation=contract_creation, @@ -1207,6 +1216,8 @@ def fn( parent_blob_count: int | None = None, parent_base_fee_per_gas: int, # Required for Osaka as using this as base ) -> int: + del parent_base_fee_per_gas + if parent_excess_blob_gas is None: assert parent_excess_blobs is not None, "Parent excess blobs are required" parent_excess_blob_gas = parent_excess_blobs * blob_gas_per_blob diff --git a/ethereum_test_forks/helpers.py b/ethereum_test_forks/helpers.py index 1cda134e00..62796f3f53 100644 --- a/ethereum_test_forks/helpers.py +++ b/ethereum_test_forks/helpers.py @@ -13,7 +13,6 @@ ValidatorFunctionWrapHandler, model_validator, ) -from semver import Version from .base_fork import BaseFork from .forks import forks, transition @@ -86,7 +85,7 @@ def get_parent_fork(fork: Type[BaseFork]) -> Type[BaseFork]: return parent_fork -def get_closest_fork(fork: Type[BaseFork], solc_version: Version) -> Optional[Type[BaseFork]]: +def get_closest_fork(fork: Type[BaseFork]) -> Optional[Type[BaseFork]]: """Return None if BaseFork is passed, otherwise return the fork itself.""" if fork is BaseFork: return None diff --git a/ethereum_test_forks/transition_base_fork.py b/ethereum_test_forks/transition_base_fork.py index 83a8b56432..81c3e3f657 100644 --- a/ethereum_test_forks/transition_base_fork.py +++ b/ethereum_test_forks/transition_base_fork.py @@ -66,6 +66,8 @@ def transition_method( block_number: int = ALWAYS_TRANSITIONED_BLOCK_NUMBER, timestamp: int = ALWAYS_TRANSITIONED_BLOCK_TIMESTAMP, ): + del cls + kwargs = {} if "block_number" in base_method_parameters: kwargs["block_number"] = block_number diff --git a/ethereum_test_types/block_access_list/modifiers.py b/ethereum_test_types/block_access_list/modifiers.py index b33f2b067c..a9df449d15 100644 --- a/ethereum_test_types/block_access_list/modifiers.py +++ b/ethereum_test_types/block_access_list/modifiers.py @@ -316,7 +316,8 @@ def transform(bal: BlockAccessList) -> BlockAccessList: def clear_all() -> Callable[[BlockAccessList], BlockAccessList]: """Return an empty BAL.""" - def transform(_bal: BlockAccessList) -> BlockAccessList: + def transform(bal: BlockAccessList) -> BlockAccessList: + del bal return BlockAccessList(root=[]) return transform diff --git a/ethereum_test_types/tests/test_transactions.py b/ethereum_test_types/tests/test_transactions.py index 5f2313ce2f..b780dce2cb 100644 --- a/ethereum_test_types/tests/test_transactions.py +++ b/ethereum_test_types/tests/test_transactions.py @@ -249,7 +249,6 @@ ], ) def test_transaction_signing( - request, tx: Transaction, expected_signature: Tuple[int, int, int], expected_sender: str, diff --git a/pytest_plugins/consume/consume.py b/pytest_plugins/consume/consume.py index e678cf7524..676c754808 100644 --- a/pytest_plugins/consume/consume.py +++ b/pytest_plugins/consume/consume.py @@ -413,7 +413,6 @@ def pytest_configure(config): # noqa: D103 config.fixtures_source.path, quiet_mode=False, force_flag=False, - disable_infer_format=False, ) index = IndexFile.model_validate_json(index_file.read_text()) diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py index cf30667c92..5ef252776a 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py @@ -42,7 +42,6 @@ def __init__(self, *args: object) -> None: def wait_for_sync( sync_eth_rpc: EthRPC, - sync_engine_rpc: EngineRPC, expected_block_hash: str | Hash, timeout: int = 10, poll_interval: float = 1.0, @@ -105,7 +104,6 @@ def test_blockchain_via_sync( eth_rpc: EthRPC, engine_rpc: EngineRPC, net_rpc: NetRPC, - admin_rpc: AdminRPC, sync_eth_rpc: EthRPC, sync_engine_rpc: EngineRPC, sync_net_rpc: NetRPC, @@ -472,7 +470,7 @@ def test_blockchain_via_sync( # Final verification assert sync_eth_rpc is not None, "sync_eth_rpc is required" assert sync_engine_rpc is not None, "sync_engine_rpc is required" - if wait_for_sync(sync_eth_rpc, sync_engine_rpc, last_valid_block_hash, timeout=5): + if wait_for_sync(sync_eth_rpc, last_valid_block_hash, timeout=5): logger.info("Sync verification successful!") # Verify the final state diff --git a/pytest_plugins/consume/simulators/sync/conftest.py b/pytest_plugins/consume/simulators/sync/conftest.py index 10af1907c2..bf9a132379 100644 --- a/pytest_plugins/consume/simulators/sync/conftest.py +++ b/pytest_plugins/consume/simulators/sync/conftest.py @@ -44,6 +44,8 @@ def pytest_generate_tests(metafunc): @pytest.hookimpl(trylast=True) def pytest_collection_modifyitems(session, config, items): """Modify test IDs to show both client and sync client clearly.""" + del session, config + for item in items: # Check if this test has both client_type and sync_client_type if ( @@ -160,7 +162,6 @@ def client_enode_url(client: Client) -> str: @pytest.fixture(scope="function") def sync_client( hive_test: HiveTest, - client: Client, # The main client under test sync_client_files: dict, environment: dict, sync_client_type: ClientType, # Separate parametrization for sync client diff --git a/pytest_plugins/consume/simulators/timing_data.py b/pytest_plugins/consume/simulators/timing_data.py index e63fedfad0..76468e04a6 100644 --- a/pytest_plugins/consume/simulators/timing_data.py +++ b/pytest_plugins/consume/simulators/timing_data.py @@ -39,5 +39,7 @@ def timing_data( total_timing_data: TimingData, client: Client ) -> Generator[TimingData, None, None]: """Record timing data for the main execution of the test case.""" + del client + with total_timing_data.time("Test case execution") as timing_data: yield timing_data diff --git a/pytest_plugins/consume/tests/test_consume_args.py b/pytest_plugins/consume/tests/test_consume_args.py index 553232e7ef..110566fd80 100644 --- a/pytest_plugins/consume/tests/test_consume_args.py +++ b/pytest_plugins/consume/tests/test_consume_args.py @@ -104,6 +104,8 @@ def test_fixtures(pytester: Pytester, fixtures_dir: Path, fill_tests: None) -> L We intentionally copy the `.meta/index.json` file to test its compatibility with consume. """ + del fill_tests + test_fixtures = [] for json_file in fixtures_dir.rglob("*.json"): target_dir = Path(pytester.path) / json_file.parent diff --git a/pytest_plugins/custom_logging/plugin_logging.py b/pytest_plugins/custom_logging/plugin_logging.py index 66d7e58b38..dfe2cf7d1a 100644 --- a/pytest_plugins/custom_logging/plugin_logging.py +++ b/pytest_plugins/custom_logging/plugin_logging.py @@ -314,13 +314,15 @@ def pytest_report_header(config: pytest.Config) -> list[str]: def pytest_terminal_summary(terminalreporter: TerminalReporter, exitstatus: int) -> None: """Display the log file path in the terminal summary like the HTML report does.""" + del exitstatus + if terminalreporter.config.option.collectonly: return if eest_log_file_path := terminalreporter.config.option.eest_log_file_path: terminalreporter.write_sep("-", f"Log file: {eest_log_file_path.resolve()}", yellow=True) -def log_only_to_file(level: int, msg: str, *args, **kwargs) -> None: +def log_only_to_file(level: int, msg: str, *args) -> None: """Log a message only to the file handler, bypassing stdout.""" if not file_handler: return @@ -344,6 +346,8 @@ def log_only_to_file(level: int, msg: str, *args, **kwargs) -> None: def pytest_runtest_logstart(nodeid: str, location: tuple[str, int, str]) -> None: """Log test start to file.""" + del location + log_only_to_file(logging.INFO, f"ℹ️ - START TEST: {nodeid}") @@ -383,4 +387,6 @@ def pytest_runtest_logreport(report: pytest.TestReport) -> None: def pytest_runtest_logfinish(nodeid: str, location: tuple[str, int, str]) -> None: """Log end of test to file.""" + del location + log_only_to_file(logging.INFO, f"ℹ️ - END TEST: {nodeid}") diff --git a/pytest_plugins/eels_resolver.py b/pytest_plugins/eels_resolver.py index 5970ba1502..d78ee9b9db 100644 --- a/pytest_plugins/eels_resolver.py +++ b/pytest_plugins/eels_resolver.py @@ -73,6 +73,8 @@ def pytest_report_header(config: pytest.Config, startdir: Path) -> str: str: A string to add to the pytest report header. """ + del startdir + eels_resolutions_file = getattr(config, "_eels_resolutions_file", None) if eels_resolutions_file: return f"EELS resolutions file: {eels_resolutions_file}" diff --git a/pytest_plugins/execute/execute.py b/pytest_plugins/execute/execute.py index 842c759a11..e6ed68af65 100644 --- a/pytest_plugins/execute/execute.py +++ b/pytest_plugins/execute/execute.py @@ -283,6 +283,8 @@ def collector( Return configured fixture collector instance used for all tests in one test module. """ + del request + collector = Collector(eth_rpc=eth_rpc) yield collector @@ -397,6 +399,8 @@ def pytest_generate_tests(metafunc: pytest.Metafunc): def pytest_collection_modifyitems(config: pytest.Config, items: List[pytest.Item]): """Remove transition tests and add the appropriate execute markers to the test.""" + del config + items_for_removal = [] for i, item in enumerate(items): if isinstance(item, EIPSpecTestItem): diff --git a/pytest_plugins/execute/execute_recover.py b/pytest_plugins/execute/execute_recover.py index d23038a501..3e25fd7509 100644 --- a/pytest_plugins/execute/execute_recover.py +++ b/pytest_plugins/execute/execute_recover.py @@ -21,6 +21,8 @@ def test_recover_funds( eth_rpc: EthRPC, ) -> None: """Recover funds from a failed remote execution.""" + del index + remaining_balance = eth_rpc.get_balance(eoa) refund_gas_limit = 21_000 tx_cost = refund_gas_limit * gas_price diff --git a/pytest_plugins/filler/filler.py b/pytest_plugins/filler/filler.py index aef7fa7503..30b605d753 100644 --- a/pytest_plugins/filler/filler.py +++ b/pytest_plugins/filler/filler.py @@ -750,6 +750,8 @@ def pytest_terminal_summary( Emphasize that fixtures have only been filled; they must now be executed to actually run the tests. """ + del exitstatus + yield if config.fixture_output.is_stdout or hasattr(config, "workerinput"): # type: ignore[attr-defined] return @@ -1069,6 +1071,8 @@ def get_fixture_collection_scope(fixture_name, config): See: https://docs.pytest.org/en/stable/how-to/fixtures.html#dynamic-scope """ + del fixture_name + if config.fixture_output.is_stdout: return "session" if config.fixture_output.single_fixture_per_file: @@ -1361,6 +1365,8 @@ def pytest_collection_modifyitems( These can't be handled in this plugins pytest_generate_tests() as the fork parametrization occurs in the forks plugin. """ + del config + items_for_removal = [] for i, item in enumerate(items): item.name = item.name.strip().replace(" ", "-") @@ -1443,6 +1449,8 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int): - Generate index file for all produced fixtures. - Create tarball of the output directory if the output is a tarball. """ + del exitstatus + # Save pre-allocation groups after phase 1 fixture_output: FixtureOutput = session.config.fixture_output # type: ignore[attr-defined] session_instance: FillingSession = session.config.filling_session # type: ignore[attr-defined] @@ -1475,9 +1483,7 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus: int): session.config.getoption("generate_index") and not session_instance.phase_manager.is_pre_alloc_generation ): - generate_fixtures_index( - fixture_output.directory, quiet_mode=True, force_flag=False, disable_infer_format=False - ) + generate_fixtures_index(fixture_output.directory, quiet_mode=True, force_flag=False) # Create tarball of the output directory if the output is a tarball. fixture_output.create_tarball() diff --git a/pytest_plugins/filler/static_filler.py b/pytest_plugins/filler/static_filler.py index 9e240a75ea..4fbe412f09 100644 --- a/pytest_plugins/filler/static_filler.py +++ b/pytest_plugins/filler/static_filler.py @@ -372,7 +372,7 @@ class so that upon instantiation within the test case, it provides the else: pytest.fail(f"{request.node.name}: Fork {marker.args[0]} not found in forks list.") else: - solc_target_fork = get_closest_fork(fork, request.config.solc_version) + solc_target_fork = get_closest_fork(fork) assert solc_target_fork is not None, "No fork supports provided solc version." if solc_target_fork != fork and request.config.getoption("verbose") >= 1: warnings.warn( diff --git a/pytest_plugins/forks/forks.py b/pytest_plugins/forks/forks.py index 6fa07821f8..6147b981de 100644 --- a/pytest_plugins/forks/forks.py +++ b/pytest_plugins/forks/forks.py @@ -533,6 +533,8 @@ def get_fork_option(config, option_name: str, parameter_name: str) -> Set[Fork]: @pytest.hookimpl(trylast=True) def pytest_report_header(config, start_path): """Pytest hook called to obtain the report header.""" + del start_path + bold = "\033[1m" warning = "\033[93m" reset = "\033[39;49m" diff --git a/pytest_plugins/pytest_hive/pytest_hive.py b/pytest_plugins/pytest_hive/pytest_hive.py index b8e0fd0cb9..34dfd78809 100644 --- a/pytest_plugins/pytest_hive/pytest_hive.py +++ b/pytest_plugins/pytest_hive/pytest_hive.py @@ -111,6 +111,8 @@ def get_hive_info(simulator: Simulation) -> HiveInfo | None: @pytest.hookimpl(trylast=True) def pytest_report_header(config, start_path): """Add lines to pytest's console output header.""" + del start_path + if config.option.collectonly: return header_lines = [f"hive simulator: {config.hive_simulator_url}"] @@ -141,6 +143,8 @@ def pytest_runtest_makereport(item, call): - result_call - test result - result_teardown - teardown result """ + del call + outcome = yield report = outcome.get_result() setattr(item, f"result_{report.when}", report) @@ -172,6 +176,8 @@ def get_test_suite_scope(fixture_name, config: pytest.Config): See: https://docs.pytest.org/en/stable/how-to/fixtures.html#dynamic-scope """ + del fixture_name + if hasattr(config, "test_suite_scope"): return config.test_suite_scope return "module" diff --git a/pytest_plugins/shared/execute_fill.py b/pytest_plugins/shared/execute_fill.py index d5330f4bf8..98fc765db0 100644 --- a/pytest_plugins/shared/execute_fill.py +++ b/pytest_plugins/shared/execute_fill.py @@ -174,6 +174,7 @@ def pytest_make_parametrize_id(config: pytest.Config, val: str, argname: str): Pytest hook called when generating test ids. We use this to generate more readable test ids for the generated tests. """ + del config return f"{argname}_{val}" diff --git a/pytest_plugins/solc/solc.py b/pytest_plugins/solc/solc.py index f134a45a7a..e46d195478 100644 --- a/pytest_plugins/solc/solc.py +++ b/pytest_plugins/solc/solc.py @@ -128,6 +128,8 @@ def solc_bin(request: pytest.FixtureRequest): @pytest.hookimpl(trylast=True) def pytest_report_header(config, start_path): """Add lines to pytest's console output header.""" + del start_path + if config.option.collectonly: return solc_version = config.stash[metadata_key]["Tools"]["solc"] diff --git a/pytest_plugins/spec_version_checker/spec_version_checker.py b/pytest_plugins/spec_version_checker/spec_version_checker.py index c5344e0882..4091e88229 100644 --- a/pytest_plugins/spec_version_checker/spec_version_checker.py +++ b/pytest_plugins/spec_version_checker/spec_version_checker.py @@ -206,6 +206,8 @@ def pytest_collection_modifyitems( session: pytest.Session, config: pytest.Config, items: List[Item] ): """Insert a new test EIPSpecTestItem for every test module with 'eip' in its path.""" + del session + github_token = config.github_token if hasattr(config, "github_token") else None modules: Set[Module] = {item.parent for item in items if isinstance(item.parent, Module)} From 42fe3c2f41860a7038023c5a5ed945bdb253273a Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Tue, 23 Sep 2025 09:17:59 +0200 Subject: [PATCH 026/102] type(refactor): EIP-7951 secp256r1 Test Vector File Reorganization (#2184) * Separate first three secp256r1 vector topic files * Extract another two topic files * Three more topic separations * Generalize infinity point topic, add test cases * Additional grouping * More sorting * Final test cases sorted * Delete original file * Apply suggestions from code review Co-authored-by: spencer * Small fixes * Linting --------- Co-authored-by: spencer --- .../test_p256verify.py | 45 +- .../vectors/secp256r1_k_and_s.json | 170 ++ .../vectors/secp256r1_modified_r_s.json | 93 + .../vectors/secp256r1_public_key.json | 191 ++ .../secp256r1_shamir_multiplication.json | 9 + .../vectors/secp256r1_signature_specific.json | 72 + .../vectors/secp256r1_small_large_r_s.json | 233 ++ .../vectors/secp256r1_special_case_hash.json | 380 +++ .../vectors/secp256r1_special_case_r_s.json | 345 +++ .../vectors/secp256r1_special_points.json | 135 ++ .../vectors/secp256r1_test.json | 2060 ----------------- .../vectors/secp256r1_u1_u2.json | 450 ++++ 12 files changed, 2119 insertions(+), 2064 deletions(-) create mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_k_and_s.json create mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_modified_r_s.json create mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_public_key.json create mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_shamir_multiplication.json create mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_signature_specific.json create mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_small_large_r_s.json create mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_hash.json create mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_r_s.json create mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_points.json delete mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_test.json create mode 100644 osaka/eip7951_p256verify_precompiles/vectors/secp256r1_u1_u2.json diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index 9a82ca4a9b..bd188a84ca 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -30,16 +30,53 @@ @pytest.mark.parametrize( "input_data,expected_output,vector_gas_value", - vectors_from_file("secp256r1_test.json"), - # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 test suite + vectors_from_file("secp256r1_signature_specific.json") + + vectors_from_file("secp256r1_shamir_multiplication.json") + + vectors_from_file("secp256r1_special_case_hash.json") + + vectors_from_file("secp256r1_u1_u2.json") + + vectors_from_file("secp256r1_k_and_s.json") + + vectors_from_file("secp256r1_public_key.json"), + # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 test suite, valid cases # Source: https://github.com/C2SP/wycheproof/blob/main/testvectors/ecdsa_secp256r1_sha256_test.json ) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) @EIPChecklist.Precompile.Test.CallContexts.Normal() @EIPChecklist.Precompile.Test.Inputs.Valid() @EIPChecklist.Precompile.Test.Inputs.MaxValues() -def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): - """Test P256Verify precompile.""" +def test_wycheproof_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): + """Test P256Verify precompile with Wycheproof test suite (valid cases).""" + state_test(env=Environment(), pre=pre, post=post, tx=tx) + + +@pytest.mark.parametrize( + "input_data,expected_output,vector_gas_value", + vectors_from_file("secp256r1_special_case_r_s.json") + + vectors_from_file("secp256r1_modified_r_s.json"), + # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 test suite, invalid cases + # Source: https://github.com/C2SP/wycheproof/blob/main/testvectors/ecdsa_secp256r1_sha256_test.json +) +@pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) +@EIPChecklist.Precompile.Test.CallContexts.Normal() +@EIPChecklist.Precompile.Test.Inputs.Invalid() +@EIPChecklist.Precompile.Test.Inputs.MaxValues() +def test_wycheproof_invalid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): + """Test P256Verify precompile with Wycheproof test suite (invalid cases).""" + state_test(env=Environment(), pre=pre, post=post, tx=tx) + + +@pytest.mark.parametrize( + "input_data,expected_output,vector_gas_value", + vectors_from_file("secp256r1_small_large_r_s.json") + + vectors_from_file("secp256r1_special_points.json"), + # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 test suite, + # valid/invalid cases + # Source: https://github.com/C2SP/wycheproof/blob/main/testvectors/ecdsa_secp256r1_sha256_test.json +) +@pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) +@EIPChecklist.Precompile.Test.CallContexts.Normal() +@EIPChecklist.Precompile.Test.Inputs.MaxValues() +def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): + """Test P256Verify precompile with Wycheproof test suite (mixed valid/invalid cases).""" state_test(env=Environment(), pre=pre, post=post, tx=tx) diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_k_and_s.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_k_and_s.json new file mode 100644 index 0000000000..ed4f0bedf9 --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_k_and_s.json @@ -0,0 +1,170 @@ +[ + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c704fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #176: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63ccc6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #177: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956efcee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #178: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaf6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f8f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #179: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #180: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb0d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb343195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #181: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c705e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca215de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #182: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #183: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b548981487540a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #184: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaa3d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #185: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b72e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #186: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb8d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #187: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c70961691a5e960d07a301dbbad4d86247ec27d7089faeb3ddd1add395efff1e0fe7254622cc371866cdf990d2c5377790e37d1f1519817f09a231bd260a9e78aeb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #694: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc5d283e13ce8ca60da868e3b0fb33e6b4f1074793274e2928250e71e2aca63e9c214dc74fa25371fb4d9e506d418ed9a1bfd6d0c8bb6591d3e0f44505a84886ce", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #695: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa70fc351da038ae0803bd1d86514ae0462f9f8216551d9315aa9d297f792eef6a341c74eed786f2d33da35360ca7aa925e753f00d6077a1e9e5fc339d634019c73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #696: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaa1e34c8f16d138673fee55c080547c2bfd4de7550065f638322bba9430ce4b60662be9bb512663aa4d7df8ab3f3b4181c5d44a7bdf42436620b7d8a6b81ac936", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #697: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c1857e1a8a8338d7fd8cf41d322a302d2078a87a23c7186150ed7cda6e52817c1bdfd0a9135a89d21ce821e29014b2898349254d748272b2d4eb8d59ee34c615377f", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #698: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb5c19fe227a61abc65c61ee7a018cc9571b2c6f663ea33583f76a686f64be078b7b4a0d734940f613d52bc48673b457c2cf78492490a5cc5606c0541d17b24ddb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #699: extreme value for k", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c70db02d1f3421d600e9d9ef9e47419dba3208eed08c2d4189a5db63abeb2739666e0ed26967b9ada9ed7ffe480827f90a0d210d5fd8ec628e31715e6b24125512a", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #700: extreme value for k and edgecase s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc6222d1962655501893c29e441395b6c05711bd3ed5a0ef72cfab338b88229c4baaae079cb44a1af070362aaa520ee24cac2626423b0bf81af1c54311d8e2fd23", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #701: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa74ccfa24c67f3def7fa81bc99c70bb0419c0952ba599f4c03361da184b04cdca5db76b797f7f41d9c729a2219478a7e629728df870800be8cf6ca7a0a82153bfa", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #702: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaea1c72c91034036bac71402b6e9ecc4af3dbde7a99dc574061e99fefff9d84dab7dd057e75b78ac6f56e34eb048f0a9d29d5d055408c90d02bc2ea918c18cb63", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #703: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185c2879a66d86cb20b820b7795da2da62b38924f7817d1cd350d936988e90e79bc5431a7268ff6931c7a759de024eff90bcb0177216db6fd1f3aaaa11fa3b6a083", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #704: extreme value for k and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bbab1c0f273f74abc2b848c75006f2ef3c54c26df27711b06558f455079aee0ba3df510f2ecef6d9a05997c776f14ad6456c179f0a13af1771e4d6c37fa48b47f2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #705: extreme value for k", + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_modified_r_s.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_modified_r_s.json new file mode 100644 index 0000000000..e49fac0054 --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_modified_r_s.json @@ -0,0 +1,93 @@ +[ + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5740946b2a147f59262ee6f5bc90bd01ed280528b62b3aed5fc93f06f739b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #3: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #5: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b8252927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #8: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502329a3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #118: modify first byte of integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e98b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #120: modify last byte of integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568475b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #121: modify last byte of integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1800b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568472927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #124: truncated integer", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f47aa2bbd0a4c384ee1493b1f518ada018ef05465583885980861905228a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #139: Modified r or s, e.g. by adding or subtracting the order of the group", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #636: r too large", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e3cd8d2f81d6953b0844c09d7b560d527cd2ef67056893eadafa52c8501387d59ee41fdb4d10402ce7a0c5e3b747adfa3a490b62a6b7719068903485c0bb6dc2d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #637: r,s are large", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd48240cd81edd91cb6936133508c3915100e81f332c4545d41189b481196851378e05b06e72d4a1bff80ea5db514aa2f93ea6dd6d9c0ae27b7837dc432f9ce89d9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #638: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a5b062947356748b0fc17f1704c65aa1dca6e1bfe6779756fa616d91eaad13df2c0b38c17f3d0672e7409cfc5992a99fff12b84a4f8432293b431113f1b2fb579d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #639: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c707a736d8e326a9ca62bbe25a34ea4e3633b499a96afa7aaa3fcf3fd88f8e07edeb3e45879d8622b93e818443a686e869eeda7bf9ae46aa3eafcc48a5934864627", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #651: r and s^-1 are close to n", + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_public_key.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_public_key.json new file mode 100644 index 0000000000..9ec469d523 --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_public_key.json @@ -0,0 +1,191 @@ +[ + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d434e262a49eab7781e353a3565e482550dd0fd5defa013c7f29745eff3569f19b0c0a93f267fb6052fd8077be769c2b98953195d7bc10de844218305c6ba17a4f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #196: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f910fe774355c04d060f76d79fd7a772e421463489221bf0a33add0be9b1979110b500dcba1c69a8fbd43fa4f57f743ce124ca8b91a1f325f3fac6181175df557374f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #197: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91bb40bf217bed3fb3950c7d39f03d36dc8e3b2cd79693f125bfd06595ee1135e3541bf3532351ebb032710bdb6a1bf1bfc89a1e291ac692b3fa4780745bb556774f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #198: x-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91664eb7ee6db84a34df3c86ea31389a5405badd5ca99231ff556d3e75a233e73a59f3c752e52eca46137642490a51560ce0badc678754b8f72e51a2901426a1bd3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #199: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f914cd0429bbabd2827009d6fcd843d4ce39c3e42e2d1631fd001985a79d1fd8b439638bf12dd682f60be7ef1d0e0d98f08b7bca77a1a2b869ae466189d2acdabe33cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #200: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91e56c6ea2d1b017091c44d8b6cb62b9f460e3ce9aed5e5fd41e8added97c56c04a308ec31f281e955be20b457e463440b4fcf2b80258078207fc1378180f89b553cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #201: y-coordinate of the public key has many trailing 0's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f911158a08d291500b4cabed3346d891eee57c176356a2624fb011f8fbbf3466830228a8c486a736006e082325b85290c5bc91f378b75d487dda46798c18f2855193cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #202: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b1db9289649f59410ea36b0c0fc8d6aa2687b29176939dd23e0dde56d309fa9d3e1535e4280559015b0dbd987366dcf43a6d1af5c23c7d584e1c3f48a12513363cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #203: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7b16e762286cb96446aa8d4e6e7578b0a341a79f2dd1a220ac6f0ca4e24ed86ddc60a700a139b04661c547d07bbb0721780146df799ccf55e55234ecb8f12bc3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #204: y-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d82a7c2717261187c8e00d8df963ff35d796edad36bc6e6bd1c91c670d9105b43dcabddaf8fcaa61f4603e7cbac0f3c0351ecd5988efb23f680d07debd1399292829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #205: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f915eb9c8845de68eb13d5befe719f462d77787802baff30ce96a5cba063254af782c026ae9be2e2a5e7ca0ff9bbd92fb6e44972186228ee9a62b87ddbe2ef66fb52829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #206: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9196843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #207: x-coordinate of the public key has many trailing 1's", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91766456dce1857c906f9996af729339464d27e9d98edc2d0e3b760297067421f6402385ecadae0d8081dccaf5d19037ec4e55376eced699e93646bfbbf19d0b41fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #208: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91c605c4b2edeab20419e6518a11b2dbc2b97ed8b07cced0b19c34f777de7b9fd9edf0f612c5f46e03c719647bc8af1b29b2cde2eda700fb1cff5e159d47326dbafffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #209: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d48b68e6cabfe03cf6141c9ac54141f210e64485d9929ad7b732bfe3b7eb8a84feedae50c61bd00e19dc26f9b7e2265e4508c389109ad2f208f0772315b6c941fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #210: x-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7c81457d4aeb6aa65957098569f0479710ad7f6595d5874c35a93d12a5dd4c7b7961a0b652878c2d568069a432ca18a1a9199f2ca574dad4b9e3a05c0a1cdb300000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #211: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f916b01332ddb6edfa9a30a1321d5858e1ee3cf97e263e669f8de5e9652e76ff3f75939545fced457309a6a04ace2bd0f70139c8f7d86b02cb1cc58f9e69e96cd5a00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #212: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91efdb884720eaeadc349f9fc356b6c0344101cd2fd8436b7d0e6a4fb93f106361f24bee6ad5dc05f7613975473aadf3aacba9e77de7d69b6ce48cb60d8113385d00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #213: x-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9131230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb070f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beffbcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #214: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91caa797da65b320ab0d5c470cda0b36b294359c7db9841d679174db34c4855743cf543a62f23e212745391aaf7505f345123d2685ee3b941d3de6d9b36242e5a0bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #215: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f917e5f0ab5d900d3d3d7867657e5d6d36519bc54084536e7d21c336ed8001859459450c07f201faec94b82dfb322e5ac676688294aad35aa72e727ff0b19b646aabcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #216: y-coordinate of the public key is small", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d7d70c581ae9e3f66dc6a480bf037ae23f8a1e4a2136fe4b03aa69f0ca25b35689c460f8a5a5c2bbba962c8a3ee833a413e85658e62a59e2af41d9127cc47224bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #217: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91341c1b9ff3c83dd5e0dfa0bf68bcdf4bb7aa20c625975e5eeee34bb396266b3472b69f061b750fd5121b22b11366fad549c634e77765a017902a67099e0a4469bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #218: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #219: y-coordinate of the public key is large", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c7038a084ffccc4ae2f8204be2abca9fb8ad4ab283b2aa50f13b6bb2347adabc69ca699799b77b1cc6dad271e88b899c12931986e958e1f5cf5653dddf7389365e2", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #173: point with x-coordinate 0", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a90000000000000000000000000000000000000000000000000000000000000000fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "Expected": "", + "Gas": 6900, + "Name": "invalid public key x param errors", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af0150000000000000000000000000000000000000000000000000000000000000000", + "Expected": "", + "Gas": 6900, + "Name": "invalid public key y param errors", + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_shamir_multiplication.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_shamir_multiplication.json new file mode 100644 index 0000000000..052e2e9658 --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_shamir_multiplication.json @@ -0,0 +1,9 @@ +[ + { + "Input": "70239dd877f7c944c422f44dea4ed1a52f2627416faf2f072fa50c772ed6f80764a1aab5000d0e804f3e2fc02bdee9be8ff312334e2ba16d11547c97711c898e6af015971cc30be6d1a206d4e013e0997772a2f91d73286ffd683b9bb2cf4f1b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #58: Edge case for Shamir multiplication", + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_signature_specific.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_signature_specific.json new file mode 100644 index 0000000000..f1145f76ef --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_signature_specific.json @@ -0,0 +1,72 @@ +[ + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd762927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #1: signature malleability", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #137: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a968ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d94697bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #138: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855b292a619339f6e567a305c951c0dcbcc42d16e47f219f9e98e76e09d8770b34a0177e60492c5a8242f76f07bfe3661bde59ec2a17ce5bd2dab2abebdf89a62e204aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #192: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "dc1921946f4af96a2856e7be399007c9e807bdf4c5332f19f59ec9dd1bb8c7b3530bd6b0c9af2d69ba897f6b5fb59695cfbf33afe66dbadcf5b8d2a2a6538e23d85e489cb7a161fd55ededcedbf4cc0c0987e3e3f0f242cae934c72caa3f43e904aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #193: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023a8ea150cb80125d7381c4c1f1da8e9de2711f9917060406a73d7904519e51388f3ab9fa68bd47973a73b2d40480c2ba50c22c9d76ec217257288293285449b8604aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #194: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "de47c9b27eb8d300dbb5f2c353e632c393262cf06340c4fa7f1b40c4cbd36f90986e65933ef2ed4ee5aada139f52b70539aaf63f00a91f29c69178490d57fb713dafedfb8da6189d372308cbf1489bbbdabf0c0217d1c0ff0f701aaa7a694b9c04aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #195: pseudorandom signature", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a878d844dc7f16b73b1f2a39730da5d8cd99fe2e70a18482384e37dcd2bfea02e1ed6572e01eb7a8d113d02c666c45ef22d3b9a6a6dea99aa43a8183c26e75d336", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #655: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a9dec6c8257dde94110eacc8c09d2e5789cc5beb81a958b02b4d62da9599a7401466fae1614174be63970b83f6524421067b06dd6f4e9c56baca4e344fdd690f1d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #656: edge case for signature malleability", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2530e782f964b2e2ff065a051bc7adc20615d8c43a1365713c88268822c253bcce5b16df652aa1ecb2dc8b46c515f9604e2e84cacfa7c6eec30428d2d3f4e08ed504aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1211: pseudorandom signature", + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_small_large_r_s.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_small_large_r_s.json new file mode 100644 index 0000000000..9dced484a5 --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_small_large_r_s.json @@ -0,0 +1,233 @@ +[ + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #113: k*G has a large x-coordinate", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #114: r too large", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254eab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c58220455419235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #115: r,s are large", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd480984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c5611feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #116: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a54201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c0595c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #117: r and s^-1 have a large Hamming weight", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9575d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #118: small r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000036627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b15726170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #120: small r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000055a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bfef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #122: small r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #124: small r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325560000000000000000000000000000000000000000000000000000000000000006cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #126: r is larger than n", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd84be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e13920f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #127: s is larger than n", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea88d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #128: small r and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7a4838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05ffa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #129: smallish r and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4d7393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #130: 100-bit r and small s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b5ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #131: small r and 100 bit s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b1d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #132: 100-bit r and s^-1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c70083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #133: r and s^-1 are close to n", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7000000000000000000000000000000000000000000000000000000000000000018aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #134: s == 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7000000000000000000000000000000000000000000000000000000000000000008aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #135: s == 0", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #113: k*G has a large x-coordinate", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000014a03ef9f92eb268cafa601072489a56380fa0dc43171d7712813b3a19a1eb5e53e213e28a608ce9a2f4a17fd830c6654018a79b3e0263d91a8ba90622df6f2f0", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #118: small r and s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000003091194c1cba17f34e286b4833701606a41cef26177ada8850b601ea1f859e70127242fcec708828758403ce2fe501983a7984e6209f4d6b95db9ad77767f55eb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #120: small r and s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005103c6ecceff59e71ea8f56fee3a4b2b148e81c2bdbdd39c195812c96dcfb41a72303a193dc591be150b883d770ec51ebb4ebce8b09042c2ecb16c448d8e57bf5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #122: small r and s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000063b66b829fe604638bcb2bfe8c22228be67390c20111bd2b451468927e87fb6eabc8e59c009361758b274ba2cad36b58fde485a3ed09dade76712fa9e9c4ac212", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #124: small r and s", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255600000000000000000000000000000000000000000000000000000000000000063b66b829fe604638bcb2bfe8c22228be67390c20111bd2b451468927e87fb6eabc8e59c009361758b274ba2cad36b58fde485a3ed09dade76712fa9e9c4ac212", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #126: r is larger than n", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd84ff2f6c24e4a33cd71c09fdcbc74a6233961b874b8c8e0eb94582092cbc50c3084fa9547afda5c66335f3f937d4c79afa120486b534139d59ae82d61ead26420", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #127: s is larger than n", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea8884b959080bb30859cd53c2fb973cf14d60cdaa8ee00587889b5bc657ac588175a02ce5c1e53cb196113c78b4cb8dc7d360e5ea7850b0f6650b0c45af2c3cd7ca", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #128: small r and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7adf4083bd6ecbda5a77ae578e5d835fa7f74a07ebb91e0570e1ff32a563354e9925af80b09a167d9ef647df28e2d9acd0d4bc4f2deec5723818edaf9071e311f8", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #129: smallish r and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4dc2569a3c9bf8c1838ca821f7ba6f000cc8679d278f3736b414a34a7c956a03770387ea85bc4f28804b4a91c9b7d65bc6434c975806795ab7d441a4e9683aeb09", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #130: 100-bit r and small s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b4a9f7da2a6c359a16540c271774a6bf1c586357c978256f44a6496d80670968ac496e73a44563f8d56fbd7bb9e4e3ae304c86f2c508eb777b03924755beb40d4", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #131: small r and 100 bit s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b874146432b3cd2c9e26204c0a34136996067d466dde4917a8ff23a8e95ca106b709b3d50976ef8b385a813bc35f3a20710bdc6edd465e6f43ac4866703a6608c", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #132: 100-bit r and s^-1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000001e84d9b232e971a43382630f99725e423ec1ecb41e55172e9c69748a03f0d5988618b15b427ad83363bd041ff75fac98ef2ee923714e7d1dfe31753793c7588d4", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #134: s == 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000000e84d9b232e971a43382630f99725e423ec1ecb41e55172e9c69748a03f0d5988618b15b427ad83363bd041ff75fac98ef2ee923714e7d1dfe31753793c7588d4", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #135: s == 0", + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_hash.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_hash.json new file mode 100644 index 0000000000..dd8bd2c603 --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_hash.json @@ -0,0 +1,380 @@ +[ + { + "Input": "00000000690ed426ccf17803ebe2bd0884bcd58a1bb5e7477ead3645f356e7a916aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf266252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #59: special case hash", + "NoBenchmark": false + }, + { + "Input": "7300000000213f2a525c6035725235c2f696ad3ebb5ee47f140697ad25770d919cc98be2347d469bf476dfc26b9b733df2d26d6ef524af917c665baccb23c882093496459effe2d8d70727b82462f61d0ec1b7847929d10ea631dacb16b56c322927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #60: special case hash", + "NoBenchmark": false + }, + { + "Input": "ddf2000000005e0be0635b245f0b97978afd25daadeb3edb4a0161c27fe0604573b3c90ecd390028058164524dde892703dce3dea0d53fa8093999f07ab8aa432f67b0b8e20636695bb7d8bf0a651c802ed25a395387b5f4188c0c4075c886342927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #61: special case hash", + "NoBenchmark": false + }, + { + "Input": "67ab1900000000784769c4ecb9e164d6642b8499588b89855be1ec355d0841a0bfab3098252847b328fadf2f89b95c851a7f0eb390763378f37e90119d5ba3ddbdd64e234e832b1067c2d058ccb44d978195ccebb65c2aaf1e2da9b8b4987e3b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #62: special case hash", + "NoBenchmark": false + }, + { + "Input": "a2bf09460000000076d7dbeffe125eaf02095dff252ee905e296b6350fc311cf204a9784074b246d8bf8bf04a4ceb1c1f1c9aaab168b1596d17093c5cd21d2cd51cce41670636783dc06a759c8847868a406c2506fe17975582fe648d1d88b522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #63: special case hash", + "NoBenchmark": false + }, + { + "Input": "3554e827c700000000e1e75e624a06b3a0a353171160858129e15c544e4f0e65ed66dc34f551ac82f63d4aa4f81fe2cb0031a91d1314f835027bca0f1ceeaa0399ca123aa09b13cd194a422e18d5fda167623c3f6e5d4d6abb8953d67c0c48c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #64: special case hash", + "NoBenchmark": false + }, + { + "Input": "9b6cd3b812610000000026941a0f0bb53255ea4c9fd0cb3426e3a54b9fc6965c060b700bef665c68899d44f2356a578d126b062023ccc3c056bf0f60a237012b8d186c027832965f4fcc78a3366ca95dedbb410cbef3f26d6be5d581c11d36102927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #65: special case hash", + "NoBenchmark": false + }, + { + "Input": "883ae39f50bf0100000000e7561c26fc82a52baa51c71ca877162f93c4ae01869f6adfe8d5eb5b2c24d7aa7934b6cf29c93ea76cd313c9132bb0c8e38c96831db26a9c9e40e55ee0890c944cf271756c906a33e66b5bd15e051593883b5e99022927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #66: special case hash", + "NoBenchmark": false + }, + { + "Input": "a1ce5d6e5ecaf28b0000000000fa7cd010540f420fb4ff7401fe9fce011d0ba6a1af03ca91677b673ad2f33615e56174a1abf6da168cebfa8868f4ba273f16b720aa73ffe48afa6435cd258b173d0c2377d69022e7d098d75caf24c8c5e06b1c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #67: special case hash", + "NoBenchmark": false + }, + { + "Input": "8ea5f645f373f580930000000038345397330012a8ee836c5494cdffd5ee8054fdc70602766f8eed11a6c99a71c973d5659355507b843da6e327a28c11893db93df5349688a085b137b1eacf456a9e9e0f6d15ec0078ca60a7f83f2b10d213502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #68: special case hash", + "NoBenchmark": false + }, + { + "Input": "660570d323e9f75fa734000000008792d65ce93eabb7d60d8d9c1bbdcb5ef305b516a314f2fce530d6537f6a6c49966c23456f63c643cf8e0dc738f7b876e675d39ffd033c92b6d717dd536fbc5efdf1967c4bd80954479ba66b0120cd16fff22927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #69: special case hash", + "NoBenchmark": false + }, + { + "Input": "d0462673154cce587dde8800000000e98d35f1f45cf9c3bf46ada2de4c568c343b2cbf046eac45842ecb7984d475831582717bebb6492fd0a485c101e29ff0a84c9b7b47a98b0f82de512bc9313aaf51701099cac5f76e68c8595fc1c1d992582927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #70: special case hash", + "NoBenchmark": false + }, + { + "Input": "bd90640269a7822680cedfef000000000caef15a6171059ab83e7b4418d7278f30c87d35e636f540841f14af54e2f9edd79d0312cfa1ab656c3fb15bfde48dcf47c15a5a82d24b75c85a692bd6ecafeb71409ede23efd08e0db9abf6340677ed2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #71: special case hash", + "NoBenchmark": false + }, + { + "Input": "33239a52d72f1311512e41222a00000000d2dcceb301c54b4beae8e284788a7338686ff0fda2cef6bc43b58cfe6647b9e2e8176d168dec3c68ff262113760f52067ec3b651f422669601662167fa8717e976e2db5e6a4cf7c2ddabb3fde9d67d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #72: special case hash", + "NoBenchmark": false + }, + { + "Input": "b8d64fbcd4a1c10f1365d4e6d95c000000007ee4a21a1cbe1dc84c2d941ffaf144a3e23bf314f2b344fc25c7f2de8b6af3e17d27f5ee844b225985ab6e2775cf2d48e223205e98041ddc87be532abed584f0411f5729500493c9cc3f4dd15e862927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #73: special case hash", + "NoBenchmark": false + }, + { + "Input": "01603d3982bf77d7a3fef3183ed092000000003a227420db4088b20fe0e9d84a2ded5b7ec8e90e7bf11f967a3d95110c41b99db3b5aa8d330eb9d638781688e97d5792c53628155e1bfc46fb1a67e3088de049c328ae1f44ec69238a009808f92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #74: special case hash", + "NoBenchmark": false + }, + { + "Input": "9ea6994f1e0384c8599aa02e6cf66d9c000000004d89ef50b7e9eb0cfbff7363bdae7bcb580bf335efd3bc3d31870f923eaccafcd40ec2f605976f15137d8b8ff6dfa12f19e525270b0106eecfe257499f373a4fb318994f24838122ce7ec3c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #75: special case hash", + "NoBenchmark": false + }, + { + "Input": "d03215a8401bcf16693979371a01068a4700000000e2fa5bf692bc670905b18c50f9c4f0cd6940e162720957ffff513799209b78596956d21ece251c2401f1c6d7033a0a787d338e889defaaabb106b95a4355e411a59c32aa5167dfab2447262927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #76: special case hash", + "NoBenchmark": false + }, + { + "Input": "307bfaaffb650c889c84bf83f0300e5dc87e000000008408fd5f64b582e3bb14f612820687604fa01906066a378d67540982e29575d019aabe90924ead5c860d3f9367702dd7dd4f75ea98afd20e328a1a99f4857b316525328230ce294b0fef2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #77: special case hash", + "NoBenchmark": false + }, + { + "Input": "bab5c4f4df540d7b33324d36bb0c157551527c00000000e4af574bb4d54ea6b89505e407657d6e8bc93db5da7aa6f5081f61980c1949f56b0f2f507da5782a7ac60d31904e3669738ffbeccab6c3656c08e0ed5cb92b3cfa5e7f71784f9c50212927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #78: special case hash", + "NoBenchmark": false + }, + { + "Input": "d4ba47f6ae28f274e4f58d8036f9c36ec2456f5b00000000c3b869197ef5e15ebbd16fbbb656b6d0d83e6a7787cd691b08735aed371732723e1c68a40404517d9d8e35dba96028b7787d91315be675877d2d097be5e8ee34560e3e7fd25c0f002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #79: special case hash", + "NoBenchmark": false + }, + { + "Input": "79fd19c7235ea212f29f1fa00984342afe0f10aafd00000000801e47f8c184e12ec9760122db98fd06ea76848d35a6da442d2ceef7559a30cf57c61e92df327e7ab271da90859479701fccf86e462ee3393fb6814c27b760c4963625c0a198782927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #80: special case hash", + "NoBenchmark": false + }, + { + "Input": "8c291e8eeaa45adbaf9aba5c0583462d79cbeb7ac97300000000a37ea6700cda54e76b7683b6650baa6a7fc49b1c51eed9ba9dd463221f7a4f1005a89fe00c592ea076886c773eb937ec1cc8374b7915cfd11b1c1ae1166152f2f7806a31c8fd2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #81: special case hash", + "NoBenchmark": false + }, + { + "Input": "0eaae8641084fa979803efbfb8140732f4cdcf66c3f78a000000003c278a6b215291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c946665d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc32927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #82: special case hash", + "NoBenchmark": false + }, + { + "Input": "e02716d01fb23a5a0068399bf01bab42ef17c6d96e13846c00000000afc0f89d207a3241812d75d947419dc58efb05e8003b33fc17eb50f9d15166a88479f107cdee749f2e492b213ce80b32d0574f62f1c5d70793cf55e382d5caadf75927672927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #83: special case hash", + "NoBenchmark": false + }, + { + "Input": "9eb0bf583a1a6b9a194e9a16bc7dab2a9061768af89d00659a00000000fc7de16554e49f82a855204328ac94913bf01bbe84437a355a0a37c0dee3cf81aa7728aea00de2507ddaf5c94e1e126980d3df16250a2eaebc8be486effe7f22b4f9292927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #84: special case hash", + "NoBenchmark": false + }, + { + "Input": "62aac98818b3b84a2c214f0d5e72ef286e1030cb53d9a82b690e00000000cd15a54c5062648339d2bff06f71c88216c26c6e19b4d80a8c602990ac82707efdfce99bbe7fcfafae3e69fd016777517aa01056317f467ad09aff09be73c9731b0d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #85: special case hash", + "NoBenchmark": false + }, + { + "Input": "3760a7f37cf96218f29ae43732e513efd2b6f552ea4b6895464b9300000000c8975bd7157a8d363b309f1f444012b1a1d23096593133e71b4ca8b059cff37eaf7faa7a28b1c822baa241793f2abc930bd4c69840fe090f2aacc46786bf9196222927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #86: special case hash", + "NoBenchmark": false + }, + { + "Input": "0da0a1d2851d33023834f2098c0880096b4320bea836cd9cbb6ff6c8000000005694a6f84b8f875c276afd2ebcfe4d61de9ec90305afb1357b95b3e0da43885e0dffad9ffd0b757d8051dec02ebdf70d8ee2dc5c7870c0823b6ccc7c679cbaa42927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #87: special case hash", + "NoBenchmark": false + }, + { + "Input": "ffffffff293886d3086fd567aafd598f0fe975f735887194a764a231e82d289aa0c30e8026fdb2b4b4968a27d16a6d08f7098f1a98d21620d7454ba9790f1ba65e470453a8a399f15baf463f9deceb53acc5ca64459149688bd2760c654243392927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #88: special case hash", + "NoBenchmark": false + }, + { + "Input": "7bffffffff2376d1e3c03445a072e24326acdc4ce127ec2e0e8d9ca99527e7b7614ea84acf736527dd73602cd4bb4eea1dfebebd5ad8aca52aa0228cf7b99a88737cc85f5f2d2f60d1b8183f3ed490e4de14368e96a9482c2a4dd193195c902f2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #89: special case hash", + "NoBenchmark": false + }, + { + "Input": "a2b5ffffffffebb251b085377605a224bc80872602a6e467fd016807e97fa395bead6734ebe44b810d3fb2ea00b1732945377338febfd439a8d74dfbd0f942fa6bb18eae36616a7d3cad35919fd21a8af4bbe7a10f73b3e036a46b103ef56e2a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #90: special case hash", + "NoBenchmark": false + }, + { + "Input": "641227ffffffff6f1b96fa5f097fcf3cc1a3c256870d45a67b83d0967d4b20c0499625479e161dacd4db9d9ce64854c98d922cbf212703e9654fae182df9bad242c177cf37b8193a0131108d97819edd9439936028864ac195b64fca76d9d6932927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #91: special case hash", + "NoBenchmark": false + }, + { + "Input": "958415d8ffffffffabad03e2fc662dc3ba203521177502298df56f36600e0f8b08f16b8093a8fb4d66a2c8065b541b3d31e3bfe694f6b89c50fb1aaa6ff6c9b29d6455e2d5d1779748573b611cb95d4a21f967410399b39b535ba3e5af81ca2e2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #92: special case hash", + "NoBenchmark": false + }, + { + "Input": "f1d8de4858ffffffff1281093536f47fe13deb04e1fbe8fb954521b6975420f8be26231b6191658a19dd72ddb99ed8f8c579b6938d19bce8eed8dc2b338cb5f8e1d9a32ee56cffed37f0f22b2dcb57d5c943c14f79694a03b9c5e96952575c892927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #93: special case hash", + "NoBenchmark": false + }, + { + "Input": "0927895f2802ffffffff10782dd14a3b32dc5d47c05ef6f1876b95c81fc31def15e76880898316b16204ac920a02d58045f36a229d4aa4f812638c455abe0443e74d357d3fcb5c8c5337bd6aba4178b455ca10e226e13f9638196506a19391232927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #94: special case hash", + "NoBenchmark": false + }, + { + "Input": "60907984aa7e8effffffff4f332862a10a57c3063fb5a30624cf6a0c3ac80589352ecb53f8df2c503a45f9846fc28d1d31e6307d3ddbffc1132315cc07f16dad1348dfa9c482c558e1d05c5242ca1c39436726ecd28258b1899792887dd0a3c62927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #95: special case hash", + "NoBenchmark": false + }, + { + "Input": "c6ff198484939170ffffffff0af42cda50f9a5f50636ea6942d6b9b8cd6ae1e24a40801a7e606ba78a0da9882ab23c7677b8642349ed3d652c5bfa5f2a9558fb3a49b64848d682ef7f605f2832f7384bdc24ed2925825bf8ea77dc59817257822927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #96: special case hash", + "NoBenchmark": false + }, + { + "Input": "de030419345ca15c75ffffffff8074799b9e0956cc43135d16dfbe4d27d7e68deacc5e1a8304a74d2be412b078924b3bb3511bac855c05c9e5e9e44df3d61e967451cd8e18d6ed1885dd827714847f96ec4bb0ed4c36ce9808db8f714204f6d12927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #97: special case hash", + "NoBenchmark": false + }, + { + "Input": "6f0e3eeaf42b28132b88fffffffff6c8665604d34acb19037e1ab78caaaac6ff2f7a5e9e5771d424f30f67fdab61e8ce4f8cd1214882adb65f7de94c31577052ac4e69808345809b44acb0b2bd889175fb75dd050c5a449ab9528f8f78daa10c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #98: special case hash", + "NoBenchmark": false + }, + { + "Input": "cdb549f773b3e62b3708d1ffffffffbe48f7c0591ddcae7d2cb222d1f8017ab9ffcda40f792ce4d93e7e0f0e95e1a2147dddd7f6487621c30a03d710b330021979938b55f8a17f7ed7ba9ade8f2065a1fa77618f0b67add8d58c422c2453a49a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #99: special case hash", + "NoBenchmark": false + }, + { + "Input": "2c3f26f96a3ac0051df4989bffffffff9fd64886c1dc4f9924d8fd6f0edb048481f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f743002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #100: special case hash", + "NoBenchmark": false + }, + { + "Input": "ac18f8418c55a2502cb7d53f9affffffff5c31d89fda6a6b8476397c04edf411dfc8bf520445cbb8ee1596fb073ea283ea130251a6fdffa5c3f5f2aaf75ca808048e33efce147c9dd92823640e338e68bfd7d0dc7a4905b3a7ac711e577e90e72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #101: special case hash", + "NoBenchmark": false + }, + { + "Input": "4f9618f98e2d3a15b24094f72bb5ffffffffa2fd3e2893683e5a6ab8cf0ee610ad019f74c6941d20efda70b46c53db166503a0e393e932f688227688ba6a576293320eb7ca0710255346bdbb3102cdcf7964ef2e0988e712bc05efe16c1993452927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #102: special case hash", + "NoBenchmark": false + }, + { + "Input": "422e82a3d56ed10a9cc21d31d37a25ffffffff67edf7c40204caae73ab0bc75aac8096842e8add68c34e78ce11dd71e4b54316bd3ebf7fffdeb7bd5a3ebc1883f5ca2f4f23d674502d4caf85d187215d36e3ce9f0ce219709f21a3aac003b7a82927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #103: special case hash", + "NoBenchmark": false + }, + { + "Input": "7075d245ccc3281b6e7b329ff738fbb417a5ffffffffa0842d9890b5cf95d018677b2d3a59b18a5ff939b70ea002250889ddcd7b7b9d776854b4943693fb92f76b4ba856ade7677bf30307b21f3ccda35d2f63aee81efd0bab6972cc0795db552927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #104: special case hash", + "NoBenchmark": false + }, + { + "Input": "3c80de54cd9226989443d593fa4fd6597e280ebeffffffffc1847eb76c217a95479e1ded14bcaed0379ba8e1b73d3115d84d31d4b7c30e1f05e1fc0d5957cfb0918f79e35b3d89487cf634a4f05b2e0c30857ca879f97c771e877027355b24432927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #105: special case hash", + "NoBenchmark": false + }, + { + "Input": "de21754e29b85601980bef3d697ea2770ce891a8cdffffffffc7906aa794b39b43dfccd0edb9e280d9a58f01164d55c3d711e14b12ac5cf3b64840ead512a0a31dbe33fa8ba84533cd5c4934365b3442ca1174899b78ef9a3199f495843897722927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #106: special case hash", + "NoBenchmark": false + }, + { + "Input": "8f65d92927cfb86a84dd59623fb531bb599e4d5f7289ffffffff2f1f2f57881c5b09ab637bd4caf0f4c7c7e4bca592fea20e9087c259d26a38bb4085f0bbff1145b7eb467b6748af618e9d80d6fdcd6aa24964e5a13f885bca8101de08eb0d752927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #107: special case hash", + "NoBenchmark": false + }, + { + "Input": "6b63e9a74e092120160bea3877dace8a2cc7cd0e8426cbfffffffffafc8c3ca85e9b1c5a028070df5728c5c8af9b74e0667afa570a6cfa0114a5039ed15ee06fb1360907e2d9785ead362bb8d7bd661b6c29eeffd3c5037744edaeb9ad990c202927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #108: special case hash", + "NoBenchmark": false + }, + { + "Input": "fc28259702a03845b6d75219444e8b43d094586e249c8699ffffffffe852512e0671a0a85c2b72d54a2fb0990e34538b4890050f5a5712f6d1a7a5fb8578f32edb1846bab6b7361479ab9c3285ca41291808f27fd5bd4fdac720e5854713694c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #109: special case hash", + "NoBenchmark": false + }, + { + "Input": "1273b4502ea4e3bccee044ee8e8db7f774ecbcd52e8ceb571757ffffffffe20a7673f8526748446477dbbb0590a45492c5d7d69859d301abbaedb35b2095103a3dc70ddf9c6b524d886bed9e6af02e0e4dec0d417a414fed3807ef4422913d7c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #110: special case hash", + "NoBenchmark": false + }, + { + "Input": "08fb565610a79baa0c566c66228d81814f8c53a15b96e602fb49ffffffffff6e7f085441070ecd2bb21285089ebb1aa6450d1a06c36d3ff39dfd657a796d12b5249712012029870a2459d18d47da9aa492a5e6cb4b2d8dafa9e4c5c54a2b9a8b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #111: special case hash", + "NoBenchmark": false + }, + { + "Input": "d59291cc2cf89f3087715fcb1aa4e79aa2403f748e97d7cd28ecaefeffffffff914c67fb61dd1e27c867398ea7322d5ab76df04bc5aa6683a8e0f30a5d287348fa07474031481dda4953e3ac1959ee8cea7e66ec412b38d6c96d28f6d37304ea2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #112: special case hash", + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_r_s.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_r_s.json new file mode 100644 index 0000000000..05e809bf92 --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_case_r_s.json @@ -0,0 +1,345 @@ +[ + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #9: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #10: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #11: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #12: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #13: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #14: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #15: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #16: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #17: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #18: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #19: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #20: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #21: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #22: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #23: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #24: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #25: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #26: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #27: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #28: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #29: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #30: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #31: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #32: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #33: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #34: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #35: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #36: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #37: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #38: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #39: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #40: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #41: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #42: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #43: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #44: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #45: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #46: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #47: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #48: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #49: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #50: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #51: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #52: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #53: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #54: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #55: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #56: Signature with special case values for r and s", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #57: Signature with special case values for r and s", + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_points.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_points.json new file mode 100644 index 0000000000..65cbd0ae22 --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_special_points.json @@ -0,0 +1,135 @@ +[ + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #3: valid", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c70b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f2871b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #136: point at infinity during verify", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #171: point duplication during verification", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc469637c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #172: duplication bug", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c706adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a647e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #173: point with x-coordinate 0", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d25045d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #175: comparison with point at infinity ", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #188: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #189: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #190: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #191: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c700203736fcb198b15d8d7a0c80f66dddd15259240aa78d08aae67c467de04503434383438d5041ea9a387ee8e4d4e84b4471b160c6bcf2568b072f8f20e87a996", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #654: point at infinity during verify", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237e2a964fc00d377a8592b8b61aafa7a4aaa7c7b9fd2b41d6e0e17bd1ba5677edcd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #689: point duplication during verification", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237ed569b03ef2c8857b6d4749e550585b5558384603d4be291f1e842e45a9881232", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #690: duplication bug", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9664ce273320d918d8bdb2e61201b4549b36b7cdc54e33b84adb6f2c10aac831e49e68831f18bda2973ac3d76bfbc8c5ee1cceed2dd862e2dc7c915c736cef1f4", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #693: comparison with point at infinity ", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #706: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #707: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #708: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "Expected": "", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #709: testing point duplication", + "NoBenchmark": false + }, + { + "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Expected": "", + "Gas": 6900, + "Name": "reference point errors", + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_test.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_test.json deleted file mode 100644 index 5a87452136..0000000000 --- a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_test.json +++ /dev/null @@ -1,2060 +0,0 @@ -[ - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd762927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #1: signature malleability", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5740946b2a147f59262ee6f5bc90bd01ed280528b62b3aed5fc93f06f739b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #3: Modified r or s, e.g. by adding or subtracting the order of the group", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #5: Modified r or s, e.g. by adding or subtracting the order of the group", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b8252927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #8: Modified r or s, e.g. by adding or subtracting the order of the group", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #9: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #10: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #11: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #12: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #13: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #14: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #15: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #16: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #17: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #18: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #19: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #20: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #21: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #22: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #23: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255100000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #24: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #25: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #26: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #27: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #28: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #29: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #30: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #31: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #32: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #33: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #34: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #35: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #36: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #37: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255200000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #38: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #39: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #40: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #41: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #42: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #43: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #44: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #45: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #46: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #47: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #48: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #49: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #50: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #51: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff0000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000012927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #52: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325512927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #53: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #54: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #55: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #56: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000001000000000000000000000000ffffffff000000010000000000000000000000010000000000000000000000002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #57: Signature with special case values for r and s", - "NoBenchmark": false - }, - { - "Input": "70239dd877f7c944c422f44dea4ed1a52f2627416faf2f072fa50c772ed6f80764a1aab5000d0e804f3e2fc02bdee9be8ff312334e2ba16d11547c97711c898e6af015971cc30be6d1a206d4e013e0997772a2f91d73286ffd683b9bb2cf4f1b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #58: Edge case for Shamir multiplication", - "NoBenchmark": false - }, - { - "Input": "00000000690ed426ccf17803ebe2bd0884bcd58a1bb5e7477ead3645f356e7a916aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf266252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #59: special case hash", - "NoBenchmark": false - }, - { - "Input": "7300000000213f2a525c6035725235c2f696ad3ebb5ee47f140697ad25770d919cc98be2347d469bf476dfc26b9b733df2d26d6ef524af917c665baccb23c882093496459effe2d8d70727b82462f61d0ec1b7847929d10ea631dacb16b56c322927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #60: special case hash", - "NoBenchmark": false - }, - { - "Input": "ddf2000000005e0be0635b245f0b97978afd25daadeb3edb4a0161c27fe0604573b3c90ecd390028058164524dde892703dce3dea0d53fa8093999f07ab8aa432f67b0b8e20636695bb7d8bf0a651c802ed25a395387b5f4188c0c4075c886342927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #61: special case hash", - "NoBenchmark": false - }, - { - "Input": "67ab1900000000784769c4ecb9e164d6642b8499588b89855be1ec355d0841a0bfab3098252847b328fadf2f89b95c851a7f0eb390763378f37e90119d5ba3ddbdd64e234e832b1067c2d058ccb44d978195ccebb65c2aaf1e2da9b8b4987e3b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #62: special case hash", - "NoBenchmark": false - }, - { - "Input": "a2bf09460000000076d7dbeffe125eaf02095dff252ee905e296b6350fc311cf204a9784074b246d8bf8bf04a4ceb1c1f1c9aaab168b1596d17093c5cd21d2cd51cce41670636783dc06a759c8847868a406c2506fe17975582fe648d1d88b522927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #63: special case hash", - "NoBenchmark": false - }, - { - "Input": "3554e827c700000000e1e75e624a06b3a0a353171160858129e15c544e4f0e65ed66dc34f551ac82f63d4aa4f81fe2cb0031a91d1314f835027bca0f1ceeaa0399ca123aa09b13cd194a422e18d5fda167623c3f6e5d4d6abb8953d67c0c48c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #64: special case hash", - "NoBenchmark": false - }, - { - "Input": "9b6cd3b812610000000026941a0f0bb53255ea4c9fd0cb3426e3a54b9fc6965c060b700bef665c68899d44f2356a578d126b062023ccc3c056bf0f60a237012b8d186c027832965f4fcc78a3366ca95dedbb410cbef3f26d6be5d581c11d36102927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #65: special case hash", - "NoBenchmark": false - }, - { - "Input": "883ae39f50bf0100000000e7561c26fc82a52baa51c71ca877162f93c4ae01869f6adfe8d5eb5b2c24d7aa7934b6cf29c93ea76cd313c9132bb0c8e38c96831db26a9c9e40e55ee0890c944cf271756c906a33e66b5bd15e051593883b5e99022927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #66: special case hash", - "NoBenchmark": false - }, - { - "Input": "a1ce5d6e5ecaf28b0000000000fa7cd010540f420fb4ff7401fe9fce011d0ba6a1af03ca91677b673ad2f33615e56174a1abf6da168cebfa8868f4ba273f16b720aa73ffe48afa6435cd258b173d0c2377d69022e7d098d75caf24c8c5e06b1c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #67: special case hash", - "NoBenchmark": false - }, - { - "Input": "8ea5f645f373f580930000000038345397330012a8ee836c5494cdffd5ee8054fdc70602766f8eed11a6c99a71c973d5659355507b843da6e327a28c11893db93df5349688a085b137b1eacf456a9e9e0f6d15ec0078ca60a7f83f2b10d213502927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #68: special case hash", - "NoBenchmark": false - }, - { - "Input": "660570d323e9f75fa734000000008792d65ce93eabb7d60d8d9c1bbdcb5ef305b516a314f2fce530d6537f6a6c49966c23456f63c643cf8e0dc738f7b876e675d39ffd033c92b6d717dd536fbc5efdf1967c4bd80954479ba66b0120cd16fff22927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #69: special case hash", - "NoBenchmark": false - }, - { - "Input": "d0462673154cce587dde8800000000e98d35f1f45cf9c3bf46ada2de4c568c343b2cbf046eac45842ecb7984d475831582717bebb6492fd0a485c101e29ff0a84c9b7b47a98b0f82de512bc9313aaf51701099cac5f76e68c8595fc1c1d992582927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #70: special case hash", - "NoBenchmark": false - }, - { - "Input": "bd90640269a7822680cedfef000000000caef15a6171059ab83e7b4418d7278f30c87d35e636f540841f14af54e2f9edd79d0312cfa1ab656c3fb15bfde48dcf47c15a5a82d24b75c85a692bd6ecafeb71409ede23efd08e0db9abf6340677ed2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #71: special case hash", - "NoBenchmark": false - }, - { - "Input": "33239a52d72f1311512e41222a00000000d2dcceb301c54b4beae8e284788a7338686ff0fda2cef6bc43b58cfe6647b9e2e8176d168dec3c68ff262113760f52067ec3b651f422669601662167fa8717e976e2db5e6a4cf7c2ddabb3fde9d67d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #72: special case hash", - "NoBenchmark": false - }, - { - "Input": "b8d64fbcd4a1c10f1365d4e6d95c000000007ee4a21a1cbe1dc84c2d941ffaf144a3e23bf314f2b344fc25c7f2de8b6af3e17d27f5ee844b225985ab6e2775cf2d48e223205e98041ddc87be532abed584f0411f5729500493c9cc3f4dd15e862927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #73: special case hash", - "NoBenchmark": false - }, - { - "Input": "01603d3982bf77d7a3fef3183ed092000000003a227420db4088b20fe0e9d84a2ded5b7ec8e90e7bf11f967a3d95110c41b99db3b5aa8d330eb9d638781688e97d5792c53628155e1bfc46fb1a67e3088de049c328ae1f44ec69238a009808f92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #74: special case hash", - "NoBenchmark": false - }, - { - "Input": "9ea6994f1e0384c8599aa02e6cf66d9c000000004d89ef50b7e9eb0cfbff7363bdae7bcb580bf335efd3bc3d31870f923eaccafcd40ec2f605976f15137d8b8ff6dfa12f19e525270b0106eecfe257499f373a4fb318994f24838122ce7ec3c72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #75: special case hash", - "NoBenchmark": false - }, - { - "Input": "d03215a8401bcf16693979371a01068a4700000000e2fa5bf692bc670905b18c50f9c4f0cd6940e162720957ffff513799209b78596956d21ece251c2401f1c6d7033a0a787d338e889defaaabb106b95a4355e411a59c32aa5167dfab2447262927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #76: special case hash", - "NoBenchmark": false - }, - { - "Input": "307bfaaffb650c889c84bf83f0300e5dc87e000000008408fd5f64b582e3bb14f612820687604fa01906066a378d67540982e29575d019aabe90924ead5c860d3f9367702dd7dd4f75ea98afd20e328a1a99f4857b316525328230ce294b0fef2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #77: special case hash", - "NoBenchmark": false - }, - { - "Input": "bab5c4f4df540d7b33324d36bb0c157551527c00000000e4af574bb4d54ea6b89505e407657d6e8bc93db5da7aa6f5081f61980c1949f56b0f2f507da5782a7ac60d31904e3669738ffbeccab6c3656c08e0ed5cb92b3cfa5e7f71784f9c50212927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #78: special case hash", - "NoBenchmark": false - }, - { - "Input": "d4ba47f6ae28f274e4f58d8036f9c36ec2456f5b00000000c3b869197ef5e15ebbd16fbbb656b6d0d83e6a7787cd691b08735aed371732723e1c68a40404517d9d8e35dba96028b7787d91315be675877d2d097be5e8ee34560e3e7fd25c0f002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #79: special case hash", - "NoBenchmark": false - }, - { - "Input": "79fd19c7235ea212f29f1fa00984342afe0f10aafd00000000801e47f8c184e12ec9760122db98fd06ea76848d35a6da442d2ceef7559a30cf57c61e92df327e7ab271da90859479701fccf86e462ee3393fb6814c27b760c4963625c0a198782927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #80: special case hash", - "NoBenchmark": false - }, - { - "Input": "8c291e8eeaa45adbaf9aba5c0583462d79cbeb7ac97300000000a37ea6700cda54e76b7683b6650baa6a7fc49b1c51eed9ba9dd463221f7a4f1005a89fe00c592ea076886c773eb937ec1cc8374b7915cfd11b1c1ae1166152f2f7806a31c8fd2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #81: special case hash", - "NoBenchmark": false - }, - { - "Input": "0eaae8641084fa979803efbfb8140732f4cdcf66c3f78a000000003c278a6b215291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c946665d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc32927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #82: special case hash", - "NoBenchmark": false - }, - { - "Input": "e02716d01fb23a5a0068399bf01bab42ef17c6d96e13846c00000000afc0f89d207a3241812d75d947419dc58efb05e8003b33fc17eb50f9d15166a88479f107cdee749f2e492b213ce80b32d0574f62f1c5d70793cf55e382d5caadf75927672927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #83: special case hash", - "NoBenchmark": false - }, - { - "Input": "9eb0bf583a1a6b9a194e9a16bc7dab2a9061768af89d00659a00000000fc7de16554e49f82a855204328ac94913bf01bbe84437a355a0a37c0dee3cf81aa7728aea00de2507ddaf5c94e1e126980d3df16250a2eaebc8be486effe7f22b4f9292927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #84: special case hash", - "NoBenchmark": false - }, - { - "Input": "62aac98818b3b84a2c214f0d5e72ef286e1030cb53d9a82b690e00000000cd15a54c5062648339d2bff06f71c88216c26c6e19b4d80a8c602990ac82707efdfce99bbe7fcfafae3e69fd016777517aa01056317f467ad09aff09be73c9731b0d2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #85: special case hash", - "NoBenchmark": false - }, - { - "Input": "3760a7f37cf96218f29ae43732e513efd2b6f552ea4b6895464b9300000000c8975bd7157a8d363b309f1f444012b1a1d23096593133e71b4ca8b059cff37eaf7faa7a28b1c822baa241793f2abc930bd4c69840fe090f2aacc46786bf9196222927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #86: special case hash", - "NoBenchmark": false - }, - { - "Input": "0da0a1d2851d33023834f2098c0880096b4320bea836cd9cbb6ff6c8000000005694a6f84b8f875c276afd2ebcfe4d61de9ec90305afb1357b95b3e0da43885e0dffad9ffd0b757d8051dec02ebdf70d8ee2dc5c7870c0823b6ccc7c679cbaa42927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #87: special case hash", - "NoBenchmark": false - }, - { - "Input": "ffffffff293886d3086fd567aafd598f0fe975f735887194a764a231e82d289aa0c30e8026fdb2b4b4968a27d16a6d08f7098f1a98d21620d7454ba9790f1ba65e470453a8a399f15baf463f9deceb53acc5ca64459149688bd2760c654243392927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #88: special case hash", - "NoBenchmark": false - }, - { - "Input": "7bffffffff2376d1e3c03445a072e24326acdc4ce127ec2e0e8d9ca99527e7b7614ea84acf736527dd73602cd4bb4eea1dfebebd5ad8aca52aa0228cf7b99a88737cc85f5f2d2f60d1b8183f3ed490e4de14368e96a9482c2a4dd193195c902f2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #89: special case hash", - "NoBenchmark": false - }, - { - "Input": "a2b5ffffffffebb251b085377605a224bc80872602a6e467fd016807e97fa395bead6734ebe44b810d3fb2ea00b1732945377338febfd439a8d74dfbd0f942fa6bb18eae36616a7d3cad35919fd21a8af4bbe7a10f73b3e036a46b103ef56e2a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #90: special case hash", - "NoBenchmark": false - }, - { - "Input": "641227ffffffff6f1b96fa5f097fcf3cc1a3c256870d45a67b83d0967d4b20c0499625479e161dacd4db9d9ce64854c98d922cbf212703e9654fae182df9bad242c177cf37b8193a0131108d97819edd9439936028864ac195b64fca76d9d6932927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #91: special case hash", - "NoBenchmark": false - }, - { - "Input": "958415d8ffffffffabad03e2fc662dc3ba203521177502298df56f36600e0f8b08f16b8093a8fb4d66a2c8065b541b3d31e3bfe694f6b89c50fb1aaa6ff6c9b29d6455e2d5d1779748573b611cb95d4a21f967410399b39b535ba3e5af81ca2e2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #92: special case hash", - "NoBenchmark": false - }, - { - "Input": "f1d8de4858ffffffff1281093536f47fe13deb04e1fbe8fb954521b6975420f8be26231b6191658a19dd72ddb99ed8f8c579b6938d19bce8eed8dc2b338cb5f8e1d9a32ee56cffed37f0f22b2dcb57d5c943c14f79694a03b9c5e96952575c892927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #93: special case hash", - "NoBenchmark": false - }, - { - "Input": "0927895f2802ffffffff10782dd14a3b32dc5d47c05ef6f1876b95c81fc31def15e76880898316b16204ac920a02d58045f36a229d4aa4f812638c455abe0443e74d357d3fcb5c8c5337bd6aba4178b455ca10e226e13f9638196506a19391232927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #94: special case hash", - "NoBenchmark": false - }, - { - "Input": "60907984aa7e8effffffff4f332862a10a57c3063fb5a30624cf6a0c3ac80589352ecb53f8df2c503a45f9846fc28d1d31e6307d3ddbffc1132315cc07f16dad1348dfa9c482c558e1d05c5242ca1c39436726ecd28258b1899792887dd0a3c62927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #95: special case hash", - "NoBenchmark": false - }, - { - "Input": "c6ff198484939170ffffffff0af42cda50f9a5f50636ea6942d6b9b8cd6ae1e24a40801a7e606ba78a0da9882ab23c7677b8642349ed3d652c5bfa5f2a9558fb3a49b64848d682ef7f605f2832f7384bdc24ed2925825bf8ea77dc59817257822927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #96: special case hash", - "NoBenchmark": false - }, - { - "Input": "de030419345ca15c75ffffffff8074799b9e0956cc43135d16dfbe4d27d7e68deacc5e1a8304a74d2be412b078924b3bb3511bac855c05c9e5e9e44df3d61e967451cd8e18d6ed1885dd827714847f96ec4bb0ed4c36ce9808db8f714204f6d12927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #97: special case hash", - "NoBenchmark": false - }, - { - "Input": "6f0e3eeaf42b28132b88fffffffff6c8665604d34acb19037e1ab78caaaac6ff2f7a5e9e5771d424f30f67fdab61e8ce4f8cd1214882adb65f7de94c31577052ac4e69808345809b44acb0b2bd889175fb75dd050c5a449ab9528f8f78daa10c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #98: special case hash", - "NoBenchmark": false - }, - { - "Input": "cdb549f773b3e62b3708d1ffffffffbe48f7c0591ddcae7d2cb222d1f8017ab9ffcda40f792ce4d93e7e0f0e95e1a2147dddd7f6487621c30a03d710b330021979938b55f8a17f7ed7ba9ade8f2065a1fa77618f0b67add8d58c422c2453a49a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #99: special case hash", - "NoBenchmark": false - }, - { - "Input": "2c3f26f96a3ac0051df4989bffffffff9fd64886c1dc4f9924d8fd6f0edb048481f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f743002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #100: special case hash", - "NoBenchmark": false - }, - { - "Input": "ac18f8418c55a2502cb7d53f9affffffff5c31d89fda6a6b8476397c04edf411dfc8bf520445cbb8ee1596fb073ea283ea130251a6fdffa5c3f5f2aaf75ca808048e33efce147c9dd92823640e338e68bfd7d0dc7a4905b3a7ac711e577e90e72927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #101: special case hash", - "NoBenchmark": false - }, - { - "Input": "4f9618f98e2d3a15b24094f72bb5ffffffffa2fd3e2893683e5a6ab8cf0ee610ad019f74c6941d20efda70b46c53db166503a0e393e932f688227688ba6a576293320eb7ca0710255346bdbb3102cdcf7964ef2e0988e712bc05efe16c1993452927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #102: special case hash", - "NoBenchmark": false - }, - { - "Input": "422e82a3d56ed10a9cc21d31d37a25ffffffff67edf7c40204caae73ab0bc75aac8096842e8add68c34e78ce11dd71e4b54316bd3ebf7fffdeb7bd5a3ebc1883f5ca2f4f23d674502d4caf85d187215d36e3ce9f0ce219709f21a3aac003b7a82927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #103: special case hash", - "NoBenchmark": false - }, - { - "Input": "7075d245ccc3281b6e7b329ff738fbb417a5ffffffffa0842d9890b5cf95d018677b2d3a59b18a5ff939b70ea002250889ddcd7b7b9d776854b4943693fb92f76b4ba856ade7677bf30307b21f3ccda35d2f63aee81efd0bab6972cc0795db552927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #104: special case hash", - "NoBenchmark": false - }, - { - "Input": "3c80de54cd9226989443d593fa4fd6597e280ebeffffffffc1847eb76c217a95479e1ded14bcaed0379ba8e1b73d3115d84d31d4b7c30e1f05e1fc0d5957cfb0918f79e35b3d89487cf634a4f05b2e0c30857ca879f97c771e877027355b24432927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #105: special case hash", - "NoBenchmark": false - }, - { - "Input": "de21754e29b85601980bef3d697ea2770ce891a8cdffffffffc7906aa794b39b43dfccd0edb9e280d9a58f01164d55c3d711e14b12ac5cf3b64840ead512a0a31dbe33fa8ba84533cd5c4934365b3442ca1174899b78ef9a3199f495843897722927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #106: special case hash", - "NoBenchmark": false - }, - { - "Input": "8f65d92927cfb86a84dd59623fb531bb599e4d5f7289ffffffff2f1f2f57881c5b09ab637bd4caf0f4c7c7e4bca592fea20e9087c259d26a38bb4085f0bbff1145b7eb467b6748af618e9d80d6fdcd6aa24964e5a13f885bca8101de08eb0d752927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #107: special case hash", - "NoBenchmark": false - }, - { - "Input": "6b63e9a74e092120160bea3877dace8a2cc7cd0e8426cbfffffffffafc8c3ca85e9b1c5a028070df5728c5c8af9b74e0667afa570a6cfa0114a5039ed15ee06fb1360907e2d9785ead362bb8d7bd661b6c29eeffd3c5037744edaeb9ad990c202927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #108: special case hash", - "NoBenchmark": false - }, - { - "Input": "fc28259702a03845b6d75219444e8b43d094586e249c8699ffffffffe852512e0671a0a85c2b72d54a2fb0990e34538b4890050f5a5712f6d1a7a5fb8578f32edb1846bab6b7361479ab9c3285ca41291808f27fd5bd4fdac720e5854713694c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #109: special case hash", - "NoBenchmark": false - }, - { - "Input": "1273b4502ea4e3bccee044ee8e8db7f774ecbcd52e8ceb571757ffffffffe20a7673f8526748446477dbbb0590a45492c5d7d69859d301abbaedb35b2095103a3dc70ddf9c6b524d886bed9e6af02e0e4dec0d417a414fed3807ef4422913d7c2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #110: special case hash", - "NoBenchmark": false - }, - { - "Input": "08fb565610a79baa0c566c66228d81814f8c53a15b96e602fb49ffffffffff6e7f085441070ecd2bb21285089ebb1aa6450d1a06c36d3ff39dfd657a796d12b5249712012029870a2459d18d47da9aa492a5e6cb4b2d8dafa9e4c5c54a2b9a8b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #111: special case hash", - "NoBenchmark": false - }, - { - "Input": "d59291cc2cf89f3087715fcb1aa4e79aa2403f748e97d7cd28ecaefeffffffff914c67fb61dd1e27c867398ea7322d5ab76df04bc5aa6683a8e0f30a5d287348fa07474031481dda4953e3ac1959ee8cea7e66ec412b38d6c96d28f6d37304ea2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #112: special case hash", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #113: k*G has a large x-coordinate", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #114: r too large", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254eab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c58220455419235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #115: r,s are large", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd480984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c5611feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #116: r and s^-1 have a large Hamming weight", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a54201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c0595c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #117: r and s^-1 have a large Hamming weight", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9575d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #118: small r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000036627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b15726170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #120: small r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000055a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bfef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #122: small r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #124: small r and s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325560000000000000000000000000000000000000000000000000000000000000006cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #126: r is larger than n", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd84be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e13920f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #127: s is larger than n", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea88d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #128: small r and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7a4838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05ffa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #129: smallish r and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4d7393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #130: 100-bit r and small s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b5ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #131: small r and 100 bit s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502300000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b1d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #132: 100-bit r and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c70083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #133: r and s^-1 are close to n", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7000000000000000000000000000000000000000000000000000000000000000018aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #134: s == 1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7000000000000000000000000000000000000000000000000000000000000000008aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #135: s == 0", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c70b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f2871b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #136: point at infinity during verify", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #137: edge case for signature malleability", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a968ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d94697bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #138: edge case for signature malleability", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502369da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b866d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #139: u1 == 1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7044a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52ed8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff3233e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #140: u1 == n - 1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c703623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab7858db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #141: u2 == 1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #142: u2 == n - 1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde91e1ba60fdedb76a46bcb51dc0b8b4b7e019f0a28721885fa5d3a8196623397db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff773504f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #143: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdea5843ffeb73af94313ba4831b53fe24f799e525b1e8e8c87b59b95b430ad9dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #144: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd03ffcabf2f1b4d2a65190db1680d62bb994e41c5251cd73b3c3dfc5e5bafc035d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #145: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4dfbc401f971cd304b33dfdb17d0fed0fe4c1a88ae648e0d2847f74977534989a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c326337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #146: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbc4024761cd2ffd43dfdb17d0fed112b988977055cd3a8e54971eba9cda5ca71c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b73877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #147: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd788048ed39a5ffa77bfb62fa1fda2257742bf35d128fb3459f2a0c909ee86f915eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #148: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd476d9131fd381bd917d0fed112bc9e0a5924b5ed5b11167edd8b23582b3cb15e5caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47adeb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #149: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8374253e3e21bd154448d0a8f640fe46fafa8b19ce78d538f6cc0a19662d3601c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b0986237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #150: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd357cfd3be4d01d413c5b9ede36cba5452c11ee7fe14879e749ae6a2d897a52d63fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #151: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd29798c5c0ee287d4a5e8e6b799fd86b8df5225298e6ffc807cd2f2bc27a0a6d89cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #152: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0b70f22c781092452dca1a5711fa3a5a1f72add1bf52c2ff7cae4820b30078dda3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #153: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd16e1e458f021248a5b9434ae23f474b43ee55ba37ea585fef95c90416600f1baf19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #154: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2252d6856831b6cf895e4f0535eeaf0e5e5809753df848fe760ad86219016a9783a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #155: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd81ffe55f178da695b28c86d8b406b15dab1a9e39661a3ae017fbe390ac0972c3dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #156: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a67e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #157: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f22eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #158: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851e84db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f356d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #159: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf291b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad66349aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #160: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb3669f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834df97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #161: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc885ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #162: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86000a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cde6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #163: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad3d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e868612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #164: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f4836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb2769ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #165: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b0992f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #166: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09eff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #167: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e378651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #168: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa6d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6def6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #169: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f0ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e15428911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #170: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #171: point duplication during verification", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc469637c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #172: duplication bug", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c706adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a647e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #173: point with x-coordinate 0", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d25045d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #175: comparison with point at infinity ", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c704fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #176: extreme value for k and edgecase s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63ccc6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #177: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956efcee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #178: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaf6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f8f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #179: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #180: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb0d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb343195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #181: extreme value for k", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c705e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca215de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #182: extreme value for k and edgecase s", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #183: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b548981487540a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #184: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaa3d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #185: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b72e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #186: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050236b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb8d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #187: extreme value for k", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #188: testing point duplication", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #189: testing point duplication", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #190: testing point duplication", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502344a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #191: testing point duplication", - "NoBenchmark": false - }, - { - "Input": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855b292a619339f6e567a305c951c0dcbcc42d16e47f219f9e98e76e09d8770b34a0177e60492c5a8242f76f07bfe3661bde59ec2a17ce5bd2dab2abebdf89a62e204aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #192: pseudorandom signature", - "NoBenchmark": false - }, - { - "Input": "dc1921946f4af96a2856e7be399007c9e807bdf4c5332f19f59ec9dd1bb8c7b3530bd6b0c9af2d69ba897f6b5fb59695cfbf33afe66dbadcf5b8d2a2a6538e23d85e489cb7a161fd55ededcedbf4cc0c0987e3e3f0f242cae934c72caa3f43e904aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #193: pseudorandom signature", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023a8ea150cb80125d7381c4c1f1da8e9de2711f9917060406a73d7904519e51388f3ab9fa68bd47973a73b2d40480c2ba50c22c9d76ec217257288293285449b8604aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #194: pseudorandom signature", - "NoBenchmark": false - }, - { - "Input": "de47c9b27eb8d300dbb5f2c353e632c393262cf06340c4fa7f1b40c4cbd36f90986e65933ef2ed4ee5aada139f52b70539aaf63f00a91f29c69178490d57fb713dafedfb8da6189d372308cbf1489bbbdabf0c0217d1c0ff0f701aaa7a694b9c04aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #195: pseudorandom signature", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d434e262a49eab7781e353a3565e482550dd0fd5defa013c7f29745eff3569f19b0c0a93f267fb6052fd8077be769c2b98953195d7bc10de844218305c6ba17a4f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #196: x-coordinate of the public key has many trailing 0's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f910fe774355c04d060f76d79fd7a772e421463489221bf0a33add0be9b1979110b500dcba1c69a8fbd43fa4f57f743ce124ca8b91a1f325f3fac6181175df557374f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #197: x-coordinate of the public key has many trailing 0's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91bb40bf217bed3fb3950c7d39f03d36dc8e3b2cd79693f125bfd06595ee1135e3541bf3532351ebb032710bdb6a1bf1bfc89a1e291ac692b3fa4780745bb556774f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #198: x-coordinate of the public key has many trailing 0's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91664eb7ee6db84a34df3c86ea31389a5405badd5ca99231ff556d3e75a233e73a59f3c752e52eca46137642490a51560ce0badc678754b8f72e51a2901426a1bd3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #199: y-coordinate of the public key has many trailing 0's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f914cd0429bbabd2827009d6fcd843d4ce39c3e42e2d1631fd001985a79d1fd8b439638bf12dd682f60be7ef1d0e0d98f08b7bca77a1a2b869ae466189d2acdabe33cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #200: y-coordinate of the public key has many trailing 0's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91e56c6ea2d1b017091c44d8b6cb62b9f460e3ce9aed5e5fd41e8added97c56c04a308ec31f281e955be20b457e463440b4fcf2b80258078207fc1378180f89b553cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #201: y-coordinate of the public key has many trailing 0's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f911158a08d291500b4cabed3346d891eee57c176356a2624fb011f8fbbf3466830228a8c486a736006e082325b85290c5bc91f378b75d487dda46798c18f2855193cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #202: y-coordinate of the public key has many trailing 1's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b1db9289649f59410ea36b0c0fc8d6aa2687b29176939dd23e0dde56d309fa9d3e1535e4280559015b0dbd987366dcf43a6d1af5c23c7d584e1c3f48a12513363cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #203: y-coordinate of the public key has many trailing 1's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7b16e762286cb96446aa8d4e6e7578b0a341a79f2dd1a220ac6f0ca4e24ed86ddc60a700a139b04661c547d07bbb0721780146df799ccf55e55234ecb8f12bc3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #204: y-coordinate of the public key has many trailing 1's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d82a7c2717261187c8e00d8df963ff35d796edad36bc6e6bd1c91c670d9105b43dcabddaf8fcaa61f4603e7cbac0f3c0351ecd5988efb23f680d07debd1399292829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #205: x-coordinate of the public key has many trailing 1's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f915eb9c8845de68eb13d5befe719f462d77787802baff30ce96a5cba063254af782c026ae9be2e2a5e7ca0ff9bbd92fb6e44972186228ee9a62b87ddbe2ef66fb52829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #206: x-coordinate of the public key has many trailing 1's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9196843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #207: x-coordinate of the public key has many trailing 1's", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91766456dce1857c906f9996af729339464d27e9d98edc2d0e3b760297067421f6402385ecadae0d8081dccaf5d19037ec4e55376eced699e93646bfbbf19d0b41fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #208: x-coordinate of the public key is large", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91c605c4b2edeab20419e6518a11b2dbc2b97ed8b07cced0b19c34f777de7b9fd9edf0f612c5f46e03c719647bc8af1b29b2cde2eda700fb1cff5e159d47326dbafffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #209: x-coordinate of the public key is large", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d48b68e6cabfe03cf6141c9ac54141f210e64485d9929ad7b732bfe3b7eb8a84feedae50c61bd00e19dc26f9b7e2265e4508c389109ad2f208f0772315b6c941fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #210: x-coordinate of the public key is large", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91b7c81457d4aeb6aa65957098569f0479710ad7f6595d5874c35a93d12a5dd4c7b7961a0b652878c2d568069a432ca18a1a9199f2ca574dad4b9e3a05c0a1cdb300000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #211: x-coordinate of the public key is small", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f916b01332ddb6edfa9a30a1321d5858e1ee3cf97e263e669f8de5e9652e76ff3f75939545fced457309a6a04ace2bd0f70139c8f7d86b02cb1cc58f9e69e96cd5a00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #212: x-coordinate of the public key is small", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91efdb884720eaeadc349f9fc356b6c0344101cd2fd8436b7d0e6a4fb93f106361f24bee6ad5dc05f7613975473aadf3aacba9e77de7d69b6ce48cb60d8113385d00000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #213: x-coordinate of the public key is small", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9131230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb070f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beffbcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #214: y-coordinate of the public key is small", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91caa797da65b320ab0d5c470cda0b36b294359c7db9841d679174db34c4855743cf543a62f23e212745391aaf7505f345123d2685ee3b941d3de6d9b36242e5a0bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #215: y-coordinate of the public key is small", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f917e5f0ab5d900d3d3d7867657e5d6d36519bc54084536e7d21c336ed8001859459450c07f201faec94b82dfb322e5ac676688294aad35aa72e727ff0b19b646aabcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #216: y-coordinate of the public key is small", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91d7d70c581ae9e3f66dc6a480bf037ae23f8a1e4a2136fe4b03aa69f0ca25b35689c460f8a5a5c2bbba962c8a3ee833a413e85658e62a59e2af41d9127cc47224bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #217: y-coordinate of the public key is large", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91341c1b9ff3c83dd5e0dfa0bf68bcdf4bb7aa20c625975e5eeee34bb396266b3472b69f061b750fd5121b22b11366fad549c634e77765a017902a67099e0a4469bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #218: y-coordinate of the public key is large", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #219: y-coordinate of the public key is large", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #3: valid", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502329a3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #118: modify first byte of integer", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e98b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #120: modify last byte of integer", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568475b2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #121: modify last byte of integer", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1800b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568472927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #124: truncated integer", - "NoBenchmark": false - }, - { - "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050232ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f47aa2bbd0a4c384ee1493b1f518ada018ef05465583885980861905228a2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_secp256r1_sha256_test.json EcdsaVerify SHA-256 #139: Modified r or s, e.g. by adding or subtracting the order of the group", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #636: r too large", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e3cd8d2f81d6953b0844c09d7b560d527cd2ef67056893eadafa52c8501387d59ee41fdb4d10402ce7a0c5e3b747adfa3a490b62a6b7719068903485c0bb6dc2d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #637: r,s are large", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd48240cd81edd91cb6936133508c3915100e81f332c4545d41189b481196851378e05b06e72d4a1bff80ea5db514aa2f93ea6dd6d9c0ae27b7837dc432f9ce89d9", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #638: r and s^-1 have a large Hamming weight", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a5b062947356748b0fc17f1704c65aa1dca6e1bfe6779756fa616d91eaad13df2c0b38c17f3d0672e7409cfc5992a99fff12b84a4f8432293b431113f1b2fb579d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #639: r and s^-1 have a large Hamming weight", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c707a736d8e326a9ca62bbe25a34ea4e3633b499a96afa7aaa3fcf3fd88f8e07edeb3e45879d8622b93e818443a686e869eeda7bf9ae46aa3eafcc48a5934864627", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #651: r and s^-1 are close to n", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c700203736fcb198b15d8d7a0c80f66dddd15259240aa78d08aae67c467de04503434383438d5041ea9a387ee8e4d4e84b4471b160c6bcf2568b072f8f20e87a996", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #654: point at infinity during verify", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a878d844dc7f16b73b1f2a39730da5d8cd99fe2e70a18482384e37dcd2bfea02e1ed6572e01eb7a8d113d02c666c45ef22d3b9a6a6dea99aa43a8183c26e75d336", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #655: edge case for signature malleability", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a9dec6c8257dde94110eacc8c09d2e5789cc5beb81a958b02b4d62da9599a7401466fae1614174be63970b83f6524421067b06dd6f4e9c56baca4e344fdd690f1d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #656: edge case for signature malleability", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25a17f5b75a35ed64623ca5cbf1f91951292db0c23f0c2ea24c3d0cad0988cabc083a7a618625c228940730b4fa3ee64faecbb2fc20fdde7c58b3a3f6300424dc6", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #657: u1 == 1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c04ba0cba291a37db13f33bf90dab628c04ec8393a0200419e9eaa1ebcc9fb5c31f3a0a0e6823a49b625ad57b12a32d4047970fc3428f0f0049ecf4265dc12f62", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #658: u1 == n - 1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c70692b6c828e0feed63d8aeaa2b7322f9ccbe8723a1ed39f229f204a434b8900efa1f6f6abcb38ea3b8fde38b98c7c271f274af56a8c5628dc3329069ae4dd5716", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #659: u2 == 1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e100cefd9162d13e64cb93687a9cd8f9755ebb5a3ef7632f800f84871874ccef09543ecbeaf7e8044ef721be2fb5f549e4b8480d2587404ebf7dbbef2c54bc0cb1", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #660: u2 == n - 1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd710f8e3edc7c2d5a3fd23de844002bb949d9f794f6d5405f6d97c1bb03dd2bd2b975183b42551cf52f291d5c1921fd5e12f50c8c85a4beb9de03efa3f0f244862243018e6866df922dc313612020311ff21e242ce3fb15bc78c406b25ab43091", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #661: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdedffbc270f722c243069a7e5f40335a61a58525c7b4db2e7a8e269274ffe4e1bc25f1d166f3e211cdf042a26f8abf6094d48b8d17191d74ed71714927446699965d06dd6a88abfa49e8b4c5da6bb922851969adf9604b5accfb52a114e77ccdb", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #662: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffda25adcae105ed7ff4f95d2344e24ee523314c3e178525d007904b68919ba4d538fe5e88243a76e41a004236218a3c3a2d6eee398a23c3a0b008d7f0164cbc0ca98a20d1bdcf573513c7cfd9b83c63e3a82d40127c897697c86b8cb387af7f240", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #663: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2e4348c645707dce6760d773de3f3e87346924b2f64bd3dd0297e766b5805ebb02148256b530fbc470c7b341970b38243ecee6d5a840a37beca2efb37e8dff2cc0adbea0882482a7489ca703a399864ba987eeb6ddb738af53a83573473cb30d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #664: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd348c673b07dce3920d773de3f3e87408869e916dbcf797d8f9684fb67753d1dca34db012ce6eda1e9c7375c5fcf3e54ed698e19615124273b3a621d021c76f8e777458d6f55a364c221e39e1205d5510bb4fbb7ddf08d8d8fdde13d1d6df7f14", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #665: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6918ce760fb9c7241aee7bc7e7d0e8110d3d22db79ef2fb1f2d09f6ceea7a3b8b97af3fe78be15f2912b6271dd8a43badb6dd2a1b315b2ce7ae37b4e7778041d930d71ee1992d2466495c42102d08e81154c305307d1dcd52d0fa4c479b278e7", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #666: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd73b3c694391d8eadde3f3e874089464715ac20e4c126bbf6d864d648969f5b5a81e7198a3c3f23901cedc7a1d6eff6e9bf81108e6c35cd8559139af3135dbcbb9ef1568530291a8061b90c9f4285eefcba990d4570a4e3b7b737525b5d580034", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #667: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb07ac7a86948c2c2989a16db1930ef1b89ce112595197656877e53c41457f28ab4d792ca121d1dba39cb9de645149c2ab573e8becc6ddff3cc9960f188ddf737f90ba23664153e93262ff73355415195858d7be1315a69456386de68285a3c8", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #668: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27e4d82cb6c061dd9337c69bf9332ed3d198662d6f2299443f62c861187db648518412b69af43aae084476a68d59bbde51fbfa9e5be80563f587c9c2652f88ef2d3b90d25baa6bdb7b0c55e5240a3a98fbc24afed8523edec1c70503fc10f233", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #669: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde7c5cf3aac2e88923b77850515fff6a12d13b356dfe9ec275c3dd81ae94609a4a08f14a644b9a935dffea4761ebaf592d1f66fe6cd373aa7f5d370af34f8352da54b5bc4025cf335900a914c2934ec2fec7a396d0a7affcad732a5741c7aaaf5", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #670: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc77838df91c1e953e016e10bddffea2317f9fee32bacfe553cede9e57a748f68ccf2296a6a89b62b90739d38af4ae3a20e9f45715b90044639241061e33f8f8caace0046491eeaa1c6e9a472b96d88f4af83e7ff1bb84438c7e058034412ae08", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #671: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8ef071c02383d2a6c02dc217bbffd446730d0318b0425e2586220907f885f97f94b0fc1525bcabf82b1f34895e5819a06c02b23e04002276e165f962c86e3927be7c2ab4d0b25303204fb32a1f8292902792225e16a6d2dbfb29fbc89a9c3376", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #672: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5668aaa0b545bbf9a044a32399ffbe69ce20074e34d7bdf5cf56282a769763965351f37e1de0c88c508527d89882d183ccdcf2efca407edb0627cadfd16de6ec44b4b57cdf960d32ebcc4c97847eed218425853b5b675eb781b766a1a1300349", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #673: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd12d6e56882f6c0027cae91a27127728f7fddf478fb4fdc2b65f40a60b0eb952748bbafc320e6735cb64019710a269c6c2b5d147bdc831325cb2fb276ac971a69d655e9a755bc9d800ad21ee3fd4d980d93a7a49a8c5ccd37005177578f51163", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #674: edge case for u1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a14b3bbd75c5e1c0c36535a934d4ab85112410b3b90fa97a31c33038964fd85cc112f7d837f8f9c36b460d636c965a5f818f2b50c5d00fb3f9705561dd6631883", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #675: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f2d823533c04cd8edc6d6f950a8e08ade04a9bafa2f14a590356935671ae9305bf43178d1f88b6a57a96924c265f0ddb75b58312907b195acb59d7797303123775", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #676: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851edb2b3408b3167d91030624c6328e8ce3ec108c105575c2f3d209b92e654bab69c34318139c50b0802c6e612f0fd3189d800df7c996d5d7b7c3d6be82836fa258", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #677: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf209179ce7c59225392216453b2ac1e9d178c24837dfae26bc1dd7ab60638527425556b42e330289f3b826b2db7a86d19d45c2860a59f2be1ddcc3b691f95a9255", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #678: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb366901959fb8deda56e5467b7e4b214ea4c2d0c2fb29d70ff19b6b1eccebd6568d7ed9dbd77a918297fd970bff01e1343f6925167db5a14d098a211c39cc3a413398", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #679: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2567f1fdc387e5350c852b4e8f8ba9d6d947e1c5dd7ccc61a5938245dd6bcab3a9960bebaf919514f9535c22eaaf0b5812857970e26662267b1f3eb1011130a11", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #680: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86003499f974ff4ca6bbb2f51682fd5f51762f9dd6dd2855262660b36d46d3e4bec2f498fae2487807e220119152f0122476c64d4fa46ddce85c4546630f0d5c5e81", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #681: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad32c5c01662cf00c1929596257db13b26ecf30d0f3ec4b9f0351b0f27094473426e986a086060d086eee822ddd2fc744247a0154b57f7a69c51d9fdafa484e4ac7", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #682: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f491d4cba813a04d86dbae94c23be6f52c15774183be7ba5b2d9f3cf010b160501900b8adfea6491019a9ac080d516025a541bf4b952b0ad7be4b1874b02fd544a", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #683: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b09ef7fd0a3a36386638330ecad41e1a3b302af36960831d0210c614b948e8aa124ef0d6d800e4047d6d3c1be0fdeaf11fcd8cab5ab59c730eb34116e35a8c7d098", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #684: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4a521dab13cc9152d8ca77035a607fea06c55cc3ca5dbeb868cea92eafe93df2a7bfb9b28531996635e6a5ccaa2826a406ce1111bdb9c2e0ca36500418a2f43de", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #685: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e37474d58a4eec16e0d565f2187fe11d4e8e7a2683a12f38b4fc01d1237a81a10976e55f73bb7cdda46bdb67ef77f6fd2969df2b67920fb5945fde3a517a6ded4cd", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #686: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa692da5cd4309d9a6e5cb525c37da8fa0879f7b57208cdabbf47d223a5b23a62140e0daa78cfdd207a7389aaed61738b17fc5fc3e6a5ed3397d2902e9125e6ab4", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #687: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f85689b3e0775c7718a90279f14a8082cfcd4d1f1679274f4e9b8805c570a0670167fcc5ca734552e09afa3640f4a034e15b9b7ca661ec7ff70d3f240ebe705b1", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #688: edge case for u2", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237e2a964fc00d377a8592b8b61aafa7a4aaa7c7b9fd2b41d6e0e17bd1ba5677edcd", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #689: point duplication during verification", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569f21d907e3890916dc4fa1f4703c1e50d3f54ddf7383e44023a41de562aa18ed80158137755b901f797a90d4ca8887e023cb2ef63b2ba2c0d455edaef42cf237ed569b03ef2c8857b6d4749e550585b5558384603d4be291f1e842e45a9881232", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #690: duplication bug", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9664ce273320d918d8bdb2e61201b4549b36b7cdc54e33b84adb6f2c10aac831e49e68831f18bda2973ac3d76bfbc8c5ee1cceed2dd862e2dc7c915c736cef1f4", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #693: comparison with point at infinity ", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c70961691a5e960d07a301dbbad4d86247ec27d7089faeb3ddd1add395efff1e0fe7254622cc371866cdf990d2c5377790e37d1f1519817f09a231bd260a9e78aeb", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #694: extreme value for k and edgecase s", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc5d283e13ce8ca60da868e3b0fb33e6b4f1074793274e2928250e71e2aca63e9c214dc74fa25371fb4d9e506d418ed9a1bfd6d0c8bb6591d3e0f44505a84886ce", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #695: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa70fc351da038ae0803bd1d86514ae0462f9f8216551d9315aa9d297f792eef6a341c74eed786f2d33da35360ca7aa925e753f00d6077a1e9e5fc339d634019c73", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #696: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaa1e34c8f16d138673fee55c080547c2bfd4de7550065f638322bba9430ce4b60662be9bb512663aa4d7df8ab3f3b4181c5d44a7bdf42436620b7d8a6b81ac936", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #697: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c1857e1a8a8338d7fd8cf41d322a302d2078a87a23c7186150ed7cda6e52817c1bdfd0a9135a89d21ce821e29014b2898349254d748272b2d4eb8d59ee34c615377f", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #698: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb5c19fe227a61abc65c61ee7a018cc9571b2c6f663ea33583f76a686f64be078b7b4a0d734940f613d52bc48673b457c2cf78492490a5cc5606c0541d17b24ddb", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #699: extreme value for k", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c70db02d1f3421d600e9d9ef9e47419dba3208eed08c2d4189a5db63abeb2739666e0ed26967b9ada9ed7ffe480827f90a0d210d5fd8ec628e31715e6b24125512a", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #700: extreme value for k and edgecase s", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc6222d1962655501893c29e441395b6c05711bd3ed5a0ef72cfab338b88229c4baaae079cb44a1af070362aaa520ee24cac2626423b0bf81af1c54311d8e2fd23", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #701: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa74ccfa24c67f3def7fa81bc99c70bb0419c0952ba599f4c03361da184b04cdca5db76b797f7f41d9c729a2219478a7e629728df870800be8cf6ca7a0a82153bfa", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #702: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaaea1c72c91034036bac71402b6e9ecc4af3dbde7a99dc574061e99fefff9d84dab7dd057e75b78ac6f56e34eb048f0a9d29d5d055408c90d02bc2ea918c18cb63", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #703: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185c2879a66d86cb20b820b7795da2da62b38924f7817d1cd350d936988e90e79bc5431a7268ff6931c7a759de024eff90bcb0177216db6fd1f3aaaa11fa3b6a083", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #704: extreme value for k and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e256b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bbab1c0f273f74abc2b848c75006f2ef3c54c26df27711b06558f455079aee0ba3df510f2ecef6d9a05997c776f14ad6456c179f0a13af1771e4d6c37fa48b47f2", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #705: extreme value for k", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #706: testing point duplication", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #707: testing point duplication", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #708: testing point duplication", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c26b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #709: testing point duplication", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2530e782f964b2e2ff065a051bc7adc20615d8c43a1365713c88268822c253bcce5b16df652aa1ecb2dc8b46c515f9604e2e84cacfa7c6eec30428d2d3f4e08ed504aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #1211: pseudorandom signature", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #113: k*G has a large x-coordinate", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000014a03ef9f92eb268cafa601072489a56380fa0dc43171d7712813b3a19a1eb5e53e213e28a608ce9a2f4a17fd830c6654018a79b3e0263d91a8ba90622df6f2f0", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #118: small r and s", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000003091194c1cba17f34e286b4833701606a41cef26177ada8850b601ea1f859e70127242fcec708828758403ce2fe501983a7984e6209f4d6b95db9ad77767f55eb", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #120: small r and s", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005103c6ecceff59e71ea8f56fee3a4b2b148e81c2bdbdd39c195812c96dcfb41a72303a193dc591be150b883d770ec51ebb4ebce8b09042c2ecb16c448d8e57bf5", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #122: small r and s", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000063b66b829fe604638bcb2bfe8c22228be67390c20111bd2b451468927e87fb6eabc8e59c009361758b274ba2cad36b58fde485a3ed09dade76712fa9e9c4ac212", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #124: small r and s", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255600000000000000000000000000000000000000000000000000000000000000063b66b829fe604638bcb2bfe8c22228be67390c20111bd2b451468927e87fb6eabc8e59c009361758b274ba2cad36b58fde485a3ed09dade76712fa9e9c4ac212", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #126: r is larger than n", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd84ff2f6c24e4a33cd71c09fdcbc74a6233961b874b8c8e0eb94582092cbc50c3084fa9547afda5c66335f3f937d4c79afa120486b534139d59ae82d61ead26420", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #127: s is larger than n", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea8884b959080bb30859cd53c2fb973cf14d60cdaa8ee00587889b5bc657ac588175a02ce5c1e53cb196113c78b4cb8dc7d360e5ea7850b0f6650b0c45af2c3cd7ca", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #128: small r and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7adf4083bd6ecbda5a77ae578e5d835fa7f74a07ebb91e0570e1ff32a563354e9925af80b09a167d9ef647df28e2d9acd0d4bc4f2deec5723818edaf9071e311f8", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #129: smallish r and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4dc2569a3c9bf8c1838ca821f7ba6f000cc8679d278f3736b414a34a7c956a03770387ea85bc4f28804b4a91c9b7d65bc6434c975806795ab7d441a4e9683aeb09", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #130: 100-bit r and small s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b4a9f7da2a6c359a16540c271774a6bf1c586357c978256f44a6496d80670968ac496e73a44563f8d56fbd7bb9e4e3ae304c86f2c508eb777b03924755beb40d4", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #131: small r and 100 bit s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2500000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b874146432b3cd2c9e26204c0a34136996067d466dde4917a8ff23a8e95ca106b709b3d50976ef8b385a813bc35f3a20710bdc6edd465e6f43ac4866703a6608c", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #132: 100-bit r and s^-1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000001e84d9b232e971a43382630f99725e423ec1ecb41e55172e9c69748a03f0d5988618b15b427ad83363bd041ff75fac98ef2ee923714e7d1dfe31753793c7588d4", - "Expected": "0000000000000000000000000000000000000000000000000000000000000001", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #134: s == 1", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000000e84d9b232e971a43382630f99725e423ec1ecb41e55172e9c69748a03f0d5988618b15b427ad83363bd041ff75fac98ef2ee923714e7d1dfe31753793c7588d4", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #135: s == 0", - "NoBenchmark": false - }, - { - "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e250000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c7038a084ffccc4ae2f8204be2abca9fb8ad4ab283b2aa50f13b6bb2347adabc69ca699799b77b1cc6dad271e88b899c12931986e958e1f5cf5653dddf7389365e2", - "Expected": "", - "Gas": 6900, - "Name": "wycheproof/ecdsa_webcrypto_test.json EcdsaP1363Verify SHA-256 #173: point with x-coordinate 0", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a90000000000000000000000000000000000000000000000000000000000000000fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", - "Expected": "", - "Gas": 6900, - "Name": "invalid public key x param errors", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af0150000000000000000000000000000000000000000000000000000000000000000", - "Expected": "", - "Gas": 6900, - "Name": "invalid public key y param errors", - "NoBenchmark": false - }, - { - "Input": "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9170bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "Expected": "", - "Gas": 6900, - "Name": "reference point errors", - "NoBenchmark": false - } -] \ No newline at end of file diff --git a/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_u1_u2.json b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_u1_u2.json new file mode 100644 index 0000000000..e7e135da1a --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/vectors/secp256r1_u1_u2.json @@ -0,0 +1,450 @@ +[ + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca60502369da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b866d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #139: u1 == 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c7044a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52ed8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff3233e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #140: u1 == n - 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c703623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab7858db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #141: u2 == 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #142: u2 == n - 1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde91e1ba60fdedb76a46bcb51dc0b8b4b7e019f0a28721885fa5d3a8196623397db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff773504f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #143: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdea5843ffeb73af94313ba4831b53fe24f799e525b1e8e8c87b59b95b430ad9dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #144: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd03ffcabf2f1b4d2a65190db1680d62bb994e41c5251cd73b3c3dfc5e5bafc035d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #145: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4dfbc401f971cd304b33dfdb17d0fed0fe4c1a88ae648e0d2847f74977534989a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c326337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #146: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbc4024761cd2ffd43dfdb17d0fed112b988977055cd3a8e54971eba9cda5ca71c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b73877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #147: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd788048ed39a5ffa77bfb62fa1fda2257742bf35d128fb3459f2a0c909ee86f915eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #148: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd476d9131fd381bd917d0fed112bc9e0a5924b5ed5b11167edd8b23582b3cb15e5caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47adeb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #149: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8374253e3e21bd154448d0a8f640fe46fafa8b19ce78d538f6cc0a19662d3601c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b0986237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #150: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd357cfd3be4d01d413c5b9ede36cba5452c11ee7fe14879e749ae6a2d897a52d63fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #151: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd29798c5c0ee287d4a5e8e6b799fd86b8df5225298e6ffc807cd2f2bc27a0a6d89cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #152: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0b70f22c781092452dca1a5711fa3a5a1f72add1bf52c2ff7cae4820b30078dda3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #153: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd16e1e458f021248a5b9434ae23f474b43ee55ba37ea585fef95c90416600f1baf19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #154: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2252d6856831b6cf895e4f0535eeaf0e5e5809753df848fe760ad86219016a9783a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #155: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd81ffe55f178da695b28c86d8b406b15dab1a9e39661a3ae017fbe390ac0972c3dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #156: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a67e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #157: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f22eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #158: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851e84db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f356d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #159: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf291b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad66349aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #160: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb3669f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834df97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #161: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc885ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #162: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86000a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cde6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #163: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad3d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e868612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #164: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f4836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb2769ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #165: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b0992f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #166: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09eff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #167: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e378651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #168: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa6d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6def6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #169: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f0ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e15428911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_secp256r1_sha256_p1363_test.json EcdsaP1363Verify SHA-256 #170: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25a17f5b75a35ed64623ca5cbf1f91951292db0c23f0c2ea24c3d0cad0988cabc083a7a618625c228940730b4fa3ee64faecbb2fc20fdde7c58b3a3f6300424dc6", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #657: u1 == 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70acd155416a8b77f34089464733ff7cd39c400e9c69af7beb9eac5054ed2ec72c04ba0cba291a37db13f33bf90dab628c04ec8393a0200419e9eaa1ebcc9fb5c31f3a0a0e6823a49b625ad57b12a32d4047970fc3428f0f0049ecf4265dc12f62", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #658: u1 == n - 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c70692b6c828e0feed63d8aeaa2b7322f9ccbe8723a1ed39f229f204a434b8900efa1f6f6abcb38ea3b8fde38b98c7c271f274af56a8c5628dc3329069ae4dd5716", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #659: u2 == 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e100cefd9162d13e64cb93687a9cd8f9755ebb5a3ef7632f800f84871874ccef09543ecbeaf7e8044ef721be2fb5f549e4b8480d2587404ebf7dbbef2c54bc0cb1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #660: u2 == n - 1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd710f8e3edc7c2d5a3fd23de844002bb949d9f794f6d5405f6d97c1bb03dd2bd2b975183b42551cf52f291d5c1921fd5e12f50c8c85a4beb9de03efa3f0f244862243018e6866df922dc313612020311ff21e242ce3fb15bc78c406b25ab43091", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #661: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdedffbc270f722c243069a7e5f40335a61a58525c7b4db2e7a8e269274ffe4e1bc25f1d166f3e211cdf042a26f8abf6094d48b8d17191d74ed71714927446699965d06dd6a88abfa49e8b4c5da6bb922851969adf9604b5accfb52a114e77ccdb", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #662: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffda25adcae105ed7ff4f95d2344e24ee523314c3e178525d007904b68919ba4d538fe5e88243a76e41a004236218a3c3a2d6eee398a23c3a0b008d7f0164cbc0ca98a20d1bdcf573513c7cfd9b83c63e3a82d40127c897697c86b8cb387af7f240", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #663: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2e4348c645707dce6760d773de3f3e87346924b2f64bd3dd0297e766b5805ebb02148256b530fbc470c7b341970b38243ecee6d5a840a37beca2efb37e8dff2cc0adbea0882482a7489ca703a399864ba987eeb6ddb738af53a83573473cb30d", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #664: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd348c673b07dce3920d773de3f3e87408869e916dbcf797d8f9684fb67753d1dca34db012ce6eda1e9c7375c5fcf3e54ed698e19615124273b3a621d021c76f8e777458d6f55a364c221e39e1205d5510bb4fbb7ddf08d8d8fdde13d1d6df7f14", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #665: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6918ce760fb9c7241aee7bc7e7d0e8110d3d22db79ef2fb1f2d09f6ceea7a3b8b97af3fe78be15f2912b6271dd8a43badb6dd2a1b315b2ce7ae37b4e7778041d930d71ee1992d2466495c42102d08e81154c305307d1dcd52d0fa4c479b278e7", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #666: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd73b3c694391d8eadde3f3e874089464715ac20e4c126bbf6d864d648969f5b5a81e7198a3c3f23901cedc7a1d6eff6e9bf81108e6c35cd8559139af3135dbcbb9ef1568530291a8061b90c9f4285eefcba990d4570a4e3b7b737525b5d580034", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #667: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb07ac7a86948c2c2989a16db1930ef1b89ce112595197656877e53c41457f28ab4d792ca121d1dba39cb9de645149c2ab573e8becc6ddff3cc9960f188ddf737f90ba23664153e93262ff73355415195858d7be1315a69456386de68285a3c8", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #668: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27e4d82cb6c061dd9337c69bf9332ed3d198662d6f2299443f62c861187db648518412b69af43aae084476a68d59bbde51fbfa9e5be80563f587c9c2652f88ef2d3b90d25baa6bdb7b0c55e5240a3a98fbc24afed8523edec1c70503fc10f233", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #669: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde7c5cf3aac2e88923b77850515fff6a12d13b356dfe9ec275c3dd81ae94609a4a08f14a644b9a935dffea4761ebaf592d1f66fe6cd373aa7f5d370af34f8352da54b5bc4025cf335900a914c2934ec2fec7a396d0a7affcad732a5741c7aaaf5", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #670: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc77838df91c1e953e016e10bddffea2317f9fee32bacfe553cede9e57a748f68ccf2296a6a89b62b90739d38af4ae3a20e9f45715b90044639241061e33f8f8caace0046491eeaa1c6e9a472b96d88f4af83e7ff1bb84438c7e058034412ae08", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #671: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8ef071c02383d2a6c02dc217bbffd446730d0318b0425e2586220907f885f97f94b0fc1525bcabf82b1f34895e5819a06c02b23e04002276e165f962c86e3927be7c2ab4d0b25303204fb32a1f8292902792225e16a6d2dbfb29fbc89a9c3376", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #672: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5668aaa0b545bbf9a044a32399ffbe69ce20074e34d7bdf5cf56282a769763965351f37e1de0c88c508527d89882d183ccdcf2efca407edb0627cadfd16de6ec44b4b57cdf960d32ebcc4c97847eed218425853b5b675eb781b766a1a1300349", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #673: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd12d6e56882f6c0027cae91a27127728f7fddf478fb4fdc2b65f40a60b0eb952748bbafc320e6735cb64019710a269c6c2b5d147bdc831325cb2fb276ac971a69d655e9a755bc9d800ad21ee3fd4d980d93a7a49a8c5ccd37005177578f51163", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #674: edge case for u1", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a14b3bbd75c5e1c0c36535a934d4ab85112410b3b90fa97a31c33038964fd85cc112f7d837f8f9c36b460d636c965a5f818f2b50c5d00fb3f9705561dd6631883", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #675: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f2d823533c04cd8edc6d6f950a8e08ade04a9bafa2f14a590356935671ae9305bf43178d1f88b6a57a96924c265f0ddb75b58312907b195acb59d7797303123775", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #676: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851edb2b3408b3167d91030624c6328e8ce3ec108c105575c2f3d209b92e654bab69c34318139c50b0802c6e612f0fd3189d800df7c996d5d7b7c3d6be82836fa258", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #677: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf209179ce7c59225392216453b2ac1e9d178c24837dfae26bc1dd7ab60638527425556b42e330289f3b826b2db7a86d19d45c2860a59f2be1ddcc3b691f95a9255", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #678: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb366901959fb8deda56e5467b7e4b214ea4c2d0c2fb29d70ff19b6b1eccebd6568d7ed9dbd77a918297fd970bff01e1343f6925167db5a14d098a211c39cc3a413398", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #679: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2567f1fdc387e5350c852b4e8f8ba9d6d947e1c5dd7ccc61a5938245dd6bcab3a9960bebaf919514f9535c22eaaf0b5812857970e26662267b1f3eb1011130a11", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #680: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc86003499f974ff4ca6bbb2f51682fd5f51762f9dd6dd2855262660b36d46d3e4bec2f498fae2487807e220119152f0122476c64d4fa46ddce85c4546630f0d5c5e81", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #681: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad32c5c01662cf00c1929596257db13b26ecf30d0f3ec4b9f0351b0f27094473426e986a086060d086eee822ddd2fc744247a0154b57f7a69c51d9fdafa484e4ac7", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #682: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f491d4cba813a04d86dbae94c23be6f52c15774183be7ba5b2d9f3cf010b160501900b8adfea6491019a9ac080d516025a541bf4b952b0ad7be4b1874b02fd544a", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #683: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b09ef7fd0a3a36386638330ecad41e1a3b302af36960831d0210c614b948e8aa124ef0d6d800e4047d6d3c1be0fdeaf11fcd8cab5ab59c730eb34116e35a8c7d098", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #684: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4a521dab13cc9152d8ca77035a607fea06c55cc3ca5dbeb868cea92eafe93df2a7bfb9b28531996635e6a5ccaa2826a406ce1111bdb9c2e0ca36500418a2f43de", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #685: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e37474d58a4eec16e0d565f2187fe11d4e8e7a2683a12f38b4fc01d1237a81a10976e55f73bb7cdda46bdb67ef77f6fd2969df2b67920fb5945fde3a517a6ded4cd", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #686: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa692da5cd4309d9a6e5cb525c37da8fa0879f7b57208cdabbf47d223a5b23a62140e0daa78cfdd207a7389aaed61738b17fc5fc3e6a5ed3397d2902e9125e6ab4", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #687: edge case for u2", + "NoBenchmark": false + }, + { + "Input": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e257ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f85689b3e0775c7718a90279f14a8082cfcd4d1f1679274f4e9b8805c570a0670167fcc5ca734552e09afa3640f4a034e15b9b7ca661ec7ff70d3f240ebe705b1", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 6900, + "Name": "wycheproof/ecdsa_test.json EcdsaVerify SHA-256 #688: edge case for u2", + "NoBenchmark": false + } +] \ No newline at end of file From 5aef86f30e9385234d85b47c5ba7a65a45dfa205 Mon Sep 17 00:00:00 2001 From: felipe Date: Tue, 23 Sep 2025 08:09:03 -0600 Subject: [PATCH 027/102] refactor(bal): absence validators -> BalAccountAbsentValues (#2175) * refactor(bal): absence validators -> BalAccountAbsentValues * feat: raise for empty lists on BAL absence checks * refactor: changes from comments on PR #2175 --- .../block_access_list/__init__.py | 592 +----------------- .../block_access_list/absence_validators.py | 140 ----- .../account_absent_values.py | 211 +++++++ .../block_access_list/account_changes.py | 126 ++++ .../block_access_list/exceptions.py | 7 + .../block_access_list/expectations.py | 398 ++++++++++++ ethereum_test_types/block_access_list/t8n.py | 47 ++ .../tests/test_block_access_lists.py | 306 ++++++--- 8 files changed, 1022 insertions(+), 805 deletions(-) delete mode 100644 ethereum_test_types/block_access_list/absence_validators.py create mode 100644 ethereum_test_types/block_access_list/account_absent_values.py create mode 100644 ethereum_test_types/block_access_list/account_changes.py create mode 100644 ethereum_test_types/block_access_list/exceptions.py create mode 100644 ethereum_test_types/block_access_list/expectations.py create mode 100644 ethereum_test_types/block_access_list/t8n.py diff --git a/ethereum_test_types/block_access_list/__init__.py b/ethereum_test_types/block_access_list/__init__.py index 3eb2e12cc8..6544bc7108 100644 --- a/ethereum_test_types/block_access_list/__init__.py +++ b/ethereum_test_types/block_access_list/__init__.py @@ -5,584 +5,30 @@ these are simple data classes that can be composed together. """ -from functools import cached_property -from typing import Any, Callable, ClassVar, Dict, List, Union - -import ethereum_rlp as eth_rlp -from pydantic import Field, PrivateAttr - -from ethereum_test_base_types import ( - Address, - Bytes, - CamelModel, - EthereumTestRootModel, - HexNumber, - RLPSerializable, - StorageKey, +from .account_absent_values import BalAccountAbsentValues +from .account_changes import ( + BalAccountChange, + BalBalanceChange, + BalCodeChange, + BalNonceChange, + BalStorageChange, + BalStorageSlot, + BlockAccessListChangeLists, ) -from ethereum_test_base_types.serialization import to_serializable_element - - -class BlockAccessListValidationError(Exception): - """Custom exception for Block Access List validation errors.""" - - pass - - -def compose( - *modifiers: Callable[["BlockAccessList"], "BlockAccessList"], -) -> Callable[["BlockAccessList"], "BlockAccessList"]: - """Compose multiple modifiers into a single modifier.""" - - def composed(bal: BlockAccessList) -> BlockAccessList: - result = bal - for modifier in modifiers: - result = modifier(result) - return result - - return composed - - -class BalNonceChange(CamelModel, RLPSerializable): - """Represents a nonce change in the block access list.""" - - tx_index: HexNumber = Field( - HexNumber(1), - description="Transaction index where the change occurred", - ) - post_nonce: HexNumber = Field(..., description="Nonce value after the transaction") - - rlp_fields: ClassVar[List[str]] = ["tx_index", "post_nonce"] - - -class BalBalanceChange(CamelModel, RLPSerializable): - """Represents a balance change in the block access list.""" - - tx_index: HexNumber = Field( - HexNumber(1), - description="Transaction index where the change occurred", - ) - post_balance: HexNumber = Field(..., description="Balance after the transaction") - - rlp_fields: ClassVar[List[str]] = ["tx_index", "post_balance"] - - -class BalCodeChange(CamelModel, RLPSerializable): - """Represents a code change in the block access list.""" - - tx_index: HexNumber = Field( - HexNumber(1), - description="Transaction index where the change occurred", - ) - new_code: Bytes = Field(..., description="New code bytes") - - rlp_fields: ClassVar[List[str]] = ["tx_index", "new_code"] - - -class BalStorageChange(CamelModel, RLPSerializable): - """Represents a change to a specific storage slot.""" - - tx_index: HexNumber = Field( - HexNumber(1), - description="Transaction index where the change occurred", - ) - post_value: StorageKey = Field(..., description="Value after the transaction") - - rlp_fields: ClassVar[List[str]] = ["tx_index", "post_value"] - - -class BalStorageSlot(CamelModel, RLPSerializable): - """Represents all changes to a specific storage slot.""" - - slot: StorageKey = Field(..., description="Storage slot key") - slot_changes: List[BalStorageChange] = Field( - default_factory=list, description="List of changes to this slot" - ) - - rlp_fields: ClassVar[List[str]] = ["slot", "slot_changes"] - - -class BalAccountChange(CamelModel, RLPSerializable): - """Represents all changes to a specific account in a block.""" - - address: Address = Field(..., description="Account address") - nonce_changes: List[BalNonceChange] = Field( - default_factory=list, description="List of nonce changes" - ) - balance_changes: List[BalBalanceChange] = Field( - default_factory=list, description="List of balance changes" - ) - code_changes: List[BalCodeChange] = Field( - default_factory=list, description="List of code changes" - ) - storage_changes: List[BalStorageSlot] = Field( - default_factory=list, description="List of storage changes" - ) - storage_reads: List[StorageKey] = Field( - default_factory=list, description="List of storage slots that were read" - ) - - rlp_fields: ClassVar[List[str]] = [ - "address", - "storage_changes", - "storage_reads", - "balance_changes", - "nonce_changes", - "code_changes", - ] - - -BlockAccessListChangeLists = Union[ - List[BalNonceChange], - List[BalBalanceChange], - List[BalCodeChange], -] - - -class BlockAccessList(EthereumTestRootModel[List[BalAccountChange]]): - """ - Block Access List for t8n tool communication and fixtures. - - This model represents the BAL exactly as defined in EIP-7928 - it is itself a list - of account changes (root model), not a container. Used for: - - Communication with t8n tools - - Fixture generation - - RLP encoding for hash verification - - Example: - bal = BlockAccessList([ - BalAccountChange(address=alice, nonce_changes=[...]), - BalAccountChange(address=bob, balance_changes=[...]) - ]) - - """ - - root: List[BalAccountChange] = Field(default_factory=list) - - def to_list(self) -> List[Any]: - """Return the list for RLP encoding per EIP-7928.""" - return to_serializable_element(self.root) - - @cached_property - def rlp(self) -> Bytes: - """Return the RLP encoded block access list for hash verification.""" - return Bytes(eth_rlp.encode(self.to_list())) - - @cached_property - def rlp_hash(self) -> Bytes: - """Return the hash of the RLP encoded block access list.""" - return self.rlp.keccak256() - - -class BalAccountExpectation(CamelModel): - """ - Represents expected changes to a specific account in a block. - - Same as BalAccountChange but without the address field, used for expectations. - """ - - nonce_changes: List[BalNonceChange] = Field( - default_factory=list, description="List of expected nonce changes" - ) - balance_changes: List[BalBalanceChange] = Field( - default_factory=list, description="List of expected balance changes" - ) - code_changes: List[BalCodeChange] = Field( - default_factory=list, description="List of expected code changes" - ) - storage_changes: List[BalStorageSlot] = Field( - default_factory=list, description="List of expected storage changes" - ) - storage_reads: List[StorageKey] = Field( - default_factory=list, description="List of expected read storage slots" - ) - should_not_exist: List["AbsenceValidator"] = Field( - default_factory=list, description="List of validators checking for forbidden conditions" - ) - - -class BlockAccessListExpectation(CamelModel): - """ - Block Access List expectation model for test writing. - - This model is used to define expected BAL values in tests. It supports: - - Partial validation (only checks explicitly set fields) - - Convenient test syntax with named parameters - - Verification against actual BAL from t8n - - Explicit exclusion of addresses (using None values) - - Example: - # In test definition - expected_block_access_list = BlockAccessListExpectation( - account_expectations={ - alice: BalAccountExpectation( - nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)] - ), - bob: None, # Bob should NOT be in the BAL - } - ) - - """ - - model_config = CamelModel.model_config | {"extra": "forbid"} - - account_expectations: Dict[Address, BalAccountExpectation | None] = Field( - default_factory=dict, description="Expected account changes or exclusions to verify" - ) - - _modifier: Callable[["BlockAccessList"], "BlockAccessList"] | None = PrivateAttr(default=None) - - def modify( - self, *modifiers: Callable[["BlockAccessList"], "BlockAccessList"] - ) -> "BlockAccessListExpectation": - """ - Create a new expectation with a modifier for invalid test cases. - - Args: - modifiers: One or more functions that take and return a BlockAccessList - - Returns: - A new BlockAccessListExpectation instance with the modifiers applied - - Example: - from ethereum_test_types.block_access_list.modifiers import remove_nonces - - expectation = BlockAccessListExpectation( - account_expectations={...} - ).modify(remove_nonces(alice)) - - """ - new_instance = self.model_copy(deep=True) - new_instance._modifier = compose(*modifiers) - return new_instance - - def modify_if_invalid_test(self, t8n_bal: "BlockAccessList") -> "BlockAccessList": - """ - Apply the modifier to the given BAL if this is an invalid test case. - - Args: - t8n_bal: The BlockAccessList from t8n tool - - Returns: - The potentially transformed BlockAccessList for the fixture - - """ - if self._modifier: - return self._modifier(t8n_bal) - return t8n_bal - - def verify_against(self, actual_bal: "BlockAccessList") -> None: - """ - Verify that the actual BAL from the client matches this expected BAL. - - Validation steps: - 1. Validate actual BAL conforms to EIP-7928 ordering requirements - 2. Verify address expectations - presence or explicit absence - 3. Verify expected changes within accounts match actual changes - - Args: - actual_bal: The BlockAccessList model from the client - - Raises: - Exception: If verification fails - - """ - # validate the actual BAL structure follows EIP-7928 ordering - self._validate_bal_ordering(actual_bal) - - actual_accounts_by_addr = {acc.address: acc for acc in actual_bal.root} - for address, expectation in self.account_expectations.items(): - if expectation is None: - # check explicit exclusion of address when set to `None` - if address in actual_accounts_by_addr: - raise BlockAccessListValidationError( - f"Address {address} should not be in BAL but was found" - ) - else: - # check address is present and validate changes - if address not in actual_accounts_by_addr: - raise BlockAccessListValidationError( - f"Expected address {address} not found in actual BAL" - ) - - actual_account = actual_accounts_by_addr[address] - try: - self._compare_account_expectations(expectation, actual_account) - except AssertionError as e: - raise BlockAccessListValidationError(f"Account {address}: {str(e)}") from e - - @staticmethod - def _validate_bal_ordering(bal: "BlockAccessList") -> None: - """ - Validate that the actual BAL follows EIP-7928 ordering requirements. - - Per EIP-7928: - - Addresses must be in lexicographic (bytewise) order - - Storage keys must be in lexicographic order within each account - - Block access indices must be in ascending order within each change list - - Args: - bal: The BlockAccessList to validate - - Raises: - Exception: If BAL doesn't follow EIP-7928 ordering - - """ - addresses = [acc.address for acc in bal.root] - - # Check addresses are in lexicographic order - sorted_addresses = sorted(addresses, key=lambda x: bytes(x)) - if addresses != sorted_addresses: - raise BlockAccessListValidationError( - f"BAL addresses not in lexicographic order per EIP-7928. " - f"Got: {[str(a) for a in addresses]}, " - f"Expected: {[str(a) for a in sorted_addresses]}" - ) - - # Check ordering within each account - for account in bal.root: - # Check storage slots are in lexicographic order - if account.storage_changes: - slots = [s.slot for s in account.storage_changes] - sorted_slots = sorted(slots, key=lambda x: bytes(x)) - if slots != sorted_slots: - raise BlockAccessListValidationError( - f"Account {account.address}: Storage slots not in lexicographic order. " - f"Got: {slots}, Expected: {sorted_slots}" - ) - - # Check tx indices within each storage slot are in ascending order - for slot_change in account.storage_changes: - if slot_change.slot_changes: - tx_indices = [c.tx_index for c in slot_change.slot_changes] - if tx_indices != sorted(tx_indices): - raise BlockAccessListValidationError( - f"Account {account.address}, Slot {slot_change.slot}: " - f"tx_indices not in ascending order. Got: {tx_indices}" - ) - - # Check storage reads are in lexicographic order - if account.storage_reads: - sorted_reads = sorted(account.storage_reads, key=lambda x: bytes(x)) - if account.storage_reads != sorted_reads: - raise BlockAccessListValidationError( - f"Account {account.address}: Storage reads not in " - f"lexicographic order. Got: {account.storage_reads}, " - f"Expected: {sorted_reads}" - ) - - # Check tx indices in other change lists - changes_to_check: List[tuple[str, Union[BlockAccessListChangeLists]]] = [ - ("nonce_changes", account.nonce_changes), - ("balance_changes", account.balance_changes), - ("code_changes", account.code_changes), - ] - for field_name, changes in changes_to_check: - if changes: - tx_indices = [c.tx_index for c in changes] - if tx_indices != sorted(tx_indices): - raise BlockAccessListValidationError( - f"Account {account.address}: {field_name} tx_indices " - f"not in ascending order. Got: {tx_indices}" - ) - - def _compare_account_expectations( - self, expected: BalAccountExpectation, actual: BalAccountChange - ) -> None: - """ - Compare expected account changes with actual BAL account entry. - - Only validates fields that were explicitly set in the expected model, - using model_fields_set to determine what was intentionally specified. - """ - # Run absence validators first - if "should_not_exist" in expected.model_fields_set: - for validator in expected.should_not_exist: - validator(actual) - - change_fields = { - "nonce_changes", - "balance_changes", - "code_changes", - "storage_changes", - } - bal_fields = change_fields | {"storage_reads"} - - # Only check fields that were explicitly set in the expected model - for field_name in expected.model_fields_set.intersection(bal_fields): - expected_value = getattr(expected, field_name) - actual_value = getattr(actual, field_name) - - # empty list explicitly set (no changes expected) - if not expected_value: - if actual_value: - raise BlockAccessListValidationError( - f"Expected {field_name} to be empty but found: {actual_value}" - ) - continue - - if field_name == "storage_reads": - # EIP-7928: Storage reads must be in lexicographic order - # check as subsequence - expected_reads = [ - bytes(v) if hasattr(v, "__bytes__") else v for v in expected_value - ] - actual_reads = [bytes(v) if hasattr(v, "__bytes__") else v for v in actual_value] - - # Check that expected reads form a subsequence of actual reads - actual_idx = 0 - for exp_read in expected_reads: - found = False - while actual_idx < len(actual_reads): - if actual_reads[actual_idx] == exp_read: - found = True - actual_idx += 1 - break - actual_idx += 1 - - if not found: - exp_str = exp_read.hex() if isinstance(exp_read, bytes) else str(exp_read) - actual_str = [ - r.hex() if isinstance(r, bytes) else str(r) for r in actual_reads - ] - raise BlockAccessListValidationError( - f"Storage read {exp_str} not found or not in correct order. " - f"Actual reads: {actual_str}" - ) - - elif field_name in change_fields: - # For lists of changes, convert Pydantic models to dicts for - # comparison - expected_data = [item.model_dump() for item in expected_value] - actual_data = [item.model_dump() for item in actual_value] - self._validate_change_lists(field_name, expected_data, actual_data) - - @staticmethod - def _validate_change_lists(field_name: str, expected: List, actual: List) -> None: - """ - Validate that expected change lists form a subsequence of actual changes. - - Note: Ordering validation per EIP-7928 is already done in _validate_bal_ordering. - This method only checks that expected items appear in the actual list as a subsequence. - - Raises: - AssertionError: If expected changes are not found or not in correct order - - """ - if field_name == "storage_changes": - # Storage changes are nested (slot -> changes) - expected_slots = [slot["slot"] for slot in expected] - actual_slots = [slot["slot"] for slot in actual] - - # Check expected slots form a subsequence (ordering already validated) - actual_idx = 0 - for exp_slot in expected_slots: - found = False - while actual_idx < len(actual_slots): - if actual_slots[actual_idx] == exp_slot: - found = True - break - actual_idx += 1 - - if not found: - raise BlockAccessListValidationError( - f"Expected storage slot {exp_slot} not found or not in " - f"correct order. Actual slots: {actual_slots}" - ) - - # check changes within each slot - expected_by_slot = {slot["slot"]: slot["slot_changes"] for slot in expected} - actual_by_slot = {slot["slot"]: slot["slot_changes"] for slot in actual} - - for slot, exp_changes in expected_by_slot.items(): - if slot not in actual_by_slot: - raise BlockAccessListValidationError( - f"Expected storage slot {slot} not found in actual" - ) - - act_changes = actual_by_slot[slot] - - # Check that expected changes form a subsequence - exp_tuples = [ - ( - c["tx_index"], - bytes(c["post_value"]) - if hasattr(c["post_value"], "__bytes__") - else c["post_value"], - ) - for c in exp_changes - ] - act_tuples = [ - ( - c["tx_index"], - bytes(c["post_value"]) - if hasattr(c["post_value"], "__bytes__") - else c["post_value"], - ) - for c in act_changes - ] - - act_idx = 0 - for exp_tuple in exp_tuples: - found = False - while act_idx < len(act_tuples): - if act_tuples[act_idx] == exp_tuple: - found = True - act_idx += 1 - break - act_idx += 1 - - if not found: - raise BlockAccessListValidationError( - f"Slot {slot}: Expected change {exp_tuple} not found " - f"or not in correct order. Actual changes: {act_tuples}" - ) - - else: - # Create tuples for comparison (ordering already validated) - if field_name == "nonce_changes": - expected_tuples = [(c["tx_index"], c["post_nonce"]) for c in expected] - actual_tuples = [(c["tx_index"], c["post_nonce"]) for c in actual] - item_type = "nonce" - elif field_name == "balance_changes": - expected_tuples = [(c["tx_index"], int(c["post_balance"])) for c in expected] - actual_tuples = [(c["tx_index"], int(c["post_balance"])) for c in actual] - item_type = "balance" - elif field_name == "code_changes": - expected_tuples = [(c["tx_index"], bytes(c["new_code"])) for c in expected] - actual_tuples = [(c["tx_index"], bytes(c["new_code"])) for c in actual] - item_type = "code" - else: - # sanity check - raise ValueError(f"Unexpected field type: {field_name}") - - # Check that expected forms a subsequence of actual - actual_idx = 0 - for exp_tuple in expected_tuples: - found = False - while actual_idx < len(actual_tuples): - if actual_tuples[actual_idx] == exp_tuple: - found = True - actual_idx += 1 - break - actual_idx += 1 - - if not found: - raise BlockAccessListValidationError( - f"{item_type.capitalize()} change {exp_tuple} not found " - f"or not in correct order. Actual changes: {actual_tuples}" - ) - - -AbsenceValidator = Callable[[BalAccountChange], None] - +from .exceptions import BlockAccessListValidationError +from .expectations import ( + BalAccountExpectation, + BlockAccessListExpectation, + compose, +) +from .t8n import BlockAccessList __all__ = [ # Core models - "AbsenceValidator", "BlockAccessList", "BlockAccessListExpectation", "BalAccountExpectation", + "BalAccountAbsentValues", # Change types "BalAccountChange", "BalNonceChange", @@ -590,4 +36,8 @@ def _validate_change_lists(field_name: str, expected: List, actual: List) -> Non "BalCodeChange", "BalStorageChange", "BalStorageSlot", + # Utilities + "BlockAccessListChangeLists", + "BlockAccessListValidationError", + "compose", ] diff --git a/ethereum_test_types/block_access_list/absence_validators.py b/ethereum_test_types/block_access_list/absence_validators.py deleted file mode 100644 index 532f06a42c..0000000000 --- a/ethereum_test_types/block_access_list/absence_validators.py +++ /dev/null @@ -1,140 +0,0 @@ -""" -Absence validator functions for BAL testing. - -This module provides validator functions that check for the absence of specific -changes in Block Access Lists. These validators are used with the -``should_not_exist`` field in BalAccountExpectation to ensure certain changes -do *not* occur. - -All validator functions must be decorated with -``@validate_call(validate_return=True)`` to ensure proper type validation. -This is enforced via tests. -""" - -from typing import Set - -from pydantic import validate_call - -from ethereum_test_base_types import Number, StorageKey - -from . import AbsenceValidator, BalAccountChange - - -@validate_call(validate_return=True) -def no_nonce_changes(tx_indices: Set[Number] | None = None) -> AbsenceValidator: - """ - Forbid nonce changes at specified transaction indices or all indices if None. - - Args: - tx_indices: Set of transaction indices to check. If None, - checks all transactions. - - """ - - def check(account: BalAccountChange) -> None: - for nonce_change in account.nonce_changes: - if tx_indices is None or nonce_change.tx_index in tx_indices: - raise AssertionError( - f"Unexpected nonce change found at tx {nonce_change.tx_index}" - ) - - return check - - -@validate_call(validate_return=True) -def no_balance_changes(tx_indices: Set[Number] | None = None) -> AbsenceValidator: - """ - Forbid balance changes at specified transaction indices or all indices - if None. - - Args: - tx_indices: Set of transaction indices to check. If None, - checks all transactions. - - """ - - def check(account: BalAccountChange) -> None: - for balance_change in account.balance_changes: - if tx_indices is None or balance_change.tx_index in tx_indices: - raise AssertionError( - f"Unexpected balance change found at tx {balance_change.tx_index}" - ) - - return check - - -@validate_call(validate_return=True) -def no_storage_changes( - slots: Set[StorageKey] | None = None, - tx_indices: Set[Number] | None = None, -) -> AbsenceValidator: - """ - Forbid storage changes at specified slots and/or transaction indices. - - Args: - slots: Set of storage slots to check. If None, checks all slots. - tx_indices: Set of transaction indices to check. If None, - checks all transactions. - - """ - - def check(account: BalAccountChange) -> None: - for storage_slot in account.storage_changes: - if slots is None or storage_slot.slot in slots: - for slot_change in storage_slot.slot_changes: - if tx_indices is None or slot_change.tx_index in tx_indices: - raise AssertionError( - "Unexpected storage change found at slot " - f"{storage_slot.slot} in tx " - f"{slot_change.tx_index}" - ) - - return check - - -@validate_call(validate_return=True) -def no_storage_reads(slots: Set[StorageKey] | None = None) -> AbsenceValidator: - """ - Forbid storage reads at specified slots or all slots if None. - - Args: - slots: Set of storage slots to check. If None, checks all slots. - - """ - - def check(account: BalAccountChange) -> None: - for read_slot in account.storage_reads: - if slots is None or read_slot in slots: - raise AssertionError(f"Unexpected storage read found at slot {read_slot}") - - return check - - -@validate_call(validate_return=True) -def no_code_changes(tx_indices: Set[Number] | None = None) -> AbsenceValidator: - """ - Forbid code changes at specified transaction indices or all indices - if None. - - Args: - tx_indices: Set of transaction indices to check. If None, - checks all transactions. - - """ - - def check(account: BalAccountChange) -> None: - for code_change in account.code_changes: - if tx_indices is None or code_change.tx_index in tx_indices: - raise AssertionError(f"Unexpected code change found at tx {code_change.tx_index}") - - return check - - -__all__ = [ - "AbsenceValidator", - "no_nonce_changes", - "no_balance_changes", - "no_storage_changes", - "no_storage_reads", - "no_code_changes", -] diff --git a/ethereum_test_types/block_access_list/account_absent_values.py b/ethereum_test_types/block_access_list/account_absent_values.py new file mode 100644 index 0000000000..7bf3fd2213 --- /dev/null +++ b/ethereum_test_types/block_access_list/account_absent_values.py @@ -0,0 +1,211 @@ +""" +BalAccountAbsentValues class for BAL testing. + +This module provides a unified class for specifying explicit absent values in Block Access Lists. +This class uses the same change classes as BalAccountChanges to specify specific values that +should NOT exist in the BAL. For checking complete absence, use BalAccountExpectation +with empty lists instead. +""" + +from typing import List + +from pydantic import Field, model_validator + +from ethereum_test_base_types import CamelModel, StorageKey + +from .account_changes import ( + BalAccountChange, + BalBalanceChange, + BalCodeChange, + BalNonceChange, + BalStorageSlot, +) +from .exceptions import BlockAccessListValidationError + +EMPTY_LIST_ERROR_MSG = ( + "Empty lists are not allowed. This would mean 'check for any change' and " + "is bad practice. Instead, use the `BalAccountExpectation` to define " + "explicit, expected changes." +) + + +class BalAccountAbsentValues(CamelModel): + """ + Represents explicit absent value expectations for a specific account in a block. + + This class specifies specific changes that should NOT exist in the BAL for a + given account. + + IMPORTANT: This class is for checking that specific values are absent, NOT for + checking that entire categories are empty. For complete absence checks + (e.g., "no nonce changes at all"), use BalAccountExpectation with empty lists + instead. + + The validation works by checking that none of the specified explicit changes + exist in the actual BAL. + + Example: + # Forbid specific nonce change at tx 1 with post_nonce=5, and specific + # storage change + absent_values = BalAccountAbsentValues( + nonce_changes=[ + # Forbid exact nonce change at this tx + BalNonceChange(tx_index=1, post_nonce=5), + ], + storage_changes=[ + BalStorageSlot( + slot=0x42, + slot_changes=[ + # Forbid exact storage change at this slot and tx + BalStorageChange(tx_index=2, post_value=0x99) + ], + ) + ], + ) + + For checking complete absence: + # Use BalAccountExpectation with empty lists instead + expectation = BalAccountExpectation( + nonce_changes=[], # Expect NO nonce changes at all + storage_changes=[], # Expect NO storage changes at all + ) + + """ + + nonce_changes: List[BalNonceChange] = Field( + default_factory=list, + description="List of nonce changes that should NOT exist in the BAL. " + "Validates that none of these changes are present.", + ) + balance_changes: List[BalBalanceChange] = Field( + default_factory=list, + description="List of balance changes that should NOT exist in the BAL. " + "Validates that none of these changes are present.", + ) + code_changes: List[BalCodeChange] = Field( + default_factory=list, + description="List of code changes that should NOT exist in the BAL. " + "Validates that none of these changes are present.", + ) + storage_changes: List[BalStorageSlot] = Field( + default_factory=list, + description="List of storage slots/changes that should NOT exist in the BAL. " + "Validates that none of these changes are present.", + ) + storage_reads: List[StorageKey] = Field( + default_factory=list, + description="List of storage slots that should NOT be read.", + ) + + @model_validator(mode="after") + def validate_specific_absences_only(self) -> "BalAccountAbsentValues": + """Ensure absence fields contain specific values, not empty checks.""" + # at least one field must have content + if not any( + [ + self.nonce_changes, + self.balance_changes, + self.code_changes, + self.storage_changes, + self.storage_reads, + ] + ): + raise ValueError( + "At least one absence field must be specified. " + "`BalAccountAbsentValues` is for checking specific forbidden values. " + f"{EMPTY_LIST_ERROR_MSG}" + ) + + # check that no fields are explicitly set to empty lists + field_checks = [ + ("nonce_changes", self.nonce_changes), + ("balance_changes", self.balance_changes), + ("code_changes", self.code_changes), + ("storage_changes", self.storage_changes), + ("storage_reads", self.storage_reads), + ] + + for field_name, field_value in field_checks: + if field_name in self.model_fields_set and field_value == []: + raise ValueError( + f"`BalAccountAbsentValues.{field_name}` cannot be an empty list. " + f"{EMPTY_LIST_ERROR_MSG}" + ) + + # validate that storage_changes don't have empty slot_changes + for storage_slot in self.storage_changes: + if not storage_slot.slot_changes: + raise ValueError( + f"`BalAccountAbsentValues.storage_changes[{storage_slot.slot}].slot_changes` " + f"cannot be an empty list. {EMPTY_LIST_ERROR_MSG}" + ) + + return self + + @staticmethod + def _validate_forbidden_changes( + actual_changes: List, + forbidden_changes: List, + match_fn, + error_msg_fn, + ) -> None: + for actual in actual_changes: + for forbidden in forbidden_changes: + if match_fn(actual, forbidden): + raise BlockAccessListValidationError(error_msg_fn(actual)) + + def validate_against(self, account: BalAccountChange) -> None: + """ + Validate that the account does not contain the forbidden changes specified in + this object. + + Args: + account: The BalAccountChange to validate against + + Raises: + BlockAccessListValidationError: If any forbidden changes are found + + """ + self._validate_forbidden_changes( + account.nonce_changes, + self.nonce_changes, + lambda a, f: a.tx_index == f.tx_index and a.post_nonce == f.post_nonce, + lambda a: f"Unexpected nonce change found at tx {a.tx_index}", + ) + self._validate_forbidden_changes( + account.balance_changes, + self.balance_changes, + lambda a, f: a.tx_index == f.tx_index and a.post_balance == f.post_balance, + lambda a: f"Unexpected balance change found at tx {a.tx_index}", + ) + self._validate_forbidden_changes( + account.code_changes, + self.code_changes, + lambda a, f: a.tx_index == f.tx_index and a.new_code == f.new_code, + lambda a: f"Unexpected code change found at tx {a.tx_index}", + ) + + for forbidden_storage_slot in self.storage_changes: + for actual_storage_slot in account.storage_changes: + if actual_storage_slot.slot == forbidden_storage_slot.slot: + slot_id = actual_storage_slot.slot + self._validate_forbidden_changes( + actual_storage_slot.slot_changes, + forbidden_storage_slot.slot_changes, + lambda a, f: (a.tx_index == f.tx_index and a.post_value == f.post_value), + lambda a, slot=slot_id: ( + f"Unexpected storage change found at slot {slot} in tx {a.tx_index}" + ), + ) + + for forbidden_read in self.storage_reads: + for actual_read in account.storage_reads: + if actual_read == forbidden_read: + raise BlockAccessListValidationError( + f"Unexpected storage read found at slot {actual_read}" + ) + + +__all__ = [ + "BalAccountAbsentValues", +] diff --git a/ethereum_test_types/block_access_list/account_changes.py b/ethereum_test_types/block_access_list/account_changes.py new file mode 100644 index 0000000000..5edb0b9fc5 --- /dev/null +++ b/ethereum_test_types/block_access_list/account_changes.py @@ -0,0 +1,126 @@ +""" +Account change classes for Block Access List. + +This module contains the core data structures representing changes to accounts +in a block access list as defined in EIP-7928. +""" + +from typing import ClassVar, List, Union + +from pydantic import Field + +from ethereum_test_base_types import ( + Address, + Bytes, + CamelModel, + HexNumber, + RLPSerializable, + StorageKey, +) + + +class BalNonceChange(CamelModel, RLPSerializable): + """Represents a nonce change in the block access list.""" + + tx_index: HexNumber = Field( + HexNumber(1), + description="Transaction index where the change occurred", + ) + post_nonce: HexNumber = Field(..., description="Nonce value after the transaction") + + rlp_fields: ClassVar[List[str]] = ["tx_index", "post_nonce"] + + +class BalBalanceChange(CamelModel, RLPSerializable): + """Represents a balance change in the block access list.""" + + tx_index: HexNumber = Field( + HexNumber(1), + description="Transaction index where the change occurred", + ) + post_balance: HexNumber = Field(..., description="Balance after the transaction") + + rlp_fields: ClassVar[List[str]] = ["tx_index", "post_balance"] + + +class BalCodeChange(CamelModel, RLPSerializable): + """Represents a code change in the block access list.""" + + tx_index: HexNumber = Field( + HexNumber(1), + description="Transaction index where the change occurred", + ) + new_code: Bytes = Field(..., description="New code bytes") + + rlp_fields: ClassVar[List[str]] = ["tx_index", "new_code"] + + +class BalStorageChange(CamelModel, RLPSerializable): + """Represents a change to a specific storage slot.""" + + tx_index: HexNumber = Field( + HexNumber(1), + description="Transaction index where the change occurred", + ) + post_value: StorageKey = Field(..., description="Value after the transaction") + + rlp_fields: ClassVar[List[str]] = ["tx_index", "post_value"] + + +class BalStorageSlot(CamelModel, RLPSerializable): + """Represents all changes to a specific storage slot.""" + + slot: StorageKey = Field(..., description="Storage slot key") + slot_changes: List[BalStorageChange] = Field( + default_factory=list, description="List of changes to this slot" + ) + + rlp_fields: ClassVar[List[str]] = ["slot", "slot_changes"] + + +class BalAccountChange(CamelModel, RLPSerializable): + """Represents all changes to a specific account in a block.""" + + address: Address = Field(..., description="Account address") + nonce_changes: List[BalNonceChange] = Field( + default_factory=list, description="List of nonce changes" + ) + balance_changes: List[BalBalanceChange] = Field( + default_factory=list, description="List of balance changes" + ) + code_changes: List[BalCodeChange] = Field( + default_factory=list, description="List of code changes" + ) + storage_changes: List[BalStorageSlot] = Field( + default_factory=list, description="List of storage changes" + ) + storage_reads: List[StorageKey] = Field( + default_factory=list, description="List of storage slots that were read" + ) + + rlp_fields: ClassVar[List[str]] = [ + "address", + "storage_changes", + "storage_reads", + "balance_changes", + "nonce_changes", + "code_changes", + ] + + +BlockAccessListChangeLists = Union[ + List[BalNonceChange], + List[BalBalanceChange], + List[BalCodeChange], +] + + +__all__ = [ + "BalNonceChange", + "BalBalanceChange", + "BalCodeChange", + "BalStorageChange", + "BalStorageSlot", + "BalAccountChange", + "BlockAccessListChangeLists", +] diff --git a/ethereum_test_types/block_access_list/exceptions.py b/ethereum_test_types/block_access_list/exceptions.py new file mode 100644 index 0000000000..8a26cfef85 --- /dev/null +++ b/ethereum_test_types/block_access_list/exceptions.py @@ -0,0 +1,7 @@ +"""Exceptions related to block access list validation.""" + + +class BlockAccessListValidationError(Exception): + """Custom exception for Block Access List validation errors.""" + + pass diff --git a/ethereum_test_types/block_access_list/expectations.py b/ethereum_test_types/block_access_list/expectations.py new file mode 100644 index 0000000000..ffa213bd51 --- /dev/null +++ b/ethereum_test_types/block_access_list/expectations.py @@ -0,0 +1,398 @@ +""" +Block Access List expectation classes for test validation. + +This module contains classes for defining and validating expected BAL values in tests. +""" + +from typing import Any, Callable, Dict, List, Optional + +from pydantic import Field, PrivateAttr + +from ethereum_test_base_types import Address, CamelModel, StorageKey + +from .account_absent_values import BalAccountAbsentValues +from .account_changes import ( + BalAccountChange, + BalBalanceChange, + BalCodeChange, + BalNonceChange, + BalStorageSlot, + BlockAccessListChangeLists, +) +from .exceptions import BlockAccessListValidationError +from .t8n import BlockAccessList + + +class BalAccountExpectation(CamelModel): + """ + Represents expected changes to a specific account in a block. + + Same as BalAccountChange but without the address field, used for expectations. + """ + + nonce_changes: List[BalNonceChange] = Field( + default_factory=list, description="List of expected nonce changes" + ) + balance_changes: List[BalBalanceChange] = Field( + default_factory=list, description="List of expected balance changes" + ) + code_changes: List[BalCodeChange] = Field( + default_factory=list, description="List of expected code changes" + ) + storage_changes: List[BalStorageSlot] = Field( + default_factory=list, description="List of expected storage changes" + ) + storage_reads: List[StorageKey] = Field( + default_factory=list, description="List of expected read storage slots" + ) + absent_values: Optional[BalAccountAbsentValues] = Field( + default=None, description="Explicit absent value expectations using BalAccountAbsentValues" + ) + + +def compose( + *modifiers: Callable[["BlockAccessList"], "BlockAccessList"], +) -> Callable[["BlockAccessList"], "BlockAccessList"]: + """Compose multiple modifiers into a single modifier.""" + + def composed(bal: BlockAccessList) -> BlockAccessList: + result = bal + for modifier in modifiers: + result = modifier(result) + return result + + return composed + + +class BlockAccessListExpectation(CamelModel): + """ + Block Access List expectation model for test writing. + + This model is used to define expected BAL values in tests. It supports: + - Partial validation (only checks explicitly set fields) + - Convenient test syntax with named parameters + - Verification against actual BAL from t8n + - Explicit exclusion of addresses (using None values) + + Example: + # In test definition + expected_block_access_list = BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)] + ), + bob: None, # Bob should NOT be in the BAL + } + ) + + """ + + model_config = CamelModel.model_config | {"extra": "forbid"} + + account_expectations: Dict[Address, BalAccountExpectation | None] = Field( + default_factory=dict, description="Expected account changes or exclusions to verify" + ) + + _modifier: Callable[["BlockAccessList"], "BlockAccessList"] | None = PrivateAttr(default=None) + + def modify( + self, *modifiers: Callable[["BlockAccessList"], "BlockAccessList"] + ) -> "BlockAccessListExpectation": + """ + Create a new expectation with a modifier for invalid test cases. + + Args: + modifiers: One or more functions that take and return a BlockAccessList + + Returns: + A new BlockAccessListExpectation instance with the modifiers applied + + Example: + from ethereum_test_types.block_access_list.modifiers import remove_nonces + + expectation = BlockAccessListExpectation( + account_expectations={...} + ).modify(remove_nonces(alice)) + + """ + new_instance = self.model_copy(deep=True) + new_instance._modifier = compose(*modifiers) + return new_instance + + def modify_if_invalid_test(self, t8n_bal: "BlockAccessList") -> "BlockAccessList": + """ + Apply the modifier to the given BAL if this is an invalid test case. + + Args: + t8n_bal: The BlockAccessList from t8n tool + + Returns: + The potentially transformed BlockAccessList for the fixture + + """ + if self._modifier: + return self._modifier(t8n_bal) + return t8n_bal + + def verify_against(self, actual_bal: "BlockAccessList") -> None: + """ + Verify that the actual BAL from the client matches this expected BAL. + + Validation steps: + 1. Validate actual BAL conforms to EIP-7928 ordering requirements + 2. Verify address expectations - presence or explicit absence + 3. Verify expected changes within accounts match actual changes + + Args: + actual_bal: The BlockAccessList model from the client + + Raises: + BlockAccessListValidationError: If verification fails + + """ + # validate the actual BAL structure follows EIP-7928 ordering + self._validate_bal_ordering(actual_bal) + + actual_accounts_by_addr = {acc.address: acc for acc in actual_bal.root} + for address, expectation in self.account_expectations.items(): + if expectation is None: + # check explicit exclusion of address when set to `None` + if address in actual_accounts_by_addr: + raise BlockAccessListValidationError( + f"Address {address} should not be in BAL but was found" + ) + else: + # check address is present and validate changes + if address not in actual_accounts_by_addr: + raise BlockAccessListValidationError( + f"Expected address {address} not found in actual BAL" + ) + + actual_account = actual_accounts_by_addr[address] + try: + self._compare_account_expectations(expectation, actual_account) + except AssertionError as e: + raise BlockAccessListValidationError(f"Account {address}: {str(e)}") from e + + @staticmethod + def _validate_bal_ordering(bal: "BlockAccessList") -> None: + """ + Validate BAL ordering follows EIP-7928 requirements. + + Args: + bal: The BlockAccessList to validate + + Raises: + BlockAccessListValidationError: If ordering is invalid + + """ + # Check address ordering (ascending) + for i in range(1, len(bal.root)): + if bal.root[i - 1].address >= bal.root[i].address: + raise BlockAccessListValidationError( + f"BAL addresses are not in lexicographic order: " + f"{bal.root[i - 1].address} >= {bal.root[i].address}" + ) + + # Check transaction index ordering within accounts + for account in bal.root: + change_lists: List[BlockAccessListChangeLists] = [ + account.nonce_changes, + account.balance_changes, + account.code_changes, + ] + for change_list in change_lists: + for i in range(1, len(change_list)): + if change_list[i - 1].tx_index >= change_list[i].tx_index: + raise BlockAccessListValidationError( + f"Transaction indices not in ascending order in account " + f"{account.address}: {change_list[i - 1].tx_index} >= " + f"{change_list[i].tx_index}" + ) + + # Check storage slot ordering + for i in range(1, len(account.storage_changes)): + if account.storage_changes[i - 1].slot >= account.storage_changes[i].slot: + raise BlockAccessListValidationError( + f"Storage slots not in ascending order in account " + f"{account.address}: {account.storage_changes[i - 1].slot} >= " + f"{account.storage_changes[i].slot}" + ) + + # Check transaction index ordering within storage slots + for storage_slot in account.storage_changes: + for i in range(1, len(storage_slot.slot_changes)): + if ( + storage_slot.slot_changes[i - 1].tx_index + >= storage_slot.slot_changes[i].tx_index + ): + raise BlockAccessListValidationError( + f"Transaction indices not in ascending order in storage slot " + f"{storage_slot.slot} of account {account.address}: " + f"{storage_slot.slot_changes[i - 1].tx_index} >= " + f"{storage_slot.slot_changes[i].tx_index}" + ) + + # Check storage reads ordering + for i in range(1, len(account.storage_reads)): + if account.storage_reads[i - 1] >= account.storage_reads[i]: + raise BlockAccessListValidationError( + f"Storage reads not in ascending order in account " + f"{account.address}: {account.storage_reads[i - 1]} >= " + f"{account.storage_reads[i]}" + ) + + @staticmethod + def _compare_account_expectations( + expected: BalAccountExpectation, actual: BalAccountChange + ) -> None: + """ + Compare expected and actual account changes using subsequence validation. + + Args: + expected: The expected account changes + actual: The actual account changes from the BAL + + Raises: + AssertionError: If validation fails + + """ + # Check absence expectations first if defined + if expected.absent_values is not None: + expected.absent_values.validate_against(actual) + + # Validate expected changes using subsequence validation + field_pairs: List[tuple[str, Any, Any]] = [ + ("nonce_changes", expected.nonce_changes, actual.nonce_changes), + ("balance_changes", expected.balance_changes, actual.balance_changes), + ("code_changes", expected.code_changes, actual.code_changes), + ("storage_changes", expected.storage_changes, actual.storage_changes), + ("storage_reads", expected.storage_reads, actual.storage_reads), + ] + + for field_name, expected_list, actual_list in field_pairs: + # Only validate fields that were explicitly set + if field_name not in expected.model_fields_set: + continue + + if field_name == "storage_reads": + # storage_reads is a simple list of StorageKey + actual_idx = 0 + for expected_read in expected_list: + found = False + while actual_idx < len(actual_list): + if actual_list[actual_idx] == expected_read: + found = True + actual_idx += 1 + break + actual_idx += 1 + + if not found: + raise AssertionError( + f"Storage read {expected_read} not found or not in correct order. " + f"Actual reads: {actual_list}" + ) + + elif field_name == "storage_changes": + # storage_changes is a list of BalStorageSlot + actual_idx = 0 + for expected_slot in expected_list: + found = False + while actual_idx < len(actual_list): + if actual_list[actual_idx].slot == expected_slot.slot: + # Found matching slot, now validate slot_changes + actual_slot_changes = actual_list[actual_idx].slot_changes + expected_slot_changes = expected_slot.slot_changes + + if not expected_slot_changes: + # Empty expected means any slot_changes are acceptable + pass + else: + # Validate slot_changes as subsequence + slot_actual_idx = 0 + for expected_change in expected_slot_changes: + slot_found = False + while slot_actual_idx < len(actual_slot_changes): + actual_change = actual_slot_changes[slot_actual_idx] + if ( + actual_change.tx_index == expected_change.tx_index + and actual_change.post_value + == expected_change.post_value + ): + slot_found = True + slot_actual_idx += 1 + break + slot_actual_idx += 1 + + if not slot_found: + raise AssertionError( + f"Storage change {expected_change} not found " + f"or not in correct order in slot " + f"{expected_slot.slot}. " + f"Actual slot changes: {actual_slot_changes}" + ) + + found = True + actual_idx += 1 + break + actual_idx += 1 + + if not found: + raise AssertionError( + f"Storage slot {expected_slot.slot} not found " + f"or not in correct order. Actual slots: " + f"{[s.slot for s in actual_list]}" + ) + + else: + # Handle nonce_changes, balance_changes, code_changes + if not expected_list and actual_list: + # Empty expected but non-empty actual - error + item_type = field_name.replace("_changes", "") + raise AssertionError( + f"Expected {field_name} to be empty but found {actual_list}" + ) + + else: + # Create tuples for comparison (ordering already validated) + if field_name == "nonce_changes": + expected_tuples = [(c.tx_index, c.post_nonce) for c in expected_list] + actual_tuples = [(c.tx_index, c.post_nonce) for c in actual_list] + item_type = "nonce" + elif field_name == "balance_changes": + expected_tuples = [ + (c.tx_index, int(c.post_balance)) for c in expected_list + ] + actual_tuples = [(c.tx_index, int(c.post_balance)) for c in actual_list] + item_type = "balance" + elif field_name == "code_changes": + expected_tuples = [(c.tx_index, bytes(c.new_code)) for c in expected_list] + actual_tuples = [(c.tx_index, bytes(c.new_code)) for c in actual_list] + item_type = "code" + else: + # sanity check + raise ValueError(f"Unexpected field type: {field_name}") + + # Check that expected forms a subsequence of actual + actual_idx = 0 + for exp_tuple in expected_tuples: + found = False + while actual_idx < len(actual_tuples): + if actual_tuples[actual_idx] == exp_tuple: + found = True + actual_idx += 1 + break + actual_idx += 1 + + if not found: + raise AssertionError( + f"{item_type.capitalize()} change {exp_tuple} not found " + f"or not in correct order. Actual changes: {actual_tuples}" + ) + + +__all__ = [ + "BalAccountExpectation", + "BlockAccessListExpectation", + "compose", +] diff --git a/ethereum_test_types/block_access_list/t8n.py b/ethereum_test_types/block_access_list/t8n.py new file mode 100644 index 0000000000..808ace06f5 --- /dev/null +++ b/ethereum_test_types/block_access_list/t8n.py @@ -0,0 +1,47 @@ +"""Block Access List (BAL) for t8n tool communication and fixtures.""" + +from functools import cached_property +from typing import Any, List + +import ethereum_rlp as eth_rlp +from pydantic import Field + +from ethereum_test_base_types import Bytes, EthereumTestRootModel +from ethereum_test_base_types.serialization import to_serializable_element + +from .account_changes import BalAccountChange + + +class BlockAccessList(EthereumTestRootModel[List[BalAccountChange]]): + """ + Block Access List for t8n tool communication and fixtures. + + This model represents the BAL exactly as defined in EIP-7928 - it is itself a list + of account changes (root model), not a container. Used for: + - Communication with t8n tools + - Fixture generation + - RLP encoding for hash verification + + Example: + bal = BlockAccessList([ + BalAccountChange(address=alice, nonce_changes=[...]), + BalAccountChange(address=bob, balance_changes=[...]) + ]) + + """ + + root: List[BalAccountChange] = Field(default_factory=list) + + def to_list(self) -> List[Any]: + """Return the list for RLP encoding per EIP-7928.""" + return to_serializable_element(self.root) + + @cached_property + def rlp(self) -> Bytes: + """Return the RLP encoded block access list for hash verification.""" + return Bytes(eth_rlp.encode(self.to_list())) + + @cached_property + def rlp_hash(self) -> Bytes: + """Return the hash of the RLP encoded block access list.""" + return self.rlp.keccak256() diff --git a/ethereum_test_types/tests/test_block_access_lists.py b/ethereum_test_types/tests/test_block_access_lists.py index 4406d413b8..e8a36d7321 100644 --- a/ethereum_test_types/tests/test_block_access_lists.py +++ b/ethereum_test_types/tests/test_block_access_lists.py @@ -4,6 +4,7 @@ from ethereum_test_base_types import Address, StorageKey from ethereum_test_types.block_access_list import ( + BalAccountAbsentValues, BalAccountChange, BalAccountExpectation, BalBalanceChange, @@ -14,14 +15,6 @@ BlockAccessList, BlockAccessListExpectation, BlockAccessListValidationError, - absence_validators, -) -from ethereum_test_types.block_access_list.absence_validators import ( - no_balance_changes, - no_code_changes, - no_nonce_changes, - no_storage_changes, - no_storage_reads, ) @@ -231,7 +224,7 @@ def test_missing_expected_address(): Address(0xB), Address(0xA), # should come first ], - "BAL addresses not in lexicographic order per EIP-7928", + "BAL addresses are not in lexicographic order", ), ( [ @@ -239,7 +232,7 @@ def test_missing_expected_address(): Address(0x3), Address(0x2), ], - "BAL addresses not in lexicographic order per EIP-7928", + "BAL addresses are not in lexicographic order", ), ], ) @@ -261,11 +254,11 @@ def test_actual_bal_address_ordering_validation(addresses, error_message): [ ( [StorageKey(0x02), StorageKey(0x01)], # 0x02 before 0x01 - "Storage slots not in lexicographic order", + "Storage slots not in ascending order", ), ( [StorageKey(0x01), StorageKey(0x03), StorageKey(0x02)], - "Storage slots not in lexicographic order", + "Storage slots not in ascending order", ), ], ) @@ -293,10 +286,10 @@ def test_actual_bal_storage_slot_ordering(storage_slots, error_message): @pytest.mark.parametrize( "storage_reads,error_message", [ - ([StorageKey(0x02), StorageKey(0x01)], "Storage reads not in lexicographic order"), + ([StorageKey(0x02), StorageKey(0x01)], "Storage reads not in ascending order"), ( [StorageKey(0x01), StorageKey(0x03), StorageKey(0x02)], - "Storage reads not in lexicographic order", + "Storage reads not in ascending order", ), ], ) @@ -336,7 +329,7 @@ def test_actual_bal_tx_indices_ordering(field_name): with pytest.raises( BlockAccessListValidationError, - match="tx_indices not in ascending order", + match="Transaction indices not in ascending order", ): expectation.verify_against(actual_bal) @@ -521,7 +514,7 @@ def test_expected_tx_indices_ordering(expected_tx_indices, should_pass): @pytest.mark.parametrize("has_change_should_raise", [True, False]) -def test_absence_validator_nonce_changes(has_change_should_raise): +def test_absent_values_nonce_changes(has_change_should_raise): """Test nonce_changes_at_tx validator with present/absent changes.""" alice = Address(0xA) @@ -542,7 +535,11 @@ def test_absence_validator_nonce_changes(has_change_should_raise): expectation = BlockAccessListExpectation( account_expectations={ # no nonce changes at tx 2 - alice: BalAccountExpectation(should_not_exist=[no_nonce_changes({2})]) + alice: BalAccountExpectation( + absent_values=BalAccountAbsentValues( + nonce_changes=[BalNonceChange(tx_index=2, post_nonce=2)] + ) + ) } ) @@ -554,7 +551,7 @@ def test_absence_validator_nonce_changes(has_change_should_raise): @pytest.mark.parametrize("has_change_should_raise", [True, False]) -def test_absence_validator_balance_changes(has_change_should_raise): +def test_absent_values_balance_changes(has_change_should_raise): """Test balance_changes_at_tx validator with present/absent changes.""" alice = Address(0xA) @@ -575,7 +572,9 @@ def test_absence_validator_balance_changes(has_change_should_raise): expectation = BlockAccessListExpectation( account_expectations={ alice: BalAccountExpectation( - should_not_exist=[no_balance_changes({2})], + absent_values=BalAccountAbsentValues( + balance_changes=[BalBalanceChange(tx_index=2, post_balance=200)] + ) ), } ) @@ -591,7 +590,7 @@ def test_absence_validator_balance_changes(has_change_should_raise): @pytest.mark.parametrize("has_change_should_raise", [True, False]) -def test_absence_validator_storage_changes(has_change_should_raise): +def test_absent_values_storage_changes(has_change_should_raise): """Test storage_changes_at_slots validator with present/absent changes.""" contract = Address(0xC) @@ -621,7 +620,16 @@ def test_absence_validator_storage_changes(has_change_should_raise): expectation = BlockAccessListExpectation( account_expectations={ # no storage changes at slot 0x42 - contract: BalAccountExpectation(should_not_exist=[no_storage_changes(slots={0x42})]), + contract: BalAccountExpectation( + absent_values=BalAccountAbsentValues( + storage_changes=[ + BalStorageSlot( + slot=0x42, + slot_changes=[BalStorageChange(tx_index=1, post_value=0xBEEF)], + ) + ] + ) + ), } ) @@ -633,7 +641,7 @@ def test_absence_validator_storage_changes(has_change_should_raise): @pytest.mark.parametrize("has_read_should_raise", [True, False]) -def test_absence_validator_storage_reads(has_read_should_raise): +def test_absent_values_storage_reads(has_read_should_raise): """Test storage_reads_at_slots validator with present/absent reads.""" contract = Address(0xC) @@ -654,7 +662,9 @@ def test_absence_validator_storage_reads(has_read_should_raise): expectation = BlockAccessListExpectation( account_expectations={ # no storage reads at slot 0x42 - contract: BalAccountExpectation(should_not_exist=[no_storage_reads({0x42})]), + contract: BalAccountExpectation( + absent_values=BalAccountAbsentValues(storage_reads=[StorageKey(0x42)]) + ), } ) @@ -666,7 +676,7 @@ def test_absence_validator_storage_reads(has_read_should_raise): @pytest.mark.parametrize("has_change_should_raise", [True, False]) -def test_absence_validator_code_changes(has_change_should_raise): +def test_absent_values_code_changes(has_change_should_raise): """Test code_changes_at_tx validator with present/absent changes.""" alice = Address(0xA) @@ -687,7 +697,11 @@ def test_absence_validator_code_changes(has_change_should_raise): expectation = BlockAccessListExpectation( account_expectations={ # no code changes at tx 2 - alice: BalAccountExpectation(should_not_exist=[no_code_changes({2})]), + alice: BalAccountExpectation( + absent_values=BalAccountAbsentValues( + code_changes=[BalCodeChange(tx_index=2, new_code=b"\x60\x00")] + ) + ), } ) @@ -698,7 +712,7 @@ def test_absence_validator_code_changes(has_change_should_raise): expectation.verify_against(actual_bal) -def test_multiple_absence_validators(): +def test_multiple_absent_valuess(): """Test multiple absence validators working together.""" contract = Address(0xC) @@ -730,13 +744,29 @@ def test_multiple_absence_validators(): slot_changes=[BalStorageChange(tx_index=1, post_value=0x99)], ) ], - should_not_exist=[ - no_nonce_changes({1, 2}), # No nonce changes at tx 1 or 2 - no_balance_changes({1, 2}), # No balance changes at tx 1 or 2 - no_storage_changes(slots={0x42, 0x43}), # These slots not changed - no_storage_reads({0x42, 0x43}), # These slots not read - no_code_changes({1, 2}), # No code changes at tx 1 or 2 - ], + absent_values=BalAccountAbsentValues( + nonce_changes=[ + BalNonceChange(tx_index=1, post_nonce=0), + BalNonceChange(tx_index=2, post_nonce=0), + ], + balance_changes=[ + BalBalanceChange(tx_index=1, post_balance=0), + BalBalanceChange(tx_index=2, post_balance=0), + ], + storage_changes=[ + BalStorageSlot( + slot=0x42, slot_changes=[BalStorageChange(tx_index=1, post_value=0)] + ), + BalStorageSlot( + slot=0x43, slot_changes=[BalStorageChange(tx_index=1, post_value=0)] + ), + ], + storage_reads=[StorageKey(0x42), StorageKey(0x43)], + code_changes=[ + BalCodeChange(tx_index=1, new_code=b""), + BalCodeChange(tx_index=2, new_code=b""), + ], + ), ), } ) @@ -744,7 +774,7 @@ def test_multiple_absence_validators(): expectation.verify_against(actual_bal) -def test_absence_validator_with_multiple_tx_indices(): +def test_absent_values_with_multiple_tx_indices(): """Test absence validators with multiple transaction indices.""" alice = Address(0xA) @@ -768,10 +798,12 @@ def test_absence_validator_with_multiple_tx_indices(): BalNonceChange(tx_index=1, post_nonce=1), BalNonceChange(tx_index=3, post_nonce=2), ], - should_not_exist=[ - # should not be changes at tx 2 and 4 - no_nonce_changes({2, 4}), - ], + absent_values=BalAccountAbsentValues( + nonce_changes=[ + BalNonceChange(tx_index=2, post_nonce=0), + BalNonceChange(tx_index=4, post_nonce=0), + ] + ), ), } ) @@ -781,10 +813,13 @@ def test_absence_validator_with_multiple_tx_indices(): expectation_fail = BlockAccessListExpectation( account_expectations={ alice: BalAccountExpectation( - should_not_exist=[ - # wrongly forbid change at txs 1 and 2 (1 exists, so should fail) - no_nonce_changes({1, 2}), - ], + absent_values=BalAccountAbsentValues( + nonce_changes=[ + # wrongly forbid change at txs 1 and 2 (1 exists, so should fail) + BalNonceChange(tx_index=1, post_nonce=1), + BalNonceChange(tx_index=2, post_nonce=0), + ] + ), ), } ) @@ -793,69 +828,152 @@ def test_absence_validator_with_multiple_tx_indices(): expectation_fail.verify_against(actual_bal) -@pytest.mark.parametrize( - "validator_func,field_name,changes,error_pattern", - [ - ( - no_nonce_changes(), - "nonce_changes", - [BalNonceChange(tx_index=1, post_nonce=1)], - "Unexpected nonce change found at tx", - ), - ( - no_balance_changes(), - "balance_changes", - [BalBalanceChange(tx_index=2, post_balance=100)], - "Unexpected balance change found at tx", - ), - ( - no_code_changes(), - "code_changes", - [BalCodeChange(tx_index=3, new_code=b"\x60\x00")], - "Unexpected code change found at tx", - ), - ( - no_storage_reads(), - "storage_reads", - [StorageKey(0x42)], - "Unexpected storage read found at slot", - ), - ( - no_storage_changes(), - "storage_changes", - [ - BalStorageSlot( - slot=0x01, slot_changes=[BalStorageChange(tx_index=1, post_value=99)] - ) - ], - "Unexpected storage change found at slot", - ), - ], -) -def test_absence_validator_forbids_all(validator_func, field_name, changes, error_pattern): - """Test that validators without specific indices/slots forbid ALL changes.""" +def test_bal_account_absent_values_comprehensive(): + """Test comprehensive BalAccountAbsentValues usage.""" addr = Address(0xA) - actual_bal = BlockAccessList([BalAccountChange(address=addr, **{field_name: changes})]) + # Test forbidding nonce changes + actual_bal = BlockAccessList( + [BalAccountChange(address=addr, nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)])] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + addr: BalAccountExpectation( + absent_values=BalAccountAbsentValues( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)] + ) + ), + } + ) + + with pytest.raises( + BlockAccessListValidationError, match="Unexpected nonce change found at tx" + ): + expectation.verify_against(actual_bal) + + # Test forbidding balance changes + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=addr, balance_changes=[BalBalanceChange(tx_index=2, post_balance=100)] + ) + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + addr: BalAccountExpectation( + absent_values=BalAccountAbsentValues( + balance_changes=[BalBalanceChange(tx_index=2, post_balance=100)] + ) + ), + } + ) + + with pytest.raises( + BlockAccessListValidationError, match="Unexpected balance change found at tx" + ): + expectation.verify_against(actual_bal) + + # Test forbidding code changes + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=addr, code_changes=[BalCodeChange(tx_index=3, new_code=b"\x60\x00")] + ) + ] + ) expectation = BlockAccessListExpectation( account_expectations={ - addr: BalAccountExpectation(should_not_exist=[validator_func]), + addr: BalAccountExpectation( + absent_values=BalAccountAbsentValues( + code_changes=[BalCodeChange(tx_index=3, new_code=b"\x60\x00")] + ) + ), } ) - with pytest.raises(Exception, match=error_pattern): + with pytest.raises(BlockAccessListValidationError, match="Unexpected code change found at tx"): expectation.verify_against(actual_bal) + # Test forbidding storage reads + actual_bal = BlockAccessList( + [BalAccountChange(address=addr, storage_reads=[StorageKey(0x42)])] + ) -def test_all_absence_validators_use_validate_call(): - """Test that all exported absence validators use @validate_call decorator.""" - validator_names = [name for name in absence_validators.__all__ if name != "AbsenceValidator"] + expectation = BlockAccessListExpectation( + account_expectations={ + addr: BalAccountExpectation( + absent_values=BalAccountAbsentValues(storage_reads=[StorageKey(0x42)]) + ), + } + ) - for name in validator_names: - func = getattr(absence_validators, name) + with pytest.raises( + BlockAccessListValidationError, match="Unexpected storage read found at slot" + ): + expectation.verify_against(actual_bal) - assert hasattr(func, "__wrapped__"), ( - f"{name} is not decorated with `@validate_call`. " - "All validators must use `@validate_call(validate_return=True)`." + # Test forbidding storage changes + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=addr, + storage_changes=[ + BalStorageSlot( + slot=0x01, slot_changes=[BalStorageChange(tx_index=1, post_value=99)] + ) + ], + ) + ] + ) + + expectation = BlockAccessListExpectation( + account_expectations={ + addr: BalAccountExpectation( + absent_values=BalAccountAbsentValues( + storage_changes=[ + BalStorageSlot( + slot=0x01, slot_changes=[BalStorageChange(tx_index=1, post_value=99)] + ) + ] + ) + ), + } + ) + + with pytest.raises( + BlockAccessListValidationError, match="Unexpected storage change found at slot" + ): + expectation.verify_against(actual_bal) + + +@pytest.mark.parametrize( + "field_name,field_value", + [ + ("nonce_changes", []), + ("balance_changes", []), + ("code_changes", []), + ("storage_changes", []), + ("storage_reads", []), + ], +) +def test_bal_account_absent_values_empty_list_validation_raises(field_name, field_value): + """Test that empty lists in BalAccountAbsentValues fields raise appropriate errors.""" + with pytest.raises(ValueError, match="Empty lists are not allowed"): + BalAccountAbsentValues(**{field_name: field_value}) + + +def test_bal_account_absent_values_empty_slot_changes_raises(): + """Test that empty slot_changes in storage_changes raises appropriate error.""" + with pytest.raises(ValueError, match="Empty lists are not allowed"): + BalAccountAbsentValues( + storage_changes=[ + BalStorageSlot( + slot=0x42, + slot_changes=[], # Empty list should raise error + ) + ] ) From 38d9324cac6b33a45e47e264ac892097f8dd789d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Thu, 25 Sep 2025 01:59:52 +0800 Subject: [PATCH 028/102] feat(benchmark): add `benchmark_test` test type (#1945) * feat: wrap blockchain test for benchmark * feat: wrap state test for benchmark * feat(benchmark): add code generator to generate transaction * fix: resolve typing issue * refactor: update benchmark code generator and test wrapper * fix: udpate example changes * refactor: resolve typing and update func interface * refactor: remove benchmark state test wrapper * fix: pydantic model validation for benchmark manager * refactor synatx and parameter * refactor: remove benchmark manager feature * refactor: update logic and add benchmark tests * refactor: enforce single property requirement in blockchain test generation * refactor: update Bytecode serialization schema to use format_ser_schema * refactor: update import paths * refactor: update serialization schema * refactor: remove unused parameters * doc: add changelog entry * fix typo --- ethereum_test_benchmark/__init__.py | 13 + .../benchmark_code_generator.py | 68 +++++ ethereum_test_specs/__init__.py | 4 + ethereum_test_specs/benchmark.py | 257 ++++++++++++++++++ ethereum_test_specs/tests/test_benchmark.py | 105 +++++++ ethereum_test_tools/__init__.py | 12 + ethereum_test_vm/bytecode.py | 22 +- pytest_plugins/shared/execute_fill.py | 1 + 8 files changed, 481 insertions(+), 1 deletion(-) create mode 100644 ethereum_test_benchmark/__init__.py create mode 100644 ethereum_test_benchmark/benchmark_code_generator.py create mode 100644 ethereum_test_specs/benchmark.py create mode 100644 ethereum_test_specs/tests/test_benchmark.py diff --git a/ethereum_test_benchmark/__init__.py b/ethereum_test_benchmark/__init__.py new file mode 100644 index 0000000000..60f0e66a5f --- /dev/null +++ b/ethereum_test_benchmark/__init__.py @@ -0,0 +1,13 @@ +"""Benchmark code generator classes for creating optimized bytecode patterns.""" + +from .benchmark_code_generator import ( + BenchmarkCodeGenerator, + ExtCallGenerator, + JumpLoopGenerator, +) + +__all__ = ( + "BenchmarkCodeGenerator", + "ExtCallGenerator", + "JumpLoopGenerator", +) diff --git a/ethereum_test_benchmark/benchmark_code_generator.py b/ethereum_test_benchmark/benchmark_code_generator.py new file mode 100644 index 0000000000..9c2c9b7814 --- /dev/null +++ b/ethereum_test_benchmark/benchmark_code_generator.py @@ -0,0 +1,68 @@ +"""Benchmark code generator classes for creating optimized bytecode patterns.""" + +from ethereum_test_forks import Fork +from ethereum_test_specs.benchmark import BenchmarkCodeGenerator +from ethereum_test_types import Alloc, Transaction +from ethereum_test_vm import Bytecode +from ethereum_test_vm.opcodes import Opcodes as Op + + +class JumpLoopGenerator(BenchmarkCodeGenerator): + """Generates bytecode that loops execution using JUMP operations.""" + + def deploy_contracts(self, pre: Alloc, fork: Fork) -> None: + """Deploy the looping contract.""" + # Benchmark Test Structure: + # setup + JUMPDEST + attack + attack + ... + attack + JUMP(setup_length) + code = self.generate_repeated_code(self.attack_block, self.setup, fork) + self._contract_address = pre.deploy_contract(code=code) + + def generate_transaction(self, pre: Alloc, gas_limit: int, fork: Fork) -> Transaction: + """Generate transaction that executes the looping contract.""" + if not hasattr(self, "_contract_address"): + raise ValueError("deploy_contracts must be called before generate_transaction") + + return Transaction( + to=self._contract_address, + gas_limit=gas_limit, + sender=pre.fund_eoa(), + ) + + +class ExtCallGenerator(BenchmarkCodeGenerator): + """Generates bytecode that fills the contract to maximum allowed code size.""" + + def deploy_contracts(self, pre: Alloc, fork: Fork) -> None: + """Deploy both target and caller contracts.""" + # Benchmark Test Structure: + # There are two contracts: + # 1. The target contract that executes certain operation but not loop (e.g. PUSH) + # 2. The loop contract that calls the target contract in a loop + + max_iterations = min( + fork.max_stack_height(), fork.max_code_size() // len(self.attack_block) + ) + + # Deploy target contract that contains the actual attack block + self._target_contract_address = pre.deploy_contract( + code=self.attack_block * max_iterations + ) + + # Create caller contract that repeatedly calls the target contract + # attack = POP(STATICCALL(GAS, target_contract_address, 0, 0, 0, 0)) + # setup + JUMPDEST + attack + attack + ... + attack + JUMP(setup_length) + code_sequence = Op.POP(Op.STATICCALL(Op.GAS, self._target_contract_address, 0, 0, 0, 0)) + + caller_code = self.generate_repeated_code(code_sequence, Bytecode(), fork) + self._contract_address = pre.deploy_contract(code=caller_code) + + def generate_transaction(self, pre: Alloc, gas_limit: int, fork: Fork) -> Transaction: + """Generate transaction that executes the caller contract.""" + if not hasattr(self, "_contract_address"): + raise ValueError("deploy_contracts must be called before generate_transaction") + + return Transaction( + to=self._contract_address, + gas_limit=gas_limit, + sender=pre.fund_eoa(), + ) diff --git a/ethereum_test_specs/__init__.py b/ethereum_test_specs/__init__.py index 790e2b4351..e0baf8c518 100644 --- a/ethereum_test_specs/__init__.py +++ b/ethereum_test_specs/__init__.py @@ -2,6 +2,7 @@ from .base import BaseTest, TestSpec from .base_static import BaseStaticTest +from .benchmark import BenchmarkTest, BenchmarkTestFiller, BenchmarkTestSpec from .blobs import BlobsTest, BlobsTestFiller, BlobsTestSpec from .blockchain import ( BlockchainTest, @@ -23,6 +24,9 @@ __all__ = ( "BaseStaticTest", "BaseTest", + "BenchmarkTest", + "BenchmarkTestFiller", + "BenchmarkTestSpec", "BlobsTest", "BlobsTestFiller", "BlobsTestSpec", diff --git a/ethereum_test_specs/benchmark.py b/ethereum_test_specs/benchmark.py new file mode 100644 index 0000000000..440faa8b84 --- /dev/null +++ b/ethereum_test_specs/benchmark.py @@ -0,0 +1,257 @@ +"""Ethereum benchmark test spec definition and filler.""" + +import math +from abc import ABC, abstractmethod +from dataclasses import dataclass, field +from typing import Callable, ClassVar, Dict, Generator, List, Sequence, Type + +import pytest +from pydantic import ConfigDict, Field + +from ethereum_clis import TransitionTool +from ethereum_test_base_types import HexNumber +from ethereum_test_exceptions import BlockException, TransactionException +from ethereum_test_execution import ( + BaseExecute, + ExecuteFormat, + LabeledExecuteFormat, + TransactionPost, +) +from ethereum_test_fixtures import ( + BaseFixture, + BlockchainEngineFixture, + BlockchainEngineXFixture, + BlockchainFixture, + FixtureFormat, + LabeledFixtureFormat, +) +from ethereum_test_forks import Fork +from ethereum_test_types import Alloc, Environment, Transaction +from ethereum_test_vm import Bytecode +from ethereum_test_vm.opcodes import Opcodes as Op + +from .base import BaseTest +from .blockchain import Block, BlockchainTest + + +@dataclass(kw_only=True) +class BenchmarkCodeGenerator(ABC): + """Abstract base class for generating benchmark bytecode.""" + + attack_block: Bytecode + setup: Bytecode = field(default_factory=Bytecode) + + @abstractmethod + def deploy_contracts(self, pre: Alloc, fork: Fork) -> None: + """Deploy any contracts needed for the benchmark.""" + ... + + @abstractmethod + def generate_transaction(self, pre: Alloc, gas_limit: int, fork: Fork) -> Transaction: + """Generate a transaction with the specified gas limit.""" + ... + + def generate_repeated_code( + self, repeated_code: Bytecode, setup: Bytecode, fork: Fork + ) -> Bytecode: + """Calculate the maximum number of iterations that can fit in the code size limit.""" + assert len(repeated_code) > 0, "repeated_code cannot be empty" + max_code_size = fork.max_code_size() + + overhead = len(setup) + len(Op.JUMPDEST) + len(Op.JUMP(len(setup))) + available_space = max_code_size - overhead + max_iterations = available_space // len(repeated_code) + + code = setup + Op.JUMPDEST + repeated_code * max_iterations + Op.JUMP(len(setup)) + self._validate_code_size(code, fork) + + return code + + def _validate_code_size(self, code: Bytecode, fork: Fork) -> None: + """Validate that the generated code fits within size limits.""" + if len(code) > fork.max_code_size(): + raise ValueError( + f"Generated code size {len(code)} exceeds maximum allowed size " + f"{fork.max_code_size()}" + ) + + +class BenchmarkTest(BaseTest): + """Test type designed specifically for benchmark test cases.""" + + model_config = ConfigDict(extra="forbid") + + pre: Alloc + post: Alloc = Field(default_factory=Alloc) + tx: Transaction | None = None + blocks: List[Block] | None = None + block_exception: ( + List[TransactionException | BlockException] | TransactionException | BlockException | None + ) = None + env: Environment = Field(default_factory=Environment) + expected_benchmark_gas_used: int | None = None + gas_benchmark_value: int = Field(default_factory=lambda: int(Environment().gas_limit)) + code_generator: BenchmarkCodeGenerator | None = None + + supported_fixture_formats: ClassVar[Sequence[FixtureFormat | LabeledFixtureFormat]] = [ + BlockchainFixture, + BlockchainEngineFixture, + BlockchainEngineXFixture, + ] + + supported_execute_formats: ClassVar[Sequence[LabeledExecuteFormat]] = [ + LabeledExecuteFormat( + TransactionPost, + "benchmark_test", + "An execute test derived from a benchmark test", + ), + ] + + supported_markers: ClassVar[Dict[str, str]] = { + "blockchain_test_engine_only": "Only generate a blockchain test engine fixture", + "blockchain_test_only": "Only generate a blockchain test fixture", + } + + @classmethod + def pytest_parameter_name(cls) -> str: + """Return the parameter name used in pytest to select this spec type.""" + return "benchmark_test" + + @classmethod + def discard_fixture_format_by_marks( + cls, + fixture_format: FixtureFormat, + fork: Fork, + markers: List[pytest.Mark], + ) -> bool: + """Discard a fixture format from filling if the appropriate marker is used.""" + if "blockchain_test_only" in [m.name for m in markers]: + return fixture_format != BlockchainFixture + if "blockchain_test_engine_only" in [m.name for m in markers]: + return fixture_format != BlockchainEngineFixture + return False + + def get_genesis_environment(self, fork: Fork) -> Environment: + """Get the genesis environment for this benchmark test.""" + return self.env + + def split_transaction(self, tx: Transaction, gas_limit_cap: int | None) -> List[Transaction]: + """Split a transaction that exceeds the gas limit cap into multiple transactions.""" + if gas_limit_cap is None: + tx.gas_limit = HexNumber(self.gas_benchmark_value) + return [tx] + + if gas_limit_cap >= self.gas_benchmark_value: + tx.gas_limit = HexNumber(self.gas_benchmark_value) + return [tx] + + num_splits = math.ceil(self.gas_benchmark_value / gas_limit_cap) + remaining_gas = self.gas_benchmark_value + + split_transactions = [] + for i in range(num_splits): + split_tx = tx.model_copy() + split_tx.gas_limit = HexNumber(remaining_gas if i == num_splits - 1 else gas_limit_cap) + remaining_gas -= gas_limit_cap + split_tx.nonce = HexNumber(tx.nonce + i) + split_transactions.append(split_tx) + + return split_transactions + + def generate_blocks_from_code_generator(self, fork: Fork) -> List[Block]: + """Generate blocks using the code generator.""" + if self.code_generator is None: + raise Exception("Code generator is not set") + + self.code_generator.deploy_contracts(self.pre, fork) + gas_limit = fork.transaction_gas_limit_cap() or self.gas_benchmark_value + benchmark_tx = self.code_generator.generate_transaction(self.pre, gas_limit, fork) + + execution_txs = self.split_transaction(benchmark_tx, gas_limit) + execution_block = Block(txs=execution_txs) + + return [execution_block] + + def generate_blockchain_test(self, fork: Fork) -> BlockchainTest: + """Create a BlockchainTest from this BenchmarkTest.""" + set_props = [ + name + for name, val in [ + ("code_generator", self.code_generator), + ("blocks", self.blocks), + ("tx", self.tx), + ] + if val is not None + ] + + if len(set_props) != 1: + raise ValueError( + f"Exactly one must be set, but got {len(set_props)}: {', '.join(set_props)}" + ) + + if self.code_generator is not None: + generated_blocks = self.generate_blocks_from_code_generator(fork) + return BlockchainTest.from_test( + base_test=self, + genesis_environment=self.env, + pre=self.pre, + post=self.post, + blocks=generated_blocks, + ) + elif self.blocks is not None: + return BlockchainTest.from_test( + base_test=self, + genesis_environment=self.env, + pre=self.pre, + post=self.post, + blocks=self.blocks, + ) + elif self.tx is not None: + gas_limit = fork.transaction_gas_limit_cap() or self.gas_benchmark_value + + transactions = self.split_transaction(self.tx, gas_limit) + + blocks = [Block(txs=transactions)] + + return BlockchainTest.from_test( + base_test=self, + pre=self.pre, + post=self.post, + blocks=blocks, + genesis_environment=self.env, + ) + else: + raise ValueError("Cannot create BlockchainTest without transactions or blocks") + + def generate( + self, + t8n: TransitionTool, + fork: Fork, + fixture_format: FixtureFormat, + ) -> BaseFixture: + """Generate the blockchain test fixture.""" + self.check_exception_test(exception=self.tx.error is not None if self.tx else False) + if fixture_format in BlockchainTest.supported_fixture_formats: + return self.generate_blockchain_test(fork=fork).generate( + t8n=t8n, fork=fork, fixture_format=fixture_format + ) + else: + raise Exception(f"Unsupported fixture format: {fixture_format}") + + def execute( + self, + *, + fork: Fork, + execute_format: ExecuteFormat, + ) -> BaseExecute: + """Execute the benchmark test by sending it to the live network.""" + if execute_format == TransactionPost: + return TransactionPost( + blocks=[[self.tx]], + post=self.post, + ) + raise Exception(f"Unsupported execute format: {execute_format}") + + +BenchmarkTestSpec = Callable[[str], Generator[BenchmarkTest, None, None]] +BenchmarkTestFiller = Type[BenchmarkTest] diff --git a/ethereum_test_specs/tests/test_benchmark.py b/ethereum_test_specs/tests/test_benchmark.py new file mode 100644 index 0000000000..bd4a699720 --- /dev/null +++ b/ethereum_test_specs/tests/test_benchmark.py @@ -0,0 +1,105 @@ +"""Tests for the BenchmarkTest class and its transaction splitting functionality.""" + +import pytest + +from ethereum_test_base_types import HexNumber +from ethereum_test_specs.benchmark import BenchmarkTest +from ethereum_test_types import Alloc, Environment, Transaction + + +@pytest.mark.parametrize( + "gas_benchmark_value_millions,expected_splits", + [ + (1, 1), # 1M / 16M = 1 transaction + (10, 1), # 10M / 16M = 1 transaction + (30, 2), # 30M / 16M = 2 transactions (16M + 14M) + (45, 3), # 45M / 16M = 3 transactions (16M + 16M + 13M) + (60, 4), # 60M / 16M = 4 transactions (16M + 16M + 16M + 12M) + (100, 7), # 100M / 16M = 7 transactions (6x16M + 4M) + (150, 10), # 150M / 16M = 10 transactions (9x16M + 6M) + ], +) +def test_split_transaction(gas_benchmark_value_millions: int, expected_splits: int): + """Test that transaction splitting works correctly for Osaka fork gas cap.""" + gas_benchmark_value = gas_benchmark_value_millions * 1_000_000 + gas_limit_cap = 16_000_000 # Osaka's transaction gas limit cap + + # Create a minimal BenchmarkTest instance + benchmark_test = BenchmarkTest( + pre=Alloc(), + post=Alloc(), + tx=Transaction(sender=HexNumber(0), to=HexNumber(0), nonce=0), + env=Environment(), + gas_benchmark_value=gas_benchmark_value, + ) + + # Test the split_transaction method + assert benchmark_test.tx is not None, "Transaction should not be None" + split_txs = benchmark_test.split_transaction(benchmark_test.tx, gas_limit_cap) + + # Verify the number of transactions + assert len(split_txs) == expected_splits, ( + f"Expected {expected_splits} transactions for {gas_benchmark_value_millions}M gas, " + f"got {len(split_txs)}" + ) + + # Verify total gas equals the benchmark value + total_gas = sum(tx.gas_limit for tx in split_txs) + assert total_gas == gas_benchmark_value, ( + f"Total gas {total_gas} doesn't match benchmark value {gas_benchmark_value}" + ) + + # Verify no transaction exceeds the cap + for i, tx in enumerate(split_txs): + assert tx.gas_limit <= gas_limit_cap, ( + f"Transaction {i} gas limit {tx.gas_limit} exceeds cap {gas_limit_cap}" + ) + + # Verify nonces increment correctly + for i, tx in enumerate(split_txs): + assert tx.nonce == i, f"Transaction {i} has incorrect nonce {tx.nonce}" + + # Verify gas distribution + for i, tx in enumerate(split_txs[:-1]): # All but last should be at cap + assert tx.gas_limit == gas_limit_cap, ( + f"Transaction {i} should have gas limit {gas_limit_cap}, got {tx.gas_limit}" + ) + + # Last transaction should have the remainder + if expected_splits > 1: + expected_last_gas = gas_benchmark_value - (gas_limit_cap * (expected_splits - 1)) + assert split_txs[-1].gas_limit == expected_last_gas, ( + f"Last transaction should have {expected_last_gas} gas, got {split_txs[-1].gas_limit}" + ) + + +@pytest.mark.parametrize( + "gas_benchmark_value,gas_limit_cap", + [ + (50_000_000, None), # No cap - should return single transaction + (50_000_000, 100_000_000), # Cap higher than benchmark value + ], +) +def test_split_transaction_edge_cases(gas_benchmark_value: int, gas_limit_cap: int | None): + """Test edge cases for transaction splitting.""" + benchmark_test = BenchmarkTest( + pre=Alloc(), + post=Alloc(), + tx=Transaction(sender=HexNumber(0), to=HexNumber(0), nonce=0, gas_limit=1_000_000_000), + env=Environment(), + gas_benchmark_value=gas_benchmark_value, + ) + + assert benchmark_test.tx is not None, "Transaction should not be None" + split_txs = benchmark_test.split_transaction(benchmark_test.tx, gas_limit_cap) + + # Should return single transaction in both cases + assert len(split_txs) == 1, f"Expected 1 transaction, got {len(split_txs)}" + + if gas_limit_cap is None: + # When no cap, gas_limit should be benchmark value + assert split_txs[0].gas_limit == gas_benchmark_value + else: + # When cap > benchmark, gas_limit should be min of tx.gas_limit and benchmark + assert benchmark_test.tx is not None, "Transaction should not be None" + assert split_txs[0].gas_limit == min(benchmark_test.tx.gas_limit, gas_benchmark_value) diff --git a/ethereum_test_tools/__init__.py b/ethereum_test_tools/__init__.py index bb0b026ef9..fc8057c001 100644 --- a/ethereum_test_tools/__init__.py +++ b/ethereum_test_tools/__init__.py @@ -16,6 +16,11 @@ TestPrivateKey2, ) from ethereum_test_base_types.reference_spec import ReferenceSpec, ReferenceSpecTypes +from ethereum_test_benchmark import ( + BenchmarkCodeGenerator, + ExtCallGenerator, + JumpLoopGenerator, +) from ethereum_test_exceptions import ( BlockException, EngineAPIError, @@ -25,6 +30,8 @@ from ethereum_test_fixtures import BaseFixture, FixtureCollector from ethereum_test_specs import ( BaseTest, + BenchmarkTest, + BenchmarkTestFiller, BlobsTest, BlobsTestFiller, BlockchainTest, @@ -112,6 +119,9 @@ "BalStorageSlot", "BaseFixture", "BaseTest", + "BenchmarkCodeGenerator", + "BenchmarkTest", + "BenchmarkTestFiller", "Blob", "BlockAccessList", "BlobsTest", @@ -128,6 +138,7 @@ "CodeGasMeasure", "Conditional", "ConsolidationRequest", + "ExtCallGenerator", "DeploymentTestType", "DepositRequest", "EngineAPIError", @@ -143,6 +154,7 @@ "Hash", "Header", "Initcode", + "JumpLoopGenerator", "Macro", "Macros", "NetworkWrappedTransaction", diff --git a/ethereum_test_vm/bytecode.py b/ethereum_test_vm/bytecode.py index e07ab2cad0..5eea5b0cce 100644 --- a/ethereum_test_vm/bytecode.py +++ b/ethereum_test_vm/bytecode.py @@ -1,6 +1,13 @@ """Ethereum Virtual Machine bytecode primitives and utilities.""" -from typing import SupportsBytes +from typing import Any, SupportsBytes + +from pydantic import GetCoreSchemaHandler +from pydantic_core.core_schema import ( + PlainValidatorFunctionSchema, + no_info_plain_validator_function, + plain_serializer_function_ser_schema, +) from ethereum_test_base_types import Bytes, Hash @@ -217,3 +224,16 @@ def hex(self) -> str: def keccak256(self) -> Hash: """Return the keccak256 hash of the opcode byte representation.""" return Bytes(self._bytes_).keccak256() + + @classmethod + def __get_pydantic_core_schema__( + cls, source_type: Any, handler: GetCoreSchemaHandler + ) -> PlainValidatorFunctionSchema: + """Provide Pydantic core schema for Bytecode serialization and validation.""" + return no_info_plain_validator_function( + cls, + serialization=plain_serializer_function_ser_schema( + lambda bytecode: "0x" + bytecode.hex(), + info_arg=False, + ), + ) diff --git a/pytest_plugins/shared/execute_fill.py b/pytest_plugins/shared/execute_fill.py index 98fc765db0..21b9b7ea5b 100644 --- a/pytest_plugins/shared/execute_fill.py +++ b/pytest_plugins/shared/execute_fill.py @@ -13,6 +13,7 @@ from ..spec_version_checker.spec_version_checker import EIPSpecTestItem ALL_FIXTURE_PARAMETERS = { + "gas_benchmark_value", "genesis_environment", "env", } From e92ba45589742e4b31990d8ed090d09258f5dd03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Thu, 25 Sep 2025 01:59:52 +0800 Subject: [PATCH 029/102] feat(benchmark): add `benchmark_test` test type (#1945) * feat: wrap blockchain test for benchmark * feat: wrap state test for benchmark * feat(benchmark): add code generator to generate transaction * fix: resolve typing issue * refactor: update benchmark code generator and test wrapper * fix: udpate example changes * refactor: resolve typing and update func interface * refactor: remove benchmark state test wrapper * fix: pydantic model validation for benchmark manager * refactor synatx and parameter * refactor: remove benchmark manager feature * refactor: update logic and add benchmark tests * refactor: enforce single property requirement in blockchain test generation * refactor: update Bytecode serialization schema to use format_ser_schema * refactor: update import paths * refactor: update serialization schema * refactor: remove unused parameters * doc: add changelog entry * fix typo --- benchmark/conftest.py | 8 ++++++ benchmark/test_worst_blocks.py | 7 +++-- benchmark/test_worst_compute.py | 48 +++++++-------------------------- 3 files changed, 23 insertions(+), 40 deletions(-) diff --git a/benchmark/conftest.py b/benchmark/conftest.py index 3af1bf9ade..1e2e781381 100644 --- a/benchmark/conftest.py +++ b/benchmark/conftest.py @@ -4,6 +4,8 @@ import pytest +from ethereum_test_forks import Fork + DEFAULT_BENCHMARK_FORK = "Prague" @@ -59,3 +61,9 @@ def pytest_collection_modifyitems(config, items): for i in reversed(items_for_removal): items.pop(i) + + +@pytest.fixture +def tx_gas_limit_cap(fork: Fork, gas_benchmark_value: int) -> int: + """Return the transaction gas limit cap.""" + return fork.transaction_gas_limit_cap() or gas_benchmark_value diff --git a/benchmark/test_worst_blocks.py b/benchmark/test_worst_blocks.py index 38e6d5f71e..b71f303506 100644 --- a/benchmark/test_worst_blocks.py +++ b/benchmark/test_worst_blocks.py @@ -9,14 +9,15 @@ import pytest +from ethereum_test_base_types import Account from ethereum_test_forks import Fork from ethereum_test_tools import ( AccessList, - Account, Address, Alloc, Block, BlockchainTestFiller, + Environment, Hash, StateTestFiller, Transaction, @@ -112,11 +113,13 @@ def ether_transfer_case( def test_block_full_of_ether_transfers( blockchain_test: BlockchainTestFiller, pre: Alloc, + env: Environment, case_id: str, ether_transfer_case, iteration_count: int, transfer_amount: int, intrinsic_cost: int, + gas_benchmark_value: int, ): """ Single test for ether transfer scenarios. @@ -153,10 +156,10 @@ def test_block_full_of_ether_transfers( ) blockchain_test( + genesis_environment=env, pre=pre, post=post_state, blocks=[Block(txs=txs)], - exclude_full_post_state_in_output=True, expected_benchmark_gas_used=iteration_count * intrinsic_cost, ) diff --git a/benchmark/test_worst_compute.py b/benchmark/test_worst_compute.py index 9bfdee1648..d7437a77e4 100644 --- a/benchmark/test_worst_compute.py +++ b/benchmark/test_worst_compute.py @@ -15,10 +15,12 @@ from py_ecc.bn128 import G1, G2, multiply from ethereum_test_base_types.base_types import Bytes +from ethereum_test_benchmark.benchmark_code_generator import JumpLoopGenerator from ethereum_test_forks import Fork from ethereum_test_tools import ( Address, Alloc, + BenchmarkTestFiller, Block, BlockchainTestFiller, Bytecode, @@ -1842,30 +1844,14 @@ def test_worst_jumpis( @pytest.mark.slow def test_worst_jumpdests( - state_test: StateTestFiller, + benchmark_test: BenchmarkTestFiller, pre: Alloc, - fork: Fork, - gas_benchmark_value: int, ): """Test running a JUMPDEST-intensive contract.""" - max_code_size = fork.max_code_size() - - # Create and deploy a contract with many JUMPDESTs - code_suffix = Op.JUMP(Op.PUSH0) - code_body = Op.JUMPDEST * (max_code_size - len(code_suffix)) - code = code_body + code_suffix - jumpdests_address = pre.deploy_contract(code=code) - - tx = Transaction( - to=jumpdests_address, - gas_limit=gas_benchmark_value, - sender=pre.fund_eoa(), - ) - - state_test( + benchmark_test( pre=pre, post={}, - tx=tx, + code_generator=JumpLoopGenerator(attack_block=Op.JUMPDEST), ) @@ -2764,31 +2750,17 @@ def test_worst_calldataload( ], ) def test_worst_swap( - state_test: StateTestFiller, + benchmark_test: BenchmarkTestFiller, pre: Alloc, - fork: Fork, opcode: Opcode, - gas_benchmark_value: int, ): """Test running a block with as many SWAP as possible.""" - max_code_size = fork.max_code_size() - - code_prefix = Op.JUMPDEST + Op.PUSH0 * opcode.min_stack_height - code_suffix = Op.PUSH0 + Op.JUMP - opcode_sequence = opcode * (max_code_size - len(code_prefix) - len(code_suffix)) - code = code_prefix + opcode_sequence + code_suffix - assert len(code) <= max_code_size - - tx = Transaction( - to=pre.deploy_contract(code=code), - gas_limit=gas_benchmark_value, - sender=pre.fund_eoa(), - ) - - state_test( + benchmark_test( pre=pre, post={}, - tx=tx, + code_generator=JumpLoopGenerator( + attack_block=opcode, setup=Op.PUSH0 * opcode.min_stack_height + ), ) From 832ba4420400a958d7c3b53ef747341e01f5ec03 Mon Sep 17 00:00:00 2001 From: CPerezz <37264926+CPerezz@users.noreply.github.com> Date: Thu, 25 Sep 2025 15:51:52 +0200 Subject: [PATCH 030/102] fix(execute): add missing return statement stub contract deployment (#2193) --- pytest_plugins/execute/pre_alloc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytest_plugins/execute/pre_alloc.py b/pytest_plugins/execute/pre_alloc.py index 40ab87f803..273a6ab3a4 100644 --- a/pytest_plugins/execute/pre_alloc.py +++ b/pytest_plugins/execute/pre_alloc.py @@ -259,6 +259,7 @@ def deploy_contract( storage={}, ), ) + return contract_address initcode_prefix = Bytecode() From 6d3cb3c006751aa148013696afc73311e2eec681 Mon Sep 17 00:00:00 2001 From: raxhvl <10168946+raxhvl@users.noreply.github.com> Date: Thu, 25 Sep 2025 17:25:24 +0200 Subject: [PATCH 031/102] =?UTF-8?q?=E2=9C=A8=20feat(fill):=20watch=20mode?= =?UTF-8?q?=20(#2173)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: raxhvl --- cli/pytest_commands/fill.py | 25 ++++++++- cli/pytest_commands/processors.py | 8 +++ cli/pytest_commands/watcher.py | 86 +++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 cli/pytest_commands/watcher.py diff --git a/cli/pytest_commands/fill.py b/cli/pytest_commands/fill.py index 452a6f1d27..f0f3ce5328 100644 --- a/cli/pytest_commands/fill.py +++ b/cli/pytest_commands/fill.py @@ -5,7 +5,8 @@ import click from .base import PytestCommand, PytestExecution, common_pytest_options -from .processors import HelpFlagsProcessor, StdoutFlagsProcessor +from .processors import HelpFlagsProcessor, StdoutFlagsProcessor, WatchFlagsProcessor +from .watcher import FileWatcher class FillCommand(PytestCommand): @@ -18,6 +19,7 @@ def __init__(self, **kwargs): argument_processors=[ HelpFlagsProcessor("fill"), StdoutFlagsProcessor(), + WatchFlagsProcessor(), ], **kwargs, ) @@ -174,6 +176,27 @@ def _is_tarball_output(self, args: List[str]) -> bool: return str(output_path).endswith(".tar.gz") return False + def _is_watch_mode(self, args: List[str]) -> bool: + """Check if any watch flag is present in arguments.""" + return any(flag in args for flag in ["--watch", "--watcherfall"]) + + def _is_verbose_watch_mode(self, args: List[str]) -> bool: + """Check if verbose watch flag (--watcherfall) is present in arguments.""" + return "--watcherfall" in args + + def execute(self, pytest_args: List[str]) -> None: + """Execute the command with optional watch mode support.""" + if self._is_watch_mode(pytest_args): + self._execute_with_watch(pytest_args) + else: + super().execute(pytest_args) + + def _execute_with_watch(self, pytest_args: List[str]) -> None: + """Execute fill command in watch mode.""" + verbose = self._is_verbose_watch_mode(pytest_args) + watcher = FileWatcher(console=self.runner.console, verbose=verbose) + watcher.run_with_watch(pytest_args) + class PhilCommand(FillCommand): """Friendly fill command with emoji reporting.""" diff --git a/cli/pytest_commands/processors.py b/cli/pytest_commands/processors.py index 5810d87f0c..ef6a44dd1e 100644 --- a/cli/pytest_commands/processors.py +++ b/cli/pytest_commands/processors.py @@ -118,6 +118,14 @@ def _has_parallelism_flag(self, args: List[str]) -> bool: return "-n" in args +class WatchFlagsProcessor(ArgumentProcessor): + """Processes --watch and --watcherfall flags for file watching functionality.""" + + def process_args(self, args: List[str]) -> List[str]: + """Remove --watch and --watcherfall flags from args passed to pytest.""" + return [arg for arg in args if arg not in ["--watch", "--watcherfall"]] + + class ConsumeCommandProcessor(ArgumentProcessor): """Processes consume-specific command arguments.""" diff --git a/cli/pytest_commands/watcher.py b/cli/pytest_commands/watcher.py new file mode 100644 index 0000000000..bec93dc02f --- /dev/null +++ b/cli/pytest_commands/watcher.py @@ -0,0 +1,86 @@ +"""File watcher implementation for --watch flag functionality.""" + +import os +import subprocess +import time +from pathlib import Path +from typing import Dict + +from rich.console import Console + + +class FileWatcher: + """Simple file watcher that re-runs the fill command on changes.""" + + def __init__(self, console=None, verbose=False): + """Initialize the file watcher.""" + self.console = console or Console(highlight=False) + self.verbose = verbose + + def run_with_watch(self, args): + """Watch for file changes and re-run fill command.""" + file_mtimes: Dict[Path, float] = {} + + def get_file_mtimes(): + """Get current modification times of all test and source files.""" + mtimes = {} + # Watch tests directory + tests_dir = Path("tests") + if tests_dir.exists(): + for py_file in tests_dir.rglob("*.py"): + try: + mtimes[py_file] = py_file.stat().st_mtime + except (OSError, FileNotFoundError): + pass + # Watch src directory + src_dir = Path("src") + if src_dir.exists(): + for py_file in src_dir.rglob("*.py"): + try: + mtimes[py_file] = py_file.stat().st_mtime + except (OSError, FileNotFoundError): + pass + return mtimes + + def run_fill(): + """Run fill command without --watch / --watcherfall flag.""" + clean_args = [arg for arg in args if arg not in ["--watch", "--watcherfall"]] + cmd = ["uv", "run", "fill"] + clean_args + result = subprocess.run(cmd) + + if result.returncode == 0: + self.console.print("[green]✓ Fill completed[/green]") + else: + self.console.print(f"[red]✗ Fill failed (exit {result.returncode})[/red]") + + # Setup + mode_desc = "watcherfall mode (verbose)" if self.verbose else "watch mode" + self.console.print(f"[blue]Starting {mode_desc}...[/blue]") + file_mtimes = get_file_mtimes() + + # Initial run + self.console.print("[green]Running initial fill...[/green]") + run_fill() + + file_count = len(file_mtimes) + self.console.print( + f"[blue]Watching {file_count} files in tests/ and src/ directories." + "\n Press Ctrl+C to stop.[/blue]" + ) + + # Watch loop + try: + while True: + time.sleep(0.5) + current_mtimes = get_file_mtimes() + + if current_mtimes != file_mtimes: + if not self.verbose: + os.system("clear" if os.name != "nt" else "cls") + self.console.print("[yellow]File changes detected, re-running...[/yellow]\n") + run_fill() + file_mtimes = current_mtimes + self.console.print("\n[blue]Watching for changes...[/blue]") + + except KeyboardInterrupt: + self.console.print("\n[yellow]Watch mode stopped.[/yellow]") From 8b02298cca38eb4cd7c880823ad335e0388109f1 Mon Sep 17 00:00:00 2001 From: felix Date: Thu, 25 Sep 2025 16:39:21 +0000 Subject: [PATCH 032/102] chore: shorten docstrings and single-line comments to 79 (ruff w505: doc-line-too-long) (#2180) * split comments across multiple lines when necessary * chore(tooling): check w505 in tox lint env * fixes * chore: remove abstract and other admonitions from test module docstrings * fixes * chore: fix more malformatted tables * chore: fix broken unordered-lists/args * chore: fix broken unordered-lists/args * chore: improve docstrings, also for D205 * chore: improve docstrings, also for D205 * chore: fix long or poorly formatted comments * chore: manually revert and fix docstrings/comments * fix: bad string formatting fix in unit test * last batch of manual fixes * fix * fix --------- Co-authored-by: danceratopz --- cli/check_fixtures.py | 13 +- cli/compare_fixtures.py | 14 +- cli/eest/commands/clean.py | 13 +- cli/eest/make/cli.py | 13 +- cli/eest/make/commands/__init__.py | 7 +- cli/eest/make/commands/test.py | 16 +- cli/eest/quotes.py | 4 +- cli/eofwrap.py | 38 +- cli/evm_bytes.py | 14 +- cli/extract_config.py | 16 +- cli/fillerconvert/fillerconvert.py | 3 +- cli/fillerconvert/verify_filled.py | 10 +- cli/gen_index.py | 8 +- cli/generate_checklist_stubs.py | 9 +- cli/gentest/request_manager.py | 16 +- cli/gentest/source_code_generator.py | 24 +- cli/gentest/test_context_providers.py | 16 +- cli/gentest/test_providers.py | 28 +- cli/gentest/tests/test_cli.py | 8 +- cli/hasher.py | 5 +- cli/input/input_repository.py | 4 +- cli/input/questionary_input_repository.py | 5 +- cli/modify_static_test_gas_limits.py | 12 +- cli/order_fixtures.py | 42 +- cli/pytest_commands/base.py | 20 +- cli/pytest_commands/fill.py | 30 +- cli/pytest_commands/processors.py | 21 +- cli/show_pre_alloc_group_stats.py | 42 +- cli/tests/test_evm_bytes.py | 9 +- cli/tests/test_generate_all_formats.py | 24 +- cli/tests/test_order_fixtures.py | 4 +- cli/tests/test_pytest_fill_command.py | 27 +- cli/tox_helpers.py | 19 +- config/docs.py | 5 +- config/env.py | 24 +- conftest.py | 6 +- ethereum_clis/__init__.py | 5 +- ethereum_clis/cli_types.py | 8 +- ethereum_clis/clis/ethereumjs.py | 5 +- ethereum_clis/clis/ethrex.py | 3 +- ethereum_clis/clis/evmone.py | 11 +- ethereum_clis/clis/execution_specs.py | 31 +- ethereum_clis/clis/geth.py | 24 +- ethereum_clis/clis/nethermind.py | 31 +- ethereum_clis/clis/nimbus.py | 7 +- ethereum_clis/ethereum_cli.py | 41 +- ethereum_clis/fixture_consumer_tool.py | 4 +- ethereum_clis/tests/test_execution_specs.py | 19 +- .../tests/test_transition_tools_support.py | 4 +- ethereum_clis/transition_tool.py | 59 +- ethereum_test_base_types/base_types.py | 45 +- ethereum_test_base_types/composite_types.py | 78 ++- ethereum_test_base_types/conversions.py | 16 +- ethereum_test_base_types/mixins.py | 63 +- ethereum_test_base_types/pydantic.py | 8 +- .../reference_spec/reference_spec.py | 19 +- ethereum_test_base_types/serialization.py | 25 +- .../tests/test_reference_spec.py | 3 +- ethereum_test_benchmark/__init__.py | 5 +- .../benchmark_code_generator.py | 24 +- ethereum_test_checklists/eip_checklist.py | 86 +-- ethereum_test_checklists/eip_checklist.pyi | 3 +- .../test_checklist_template_consistency.py | 19 +- ethereum_test_exceptions/exception_mapper.py | 34 +- ethereum_test_exceptions/exceptions.py | 629 ++++++------------ ethereum_test_exceptions/exceptions/base.py | 10 +- ethereum_test_exceptions/exceptions/block.py | 171 ++--- ethereum_test_exceptions/exceptions/eof.py | 202 ++---- .../exceptions/transaction.py | 253 +++---- .../tests/test_exceptions.py | 5 +- ethereum_test_execution/base.py | 8 +- ethereum_test_execution/blob_transaction.py | 18 +- ethereum_test_execution/transaction_post.py | 4 +- ethereum_test_fixtures/base.py | 18 +- ethereum_test_fixtures/blockchain.py | 66 +- ethereum_test_fixtures/collector.py | 31 +- ethereum_test_fixtures/consume.py | 9 +- ethereum_test_fixtures/file.py | 19 +- ethereum_test_fixtures/pre_alloc_groups.py | 13 +- ethereum_test_fixtures/state.py | 4 +- .../tests/test_blockchain.py | 5 +- ethereum_test_fixtures/tests/test_state.py | 5 +- ethereum_test_forks/base_fork.py | 251 +++++-- ethereum_test_forks/forks/forks.py | 219 ++++-- ethereum_test_forks/helpers.py | 41 +- .../tests/test_fork_range_descriptor.py | 4 +- ethereum_test_forks/tests/test_forks.py | 19 +- ethereum_test_forks/transition_base_fork.py | 4 +- ethereum_test_rpc/__init__.py | 4 +- ethereum_test_rpc/rpc.py | 119 +++- ethereum_test_rpc/rpc_types.py | 11 +- ethereum_test_rpc/tests/test_types.py | 4 +- ethereum_test_specs/base.py | 40 +- ethereum_test_specs/base_static.py | 58 +- ethereum_test_specs/benchmark.py | 20 +- ethereum_test_specs/blockchain.py | 142 ++-- ethereum_test_specs/eof.py | 172 ++--- ethereum_test_specs/helpers.py | 24 +- ethereum_test_specs/state.py | 51 +- ethereum_test_specs/static_state/account.py | 9 +- .../static_state/common/common.py | 46 +- .../static_state/common/compile_yul.py | 25 +- .../static_state/common/tags.py | 21 +- .../static_state/expect_section.py | 9 +- .../static_state/general_transaction.py | 4 +- .../static_state/state_static.py | 9 +- ethereum_test_specs/tests/test_benchmark.py | 13 +- ethereum_test_specs/tests/test_expect.py | 21 +- ethereum_test_specs/tests/test_fixtures.py | 4 +- ethereum_test_specs/transaction.py | 4 +- ethereum_test_tools/tests/test_code.py | 8 +- ethereum_test_tools/tools_code/generators.py | 104 +-- ethereum_test_tools/utility/generators.py | 133 ++-- ethereum_test_tools/utility/pytest.py | 136 ++-- .../utility/tests/test_pytest.py | 11 +- ethereum_test_tools/utility/versioning.py | 9 +- ethereum_test_types/account_types.py | 19 +- ethereum_test_types/blob_types.py | 65 +- .../block_access_list/__init__.py | 5 +- .../account_absent_values.py | 32 +- .../block_access_list/expectations.py | 21 +- .../block_access_list/modifiers.py | 23 +- ethereum_test_types/block_access_list/t8n.py | 6 +- ethereum_test_types/block_types.py | 13 +- ethereum_test_types/chain_config_types.py | 3 +- ethereum_test_types/eof/constants.py | 23 +- ethereum_test_types/eof/v1/__init__.py | 149 ++--- ethereum_test_types/helpers.py | 20 +- ethereum_test_types/request_types.py | 39 +- ethereum_test_types/tests/test_blob_types.py | 35 +- .../tests/test_block_access_lists.py | 20 +- ethereum_test_types/tests/test_eof_v1.py | 3 +- ethereum_test_types/tests/test_post_alloc.py | 8 +- ethereum_test_types/transaction_types.py | 92 ++- ethereum_test_types/trie.py | 40 +- ethereum_test_vm/bytecode.py | 65 +- ethereum_test_vm/evm_types.py | 4 +- ethereum_test_vm/opcodes.py | 507 ++++++++------ pytest_plugins/concurrency.py | 16 +- pytest_plugins/consume/consume.py | 63 +- pytest_plugins/consume/direct/conftest.py | 7 +- .../consume/direct/test_via_direct.py | 8 +- pytest_plugins/consume/releases.py | 30 +- pytest_plugins/consume/simulators/base.py | 19 +- .../consume/simulators/exceptions.py | 8 +- .../consume/simulators/helpers/exceptions.py | 14 +- .../consume/simulators/helpers/ruleset.py | 10 +- .../consume/simulators/helpers/timing.py | 4 +- .../consume/simulators/rlp/conftest.py | 5 +- .../simulator_logic/test_via_engine.py | 18 +- .../simulator_logic/test_via_rlp.py | 10 +- .../simulator_logic/test_via_sync.py | 32 +- .../consume/simulators/single_test_client.py | 18 +- .../consume/simulators/sync/conftest.py | 12 +- .../simulators/test_case_description.py | 36 +- .../consume/tests/test_consume_args.py | 26 +- .../tests/test_fixtures_source_input_types.py | 16 +- pytest_plugins/custom_logging/__init__.py | 5 +- .../custom_logging/plugin_logging.py | 72 +- pytest_plugins/execute/__init__.py | 5 +- .../execute/eth_config/eth_config.py | 30 +- .../execute/eth_config/execute_eth_config.py | 42 +- .../execute/eth_config/execute_types.py | 23 +- .../tests/test_execute_eth_config.py | 6 +- pytest_plugins/execute/execute.py | 55 +- pytest_plugins/execute/pre_alloc.py | 28 +- .../execute/rpc/chain_builder_eth_rpc.py | 44 +- pytest_plugins/execute/rpc/hive.py | 13 +- pytest_plugins/execute/rpc/remote.py | 13 +- pytest_plugins/execute/sender.py | 35 +- pytest_plugins/filler/eip_checklist.py | 12 +- pytest_plugins/filler/filler.py | 170 +++-- pytest_plugins/filler/fixture_output.py | 14 +- .../filler/gen_test_doc/gen_test_doc.py | 119 ++-- .../filler/gen_test_doc/page_props.py | 59 +- pytest_plugins/filler/ported_tests.py | 18 +- pytest_plugins/filler/pre_alloc.py | 56 +- pytest_plugins/filler/static_filler.py | 24 +- pytest_plugins/filler/tests/conftest.py | 7 +- .../filler/tests/test_benchmarking.py | 19 +- .../filler/tests/test_collect_only.py | 4 +- .../filler/tests/test_format_selector.py | 15 +- .../filler/tests/test_generate_all_formats.py | 25 +- .../filler/tests/test_output_directory.py | 36 +- .../filler/tests/test_phase_manager.py | 24 +- .../filler/tests/test_prealloc_group.py | 5 +- .../test_prealloc_group_usage_example.py | 23 +- .../tests/test_slow_marker_pre_alloc.py | 30 +- .../filler/tests/test_verify_sync_marker.py | 23 +- pytest_plugins/filler/witness.py | 32 +- pytest_plugins/fix_package_test_path.py | 9 +- pytest_plugins/forks/forks.py | 170 +++-- .../tests/test_bad_command_line_options.py | 11 +- .../forks/tests/test_bad_validity_markers.py | 12 +- .../tests/test_fork_parametrizer_types.py | 4 +- pytest_plugins/help/__init__.py | 4 +- pytest_plugins/help/help.py | 9 +- pytest_plugins/help/tests/test_help.py | 9 +- pytest_plugins/pytest_hive/pytest_hive.py | 56 +- pytest_plugins/shared/benchmarking.py | 10 +- pytest_plugins/shared/execute_fill.py | 30 +- pytest_plugins/shared/helpers.py | 8 +- pytest_plugins/shared/transaction_fixtures.py | 8 +- pytest_plugins/solc/solc.py | 3 +- .../spec_version_checker.py | 41 +- 205 files changed, 4228 insertions(+), 3254 deletions(-) diff --git a/cli/check_fixtures.py b/cli/check_fixtures.py index 6660bceab7..1497d5b281 100644 --- a/cli/check_fixtures.py +++ b/cli/check_fixtures.py @@ -27,14 +27,15 @@ def check_json(json_file_path: Path): """ Check all fixtures in the specified json file: 1. Load the json file into a pydantic model. This checks there are no - Validation errors when loading fixtures into EEST models. + Validation errors when loading fixtures into EEST models. 2. Serialize the loaded pydantic model to "json" (actually python data - structures, ready to written as json). + structures, ready to written as json). 3. Load the serialized data back into a pydantic model (to get an updated - hash) from step 2. + hash) from step 2. 4. Compare hashes: a. Compare the newly calculated hashes from step 2. and 3. and - b. If present, compare info["hash"] with the calculated hash from step 2. + b. If present, compare info["hash"] with the calculated hash from + step 2. """ fixtures: Fixtures = Fixtures.model_validate_json(json_file_path.read_text()) fixtures_json = to_json(fixtures) @@ -86,7 +87,9 @@ def check_json(json_file_path: Path): help="Stop and raise any exceptions encountered while checking fixtures.", ) def check_fixtures(input_str: str, quiet_mode: bool, stop_on_error: bool): - """Perform some checks on the fixtures contained in the specified directory.""" + """ + Perform some checks on the fixtures contained in the specified directory. + """ input_path = Path(input_str) success = True file_count = 0 diff --git a/cli/compare_fixtures.py b/cli/compare_fixtures.py index 787e0f9f07..bd7a5b9673 100644 --- a/cli/compare_fixtures.py +++ b/cli/compare_fixtures.py @@ -1,9 +1,9 @@ """ Compare two fixture folders and remove duplicates based on fixture hashes. -This tool reads the .meta/index.json files from two fixture directories and identifies -fixtures with identical hashes on a test case basis, then removes the duplicates from -both of the folders. Used within the coverage workflow. +This tool reads the .meta/index.json files from two fixture directories and +identifies fixtures with identical hashes on a test case basis, then removes +the duplicates from both of the folders. Used within the coverage workflow. """ import json @@ -95,8 +95,8 @@ def batch_remove_fixtures_from_files(removals_by_file): def rewrite_index(folder: Path, index: IndexFile, dry_run: bool): """ - Rewrite the index to the correct index file, or if the test count was reduced to zero, - the entire directory is deleted. + Rewrite the index to the correct index file, or if the test count was + reduced to zero, the entire directory is deleted. """ if len(index.test_cases) > 0: # Just rewrite the index @@ -130,7 +130,9 @@ def main( dry_run: bool, abort_on_empty_patch: bool, ): - """Compare two fixture folders and remove duplicates based on fixture hashes.""" + """ + Compare two fixture folders and remove duplicates based on fixture hashes. + """ try: # Load indices base_index = load_index(base) diff --git a/cli/eest/commands/clean.py b/cli/eest/commands/clean.py index a0a65ab743..58f7b93dac 100644 --- a/cli/eest/commands/clean.py +++ b/cli/eest/commands/clean.py @@ -19,18 +19,23 @@ def clean(all_files: bool, dry_run: bool, verbose: bool): """ Remove all generated files and directories from the repository. - If `--all` is specified, the virtual environment and .tox directory will also be removed. + + If `--all` is specified, the virtual environment and .tox directory will + also be removed. Args: - all_files (bool): Remove the virtual environment and .tox directory as well. + all_files (bool): Remove the virtual environment and .tox directory + as well. dry_run (bool): Simulate the cleanup without removing files. verbose (bool): Show verbose output. - Note: The virtual environment and .tox directory are not removed by default. + Note: The virtual environment and .tox directory are not removed by + default. - Example: Cleaning all generated files and directories and show the deleted items. + Example: Cleaning all generated files and directories and show the deleted + items. uv run eest clean --all -v diff --git a/cli/eest/make/cli.py b/cli/eest/make/cli.py index 413050d7a7..ae0c75ba8a 100644 --- a/cli/eest/make/cli.py +++ b/cli/eest/make/cli.py @@ -1,11 +1,14 @@ """ -The `make` CLI streamlines the process of scaffolding tasks, such as generating new test files, -enabling developers to concentrate on the core aspects of specification testing. +The `make` CLI streamlines the process of scaffolding tasks, such as generating +new test files, enabling developers to concentrate on the core aspects of +specification testing. -The module calls the appropriate function for the subcommand. If an invalid subcommand -is chosen, it throws an error and shows a list of valid subcommands. If no subcommand -is present, it shows a list of valid subcommands to choose from. + +The module calls the appropriate function for the subcommand. If an invalid +subcommand is chosen, it throws an error and shows a list of valid subcommands. +If no subcommand is present, it shows a list of valid subcommands to choose +from. """ import click diff --git a/cli/eest/make/commands/__init__.py b/cli/eest/make/commands/__init__.py index 706333ca04..64234b3000 100644 --- a/cli/eest/make/commands/__init__.py +++ b/cli/eest/make/commands/__init__.py @@ -1,7 +1,8 @@ """ -Holds subcommands for the make command. New subcommands must be created as -modules and exported from this package, then registered under the make command in -`cli.py`. +Holds subcommands for the make command. + +New subcommands must be created as modules and exported from this package, +then registered under the make command in `cli.py`. """ from .env import create_default_env diff --git a/cli/eest/make/commands/test.py b/cli/eest/make/commands/test.py index 0eb6e49141..2d30ee195b 100644 --- a/cli/eest/make/commands/test.py +++ b/cli/eest/make/commands/test.py @@ -1,9 +1,10 @@ """ Provides a CLI command to scaffold a test file. -The `test` command guides the user through a series of prompts to generate a test file -based on the selected test type, fork, EIP number, and EIP name. The generated test file -is saved in the appropriate directory with a rendered template using Jinja2. +The `test` command guides the user through a series of prompts to generate a +test file based on the selected test type, fork, EIP number, and EIP name. The +generated test file is saved in the appropriate directory with a rendered +template using Jinja2. """ import os @@ -38,10 +39,11 @@ def test(): """ Generate a new test file for an EIP. - This function guides the user through a series of prompts to generate a test file - for Ethereum execution specifications. The user is prompted to select the type of test, - the fork to use, and to provide the EIP number and name. Based on the inputs, a test file - is created in the appropriate directory with a rendered template. + This function guides the user through a series of prompts to generate a + test file for Ethereum execution specifications. The user is prompted to + select the type of test, the fork to use, and to provide the EIP number and + name. Based on the inputs, a test file is created in the appropriate + directory with a rendered template. Example: uv run eest make test diff --git a/cli/eest/quotes.py b/cli/eest/quotes.py index dfd8353072..e097a31b9f 100644 --- a/cli/eest/quotes.py +++ b/cli/eest/quotes.py @@ -51,5 +51,7 @@ def box_quote(quote): def get_quote(): - """Return random inspirational quote related to system design formatted in a box.""" + """ + Return random inspirational quote formatted in a box. + """ return box_quote(random.choice(make_something_great)) diff --git a/cli/eofwrap.py b/cli/eofwrap.py index c23a695a43..9d8382a74c 100644 --- a/cli/eofwrap.py +++ b/cli/eofwrap.py @@ -1,6 +1,6 @@ """ -Generate a JSON blockchain test from an existing JSON blockchain test by wrapping its pre-state -code in EOF wherever possible. +Generate a JSON blockchain test from an existing JSON blockchain test by +wrapping its pre-state code in EOF wherever possible. Example Usage: @@ -44,8 +44,8 @@ @click.option("--traces", is_flag=True, type=bool) def eof_wrap(input_path: str, output_dir: str, traces: bool): """ - Wrap JSON blockchain test file(s) found at `input_path` and - outputs them to the `output_dir`. + Wrap JSON blockchain test file(s) found at `input_path` and outputs them to + the `output_dir`. """ eof_wrapper = EofWrapper() @@ -116,7 +116,9 @@ class EofWrapper: GENERATION_ERRORS = "generation_errors" def __init__(self): - """Initialize the EofWrapper with metrics tracking and a unique EOF set.""" + """ + Initialize the EofWrapper with metrics tracking and a unique EOF set. + """ self.metrics = { self.FILES_GENERATED: 0, self.FILES_SKIPPED: 0, @@ -135,7 +137,8 @@ def __init__(self): file_skip_list = [ "Pyspecs", - # EXTCODE* opcodes return different results for EOF targets and that is tested elsewhere + # EXTCODE* opcodes return different results for EOF targets and that is + # tested elsewhere "stExtCodeHash", # bigint syntax "ValueOverflowParis", @@ -168,10 +171,11 @@ def __init__(self): def wrap_file(self, in_path: str, out_path: str, traces: bool): """ - Wrap code from a blockchain test JSON file from `in_path` into EOF containers, - wherever possible. If not possible - skips and tracks that in metrics. Possible means - at least one account's code can be wrapped in a valid EOF container and the assertions - on post state are satisfied. + Wrap code from a blockchain test JSON file from `in_path` into EOF + containers, wherever possible. If not possible - skips and tracks that + in metrics. Possible means at least one account's code can be wrapped + in a valid EOF container and the assertions on post state are + satisfied. """ for skip in self.file_skip_list: if skip in in_path: @@ -301,9 +305,9 @@ def _wrap_fixture(self, fixture: BlockchainFixture, traces: bool): test.blocks.append(block) elif isinstance(fixture_block, InvalidFixtureBlock): - # Skip - invalid blocks are not supported. Reason: FixtureTransaction doesn't - # support expected exception. But we can continue and test the remaining - # blocks. + # Skip - invalid blocks are not supported. Reason: + # FixtureTransaction doesn't support expected exception. But we + # can continue and test the remaining blocks. self.metrics[self.INVALID_BLOCKS_SKIPPED] += 1 else: raise TypeError("not a FixtureBlock") @@ -331,13 +335,13 @@ def _validate_eof(self, container: Container, metrics: bool = True) -> bool: return True -# `no_type_check` required because OpcodeWithOperand.opcode can be `None` when formatting as a -# string, but here it can never be `None`. +# `no_type_check` required because OpcodeWithOperand.opcode can be `None` when +# formatting as a string, but here it can never be `None`. @no_type_check def wrap_code(account_code: Bytes) -> Container: """ - Wrap `account_code` into a simplest EOF container, applying some simple heuristics in - order to obtain a valid code section termination. + Wrap `account_code` into a simplest EOF container, applying some simple + heuristics in order to obtain a valid code section termination. """ assert len(account_code) > 0 diff --git a/cli/evm_bytes.py b/cli/evm_bytes.py index 1b847ed97f..7f4a73f096 100644 --- a/cli/evm_bytes.py +++ b/cli/evm_bytes.py @@ -62,7 +62,8 @@ def terminating(self) -> bool: @property def bytecode(self) -> Bytecode: """Opcode as bytecode with its operands if any.""" - # opcode.opcode[*opcode.operands] crashes `black` formatter and doesn't work. + # opcode.opcode[*opcode.operands] crashes `black` formatter and doesn't + # work. if self.opcode: return self.opcode.__getitem__(*self.operands) if self.operands else self.opcode else: @@ -181,7 +182,8 @@ def hex_string(hex_string: str, assembly: bool): Output 1: \b - Op.PUSH1[0x42] + Op.PUSH1[0x0] + Op.MSTORE + Op.PUSH1[0x20] + Op.PUSH1[0x0] + Op.RETURN + Op.PUSH1[0x42] + Op.PUSH1[0x0] + Op.MSTORE + Op.PUSH1[0x20] + + Op.PUSH1[0x0] + Op.RETURN Example 2: Convert a hex string to assembly uv run evm_bytes hex-string --assembly 604260005260206000F3 @@ -207,14 +209,16 @@ def binary_file(binary_file, assembly: bool): """ Convert the BINARY_FILE containing EVM bytes to Python Opcodes or assembly. - BINARY_FILE is a binary file containing EVM bytes, use `-` to read from stdin. + BINARY_FILE is a binary file containing EVM bytes, use `-` to read from + stdin. Returns: (str): The processed EVM opcodes in Python or assembly format. Example: Convert the Withdrawal Request contract to assembly \b - uv run evm_bytes binary-file ./src/ethereum_test_forks/forks/contracts/withdrawal_request.bin --assembly + uv run evm_bytes binary-file ./src/ethereum_test_forks/forks/ + contracts/withdrawal_request.bin --assembly Output: \b @@ -225,6 +229,6 @@ def binary_file(binary_file, assembly: bool): jumpi ... - """ # noqa: E501,D301 + """ # noqa: D301 processed_output = format_opcodes(process_evm_bytes(binary_file.read()), assembly=assembly) click.echo(processed_output) diff --git a/cli/extract_config.py b/cli/extract_config.py index 503c352eb1..bf0e1f717c 100755 --- a/cli/extract_config.py +++ b/cli/extract_config.py @@ -1,9 +1,11 @@ #!/usr/bin/env python """ -CLI tool to extract client configuration files (chainspec/genesis.json) from Ethereum clients. +CLI tool to extract client configuration files (chainspec/genesis.json) from +Ethereum clients. -This tool spawns an Ethereum client using Hive and extracts the generated configuration -files such as /chainspec/test.json, /configs/test.cfg, or /genesis.json from the Docker container. +This tool spawns an Ethereum client using Hive and extracts the generated +configuration files such as /chainspec/test.json, /configs/test.cfg, or +/genesis.json from the Docker container. """ import io @@ -119,7 +121,9 @@ def create_genesis_from_fixture(fixture_path: Path) -> Tuple[FixtureHeader, Allo def get_client_environment_for_fixture(fork: Fork, chain_id: int) -> dict: - """Get the environment variables for starting a client with the given fixture.""" + """ + Get the environment variables for starting a client with the given fixture. + """ if fork not in ruleset: raise ValueError(f"Fork '{fork}' not found in hive ruleset") @@ -176,8 +180,8 @@ def extract_config( Extract client configuration files from Ethereum clients. This tool spawns an Ethereum client using Hive and extracts the generated - configuration files such as /chainspec/test.json, /configs/test.cfg, or /genesis.json - from the Docker container. + configuration files such as /chainspec/test.json, /configs/test.cfg, or + /genesis.json from the Docker container. """ if not fixture: raise click.UsageError("No fixture provided, use --fixture to specify a fixture") diff --git a/cli/fillerconvert/fillerconvert.py b/cli/fillerconvert/fillerconvert.py index 6cb7a5f3b5..c7392fd420 100644 --- a/cli/fillerconvert/fillerconvert.py +++ b/cli/fillerconvert/fillerconvert.py @@ -44,5 +44,6 @@ def main() -> None: # or file.endswith("vmPerformance/performanceTesterFiller.yml") # or file.endswith("vmPerformance/loopExpFiller.yml") # or file.endswith("vmPerformance/loopMulFiller.yml") - # or file.endswith("stRevertTest/RevertRemoteSubCallStorageOOGFiller.yml") + # or + # file.endswith("stRevertTest/RevertRemoteSubCallStorageOOGFiller.yml") # or file.endswith("stSolidityTest/SelfDestructFiller.yml") diff --git a/cli/fillerconvert/verify_filled.py b/cli/fillerconvert/verify_filled.py index 706d62ac3e..3c3302342e 100644 --- a/cli/fillerconvert/verify_filled.py +++ b/cli/fillerconvert/verify_filled.py @@ -34,10 +34,9 @@ class FilledStateTest(RootModel[dict[str, StateTest]]): def verify_refilled(refilled: Path, original: Path) -> int: """ - Verify post hash of the refilled test against original: - Regex the original d,g,v from the refilled test name. - Find the post record for this d,g,v and the fork of refilled test. - Compare the post hash. + Verify post hash of the refilled test against original: Regex the original + d,g,v from the refilled test name. Find the post record for this d,g,v and + the fork of refilled test. Compare the post hash. """ verified_vectors = 0 json_str = refilled.read_text(encoding="utf-8") @@ -46,7 +45,8 @@ def verify_refilled(refilled: Path, original: Path) -> int: json_str = original.read_text(encoding="utf-8") original_test_wrapper = FilledStateTest.model_validate_json(json_str) - # Each original test has only 1 test with many posts for each fork and many txs + # Each original test has only 1 test with many posts for each fork and many + # txs original_test_name, test_original = list(original_test_wrapper.root.items())[0] for refilled_test_name, refilled_test in refilled_test_wrapper.root.items(): diff --git a/cli/gen_index.py b/cli/gen_index.py index a19e239431..e1d8de1af2 100644 --- a/cli/gen_index.py +++ b/cli/gen_index.py @@ -1,4 +1,6 @@ -"""Generate an index file of all the json fixtures in the specified directory.""" +""" +Generate an index file of all the json fixtures in the specified directory. +""" import datetime import json @@ -72,7 +74,9 @@ def count_json_files_exclude_index(start_path: Path) -> int: help="Force re-generation of the index file, even if it already exists.", ) def generate_fixtures_index_cli(input_dir: str, quiet_mode: bool, force_flag: bool): - """CLI wrapper to an index of all the fixtures in the specified directory.""" + """ + CLI wrapper to an index of all the fixtures in the specified directory. + """ generate_fixtures_index( Path(input_dir), quiet_mode=quiet_mode, diff --git a/cli/generate_checklist_stubs.py b/cli/generate_checklist_stubs.py index 36d3839b36..9468521dbf 100644 --- a/cli/generate_checklist_stubs.py +++ b/cli/generate_checklist_stubs.py @@ -86,16 +86,17 @@ def generate_checklist_stubs(output: str | None, dry_run: bool) -> None: Generate mypy stub files for EIPChecklist classes. This is a development tool that generates .pyi stub files to help mypy - understand that EIPChecklist classes are callable, fixing type checking issues. + understand that EIPChecklist classes are callable, fixing type checking + issues. Examples: - # Generate stub files (auto-detect location) + Generate stub files (auto-detect location): uv run generate_checklist_stubs - # Generate to specific location + Generate to specific location: uv run generate_checklist_stubs --output /path/to/stubs.pyi - # Preview content without writing + Preview content without writing: uv run generate_checklist_stubs --dry-run """ diff --git a/cli/gentest/request_manager.py b/cli/gentest/request_manager.py index e4eac7e11d..ac517b7490 100644 --- a/cli/gentest/request_manager.py +++ b/cli/gentest/request_manager.py @@ -1,13 +1,17 @@ """ -A request manager Ethereum RPC calls. +A request manager Ethereum RPC calls. -The RequestManager handles transactions and block data retrieval from a remote Ethereum node, -utilizing Pydantic models to define the structure of transactions and blocks. +The RequestManager handles transactions and block data retrieval from a remote +Ethereum node, utilizing Pydantic models to define the structure of +transactions and blocks. Classes: -- RequestManager: The main class for managing RPC requests and responses. -- RemoteTransaction: A Pydantic model representing a transaction retrieved from the node. -- RemoteBlock: A Pydantic model representing a block retrieved from the node. + RequestManager: The main class for managing RPC requests and + responses. + RemoteTransaction: A Pydantic model representing a transaction + retrieved from the node. + RemoteBlock: A Pydantic model representing a block retrieved from + the node. """ from typing import Dict diff --git a/cli/gentest/source_code_generator.py b/cli/gentest/source_code_generator.py index e437631aad..d78dc82693 100644 --- a/cli/gentest/source_code_generator.py +++ b/cli/gentest/source_code_generator.py @@ -22,18 +22,22 @@ template_env.filters["stringify"] = lambda value: repr(value) -# generates a formatted pytest source code by writing provided data on a given template. +# generates a formatted pytest source code by writing provided data on a given +# template. def get_test_source(provider: Provider, template_path: str) -> str: """ - Generate formatted pytest source code by rendering a template with provided data. + Generate formatted pytest source code by rendering a template with provided + data. - This function uses the given template path to create a pytest-compatible source - code string. It retrieves context data from the specified provider and applies - it to the template. + This function uses the given template path to create a pytest-compatible + source code string. It retrieves context data from the specified provider + and applies it to the template. Args: - provider: An object that provides the necessary context for rendering the template. - template_path (str): The path to the Jinja2 template file used to generate tests. + provider: An object that provides the necessary context for rendering + the template. + template_path (str): The path to the Jinja2 template file + used to generate tests. Returns: str: The formatted pytest source code. @@ -49,11 +53,11 @@ def format_code(code: str) -> str: """ Format the provided Python code using the Black code formatter. - This function writes the given code to a temporary Python file, formats it using - the Black formatter, and returns the formatted code as a string. + This function writes the given code to a temporary Python file, formats it + using the Black formatter, and returns the formatted code as a string. Args: - code (str): The Python code to be formatted. + code (str): The Python code to be formatted. Returns: str: The formatted Python code. diff --git a/cli/gentest/test_context_providers.py b/cli/gentest/test_context_providers.py index f0cb5c3e02..42a56f3f0d 100644 --- a/cli/gentest/test_context_providers.py +++ b/cli/gentest/test_context_providers.py @@ -2,13 +2,14 @@ Various providers which generate contexts required to create test scripts. Classes: -- Provider: An provider generates required context for creating a test. -- BlockchainTestProvider: The BlockchainTestProvider takes a transaction hash and creates - required context to create a test. + Provider: An provider generates required context for creating a + test. + BlockchainTestProvider: The BlockchainTestProvider takes a transaction + hash and creates required context to create a test. Example: - provider = BlockchainTestContextProvider(transaction=transaction) - context = provider.get_context() + provider = BlockchainTestContextProvider(transaction=transaction) + context = provider.get_context() """ @@ -80,7 +81,8 @@ def _get_pre_state(self) -> Dict[str, Account]: def _get_transaction(self) -> Transaction: assert self.transaction_response is not None - # Validate the RPC TransactionHashResponse and convert it to a Transaction instance. + # Validate the RPC TransactionHashResponse and convert it to a + # Transaction instance. return Transaction.model_validate(self.transaction_response.model_dump()) def get_context(self) -> Dict[str, Any]: @@ -89,7 +91,7 @@ def get_context(self) -> Dict[str, Any]: Returns: Dict[str, Any]: A dictionary containing environment, - pre-state, a transaction and its hash. + pre-state, a transaction and its hash. """ self._make_rpc_calls() diff --git a/cli/gentest/test_providers.py b/cli/gentest/test_providers.py index dc29d306ee..d9cdeaba6a 100644 --- a/cli/gentest/test_providers.py +++ b/cli/gentest/test_providers.py @@ -1,14 +1,21 @@ """ -Contains various providers which generates context required to create test scripts. +Contains various providers which generates context required to create test +scripts. Classes: -- BlockchainTestProvider: The BlockchainTestProvider class takes information about a block, -a transaction, and the associated state, and provides methods to generate various elements -needed for testing, such as module docstrings, test names, and pre-state items. + BlockchainTestProvider: The BlockchainTestProvider class takes + information about a block, a transaction, and the + associated state, and provides methods to generate + various elements needed for testing, such as module + docstrings, test names, and pre-state items. Example: - provider = BlockchainTestProvider(block=block, transaction=transaction, state=state) - context = provider.get_context() + provider = BlockchainTestProvider( + block=block, + transaction=transaction, + state=state + ) + context = provider.get_context() """ @@ -22,7 +29,9 @@ class BlockchainTestProvider(BaseModel): - """Provides context required to generate a `blockchain_test` using pytest.""" + """ + Provides context required to generate a `blockchain_test` using pytest. + """ block: Environment transaction: TransactionByHashResponse @@ -103,8 +112,9 @@ def get_context(self) -> Dict[str, Any]: Get the context for generating a blockchain test. Returns: - Dict[str, Any]: A dictionary containing module docstring, test name, - test docstring, environment kwargs, pre-state items, and transaction items. + Dict[str, Any]: A dictionary containing module docstring, test + name, test docstring, environment kwargs, + pre-state items, and transaction items. """ return { diff --git a/cli/gentest/tests/test_cli.py b/cli/gentest/tests/test_cli.py index c8d9a869c6..cac98388d9 100644 --- a/cli/gentest/tests/test_cli.py +++ b/cli/gentest/tests/test_cli.py @@ -92,10 +92,10 @@ def transaction_hash(tx_type: int) -> str: # noqa: D103 @pytest.mark.parametrize("tx_type", list(transactions_by_type.keys())) def test_tx_type(pytester, tmp_path, monkeypatch, tx_type, transaction_hash, default_t8n): """Generates a test case for any transaction type.""" - ## Arrange ## - # This test is run in a CI environment, where connection to a node could be - # unreliable. Therefore, we mock the RPC request to avoid any network issues. - # This is done by patching the `get_context` method of the `StateTestProvider`. + # This test is run in a CI environment, where connection to a + # node could be unreliable. Therefore, we mock the RPC request to avoid any + # network issues. This is done by patching the `get_context` method of the + # `StateTestProvider`. runner = CliRunner() tmp_path_tests = tmp_path / "tests" tmp_path_tests.mkdir() diff --git a/cli/hasher.py b/cli/hasher.py index bd5caaeca5..ab1dd87480 100644 --- a/cli/hasher.py +++ b/cli/hasher.py @@ -20,7 +20,10 @@ class HashableItemType(IntEnum): @dataclass(kw_only=True) class HashableItem: - """Represents an item that can be hashed containing other items that can be hashed as well.""" + """ + Represents an item that can be hashed containing other items that can be + hashed as well. + """ type: HashableItemType parents: List[str] = field(default_factory=list) diff --git a/cli/input/input_repository.py b/cli/input/input_repository.py index 0a75d14de8..83b31c830b 100644 --- a/cli/input/input_repository.py +++ b/cli/input/input_repository.py @@ -6,8 +6,8 @@ class InputRepository(ABC): """ - Abstract base class for input handling. - This class defines the interface for different input types that can be swapped out. + Abstract base class for input handling. This class defines the interface + for different input types that can be swapped out. """ @abstractmethod diff --git a/cli/input/questionary_input_repository.py b/cli/input/questionary_input_repository.py index af0e2e144c..8ddc6b18b6 100644 --- a/cli/input/questionary_input_repository.py +++ b/cli/input/questionary_input_repository.py @@ -9,7 +9,10 @@ class QuestionaryInputRepository(InputRepository): - """Repository for handling various types of user inputs using the Questionary library.""" + """ + Repository for handling various types of user inputs using the Questionary + library. + """ def input_text(self, question: str) -> str: """Ask a text input question.""" diff --git a/cli/modify_static_test_gas_limits.py b/cli/modify_static_test_gas_limits.py index 17f0b5137c..35a259d88f 100644 --- a/cli/modify_static_test_gas_limits.py +++ b/cli/modify_static_test_gas_limits.py @@ -1,6 +1,6 @@ """ -Command to scan and overwrite the static tests' gas limits to new optimized value given in the -input file. +Command to scan and overwrite the static tests' gas limits to new optimized +value given in the input file. """ import json @@ -46,7 +46,9 @@ class StaticTestFile(EthereumTestRootModel): def _check_fixtures(*, input_path: Path, max_gas_limit: int | None, dry_run: bool, verbose: bool): - """Perform some checks on the fixtures contained in the specified directory.""" + """ + Perform some checks on the fixtures contained in the specified directory. + """ # Load the test dictionary from the input JSON file test_dict = GasLimitDict.model_validate_json(input_path.read_text()) @@ -207,7 +209,9 @@ def _check_fixtures(*, input_path: Path, max_gas_limit: int | None, dry_run: boo help="Print extra information.", ) def main(input_str: str, max_gas_limit, dry_run: bool, verbose: bool): - """Perform some checks on the fixtures contained in the specified directory.""" + """ + Perform some checks on the fixtures contained in the specified directory. + """ input_path = Path(input_str) if not dry_run: # Always dry-run first before actually modifying diff --git a/cli/order_fixtures.py b/cli/order_fixtures.py index 7b90281452..d35412e755 100644 --- a/cli/order_fixtures.py +++ b/cli/order_fixtures.py @@ -1,18 +1,17 @@ """ Functions and CLI interface for recursively ordering and sorting .json files. -example: Usage - - ``` - order_fixtures -i input_dir -o output_dir - ``` +Usage Example: +```console + order_fixtures -i input_dir -o output_dir +``` The CLI interface takes the paths of an input directory and an output directory. It recursively processes each .json file in the input directory and -its subdirectories, and sorts lists and dictionaries alphabetically and -writes the sorted output to .json files to the corresponding locations in the -output directory. +its subdirectories, and sorts lists and dictionaries alphabetically and writes +the sorted output to .json files to the corresponding locations in the output +directory. """ import json @@ -27,16 +26,15 @@ def recursive_sort(item: Dict[str, Any] | List[Any]) -> Dict[str, Any] | List[An Recursively sorts an item. If the item is a dictionary, it returns a new dictionary that is a sorted - version of the input dictionary. - If the item is a list, it returns a new list that is a sorted version of the - input list. The elements of the list are also sorted if they are lists or - dictionaries. + version of the input dictionary. If the item is a list, it returns a new + list that is a sorted version of the input list. The elements of the list + are also sorted if they are lists or dictionaries. Args: - item: The item to be sorted. This can be a list or a dictionary. + item: The item to be sorted. This can be a list or a dictionary. Returns: - The sorted item. + The sorted item. """ if isinstance(item, dict): @@ -45,8 +43,8 @@ def recursive_sort(item: Dict[str, Any] | List[Any]) -> Dict[str, Any] | List[An try: return sorted(cast(List[Any], [recursive_sort(x) for x in item])) except TypeError: - # If a TypeError is raised, we might be dealing with a list of dictionaries - # Sort them based on their string representation + # If a TypeError is raised, we might be dealing with a list of + # dictionaries Sort them based on their string representation return sorted((recursive_sort(x) for x in item), key=str) else: return item @@ -60,8 +58,8 @@ def order_fixture(input_path: Path, output_path: Path) -> None: to the output path. Args: - input_path: The Path object of the input .json file. - output_path: The Path object of the output .json file. + input_path: The Path object of the input .json file. + output_path: The Path object of the output .json file. Returns: None. @@ -78,9 +76,9 @@ def process_directory(input_dir: Path, output_dir: Path): """ Process a directory. - Processes each .json file in the input directory and its subdirectories, and - writes the sorted .json files to the corresponding locations in the output - directory. + Processes each .json file in the input directory and its subdirectories, + and writes the sorted .json files to the corresponding locations in the + output directory. Args: input_dir: The Path object of the input directory. @@ -106,7 +104,7 @@ def process_directory(input_dir: Path, output_dir: Path): "input_dir", type=click.Path(exists=True, file_okay=False, dir_okay=True, readable=True), required=True, - help="The input directory", + help="input directory", ) @click.option( "--output", diff --git a/cli/pytest_commands/base.py b/cli/pytest_commands/base.py index 7061741e47..444de79561 100644 --- a/cli/pytest_commands/base.py +++ b/cli/pytest_commands/base.py @@ -24,7 +24,10 @@ class PytestExecution: """Path to the pytest configuration file (e.g., 'pytest-fill.ini').""" command_logic_test_paths: List[str] = field(default_factory=list) - """List of tests that have to be appended to the start of pytest command arguments.""" + """ + List of tests that have to be appended to the start of pytest command + arguments. + """ args: List[str] = field(default_factory=list) """Arguments to pass to pytest.""" @@ -80,7 +83,8 @@ def run_multiple(self, executions: List[PytestExecution]) -> int: """ Run multiple pytest executions in sequence. - Returns the exit code of the final execution, or the first non-zero exit code. + Returns the exit code of the final execution, or the first non-zero + exit code. """ for i, execution in enumerate(executions): if execution.description and len(executions) > 1: @@ -102,8 +106,8 @@ class PytestCommand: """ Base class for pytest-based CLI commands. - Provides a standard structure for commands that execute pytest - with specific configurations and argument processing. + Provides a standard structure for commands that execute pytest with + specific configurations and argument processing. """ config_file: str @@ -138,8 +142,8 @@ def execute(self, pytest_args: List[str]) -> None: @property def test_args(self) -> List[str]: """ - Return the test-path arguments that have to be appended to all PytestExecution - instances. + Return the test-path arguments that have to be appended to all + PytestExecution instances. """ if self.command_logic_test_paths: return [str(path) for path in self.command_logic_test_paths] @@ -149,8 +153,8 @@ def create_executions(self, pytest_args: List[str]) -> List[PytestExecution]: """ Create the list of pytest executions for this command. - This method can be overridden by subclasses to implement - multi-phase execution (e.g., for future fill command). + This method can be overridden by subclasses to implement multi-phase + execution (e.g., for future fill command). """ processed_args = self.process_arguments(pytest_args) return [ diff --git a/cli/pytest_commands/fill.py b/cli/pytest_commands/fill.py index f0f3ce5328..87d5af0041 100644 --- a/cli/pytest_commands/fill.py +++ b/cli/pytest_commands/fill.py @@ -26,10 +26,12 @@ def __init__(self, **kwargs): def create_executions(self, pytest_args: List[str]) -> List[PytestExecution]: """ - Create execution plan that supports two-phase pre-allocation group generation. + Create execution plan that supports two-phase pre-allocation group + generation. Returns single execution for normal filling, or two-phase execution - when --generate-pre-alloc-groups or --generate-all-formats is specified. + when --generate-pre-alloc-groups or --generate-all-formats is + specified. """ processed_args = self.process_arguments(pytest_args) @@ -50,7 +52,10 @@ def create_executions(self, pytest_args: List[str]) -> List[PytestExecution]: ] def _create_two_phase_executions(self, args: List[str]) -> List[PytestExecution]: - """Create two-phase execution: pre-allocation group generation + fixture filling.""" + """ + Create two-phase execution: pre-allocation group generation + fixture + filling. + """ # Phase 1: Pre-allocation group generation (clean and minimal output) phase1_args = self._create_phase1_args(args) @@ -87,14 +92,16 @@ def _create_phase1_args(self, args: List[str]) -> List[str]: # Add required phase 1 flags (with quiet output by default) phase1_args = [ "--generate-pre-alloc-groups", - "-qq", # Quiet pytest output by default (user -v/-vv/-vvv can override) + "-qq", # Quiet pytest output by default (user -v/-vv/-vvv can + # override) ] + filtered_args return phase1_args def _create_phase2_args(self, args: List[str]) -> List[str]: """Create arguments for phase 2 (fixture filling).""" - # Remove --generate-pre-alloc-groups and --clean, then add --use-pre-alloc-groups + # Remove --generate-pre-alloc-groups and --clean, then add --use-pre- + # alloc-groups phase2_args = self._remove_generate_pre_alloc_groups_flag(args) phase2_args = self._remove_clean_flag(phase2_args) phase2_args = self._add_use_pre_alloc_groups_flag(phase2_args) @@ -138,7 +145,10 @@ def _remove_unwanted_phase1_args(self, args: List[str]) -> List[str]: return filtered_args def _remove_generate_pre_alloc_groups_flag(self, args: List[str]) -> List[str]: - """Remove --generate-pre-alloc-groups flag but keep --generate-all-formats for phase 2.""" + """ + Remove --generate-pre-alloc-groups flag but keep --generate-all-formats + for phase 2. + """ return [arg for arg in args if arg != "--generate-pre-alloc-groups"] def _remove_clean_flag(self, args: List[str]) -> List[str]: @@ -181,7 +191,10 @@ def _is_watch_mode(self, args: List[str]) -> bool: return any(flag in args for flag in ["--watch", "--watcherfall"]) def _is_verbose_watch_mode(self, args: List[str]) -> bool: - """Check if verbose watch flag (--watcherfall) is present in arguments.""" + """ + Check if verbose watch flag (--watcherfall) + is present in arguments. + """ return "--watcherfall" in args def execute(self, pytest_args: List[str]) -> None: @@ -257,5 +270,6 @@ def phil(pytest_args: List[str], **kwargs) -> None: if __name__ == "__main__": - # to allow debugging in vscode: in launch config, set "module": "cli.pytest_commands.fill" + # to allow debugging in vscode: in launch config, set "module": + # "cli.pytest_commands.fill" fill(prog_name="fill") diff --git a/cli/pytest_commands/processors.py b/cli/pytest_commands/processors.py index ef6a44dd1e..b63cd3a132 100644 --- a/cli/pytest_commands/processors.py +++ b/cli/pytest_commands/processors.py @@ -18,8 +18,9 @@ def __init__(self, command_type: str, required_args: List[str] | None = None): Initialize the help processor. Args: - command_type: The type of command (e.g., "fill", "consume", "execute") - required_args: The arguments that are required for the command to run + command_type: The type of command (e.g., "fill", "consume", + "execute") + required_args: The arguments that are required for the command to run """ self.command_type = command_type @@ -48,8 +49,8 @@ class StdoutFlagsProcessor(ArgumentProcessor): def process_args(self, args: List[str]) -> List[str]: """ - If the user has requested to write to stdout, add pytest arguments - to suppress pytest's test session header and summary output. + If the user has requested to write to stdout, add pytest arguments to + suppress pytest's test session header and summary output. """ if not self._is_writing_to_stdout(args): return args @@ -119,10 +120,16 @@ def _has_parallelism_flag(self, args: List[str]) -> bool: class WatchFlagsProcessor(ArgumentProcessor): - """Processes --watch and --watcherfall flags for file watching functionality.""" + """ + Processes --watch and --watcherfall flags + for file watching functionality. + """ def process_args(self, args: List[str]) -> List[str]: - """Remove --watch and --watcherfall flags from args passed to pytest.""" + """ + Remove --watch and --watcherfall + flags from args passed to pytest. + """ return [arg for arg in args if arg not in ["--watch", "--watcherfall"]] @@ -134,7 +141,7 @@ def __init__(self, is_hive: bool = False): Initialize the consume processor. Args: - is_hive: Whether this is a hive-based consume command + is_hive: Whether this is a hive-based consume command """ self.is_hive = is_hive diff --git a/cli/show_pre_alloc_group_stats.py b/cli/show_pre_alloc_group_stats.py index c7cf51cedf..492c1f0c6a 100644 --- a/cli/show_pre_alloc_group_stats.py +++ b/cli/show_pre_alloc_group_stats.py @@ -15,7 +15,9 @@ def extract_test_module(test_id: str) -> str: """Extract test module path from test ID.""" - # Example: tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py::test_beacon_root_contract_calls[fork_Cancun] # noqa: E501 + # Example: + # tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py:: + # test_beacon_root_contract_calls[fork_Cancun] if "::" in test_id: return test_id.split("::")[0] return "unknown" @@ -23,8 +25,12 @@ def extract_test_module(test_id: str) -> str: def extract_test_function(test_id: str) -> str: """Extract test function name from test ID (without parameters).""" - # Example: tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py::test_beacon_root_contract_calls[fork_Cancun] # noqa: E501 - # Returns: tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py::test_beacon_root_contract_calls # noqa: E501 + # Example: + # tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py:: + # test_beacon_root_contract_calls[fork_Cancun] + # Returns: + # tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py:: + # test_beacon_root_contract_calls if "::" in test_id: parts = test_id.split("::") if len(parts) >= 2: @@ -43,9 +49,10 @@ def calculate_size_distribution( Calculate frequency distribution of group sizes with appropriate binning. Returns: - - Group count distribution: [(range_label, group_count), ...] - - Test count distribution: [(range_label, test_count, cumulative_remaining, group_count), - ...] + Group count distribution: [(range_label, group_count), ...] + Test count distribution: [(range_label, test_count, + cumulative_remaining, + group_count), ...] """ if not test_counts: @@ -80,12 +87,15 @@ def calculate_size_distribution( # Test count distribution with group count tests_in_bin = sum(groups_in_bin) - test_distribution.append((label, tests_in_bin, 0, group_count)) # Added group_count + # Added group_count + test_distribution.append((label, tests_in_bin, 0, group_count)) - # Calculate cumulative values - # For the table sorted from largest to smallest: - # - Row N shows: if we exclude groups of size N and smaller, what % of tests remain? - # - Row N shows: if we include groups of size N and larger, how many groups is that? + # Calculate cumulative values For the table sorted from largest to + # smallest: + # Row N shows: if we exclude groups of size N and smaller, what + # percent of tests remain? + # Row N shows: if we include groups of size N and + # larger, how many groups is that? cumulative_remaining_tests = 0 cumulative_groups = 0 @@ -167,7 +177,8 @@ class SplitTestFunction(CamelModel): split_test_functions[test_function].groups += 1 split_test_functions[test_function].forks.add(fork) - # Filter to only test functions with multiple size-1 groups and calculate ratios + # Filter to only test functions with multiple size-1 groups and calculate + # ratios split_functions = {} for func, split_test_function in split_test_functions.items(): if split_test_function.groups > 1: @@ -355,7 +366,8 @@ def display_stats(stats: Dict, console: Console, verbose: int = 0): # Sort modules by group count (descending) - shows execution complexity sorted_modules = sorted( stats["module_stats"].items(), - key=lambda x: (-x[1]["groups"], -x[1]["tests"]), # Secondary sort by tests + # Secondary sort by tests + key=lambda x: (-x[1]["groups"], -x[1]["tests"]), ) # Show all modules if -vv, otherwise top 15 @@ -412,7 +424,8 @@ def display_stats(stats: Dict, console: Console, verbose: int = 0): # Shorten function path for display display_function = test_function if display_function.startswith("tests/"): - display_function = display_function[6:] # Remove "tests/" prefix + display_function = display_function[6:] # Remove "tests/" + # prefix split_table.add_row( display_function, @@ -475,7 +488,6 @@ def main(pre_alloc_folder: Path, verbose: int): The pre_alloc file is generated when running tests with the --generate-pre-alloc-groups and --use-pre-alloc-groups flags to optimize test execution by grouping tests with identical pre-allocation state. - """ console = Console() diff --git a/cli/tests/test_evm_bytes.py b/cli/tests/test_evm_bytes.py index 64bebd4182..e7e32a81e3 100644 --- a/cli/tests/test_evm_bytes.py +++ b/cli/tests/test_evm_bytes.py @@ -8,7 +8,9 @@ basic_vector = [ "0x60008080808061AAAA612d5ff1600055", - "Op.PUSH1[0x0] + Op.DUP1 + Op.DUP1 + Op.DUP1 + Op.DUP1 + Op.PUSH2[0xaaaa] + Op.PUSH2[0x2d5f] + Op.CALL + Op.PUSH1[0x0] + Op.SSTORE", # noqa: E501 + "Op.PUSH1[0x0] + Op.DUP1 + Op.DUP1 + Op.DUP1 + Op.DUP1 + " + "Op.PUSH2[0xaaaa] + Op.PUSH2[0x2d5f] + Op.CALL + Op.PUSH1[0x0] + " + "Op.SSTORE", ] complex_vector = [ "0x7fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf5f527fc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf6020527fe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff60405260786040356020355f35608a565b5f515f55602051600155604051600255005b5e56", # noqa: E501 @@ -24,8 +26,9 @@ ] rjumpv_vector = [ "0xe213b1465aef60276095472e3250cf64736f6c63430008150033a26469706673582212206eab0a7969fe", - "Op.RJUMPV[-0x4eba, 0x5aef, 0x6027, 0x6095, 0x472e, 0x3250, -0x309c, 0x736f, 0x6c63, 0x4300," - + " 0x815, 0x33, -0x5d9c, 0x6970, 0x6673, 0x5822, 0x1220, 0x6eab, 0xa79, 0x69fe]", + "Op.RJUMPV[-0x4eba, 0x5aef, 0x6027, 0x6095, 0x472e, 0x3250, -0x309c, " + "0x736f, 0x6c63, 0x4300," + " 0x815, 0x33, -0x5d9c, 0x6970, 0x6673, 0x5822, 0x1220, 0x6eab, " + "0xa79, 0x69fe]", ] diff --git a/cli/tests/test_generate_all_formats.py b/cli/tests/test_generate_all_formats.py index 9f49678464..a939f61932 100644 --- a/cli/tests/test_generate_all_formats.py +++ b/cli/tests/test_generate_all_formats.py @@ -30,7 +30,9 @@ def test_generate_all_formats_creates_two_phase_execution(): def test_generate_all_formats_preserves_other_args(): - """Test that --generate-all-formats preserves other command line arguments.""" + """ + Test that --generate-all-formats preserves other command line arguments. + """ command = FillCommand() with patch.object(command, "process_arguments", side_effect=lambda x: x): @@ -86,7 +88,8 @@ def test_legacy_generate_pre_alloc_groups_still_works(): phase1_args = executions[0].args assert "--generate-pre-alloc-groups" in phase1_args - # Phase 2: Should have --use-pre-alloc-groups but NOT --generate-all-formats + # Phase 2: Should have --use-pre-alloc-groups but NOT --generate-all- + # formats phase2_args = executions[1].args assert "--use-pre-alloc-groups" in phase2_args assert "--generate-all-formats" not in phase2_args @@ -110,7 +113,9 @@ def test_single_phase_without_flags(): def test_tarball_output_auto_enables_generate_all_formats(): - """Test that tarball output automatically enables --generate-all-formats.""" + """ + Test that tarball output automatically enables --generate-all-formats. + """ command = FillCommand() with patch.object(command, "process_arguments", side_effect=lambda x: x): @@ -124,7 +129,8 @@ def test_tarball_output_auto_enables_generate_all_formats(): phase1_args = executions[0].args assert "--generate-pre-alloc-groups" in phase1_args - # Phase 2: Should have --generate-all-formats (auto-added) and --use-pre-alloc-groups + # Phase 2: Should have --generate-all-formats (auto-added) and --use-pre- + # alloc-groups phase2_args = executions[1].args assert "--generate-all-formats" in phase2_args assert "--use-pre-alloc-groups" in phase2_args @@ -132,7 +138,10 @@ def test_tarball_output_auto_enables_generate_all_formats(): def test_tarball_output_with_explicit_generate_all_formats(): - """Test that explicit --generate-all-formats with tarball output works correctly.""" + """ + Test that explicit --generate-all-formats with tarball output works + correctly. + """ command = FillCommand() with patch.object(command, "process_arguments", side_effect=lambda x: x): @@ -150,7 +159,10 @@ def test_tarball_output_with_explicit_generate_all_formats(): def test_regular_output_does_not_auto_trigger_two_phase(): - """Test that regular directory output doesn't auto-trigger two-phase execution.""" + """ + Test that regular directory output doesn't auto-trigger two-phase + execution. + """ command = FillCommand() with patch.object(command, "process_arguments", side_effect=lambda x: x): diff --git a/cli/tests/test_order_fixtures.py b/cli/tests/test_order_fixtures.py index 27a88ceef7..0c3f2db4f7 100644 --- a/cli/tests/test_order_fixtures.py +++ b/cli/tests/test_order_fixtures.py @@ -57,7 +57,9 @@ def test_cli_invocation(input_output_dirs): def test_input_is_file_instead_of_directory(): - """Test the CLI interface when the input path is a file, not a directory.""" + """ + Test the CLI interface when the input path is a file, not a directory. + """ runner = CliRunner() with TemporaryDirectory() as temp_dir: temp_file = Path(temp_dir) / "temp_file.txt" diff --git a/cli/tests/test_pytest_fill_command.py b/cli/tests/test_pytest_fill_command.py index 95c3a3e8f4..0386b05d4e 100644 --- a/cli/tests/test_pytest_fill_command.py +++ b/cli/tests/test_pytest_fill_command.py @@ -50,11 +50,12 @@ class TestHtmlReportFlags: @pytest.fixture def fill_args(self, default_t8n): """ - Provide default arguments for the `fill` command when testing html report - generation. + Provide default arguments for the `fill` command when testing html + report generation. - Specifies a single existing example test case for faster fill execution, - and to allow for tests to check for the fixture generation location. + Specifies a single existing example test case for faster fill + execution, and to allow for tests to check for the fixture generation + location. """ return [ "-k", @@ -81,8 +82,8 @@ def monkeypatch_default_output_directory(self, monkeypatch, temp_dir): """ Monkeypatch default output directory for the pytest commands. - This avoids using the local directory in user space for the output of pytest - commands and uses the a temporary directory instead. + This avoids using the local directory in user space for the output of + pytest commands and uses the a temporary directory instead. """ def mock_default_output_directory(): @@ -101,7 +102,10 @@ def test_fill_default_output_options( fill_args, default_html_report_file_path, ): - """Test default pytest html behavior: Neither `--html` or `--output` is specified.""" + """ + Test default pytest html behavior: Neither `--html` or `--output` is + specified. + """ default_html_path = temp_dir / default_html_report_file_path result = runner.invoke(fill, fill_args) assert result.exit_code == pytest.ExitCode.OK @@ -141,7 +145,9 @@ def test_fill_output_option( fill_args, default_html_report_file_path, ): - """Tests pytest html report generation with only the `--output` flag.""" + """ + Tests pytest html report generation with only the `--output` flag. + """ output_dir = temp_dir / "non_default_output_dir" non_default_html_path = output_dir / default_html_report_file_path fill_args += ["--output", str(output_dir)] @@ -156,7 +162,10 @@ def test_fill_html_and_output_options( temp_dir, fill_args, ): - """Tests pytest html report generation with both `--output` and `--html` flags.""" + """ + Tests pytest html report generation with both `--output` and `--html` + flags. + """ output_dir = temp_dir / "non_default_output_dir_fixtures" html_path = temp_dir / "non_default_output_dir_html" / "non_default.html" fill_args += ["--output", str(output_dir), "--html", str(html_path)] diff --git a/cli/tox_helpers.py b/cli/tox_helpers.py index 7dbe0c26cf..63b4cee668 100644 --- a/cli/tox_helpers.py +++ b/cli/tox_helpers.py @@ -2,8 +2,8 @@ CLI commands used by tox.ini. Contains wrappers to the external commands markdownlint-cli2 and pyspelling -(requires aspell) that fail silently if the command is not available. The -aim is to avoid disruption to external contributors. +(requires aspell) that fail silently if the command is not available. The aim +is to avoid disruption to external contributors. """ import os @@ -23,10 +23,11 @@ def write_github_summary(title: str, tox_env: str, error_message: str, fix_comma Write a summary to GitHub Actions when a check fails. Args: - title: The title of the check that failed - tox_env: The tox environment name (e.g., "spellcheck") - error_message: Description of what went wrong - fix_commands: List of commands to fix the issue locally + title: The title of the check that failed tox_env: The tox + environment name (e.g., "spellcheck") + tox_env: The tox environment + error_message: Description of what went wrong + fix_commands: List of commands to fix the issue locally """ if not os.environ.get("GITHUB_ACTIONS"): @@ -70,7 +71,8 @@ def markdownlint(args): """ markdownlint = shutil.which("markdownlint-cli2") if not markdownlint: - # Note: There's an additional step in test.yaml to run markdownlint-cli2 in GitHub Actions + # Note: There's an additional step in test.yaml to run markdownlint- + # cli2 in GitHub Actions click.echo("********* Install 'markdownlint-cli2' to enable markdown linting *********") sys.exit(0) @@ -194,7 +196,8 @@ def codespell(): @click.command() def validate_changelog(): """ - Validate changelog formatting to ensure bullet points end with proper punctuation. + Validate changelog formatting to ensure bullet points end with proper + punctuation. Checks that all bullet points (including nested ones) end with either: - A period (.) for regular entries diff --git a/config/docs.py b/config/docs.py index f081e92d15..ac6c7e93cd 100644 --- a/config/docs.py +++ b/config/docs.py @@ -2,7 +2,7 @@ A module for managing documentation-related configurations. Classes: -- DocsConfig: Holds configurations for documentation generation. + DocsConfig: Holds configurations for documentation generation. """ from pydantic import BaseModel @@ -19,5 +19,6 @@ class DocsConfig(BaseModel): DOCS_BASE_URL: str = "https://eest.ethereum.org" - # Documentation URLs prefixed with `DOCS_URL__` to avoid conflicts with other URLs + # Documentation URLs prefixed with `DOCS_URL__` to avoid conflicts with + # other URLs DOCS_URL__WRITING_TESTS: str = f"{DOCS_BASE_URL}/main/writing_tests/" diff --git a/config/env.py b/config/env.py index 0e2811b205..f2bf92b2f2 100644 --- a/config/env.py +++ b/config/env.py @@ -1,12 +1,14 @@ """ A module for exposing application-wide environment variables. -This module is responsible for loading, parsing, and validating the application's -environment configuration from the `env.yaml` file. It uses Pydantic to ensure that -the configuration adheres to expected formats and types. +This module is responsible for loading, parsing, and validating the +application's environment configuration from the `env.yaml` file. It uses +Pydantic to ensure that the configuration adheres to expected formats and +types. Functions: -- create_default_config: Creates a default configuration file if it doesn't exist. +- create_default_config: Creates a default configuration file if it + doesn't exist. Classes: - EnvConfig: Loads the configuration and exposes it as Python objects. @@ -32,9 +34,11 @@ class RemoteNode(BaseModel): Represents a configuration for a remote node. Attributes: - - name (str): The name of the remote node. - - node_url (HttpUrl): The URL for the remote node, validated as a proper URL. - - rpc_headers (Dict[str, str]): A dictionary of optional RPC headers, defaults to empty dict. + name (str): The name of the remote node. + node_url (HttpUrl): The URL for the remote node, validated as a + proper URL. + rpc_headers (Dict[str, str]): A dictionary of optional RPC headers, + defaults to empty dict. """ @@ -48,7 +52,7 @@ class Config(BaseModel): Represents the overall environment configuration. Attributes: - - remote_nodes (List[RemoteNode]): A list of remote node configurations. + remote_nodes (List[RemoteNode]): A list of remote node configurations. """ @@ -59,8 +63,8 @@ class EnvConfig(Config): """ Loads and validates environment configuration from `env.yaml`. - This is a wrapper class for the Config model. It reads a config file - from disk into a Config model and then exposes it. + This is a wrapper class for the Config model. It reads a config file from + disk into a Config model and then exposes it. """ def __init__(self): diff --git a/conftest.py b/conftest.py index 59fb310c5f..82c42bb48b 100644 --- a/conftest.py +++ b/conftest.py @@ -14,7 +14,8 @@ for transition_tool in TransitionTool.registered_tools if ( transition_tool.is_installed() - # Currently, Besu has the same `default_binary` as Geth, so we can't use `is_installed`. + # Currently, Besu has the same `default_binary` as Geth, so we can't + # use `is_installed`. and transition_tool != BesuTransitionTool ) ] @@ -32,7 +33,8 @@ def installed_transition_tool_instances() -> Generator[ transition_tool_instance.start_server() instances[transition_tool_class.__name__] = transition_tool_instance except Exception as e: - # Record the exception in order to provide context when failing the appropriate test + # Record the exception in order to provide context when failing the + # appropriate test instances[transition_tool_class.__name__] = e yield instances for instance in instances.values(): diff --git a/ethereum_clis/__init__.py b/ethereum_clis/__init__.py index 9b2850b724..6a21ab3c2e 100644 --- a/ethereum_clis/__init__.py +++ b/ethereum_clis/__init__.py @@ -1,4 +1,7 @@ -"""Library of Python wrappers for the different implementations of transition tools.""" +""" +Library of Python wrappers for the different implementations of transition +tools. +""" from .cli_types import ( BlockExceptionWithMessage, diff --git a/ethereum_clis/cli_types.py b/ethereum_clis/cli_types.py index b6c9b48bad..d8745a1034 100644 --- a/ethereum_clis/cli_types.py +++ b/ethereum_clis/cli_types.py @@ -99,8 +99,8 @@ def from_file(cls, trace_file_path: Path) -> Self: @staticmethod def remove_gas(traces: List[TraceLine]): """ - Remove the GAS operation opcode result from the stack to make comparison possible - even if the gas has been pushed to the stack. + Remove the GAS operation opcode result from the stack to make + comparison possible even if the gas has been pushed to the stack. """ for i in range(1, len(traces)): trace = traces[i] @@ -143,7 +143,9 @@ def print(self): class Traces(EthereumTestRootModel): - """Traces returned from the transition tool for all transactions executed.""" + """ + Traces returned from the transition tool for all transactions executed. + """ root: List[TransactionTraces] diff --git a/ethereum_clis/clis/ethereumjs.py b/ethereum_clis/clis/ethereumjs.py index 45e7aed735..59214e00fa 100644 --- a/ethereum_clis/clis/ethereumjs.py +++ b/ethereum_clis/clis/ethereumjs.py @@ -39,13 +39,16 @@ def __init__( def is_fork_supported(self, fork: Fork) -> bool: """ Return True if the fork is supported by the tool. + Currently, EthereumJS-t8n provides no way to determine supported forks. """ return True class EthereumJSExceptionMapper(ExceptionMapper): - """Translate between EEST exceptions and error strings returned by EthereumJS.""" + """ + Translate between EEST exceptions and error strings returned by EthereumJS. + """ mapping_substring: ClassVar[Dict[ExceptionBase, str]] = { TransactionException.TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED: ( diff --git a/ethereum_clis/clis/ethrex.py b/ethereum_clis/clis/ethrex.py index 69cbbfde42..1d3c17a58d 100644 --- a/ethereum_clis/clis/ethrex.py +++ b/ethereum_clis/clis/ethrex.py @@ -48,7 +48,8 @@ class EthrexExceptionMapper(ExceptionMapper): r"blob versioned hashes not supported|" r"Type 3 transactions are not supported before the Cancun fork" ), - # A type 4 Transaction without a recipient won't even reach the EVM, we can't decode it. + # A type 4 Transaction without a recipient won't even reach the EVM, we + # can't decode it. TransactionException.TYPE_4_TX_CONTRACT_CREATION: ( r"unexpected length|Contract creation in type 4 transaction|" r"Error decoding field 'to' of type primitive_types::H160: InvalidLength" diff --git a/ethereum_clis/clis/evmone.py b/ethereum_clis/clis/evmone.py index c76dfd4cf9..e2f34f8fb0 100644 --- a/ethereum_clis/clis/evmone.py +++ b/ethereum_clis/clis/evmone.py @@ -37,14 +37,16 @@ def __init__( def is_fork_supported(self, fork: Fork) -> bool: """ - Return True if the fork is supported by the tool. - Currently, evmone-t8n provides no way to determine supported forks. + Return True if the fork is supported by the tool. Currently, evmone-t8n + provides no way to determine supported forks. """ return True class EvmoneExceptionMapper(ExceptionMapper): - """Translate between EEST exceptions and error strings returned by Evmone.""" + """ + Translate between EEST exceptions and error strings returned by Evmone. + """ mapping_substring: ClassVar[Dict[ExceptionBase, str]] = { TransactionException.SENDER_NOT_EOA: "sender not an eoa:", @@ -82,7 +84,8 @@ class EvmoneExceptionMapper(ExceptionMapper): ), TransactionException.NONCE_MISMATCH_TOO_LOW: "nonce too low", TransactionException.NONCE_MISMATCH_TOO_HIGH: "nonce too high", - # TODO EVMONE needs to differentiate when the section is missing in the header or body + # TODO EVMONE needs to differentiate when the section is missing in the + # header or body EOFException.MISSING_STOP_OPCODE: "err: no_terminating_instruction", EOFException.MISSING_CODE_HEADER: "err: code_section_missing", EOFException.MISSING_TYPE_HEADER: "err: type_section_missing", diff --git a/ethereum_clis/clis/execution_specs.py b/ethereum_clis/clis/execution_specs.py index 31b5dd2e43..ec2ac7a334 100644 --- a/ethereum_clis/clis/execution_specs.py +++ b/ethereum_clis/clis/execution_specs.py @@ -29,19 +29,22 @@ class ExecutionSpecsTransitionTool(TransitionTool): """ - Ethereum Specs EVM Resolver `ethereum-spec-evm-resolver` Transition Tool wrapper class. + Ethereum Specs EVM Resolver `ethereum-spec-evm-resolver` Transition Tool + wrapper class. - `ethereum-spec-evm-resolver` is installed by default for `execution-spec-tests`: + `ethereum-spec-evm-resolver` is installed by default for + `execution-spec-tests`: ```console - uv run fill --evm-bin=ethereum-spec-evm-resolver + uv run fill --evm-bin=ethereum-spec-evm-resolver ``` - To use a specific version of the `ethereum-spec-evm-resolver` tool, update it to the - desired version in `pyproject.toml`. + To use a specific version of the `ethereum-spec-evm-resolver` tool, update + it to the desired version in `pyproject.toml`. - The `ethereum-spec-evm-resolver` tool essentially wraps around the EELS evm daemon. It can - handle requests for different EVM forks, even when those forks are implemented by different - versions of EELS hosted in different places. + The `ethereum-spec-evm-resolver` tool essentially wraps around the EELS evm + daemon. It can handle requests for different EVM forks, even when those + forks are implemented by different versions of EELS hosted in different + places. """ default_binary = Path("ethereum-spec-evm-resolver") @@ -57,7 +60,9 @@ def __init__( trace: bool = False, server_url: str | None = None, ): - """Initialize the Ethereum Specs EVM Resolver Transition Tool interface.""" + """ + Initialize the Ethereum Specs EVM Resolver Transition Tool interface. + """ os.environ.setdefault("NO_PROXY", "*") # Disable proxy for local connections super().__init__( exception_mapper=ExecutionSpecsExceptionMapper(), binary=binary, trace=trace @@ -114,7 +119,8 @@ def is_fork_supported(self, fork: Fork) -> bool: """ Return True if the fork is supported by the tool. - If the fork is a transition fork, we want to check the fork it transitions to. + If the fork is a transition fork, we want to check the fork it + transitions to. `ethereum-spec-evm` appends newlines to forks in the help string. """ @@ -135,7 +141,10 @@ def _generate_post_args( class ExecutionSpecsExceptionMapper(ExceptionMapper): - """Translate between EEST exceptions and error strings returned by ExecutionSpecs.""" + """ + Translate between EEST exceptions and error strings returned by + ExecutionSpecs. + """ mapping_substring: ClassVar[Dict[ExceptionBase, str]] = { TransactionException.TYPE_4_EMPTY_AUTHORIZATION_LIST: "EmptyAuthorizationListError", diff --git a/ethereum_clis/clis/geth.py b/ethereum_clis/clis/geth.py index bf80527080..769315aa4b 100644 --- a/ethereum_clis/clis/geth.py +++ b/ethereum_clis/clis/geth.py @@ -200,7 +200,8 @@ def is_fork_supported(self, fork: Fork) -> bool: """ Return True if the fork is supported by the tool. - If the fork is a transition fork, we want to check the fork it transitions to. + If the fork is a transition fork, we want to check the fork it + transitions to. """ return fork.transition_tool_name() in self.help_string @@ -221,8 +222,8 @@ def consume_blockchain_test( """ Consume a single blockchain test. - The `evm blocktest` command takes the `--run` argument which can be used to select a - specific fixture from the fixture file when executing. + The `evm blocktest` command takes the `--run` argument which can be + used to select a specific fixture from the fixture file when executing. """ subcommand = "blocktest" global_options = [] @@ -273,10 +274,10 @@ def consume_state_test_file( """ Consume an entire state test file. - The `evm statetest` will always execute all the tests contained in a file without the - possibility of selecting a single test, so this function is cached in order to only call - the command once and `consume_state_test` can simply select the result that - was requested. + The `evm statetest` will always execute all the tests contained in a + file without the possibility of selecting a single test, so this + function is cached in order to only call the command once and + `consume_state_test` can simply select the result that was requested. """ subcommand = "statetest" global_options: List[str] = [] @@ -316,8 +317,8 @@ def consume_state_test( """ Consume a single state test. - Uses the cached result from `consume_state_test_file` in order to not call the command - every time an select a single result from there. + Uses the cached result from `consume_state_test_file` in order to not + call the command every time an select a single result from there. """ file_results = self.consume_state_test_file( fixture_path=fixture_path, @@ -346,7 +347,10 @@ def consume_fixture( fixture_name: Optional[str] = None, debug_output_path: Optional[Path] = None, ): - """Execute the appropriate geth fixture consumer for the fixture at `fixture_path`.""" + """ + Execute the appropriate geth fixture consumer for the fixture at + `fixture_path`. + """ if fixture_format == BlockchainFixture: self.consume_blockchain_test( fixture_path=fixture_path, diff --git a/ethereum_clis/clis/nethermind.py b/ethereum_clis/clis/nethermind.py index 13bf2c776f..85d6ea4484 100644 --- a/ethereum_clis/clis/nethermind.py +++ b/ethereum_clis/clis/nethermind.py @@ -96,8 +96,9 @@ def has_eof_support(self) -> bool: """ Return True if the `nethtest` binary supports the `--eofTest` flag. - Currently, nethtest EOF support is only available in nethermind's feature/evm/eof - branch https://github.com/NethermindEth/nethermind/tree/feature/evm/eof + Currently, nethtest EOF support is only available in nethermind's + feature/evm/eof branch + https://github.com/NethermindEth/nethermind/tree/feature/evm/eof """ return "--eofTest" in self.help() @@ -121,7 +122,8 @@ def _build_command_with_options( if fixture_format is BlockchainFixture: command += ["--blockTest", "--filter", f"{re.escape(fixture_name)}"] elif fixture_format is StateFixture: - # TODO: consider using `--filter` here to readily access traces from the output + # TODO: consider using `--filter` here to readily access traces + # from the output pass # no additional options needed elif fixture_format is EOFFixture: command += ["--eofTest"] @@ -144,10 +146,10 @@ def consume_state_test_file( """ Consume an entire state test file. - The `evm statetest` will always execute all the tests contained in a file without the - possibility of selecting a single test, so this function is cached in order to only call - the command once and `consume_state_test` can simply select the result that - was requested. + The `evm statetest` will always execute all the tests contained in a + file without the possibility of selecting a single test, so this + function is cached in order to only call the command once and + `consume_state_test` can simply select the result that was requested. """ result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) @@ -180,8 +182,8 @@ def consume_state_test( """ Consume a single state test. - Uses the cached result from `consume_state_test_file` in order to not call the command - every time an select a single result from there. + Uses the cached result from `consume_state_test_file` in order to not + call the command every time an select a single result from there. """ file_results, stderr = self.consume_state_test_file( fixture_path=fixture_path, @@ -203,9 +205,6 @@ def consume_state_test( for test_result in file_results if test_result["name"].removesuffix(nethtest_suffix) == f"{fixture_name.split('/')[-1]}" - # TODO: the following was required for nethermind's feature/evm/eof branch - # nethtest version: 1.32.0-unstable+025871675bd2e0839f93d2b70416ebae9dbae012 - # == f"{fixture_name.split('.py::')[-1]}" ] assert len(test_result) < 2, f"Multiple test results for {fixture_name}" assert len(test_result) == 1, f"Test result for {fixture_name} missing" @@ -254,7 +253,8 @@ def consume_eof_test_file( pattern = re.compile(r"^(test_.+?)\s+(PASS|FAIL)$", re.MULTILINE) test_results = { - match.group(1): match.group(2) == "PASS" # Convert "PASS" to True and "FAIL" to False + match.group(1): match.group(2) == "PASS" # Convert "PASS" to True + # and "FAIL" to False for match in pattern.finditer(result.stdout) } @@ -297,7 +297,10 @@ def consume_fixture( fixture_name: Optional[str] = None, debug_output_path: Optional[Path] = None, ): - """Execute the appropriate geth fixture consumer for the fixture at `fixture_path`.""" + """ + Execute the appropriate geth fixture consumer for the fixture at + `fixture_path`. + """ command = self._build_command_with_options( fixture_format, fixture_path, fixture_name, debug_output_path ) diff --git a/ethereum_clis/clis/nimbus.py b/ethereum_clis/clis/nimbus.py index 6c0960774c..a1f167c363 100644 --- a/ethereum_clis/clis/nimbus.py +++ b/ethereum_clis/clis/nimbus.py @@ -57,13 +57,16 @@ def is_fork_supported(self, fork: Fork) -> bool: """ Return True if the fork is supported by the tool. - If the fork is a transition fork, we want to check the fork it transitions to. + If the fork is a transition fork, we want to check the fork it + transitions to. """ return fork.transition_tool_name() in self.help_string class NimbusExceptionMapper(ExceptionMapper): - """Translate between EEST exceptions and error strings returned by Nimbus.""" + """ + Translate between EEST exceptions and error strings returned by Nimbus. + """ mapping_substring: ClassVar[Dict[ExceptionBase, str]] = { TransactionException.TYPE_4_TX_CONTRACT_CREATION: ( diff --git a/ethereum_clis/ethereum_cli.py b/ethereum_clis/ethereum_cli.py index 7ea060fcc7..6bdbf646ea 100644 --- a/ethereum_clis/ethereum_cli.py +++ b/ethereum_clis/ethereum_cli.py @@ -20,7 +20,9 @@ class UnknownCLIError(Exception): class CLINotFoundInPathError(Exception): - """Exception raised if the specified CLI binary is not found in the path.""" + """ + Exception raised if the specified CLI binary is not found in the path. + """ def __init__(self, message="The CLI binary was not found in the path", binary=None): """Initialize the exception.""" @@ -49,11 +51,14 @@ class EthereumCLI: cached_version: Optional[str] = None def __init__(self, *, binary: Optional[Path] = None): - """Abstract initialization method that all subclasses must implement.""" + """ + Abstract initialization method that all subclasses must implement. + """ if binary is None: binary = self.default_binary else: - # improve behavior of which by resolving the path: ~/relative paths don't work + # improve behavior of which by resolving the path: ~/relative paths + # don't work resolved_path = Path(os.path.expanduser(binary)).resolve() if resolved_path.exists(): binary = resolved_path @@ -75,10 +80,12 @@ def set_default_tool(cls, tool_subclass: Type[Any]): @classmethod def from_binary_path(cls, *, binary_path: Optional[Path], **kwargs) -> Any: """ - Instantiate the appropriate CLI subclass derived from the CLI's `binary_path`. + Instantiate the appropriate CLI subclass derived from the CLI's + `binary_path`. - This method will attempt to detect the CLI version and instantiate the appropriate - subclass based on the version output by running the CLI with the version flag. + This method will attempt to detect the CLI version and instantiate the + appropriate subclass based on the version output by running the CLI + with the version flag. """ assert cls.default_tool is not None, "default CLI implementation was never set" @@ -114,8 +121,8 @@ def from_binary_path(cls, *, binary_path: Optional[Path], **kwargs) -> Any: logger.debug(f"Successfully located the path of the t8n binary: {binary}") binary = Path(binary) - # Group the tools by version flag, so we only have to call the tool once for all the - # classes that share the same version flag + # Group the tools by version flag, so we only have to call the tool + # once for all the classes that share the same version flag for version_flag, subclasses in groupby( cls.registered_tools, key=lambda x: x.version_flag ): @@ -134,7 +141,9 @@ def from_binary_path(cls, *, binary_path: Optional[Path], **kwargs) -> Any: if result.returncode != 0: logger.debug(f"Subprocess returncode is not 0! It is: {result.returncode}") - continue # don't raise exception, you are supposed to keep trying different version flags # noqa: E501 + continue + # don't raise exception, you are supposed to keep + # trying different version flags if result.stderr: logger.debug(f"Stderr detected: {result.stderr}") # type: ignore @@ -143,10 +152,6 @@ def from_binary_path(cls, *, binary_path: Optional[Path], **kwargs) -> Any: binary_output = "" if result.stdout: binary_output = result.stdout.decode().strip() - # e.g. 1.31.10+f62cfede9b4abfb5cd62d6f138240668620a2b0d should be treated as 1.31.10 # noqa: E501 - # if "+" in binary_output: - # binary_output = binary_output.split("+")[0] - logger.debug(f"Stripped subprocess stdout: {binary_output}") for subclass in subclasses: @@ -169,7 +174,10 @@ def from_binary_path(cls, *, binary_path: Optional[Path], **kwargs) -> Any: @classmethod def detect_binary(cls, binary_output: str) -> bool: - """Return True if a CLI's `binary_output` matches the class's expected output.""" + """ + Return True if a CLI's `binary_output` matches the class's expected + output. + """ assert cls.detect_binary_pattern is not None return cls.detect_binary_pattern.match(binary_output) is not None @@ -187,7 +195,10 @@ def is_installed(cls, binary_path: Optional[Path] = None) -> bool: return binary is not None def version(self) -> str: - """Return the name and version of the CLI as reported by the CLI's version flag.""" + """ + Return the name and version of the CLI as reported by the CLI's version + flag. + """ if self.cached_version is None: result = subprocess.run( [str(self.binary), self.version_flag], diff --git a/ethereum_clis/fixture_consumer_tool.py b/ethereum_clis/fixture_consumer_tool.py index 1f958e2c13..3391c49a9c 100644 --- a/ethereum_clis/fixture_consumer_tool.py +++ b/ethereum_clis/fixture_consumer_tool.py @@ -9,8 +9,8 @@ class FixtureConsumerTool(FixtureConsumer, EthereumCLI): """ - Fixture consumer tool abstract base class which should be inherited by all fixture consumer - tool implementations. + Fixture consumer tool abstract base class which should be inherited by all + fixture consumer tool implementations. """ registered_tools: List[Type["FixtureConsumerTool"]] = [] diff --git a/ethereum_clis/tests/test_execution_specs.py b/ethereum_clis/tests/test_execution_specs.py index 964820dd8a..a748c9a5b3 100644 --- a/ethereum_clis/tests/test_execution_specs.py +++ b/ethereum_clis/tests/test_execution_specs.py @@ -22,10 +22,11 @@ @pytest.fixture(autouse=True) def monkeypatch_path_for_entry_points(monkeypatch): """ - Monkeypatch the PATH to add the "bin" directory where entrypoints are installed. + Monkeypatch the PATH to add the "bin" directory where entrypoints are + installed. - This would typically be in the venv in which pytest is running these tests and fill, - which, with uv, is `./.venv/bin`. + This would typically be in the venv in which pytest is running these tests + and fill, which, with uv, is `./.venv/bin`. This is required in order for fill to locate the ethereum-spec-evm-resolver "binary" (entrypoint) when being executed using pytester. @@ -98,7 +99,8 @@ def test_evm_tool_binary_arg(evm_tool, binary_arg): elif binary_arg == "path_type": evm_bin = which(DEFAULT_EVM_T8N_BINARY_NAME) if not evm_bin: - # typing: Path can not take None; but if it is None, we may as well fail explicitly. + # typing: Path can not take None; but if it is None, we may as well + # fail explicitly. raise Exception("Failed to find `{DEFAULT_EVM_T8N_BINARY_NAME}` in the PATH via which") evm_tool(binary=Path(evm_bin)).version() return @@ -143,7 +145,9 @@ def test_evm_t8n( env: Environment, test_dir: str, ) -> None: - """Test the `evaluate` method of the `ExecutionSpecsTransitionTool` class.""" + """ + Test the `evaluate` method of the `ExecutionSpecsTransitionTool` class. + """ expected_path = Path(FIXTURES_ROOT, test_dir, "exp.json") with open(expected_path, "r") as exp: @@ -162,8 +166,9 @@ def test_evm_t8n( ) assert to_json(t8n_output.alloc) == expected.get("alloc") if isinstance(default_t8n, ExecutionSpecsTransitionTool): - # The expected output was generated with geth, instead of deleting any info from - # this expected output, the fields not returned by eels are handled here. + # The expected output was generated with geth, instead of deleting + # any info from this expected output, the fields not returned by + # eels are handled here. missing_receipt_fields = [ "root", "status", diff --git a/ethereum_clis/tests/test_transition_tools_support.py b/ethereum_clis/tests/test_transition_tools_support.py index 953af15744..8c6f94278b 100644 --- a/ethereum_clis/tests/test_transition_tools_support.py +++ b/ethereum_clis/tests/test_transition_tools_support.py @@ -44,7 +44,9 @@ def test_ci_multi_t8n_support( installed_transition_tool_instances: Dict[str, TransitionTool | Exception], running_in_ci: bool, ): - """Check that the instances of t8n we expect in CI environment were found.""" + """ + Check that the instances of t8n we expect in CI environment were found. + """ names = set(installed_transition_tool_instances.keys()) expected_names = {"ExecutionSpecsTransitionTool"} if running_in_ci: diff --git a/ethereum_clis/transition_tool.py b/ethereum_clis/transition_tool.py index c3fa04ec27..80e5ba3a85 100644 --- a/ethereum_clis/transition_tool.py +++ b/ethereum_clis/transition_tool.py @@ -38,22 +38,24 @@ model_dump_config: Mapping = {"by_alias": True, "exclude_none": True} -# TODO: reduce NORMAL_SERVER_TIMEOUT back down to 20 once BLS timeout issue is resolved: -# https://github.com/ethereum/execution-spec-tests/issues/1894 +# TODO: reduce NORMAL_SERVER_TIMEOUT back down to 20 once BLS timeout issue is +# resolved: https://github.com/ethereum/execution-spec-tests/issues/1894 NORMAL_SERVER_TIMEOUT = 600 SLOW_REQUEST_TIMEOUT = 600 def get_valid_transition_tool_names() -> set[str]: - """Get all valid transition tool names from deployed and development forks.""" + """ + Get all valid transition tool names from deployed and development forks. + """ all_available_forks = get_forks() + get_development_forks() return {fork.transition_tool_name() for fork in all_available_forks} class TransitionTool(EthereumCLI): """ - Transition tool abstract base class which should be inherited by all transition tool - implementations. + Transition tool abstract base class which should be inherited by all + transition tool implementations. """ traces: List[Traces] | None = None @@ -80,7 +82,9 @@ def __init__( binary: Optional[Path] = None, trace: bool = False, ): - """Abstract initialization method that all subclasses must implement.""" + """ + Abstract initialization method that all subclasses must implement. + """ assert exception_mapper is not None self.exception_mapper = exception_mapper super().__init__(binary=binary) @@ -112,7 +116,9 @@ def reset_traces(self): self.traces = None def append_traces(self, new_traces: Traces): - """Append a list of traces of a state transition to the current list.""" + """ + Append a list of traces of a state transition to the current list. + """ if self.traces is None: self.traces = [] self.traces.append(new_traces) @@ -127,7 +133,10 @@ def collect_traces( temp_dir: tempfile.TemporaryDirectory, debug_output_path: str = "", ) -> Traces: - """Collect the traces from the t8n tool output and store them in the traces list.""" + """ + Collect the traces from the t8n tool output and store them in the + traces list. + """ traces: Traces = Traces(root=[]) temp_dir_path = Path(temp_dir.name) for i, r in enumerate(receipts): @@ -194,7 +203,10 @@ def _evaluate_filesystem( t8n_data: TransitionToolData, debug_output_path: str = "", ) -> TransitionToolOutput: - """Execute a transition tool using the filesystem for its inputs and outputs.""" + """ + Execute a transition tool using the filesystem for its inputs and + outputs. + """ temp_dir = tempfile.TemporaryDirectory() os.mkdir(os.path.join(temp_dir.name, "input")) os.mkdir(os.path.join(temp_dir.name, "output")) @@ -256,14 +268,16 @@ def _evaluate_filesystem( t8n_call = t8n_call.replace( os.path.dirname(file_path), os.path.join(debug_output_path, "input") ) - t8n_call = t8n_call.replace( # use a new output path for basedir and outputs + # use a new output path for basedir and outputs + t8n_call = t8n_call.replace( temp_dir.name, t8n_output_base_dir, ) t8n_script = textwrap.dedent( f"""\ #!/bin/bash - rm -rf {debug_output_path}/t8n.sh.out # hard-coded to avoid surprises + # hard-coded to avoid surprises + rm -rf {debug_output_path}/t8n.sh.out mkdir -p {debug_output_path}/t8n.sh.out/output {t8n_call} """ @@ -355,7 +369,9 @@ def _evaluate_server( debug_output_path: str = "", timeout: int, ) -> TransitionToolOutput: - """Execute the transition tool sending inputs and outputs via a server.""" + """ + Execute the transition tool sending inputs and outputs via a server. + """ request_data = t8n_data.get_request_data() request_data_json = request_data.model_dump(mode="json", **model_dump_config) @@ -424,7 +440,10 @@ def _evaluate_stream( t8n_data: TransitionToolData, debug_output_path: str = "", ) -> TransitionToolOutput: - """Execute a transition tool using stdin and stdout for its inputs and outputs.""" + """ + Execute a transition tool using stdin and stdout for its inputs and + outputs. + """ temp_dir = tempfile.TemporaryDirectory() args = self.construct_args_stream(t8n_data, temp_dir) @@ -468,7 +487,8 @@ def safe_t8n_args( self, fork_name: str, chain_id: int, reward: int, temp_dir=None ) -> List[str]: """Safely construct t8n arguments with validated inputs.""" - # Validate fork name against actual transition tool names from all available forks + # Validate fork name against actual transition tool names from all + # available forks valid_forks = get_valid_transition_tool_names() if fork_name not in valid_forks: raise ValueError(f"Invalid fork name: {fork_name}") @@ -528,7 +548,9 @@ def dump_debug_stream( args: List[str], result: subprocess.CompletedProcess, ): - """Export debug files if requested when interacting with t8n via streams.""" + """ + Export debug files if requested when interacting with t8n via streams. + """ if not debug_output_path: return @@ -539,8 +561,11 @@ def dump_debug_stream( t8n_script = textwrap.dedent( f"""\ #!/bin/bash - rm -rf {debug_output_path}/t8n.sh.out # hard-coded to avoid surprises - mkdir {debug_output_path}/t8n.sh.out # unused if tracing is not enabled + # hard-coded to avoid surprises + rm -rf {debug_output_path}/t8n.sh.out + + # unused if tracing is not enabled + mkdir {debug_output_path}/t8n.sh.out {t8n_call} < {debug_output_path}/stdin.txt """ ) diff --git a/ethereum_test_base_types/base_types.py b/ethereum_test_base_types/base_types.py index d50155ac38..041df926ca 100644 --- a/ethereum_test_base_types/base_types.py +++ b/ethereum_test_base_types/base_types.py @@ -24,15 +24,18 @@ class ToStringSchema: """ - Type converter to add a simple pydantic schema that correctly - parses and serializes the type. + Type converter to add a simple pydantic schema that correctly parses and + serializes the type. """ @staticmethod def __get_pydantic_core_schema__( source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call the class constructor without info and appends the serialization schema.""" + """ + Call the class constructor without info and appends the serialization + schema. + """ return no_info_plain_validator_function( source_type, serialization=to_string_ser_schema(), @@ -86,7 +89,9 @@ def __new__(cls, input_number: NumberConvertible | Self): @staticmethod def _get_multiplier(unit: str) -> int: - """Return the multiplier for the given unit of wei, handling synonyms.""" + """ + Return the multiplier for the given unit of wei, handling synonyms. + """ match unit: case "wei": return 1 @@ -117,7 +122,10 @@ def __str__(self) -> str: def __get_pydantic_core_schema__( source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call the class constructor without info and appends the serialization schema.""" + """ + Call the class constructor without info and appends the serialization + schema. + """ return no_info_plain_validator_function( source_type, serialization=to_string_ser_schema(), @@ -143,7 +151,10 @@ def hex(self) -> str: def __get_pydantic_core_schema__( source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call the class constructor without info and appends the serialization schema.""" + """ + Call the class constructor without info and appends the serialization + schema. + """ return no_info_plain_validator_function( source_type, serialization=to_string_ser_schema(), @@ -197,7 +208,10 @@ def sha256(self) -> "Hash": def __get_pydantic_core_schema__( source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call the class constructor without info and appends the serialization schema.""" + """ + Call the class constructor without info and appends the serialization + schema. + """ return no_info_plain_validator_function( source_type, serialization=to_string_ser_schema(), @@ -256,7 +270,10 @@ def hex(self) -> str: def __get_pydantic_core_schema__( cls: Type[Self], source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call the class constructor without info and appends the serialization schema.""" + """ + Call the class constructor without info and appends the serialization + schema. + """ pattern = f"^0x([0-9a-fA-F]{{{cls.byte_length * 2}}})*$" return no_info_plain_validator_function( source_type, @@ -341,7 +358,10 @@ def __ne__(self, other: object) -> bool: def __get_pydantic_core_schema__( cls: Type[Self], source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call the class constructor without info and appends the serialization schema.""" + """ + Call the class constructor without info and appends the serialization + schema. + """ pattern = f"^0x([0-9a-fA-F]{{{cls.byte_length * 2}}})*$" return no_info_plain_validator_function( source_type, @@ -351,7 +371,9 @@ def __get_pydantic_core_schema__( class ForkHash(FixedSizeBytes[4]): # type: ignore - """Class that helps represent the CRC config hashes and identifiers of a fork.""" + """ + Class that helps represent the CRC config hashes and identifiers of a fork. + """ pass @@ -391,7 +413,8 @@ class StorageKey(FixedSizeBytes[32]): # type: ignore def __new__(cls, value, **kwargs): """Create a new StorageKey with automatic left padding.""" - # Always apply left_padding for storage keys unless explicitly set to False + # Always apply left_padding for storage keys unless explicitly set to + # False if "left_padding" not in kwargs: kwargs["left_padding"] = True return super().__new__(cls, value, **kwargs) diff --git a/ethereum_test_base_types/composite_types.py b/ethereum_test_base_types/composite_types.py index 035bfb2a88..63fbe534ff 100644 --- a/ethereum_test_base_types/composite_types.py +++ b/ethereum_test_base_types/composite_types.py @@ -41,7 +41,9 @@ class Storage(EthereumTestRootModel[Dict[StorageKeyValueType, StorageKeyValueTyp @dataclass(kw_only=True) class InvalidTypeError(Exception): - """Invalid type used when describing test's expected storage key or value.""" + """ + Invalid type used when describing test's expected storage key or value. + """ key_or_value: Any @@ -90,8 +92,8 @@ def __str__(self): @dataclass(kw_only=True) class KeyValueMismatchError(Exception): """ - Test expected a certain value in a storage key but value found - was different. + Test expected a certain value in a storage key but value found was + different. """ address: Address @@ -101,7 +103,10 @@ class KeyValueMismatchError(Exception): hint: str def __init__(self, address: Address, key: int, want: int, got: int, hint: str = "", *args): - """Initialize the exception with the address, key, wanted and got values.""" + """ + Initialize the exception with the address, key, wanted and got + values. + """ super().__init__(args) self.address = address self.key = key @@ -183,14 +188,17 @@ def items(self): return self.root.items() def set_expect_any(self, key: StorageKeyValueTypeConvertible | StorageKeyValueType): - """Mark key to be able to have any expected value when comparing storages.""" + """ + Mark key to be able to have any expected value when comparing storages. + """ self._any_map[StorageKeyValueTypeAdapter.validate_python(key)] = True def store_next( self, value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool, hint: str = "" ) -> StorageKeyValueType: """ - Store a value in the storage and returns the key where the value is stored. + Store a value in the storage and returns the key where the value is + stored. Increments the key counter so the next time this function is called, the next key is used. @@ -208,10 +216,9 @@ def peek_slot(self) -> int: def contains(self, other: "Storage") -> bool: """ - Return True if self contains all keys with equal value as - contained by second storage. - Used for comparison with test expected post state and alloc returned - by the transition tool. + Return True if self contains all keys with equal value as contained by + second storage. Used for comparison with test expected post state and + alloc returned by the transition tool. """ for key in other.keys(): if key not in self: @@ -222,11 +229,10 @@ def contains(self, other: "Storage") -> bool: def must_contain(self, address: Address, other: "Storage"): """ - Succeeds only if self contains all keys with equal value as - contained by second storage. - Used for comparison with test expected post state and alloc returned - by the transition tool. - Raises detailed exception when a difference is found. + Succeeds only if self contains all keys with equal value as contained + by second storage. Used for comparison with test expected post state + and alloc returned by the transition tool. Raises detailed exception + when a difference is found. """ for key in other.keys(): if key not in self: @@ -283,8 +289,9 @@ def must_be_equal(self, address: Address, other: "Storage | None"): def canary(self) -> "Storage": """ - Return a canary storage filled with non-zero values where the current storage expects - zero values, to guarantee that the test overwrites the storage. + Return a canary storage filled with non-zero values where the current + storage expects zero values, to guarantee that the test overwrites the + storage. """ return Storage({key: HashInt(0xBA5E) for key in self.keys() if self[key] == 0}) @@ -294,22 +301,15 @@ class Account(CamelModel): nonce: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0) """ - The scalar value equal to a) the number of transactions sent by - an Externally Owned Account, b) the amount of contracts created by a - contract. + The scalar value equal to a) the number of transactions sent by an + Externally Owned Account, b) the amount of contracts created by a contract. """ balance: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0) - """ - The amount of Wei (10-18 Eth) the account has. - """ + """The amount of Wei (10-18 Eth) the account has.""" code: Bytes = Bytes(b"") - """ - Bytecode contained by the account. - """ + """Bytecode contained by the account.""" storage: Storage = Field(default_factory=Storage) - """ - Storage within a contract. - """ + """Storage within a contract.""" NONEXISTENT: ClassVar[None] = None """ @@ -329,7 +329,9 @@ class NonceMismatchError(Exception): got: int | None def __init__(self, address: Address, want: int | None, got: int | None, *args): - """Initialize the exception with the address, wanted and got values.""" + """ + Initialize the exception with the address, wanted and got values. + """ super().__init__(args) self.address = address self.want = want @@ -348,8 +350,8 @@ def __str__(self): @dataclass(kw_only=True) class BalanceMismatchError(Exception): """ - Test expected a certain balance for an account but a different - value was found. + Test expected a certain balance for an account but a different value + was found. """ address: Address @@ -357,7 +359,9 @@ class BalanceMismatchError(Exception): got: int | None def __init__(self, address: Address, want: int | None, got: int | None, *args): - """Initialize the exception with the address, wanted and got values.""" + """ + Initialize the exception with the address, wanted and got values. + """ super().__init__(args) self.address = address self.want = want @@ -376,8 +380,8 @@ def __str__(self): @dataclass(kw_only=True) class CodeMismatchError(Exception): """ - Test expected a certain bytecode for an account but a different - one was found. + Test expected a certain bytecode for an account but a different one was + found. """ address: Address @@ -385,7 +389,9 @@ class CodeMismatchError(Exception): got: bytes | None def __init__(self, address: Address, want: bytes | None, got: bytes | None, *args): - """Initialize the exception with the address, wanted and got values.""" + """ + Initialize the exception with the address, wanted and got values. + """ super().__init__(args) self.address = address self.want = want diff --git a/ethereum_test_base_types/conversions.py b/ethereum_test_base_types/conversions.py index e99743ba24..84fbb77895 100644 --- a/ethereum_test_base_types/conversions.py +++ b/ethereum_test_base_types/conversions.py @@ -60,12 +60,16 @@ def to_fixed_size_bytes( """ Convert multiple types into fixed-size bytes. - :param input_bytes: The input data to convert. - :param size: The size of the output bytes. - :param left_padding: Whether to allow left-padding of the input data bytes using zeros. If the - input data is an integer, padding is always performed. - :param right_padding: Whether to allow right-padding of the input data bytes using zeros. If - the input data is an integer, padding is always performed. + Args: + input_bytes: The input data to convert. + size: The size of the output bytes. + left_padding: Whether to allow left-padding of the input data bytes + using zeros. If the input data is an integer, padding is + always performed. + right_padding: Whether to allow right-padding of the input data bytes + using zeros. If the input data is an integer, padding + is always performed. + """ if isinstance(input_bytes, int): return int.to_bytes(input_bytes, length=size, byteorder="big", signed=input_bytes < 0) diff --git a/ethereum_test_base_types/mixins.py b/ethereum_test_base_types/mixins.py index f44eafcaa5..d5c1d4cf5f 100644 --- a/ethereum_test_base_types/mixins.py +++ b/ethereum_test_base_types/mixins.py @@ -8,10 +8,10 @@ class ModelCustomizationsMixin: """ A mixin that customizes the behavior of pydantic models. Any pydantic - configuration override that must apply to all models - should be placed here. + configuration override that must apply to all models should be placed here. - This mixin is applied to both `EthereumTestBaseModel` and `EthereumTestRootModel`. + This mixin is applied to both `EthereumTestBaseModel` and + `EthereumTestRootModel`. """ def serialize( @@ -23,12 +23,18 @@ def serialize( """ Serialize the model to the specified format with the given parameters. - :param mode: The mode of serialization. - If mode is 'json', the output will only contain JSON serializable types. - If mode is 'python', the output may contain non-JSON-serializable Python objects. - :param by_alias: Whether to use aliases for field names. - :param exclude_none: Whether to exclude fields with None values, default is True. - :return: The serialized representation of the model. + Args: + mode: The mode of serialization. If mode is 'json', the output + will only contain JSON serializable types. If mode is + 'python', the output may contain non-JSON-serializable + Python objects. + by_alias: Whether to use aliases for field names. + exclude_none: Whether to exclude fields with None values, + default is True. + + Returns: + dict[str, Any]: The serialized representation of the model. + """ if not hasattr(self, "model_dump"): raise NotImplementedError( @@ -41,35 +47,44 @@ def __repr_args__(self): """ Generate a list of attribute-value pairs for the object representation. - This method serializes the model, retrieves the attribute names, - and constructs a list of tuples containing attribute names and their corresponding values. - Only attributes with non-None values are included in the list. + This method serializes the model, retrieves the attribute names, and + constructs a list of tuples containing attribute names and their + corresponding values. Only attributes with non-None values are included + in the list. - This method is used by the __repr__ method to generate the object representation, - and is used by `gentest` module to generate the test cases. + This method is used by the __repr__ method to generate the object + representation, and is used by `gentest` module to generate the test + cases. See: - - https://pydantic-docs.helpmanual.io/usage/models/#custom-repr - - https://github.com/ethereum/execution-spec-tests/pull/901#issuecomment-2443296835 + https://pydantic-docs.helpmanual.io/usage/models/ + #custom-repr + + and + + https://github.com/ethereum/execution-spec-tests/pull/ + 901#issuecomment-24432968 35 Returns: - List[Tuple[str, Any]]: A list of tuples where each tuple contains an attribute name - and its corresponding non-None value. + List[Tuple[str, Any]]: A list of tuples where each tuple + contains an attribute name and its + corresponding non-None value. """ attrs_names = self.serialize(mode="python", by_alias=False).keys() attrs = ((s, getattr(self, s)) for s in attrs_names) - # Convert field values based on their type. - # This ensures consistency between JSON and Python object representations. - # Should a custom `__repr__` be needed for a specific type, it can added in the - # match statement below. - # Otherwise, the default string representation is used. + # Convert field values based on their type. This ensures consistency + # between JSON and Python object representations. Should a custom + # `__repr__` be needed for a specific type, it can added in the match + # statement below. Otherwise, the default string representation is + # used. repr_attrs = [] for a, v in attrs: match v: # Note: The `None` case handles an edge case with transactions - # see: https://github.com/ethereum/execution-spec-tests/pull/901#discussion_r1828491918 # noqa: E501 + # see: https://github.com/ethereum/execution-spec-tests/pull/ + # 901#discussion_r1828491918 case list() | dict() | BaseModel() | None: repr_attrs.append((a, v)) case _: diff --git a/ethereum_test_base_types/pydantic.py b/ethereum_test_base_types/pydantic.py index 6471fe07fa..6d58f1fcf9 100644 --- a/ethereum_test_base_types/pydantic.py +++ b/ethereum_test_base_types/pydantic.py @@ -27,7 +27,9 @@ class CopyValidateModel(EthereumTestBaseModel): """Model that supports copying with validation.""" def copy(self: Self, **kwargs) -> Self: - """Create a copy of the model with the updated fields that are validated.""" + """ + Create a copy of the model with the updated fields that are validated. + """ return self.__class__(**(self.model_dump(exclude_unset=True) | kwargs)) @@ -35,8 +37,8 @@ class CamelModel(CopyValidateModel): """ A base model that converts field names to camel case when serializing. - For example, the field name `current_timestamp` in a Python model will be represented - as `currentTimestamp` when it is serialized to json. + For example, the field name `current_timestamp` in a Python model will be + represented as `currentTimestamp` when it is serialized to json. """ model_config = ConfigDict( diff --git a/ethereum_test_base_types/reference_spec/reference_spec.py b/ethereum_test_base_types/reference_spec/reference_spec.py index 96a0f49392..3bf3611352 100644 --- a/ethereum_test_base_types/reference_spec/reference_spec.py +++ b/ethereum_test_base_types/reference_spec/reference_spec.py @@ -36,7 +36,10 @@ def name(self) -> str: @abstractmethod def has_known_version(self) -> bool: - """Return true if the reference spec object is hard-coded with a latest known version.""" + """ + Return true if the reference spec object is hard-coded with a latest + known version. + """ pass @abstractmethod @@ -46,7 +49,9 @@ def known_version(self) -> str: @abstractmethod def api_url(self) -> str: - """Return the URL required to poll the version from an API, if needed.""" + """ + Return the URL required to poll the version from an API, if needed. + """ pass @abstractmethod @@ -64,13 +69,19 @@ def is_outdated(self) -> bool: @abstractmethod def write_info(self, info: Dict[str, Dict[str, Any] | str]): - """Write info about the reference specification used into the output fixture.""" + """ + Write info about the reference specification used into the output + fixture. + """ pass @staticmethod @abstractmethod def parseable_from_module(module_dict: Dict[str, Any]) -> bool: - """Check whether the module's dict contains required reference spec information.""" + """ + Check whether the module's dict contains required reference spec + information. + """ pass @staticmethod diff --git a/ethereum_test_base_types/serialization.py b/ethereum_test_base_types/serialization.py index 35aeaaf233..f0f18f5084 100644 --- a/ethereum_test_base_types/serialization.py +++ b/ethereum_test_base_types/serialization.py @@ -36,26 +36,29 @@ class RLPSerializable: def get_rlp_fields(self) -> List[str]: """ - Return an ordered list of field names to be included in RLP serialization. + Return an ordered list of field names to be included in RLP + serialization. Function can be overridden to customize the logic to return the fields. By default, rlp_fields class variable is used. - The list can be nested list up to one extra level to represent nested fields. + The list can be nested list up to one extra level to represent nested + fields. """ return self.rlp_fields def get_rlp_signing_fields(self) -> List[str]: """ - Return an ordered list of field names to be included in the RLP serialization of the object - signature. + Return an ordered list of field names to be included in the RLP + serialization of the object signature. Function can be overridden to customize the logic to return the fields. By default, rlp_signing_fields class variable is used. - The list can be nested list up to one extra level to represent nested fields. + The list can be nested list up to one extra level to represent nested + fields. """ return self.rlp_signing_fields @@ -69,7 +72,8 @@ def get_rlp_prefix(self) -> bytes: def get_rlp_signing_prefix(self) -> bytes: """ - Return a prefix that has to be appended to the serialized signing object. + Return a prefix that has to be appended to the serialized signing + object. By default, an empty string is returned. """ @@ -117,8 +121,9 @@ def to_list(self, signing: bool = False) -> List[Any]: field_list = self.get_rlp_signing_fields() else: if self.signable: - # Automatically sign signable objects during full serialization: - # Ensures nested objects have valid signatures in the final RLP. + # Automatically sign signable objects during full + # serialization: Ensures nested objects have valid signatures + # in the final RLP. self.sign() field_list = self.get_rlp_fields() @@ -136,7 +141,9 @@ def rlp(self) -> Bytes: class SignableRLPSerializable(RLPSerializable): - """Class that adds RLP serialization to another class with signing support.""" + """ + Class that adds RLP serialization to another class with signing support. + """ signable: ClassVar[bool] = True diff --git a/ethereum_test_base_types/tests/test_reference_spec.py b/ethereum_test_base_types/tests/test_reference_spec.py index bd94814d07..dbb15d89cc 100644 --- a/ethereum_test_base_types/tests/test_reference_spec.py +++ b/ethereum_test_base_types/tests/test_reference_spec.py @@ -8,7 +8,8 @@ from ..reference_spec.git_reference_spec import GitReferenceSpec from ..reference_spec.reference_spec import NoLatestKnownVersionError -# the content field from https://api.github.com/repos/ethereum/EIPs/contents/EIPS/eip-100.md +# the content field from +# https://api.github.com/repos/ethereum/EIPs/contents/EIPS/eip-100.md # as of 2023-08-29 response_content = "LS0tCmVpcDogMTAwCnRpdGxlOiBDaGFuZ2UgZGlmZmljdWx0eSBhZGp1c3Rt\ ZW50IHRvIHRhcmdldCBtZWFuIGJsb2NrIHRpbWUgaW5jbHVkaW5nIHVuY2xl\ diff --git a/ethereum_test_benchmark/__init__.py b/ethereum_test_benchmark/__init__.py index 60f0e66a5f..fb8b71a207 100644 --- a/ethereum_test_benchmark/__init__.py +++ b/ethereum_test_benchmark/__init__.py @@ -1,4 +1,7 @@ -"""Benchmark code generator classes for creating optimized bytecode patterns.""" +""" +Benchmark code generator classes for +creating optimized bytecode patterns. +""" from .benchmark_code_generator import ( BenchmarkCodeGenerator, diff --git a/ethereum_test_benchmark/benchmark_code_generator.py b/ethereum_test_benchmark/benchmark_code_generator.py index 9c2c9b7814..311b4132c3 100644 --- a/ethereum_test_benchmark/benchmark_code_generator.py +++ b/ethereum_test_benchmark/benchmark_code_generator.py @@ -1,4 +1,7 @@ -"""Benchmark code generator classes for creating optimized bytecode patterns.""" +""" +Benchmark code generator classes for creating +optimized bytecode patterns. +""" from ethereum_test_forks import Fork from ethereum_test_specs.benchmark import BenchmarkCodeGenerator @@ -13,7 +16,8 @@ class JumpLoopGenerator(BenchmarkCodeGenerator): def deploy_contracts(self, pre: Alloc, fork: Fork) -> None: """Deploy the looping contract.""" # Benchmark Test Structure: - # setup + JUMPDEST + attack + attack + ... + attack + JUMP(setup_length) + # setup + JUMPDEST + attack + attack + ... + + # attack + JUMP(setup_length) code = self.generate_repeated_code(self.attack_block, self.setup, fork) self._contract_address = pre.deploy_contract(code=code) @@ -30,13 +34,17 @@ def generate_transaction(self, pre: Alloc, gas_limit: int, fork: Fork) -> Transa class ExtCallGenerator(BenchmarkCodeGenerator): - """Generates bytecode that fills the contract to maximum allowed code size.""" + """ + Generates bytecode that fills the contract to + maximum allowed code size. + """ def deploy_contracts(self, pre: Alloc, fork: Fork) -> None: """Deploy both target and caller contracts.""" # Benchmark Test Structure: # There are two contracts: - # 1. The target contract that executes certain operation but not loop (e.g. PUSH) + # 1. The target contract that executes certain operation + # but not loop (e.g. PUSH) # 2. The loop contract that calls the target contract in a loop max_iterations = min( @@ -49,8 +57,12 @@ def deploy_contracts(self, pre: Alloc, fork: Fork) -> None: ) # Create caller contract that repeatedly calls the target contract - # attack = POP(STATICCALL(GAS, target_contract_address, 0, 0, 0, 0)) - # setup + JUMPDEST + attack + attack + ... + attack + JUMP(setup_length) + # attack = POP( + # STATICCALL(GAS, target_contract_address, 0, 0, 0, 0) + # ) + # + # setup + JUMPDEST + attack + attack + ... + attack + + # JUMP(setup_length) code_sequence = Op.POP(Op.STATICCALL(Op.GAS, self._target_contract_address, 0, 0, 0, 0)) caller_code = self.generate_repeated_code(code_sequence, Bytecode(), fork) diff --git a/ethereum_test_checklists/eip_checklist.py b/ethereum_test_checklists/eip_checklist.py index 9a3b0b26cd..1361965eb7 100644 --- a/ethereum_test_checklists/eip_checklist.py +++ b/ethereum_test_checklists/eip_checklist.py @@ -1,12 +1,12 @@ """ EIP Testing Checklist Enum definitions. -Note: This module includes a companion .pyi stub file that provides mypy type hints -for making EIPChecklist classes callable. The stub file is auto-generated using: - uv run generate_checklist_stubs +Note: This module includes a companion .pyi stub file that provides mypy type +hints for making EIPChecklist classes callable. The stub file is auto-generated +using: uv run generate_checklist_stubs -If you modify the EIPChecklist class structure, regenerate the stub file to maintain -proper type checking support. +If you modify the EIPChecklist class structure, regenerate the stub file to +maintain proper type checking support. """ import re @@ -16,9 +16,11 @@ def camel_to_snake(name: str) -> str: """Convert CamelCase to snake_case.""" - # Insert an underscore before any uppercase letter that follows a lowercase letter + # Insert an underscore before any uppercase letter that follows a lowercase + # letter s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name) - # Insert an underscore before any uppercase letter that follows a lowercase letter or number + # Insert an underscore before any uppercase letter that follows a lowercase + # letter or number return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower() @@ -73,8 +75,8 @@ def __repr__(cls) -> str: def __call__(cls, *args, **kwargs): """Return a pytest mark decorator for the checklist item.""" - # If called with a function as the first argument (direct decorator usage) - # and no other arguments, apply the decorator to the function + # If called with a function as the first argument (direct decorator + # usage) and no other arguments, apply the decorator to the function if len(args) == 1 and len(kwargs) == 0 and callable(args[0]): func = args[0] marker = pytest.mark.eip_checklist(cls._path) @@ -93,20 +95,21 @@ class EIPChecklist: """ Main namespace for EIP testing checklist items. - This class provides a structured way to reference checklist items for EIP testing. - The class structure is automatically converted to callable pytest markers. + This class provides a structured way to reference checklist items for EIP + testing. The class structure is automatically converted to callable pytest + markers. - Note: If you modify this class structure, regenerate the type stub file using: - uv run generate_checklist_stubs + Note: If you modify this class structure, regenerate the type stub file + using: uv run generate_checklist_stubs Examples: - @EIPChecklist.Opcode.Test.GasUsage.Normal() - def test_normal_gas(): - pass + @EIPChecklist.Opcode.Test.GasUsage.Normal() + def test_normal_gas(): + pass - @EIPChecklist.Opcode.Test.StackOverflow - def test_stack_overflow(): - pass + @EIPChecklist.Opcode.Test.StackOverflow + def test_stack_overflow(): + pass """ @@ -239,8 +242,9 @@ class Even(ChecklistItem): class DataPortionVariables(ChecklistItem, override_name="data_portion_variables"): """ - If the opcode contains variables in its data portion, for each variable `n` - of the opcode that accesses the nth stack item, test `n` being. + If the opcode contains variables in its data portion, for + each variable `n` of the opcode that accesses the nth stack + item, test `n` being. """ class Top(ChecklistItem): @@ -1688,28 +1692,31 @@ class Test(ChecklistItem): """Test vectors for the new validity constraint.""" class ForkTransition(ChecklistItem): - """Tests for the new transaction validity constraint on fork boundary.""" + """ + Tests for the new transaction validity constraint on fork + boundary. + """ class AcceptedBeforeFork(ChecklistItem): """ - Verify that a block before the activation fork is accepted even when the new - constraint is not met. + Verify that a block before the activation fork is accepted + even when the new constraint is not met. """ pass class AcceptedAfterFork(ChecklistItem): """ - Verify that a block after the activation fork is accepted when the new - validity constraint is met. + Verify that a block after the activation fork is accepted + when the new validity constraint is met. """ pass class RejectedAfterFork(ChecklistItem): """ - Verify that a block after the activation fork is rejected when the new - validity constraint is not met. + Verify that a block after the activation fork is rejected + when the new validity constraint is not met. """ pass @@ -1721,36 +1728,41 @@ class Test(ChecklistItem): """Test vectors for the modified validity constraint.""" class ForkTransition(ChecklistItem): - """Tests for the modified transaction validity constraint on fork boundary.""" + """ + Tests for the modified transaction validity constraint on fork + boundary. + """ class AcceptedBeforeFork(ChecklistItem): """ - Verify that a block before the activation fork is accepted when the existing - constraint is met and, ideally, the new constraint is not met. + Verify that a block before the activation fork is accepted + when the existing constraint is met and, ideally, the new + constraint is not met. """ pass class RejectedBeforeFork(ChecklistItem): """ - Verify that a block before the activation fork is rejected when the existing - constraint is not met and, ideally, the new constraint is met. + Verify that a block before the activation fork is rejected + when the existing constraint is not met and, ideally, the + new constraint is met. """ pass class AcceptedAfterFork(ChecklistItem): """ - Verify that a block after the activation fork is accepted when the new - validity constraint is met. + Verify that a block after the activation fork is accepted + when the new validity constraint is met. """ pass class RejectedAfterFork(ChecklistItem): """ - Verify that a block after the activation fork is rejected when the new - validity constraint is not met. + Verify that a block after the activation fork is rejected + when the new validity constraint is not met. """ pass diff --git a/ethereum_test_checklists/eip_checklist.pyi b/ethereum_test_checklists/eip_checklist.pyi index 2a0f37d22d..6dd2653923 100644 --- a/ethereum_test_checklists/eip_checklist.pyi +++ b/ethereum_test_checklists/eip_checklist.pyi @@ -1,7 +1,8 @@ """ Type stubs for EIP checklist - auto-generated. -DO NOT EDIT MANUALLY - This file is generated by `uv run generate_checklist_stubs` +DO NOT EDIT MANUALLY - +This file is generated by `uv run generate_checklist_stubs` """ from typing import Any, Callable, TypeVar, overload diff --git a/ethereum_test_checklists/tests/test_checklist_template_consistency.py b/ethereum_test_checklists/tests/test_checklist_template_consistency.py index 69be5f2157..f8a190ae57 100644 --- a/ethereum_test_checklists/tests/test_checklist_template_consistency.py +++ b/ethereum_test_checklists/tests/test_checklist_template_consistency.py @@ -33,7 +33,9 @@ def extract_markdown_ids(markdown_content: str) -> Set[str]: def get_all_checklist_ids(obj) -> Set[str]: - """Recursively extract all checklist IDs from EIPChecklist and its children.""" + """ + Recursively extract all checklist IDs from EIPChecklist and its children. + """ ids = set() # Iterate through all attributes of the object @@ -59,7 +61,9 @@ def get_all_checklist_ids(obj) -> Set[str]: def test_checklist_template_consistency(): - """Test that all IDs in markdown template match EIPChecklist class exactly.""" + """ + Test that all IDs in markdown template match EIPChecklist class exactly. + """ # Read the markdown template with open(TEMPLATE_PATH, "r", encoding="utf-8") as f: markdown_content = f.read() @@ -135,7 +139,10 @@ def test_id_extraction_functions(): def test_eip_checklist_decorator_usage(): - """Test EIPChecklist items work correctly as decorators both with and without parentheses.""" + """ + Test EIPChecklist items work correctly as decorators both with and without + parentheses. + """ # Test decorator with parentheses @EIPChecklist.Opcode.Test.StackComplexOperations() @@ -149,7 +156,8 @@ def test_function_with_parens(): assert len(eip_markers) == 1 assert eip_markers[0].args == ("opcode/test/stack_complex_operations",) - # Test decorator without parentheses (direct usage - this is the key fix for issue #1) + # Test decorator without parentheses (direct usage - this is the key fix + # for issue #1) @EIPChecklist.Opcode.Test.StackOverflow def test_function_no_parens(): pass @@ -192,6 +200,7 @@ def test_eip_checklist_pytest_param_usage(): with pytest.raises((TypeError, AssertionError)): pytest.param( "test_value", - marks=EIPChecklist.Opcode.Test.StackOverflow, # Without () should fail + # Without () should fail + marks=EIPChecklist.Opcode.Test.StackOverflow, id="should_fail", ) diff --git a/ethereum_test_exceptions/exception_mapper.py b/ethereum_test_exceptions/exception_mapper.py index 43d4d7af66..cf8e7b4e76 100644 --- a/ethereum_test_exceptions/exception_mapper.py +++ b/ethereum_test_exceptions/exception_mapper.py @@ -20,9 +20,11 @@ class ExceptionMapper(ABC): mapping_substring: ClassVar[Dict[ExceptionBase, str]] """ - Mapping of exception to substring that should be present in the error message. + Mapping of exception to substring that should be present in the error + message. - Items in this mapping are used for substring matching (`substring in message`). + Items in this mapping are used for substring matching (`substring in + message`). """ mapping_regex: ClassVar[Dict[ExceptionBase, str]] @@ -34,13 +36,14 @@ class ExceptionMapper(ABC): """ reliable: ClassVar[bool] = True """ - Whether the exceptions returned by the tool are reliable and can be accurately - mapped to the exceptions in this class. + Whether the exceptions returned by the tool are reliable and can be + accurately mapped to the exceptions in this class. """ def __init__(self) -> None: """Initialize the exception mapper.""" - # Ensure that the subclass has properly defined mapping_substring before accessing it + # Ensure that the subclass has properly defined mapping_substring + # before accessing it assert self.mapping_substring is not None, "mapping_substring must be defined in subclass" assert self.mapping_regex is not None, "mapping_regex must be defined in subclass" self.mapper_name = self.__class__.__name__ @@ -66,8 +69,8 @@ def message_to_exception( class ExceptionWithMessage(BaseModel, Generic[ExceptionBoundTypeVar]): """ - Class that contains the exception along with the verbatim message from the external - tool/client. + Class that contains the exception along with the verbatim message from the + external tool/client. """ exceptions: List[ExceptionBoundTypeVar] @@ -86,8 +89,8 @@ def __str__(self): def mapper_validator(v: str, info: ValidationInfo) -> Dict[str, Any] | UndefinedException | None: """ - Use the exception mapper that must be included in the context to map the exception - from the external tool. + Use the exception mapper that must be included in the context to map the + exception from the external tool. """ if v is None: return v @@ -110,17 +113,18 @@ def mapper_validator(v: str, info: ValidationInfo) -> Dict[str, Any] | Undefined ExceptionMapperValidator = BeforeValidator(mapper_validator) """ -Validator that can be used to annotate a pydantic field in a model that is meant to be -parsed from an external tool or client. +Validator that can be used to annotate a pydantic field in a model that is +meant to be parsed from an external tool or client. -The annotated type must be an union that can include `None`, `UndefinedException` and a -custom model as: +The annotated type must be an union that can include `None`, +`UndefinedException` and a custom model as: ``` class BlockExceptionWithMessage(ExceptionWithMessage[BlockException]): pass ``` where `BlockException` can be any derivation of `ExceptionBase`. -The `message` attribute is the verbatim message received from the external tool or client, -and can be used to be printed for extra context information in case of failures. +The `message` attribute is the verbatim message received from the external tool +or client, and can be used to be printed for extra context information in case +of failures. """ diff --git a/ethereum_test_exceptions/exceptions.py b/ethereum_test_exceptions/exceptions.py index 437b5ad8f2..8de5ac505c 100644 --- a/ethereum_test_exceptions/exceptions.py +++ b/ethereum_test_exceptions/exceptions.py @@ -25,7 +25,10 @@ def __init_subclass__(cls) -> None: def __get_pydantic_core_schema__( cls, source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call class constructor without info and appends the serialization schema.""" + """ + Call class constructor without info and appends the serialization + schema. + """ return no_info_plain_validator_function( cls.from_str, serialization=to_string_ser_schema(), @@ -104,7 +107,10 @@ def __new__(cls, value: str, *, mapper_name: str | None = None) -> "UndefinedExc def __get_pydantic_core_schema__( cls, source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call class constructor without info and appends the serialization schema.""" + """ + Call class constructor without info and appends the serialization + schema. + """ return no_info_plain_validator_function( cls, serialization=to_string_ser_schema(), @@ -114,195 +120,125 @@ def __get_pydantic_core_schema__( @unique class TransactionException(ExceptionBase): """ - Exception raised when a transaction is invalid, and thus cannot be executed. + Exception raised when a transaction is invalid, and thus cannot be + executed. - If a transaction with any of these exceptions is included in a block, the block is invalid. + If a transaction with any of these exceptions is included in a block, the + block is invalid. """ TYPE_NOT_SUPPORTED = auto() - """ - Transaction type is not supported on this chain configuration. - """ + """Transaction type is not supported on this chain configuration.""" SENDER_NOT_EOA = auto() - """ - Transaction is coming from address that is not exist anymore. - """ + """Transaction is coming from address that is not exist anymore.""" ADDRESS_TOO_SHORT = auto() - """ - Transaction `to` is not allowed to be less than 20 bytes. - """ + """Transaction `to` is not allowed to be less than 20 bytes.""" ADDRESS_TOO_LONG = auto() - """ - Transaction `to` is not allowed to be more than 20 bytes. - """ + """Transaction `to` is not allowed to be more than 20 bytes.""" NONCE_MISMATCH_TOO_HIGH = auto() - """ - Transaction nonce > sender.nonce. - """ + """Transaction nonce > sender.nonce.""" NONCE_MISMATCH_TOO_LOW = auto() - """ - Transaction nonce < sender.nonce. - """ + """Transaction nonce < sender.nonce.""" NONCE_TOO_BIG = auto() """ - Transaction `nonce` is not allowed to be max_uint64 - 1 (this is probably TransactionTest). + Transaction `nonce` is not allowed to be max_uint64 - 1 (this is probably + TransactionTest). """ NONCE_IS_MAX = auto() """ - Transaction `nonce` is not allowed to be max_uint64 - 1 (this is StateTests). + Transaction `nonce` is not allowed to be max_uint64 - 1 (this is + StateTests). """ NONCE_OVERFLOW = auto() - """ - Transaction `nonce` is not allowed to be more than uint64. - """ + """Transaction `nonce` is not allowed to be more than uint64.""" GASLIMIT_OVERFLOW = auto() - """ - Transaction gaslimit exceeds 2^64-1 maximum value. - """ + """Transaction gaslimit exceeds 2^64-1 maximum value.""" VALUE_OVERFLOW = auto() - """ - Transaction value exceeds 2^256-1 maximum value. - """ + """Transaction value exceeds 2^256-1 maximum value.""" GASPRICE_OVERFLOW = auto() - """ - Transaction gasPrice exceeds 2^256-1 maximum value. - """ + """Transaction gasPrice exceeds 2^256-1 maximum value.""" GASLIMIT_PRICE_PRODUCT_OVERFLOW = auto() - """ - Transaction gasPrice * gasLimit exceeds 2^256-1 maximum value. - """ + """Transaction gasPrice * gasLimit exceeds 2^256-1 maximum value.""" INVALID_SIGNATURE_VRS = auto() - """ - Invalid transaction v, r, s values. - """ + """Invalid transaction v, r, s values.""" RLP_INVALID_SIGNATURE_R = auto() - """ - Error reading transaction signature R value. - """ + """Error reading transaction signature R value.""" RLP_INVALID_SIGNATURE_S = auto() - """ - Error reading transaction signature S value. - """ + """Error reading transaction signature S value.""" RLP_LEADING_ZEROS_GASLIMIT = auto() - """ - Error reading transaction gaslimit field RLP. - """ + """Error reading transaction gaslimit field RLP.""" RLP_LEADING_ZEROS_GASPRICE = auto() - """ - Error reading transaction gasprice field RLP. - """ + """Error reading transaction gasprice field RLP.""" RLP_LEADING_ZEROS_VALUE = auto() - """ - Error reading transaction value field RLP. - """ + """Error reading transaction value field RLP.""" RLP_LEADING_ZEROS_NONCE = auto() - """ - Error reading transaction nonce field RLP. - """ + """Error reading transaction nonce field RLP.""" RLP_LEADING_ZEROS_R = auto() - """ - Error reading transaction signature R field RLP. - """ + """Error reading transaction signature R field RLP.""" RLP_LEADING_ZEROS_S = auto() - """ - Error reading transaction signature S field RLP. - """ + """Error reading transaction signature S field RLP.""" RLP_LEADING_ZEROS_V = auto() - """ - Error reading transaction signature V field RLP. - """ + """Error reading transaction signature V field RLP.""" RLP_LEADING_ZEROS_BASEFEE = auto() - """ - Error reading transaction basefee field RLP. - """ + """Error reading transaction basefee field RLP.""" RLP_LEADING_ZEROS_PRIORITY_FEE = auto() - """ - Error reading transaction priority fee field RLP. - """ + """Error reading transaction priority fee field RLP.""" RLP_LEADING_ZEROS_DATA_SIZE = auto() """ - Error reading transaction data field RLP, (rlp field length has leading zeros). + Error reading transaction data field RLP, (rlp field length has leading + zeros). """ RLP_LEADING_ZEROS_NONCE_SIZE = auto() """ - Error reading transaction nonce field RLP, (rlp field length has leading zeros). + Error reading transaction nonce field RLP, (rlp field length has leading + zeros). """ RLP_TOO_FEW_ELEMENTS = auto() """ - Error reading transaction RLP, structure has too few elements than expected. + Error reading transaction RLP, structure has too few elements than + expected. """ RLP_TOO_MANY_ELEMENTS = auto() """ - Error reading transaction RLP, structure has too many elements than expected. + Error reading transaction RLP, structure has too many elements than + expected. """ RLP_ERROR_EOF = auto() - """ - Error reading transaction RLP, rlp stream unexpectedly finished. - """ + """Error reading transaction RLP, rlp stream unexpectedly finished.""" RLP_ERROR_SIZE = auto() - """ - Error reading transaction RLP, rlp size is invalid. - """ + """Error reading transaction RLP, rlp size is invalid.""" RLP_ERROR_SIZE_LEADING_ZEROS = auto() - """ - Error reading transaction RLP, field size has leading zeros. - """ + """Error reading transaction RLP, field size has leading zeros.""" INVALID_CHAINID = auto() - """ - Transaction chain id encoding is incorrect. - """ + """Transaction chain id encoding is incorrect.""" RLP_INVALID_DATA = auto() - """ - Transaction data field is invalid rlp. - """ + """Transaction data field is invalid rlp.""" RLP_INVALID_GASLIMIT = auto() - """ - Transaction gaslimit field is invalid rlp. - """ + """Transaction gaslimit field is invalid rlp.""" RLP_INVALID_NONCE = auto() - """ - Transaction nonce field is invalid rlp. - """ + """Transaction nonce field is invalid rlp.""" RLP_INVALID_TO = auto() - """ - Transaction to field is invalid rlp. - """ + """Transaction to field is invalid rlp.""" RLP_INVALID_ACCESS_LIST_ADDRESS_TOO_LONG = auto() - """ - Transaction access list address is > 20 bytes. - """ + """Transaction access list address is > 20 bytes.""" RLP_INVALID_ACCESS_LIST_ADDRESS_TOO_SHORT = auto() - """ - Transaction access list address is < 20 bytes. - """ + """Transaction access list address is < 20 bytes.""" RLP_INVALID_ACCESS_LIST_STORAGE_TOO_LONG = auto() - """ - Transaction access list storage hash > 32 bytes. - """ + """Transaction access list storage hash > 32 bytes.""" RLP_INVALID_ACCESS_LIST_STORAGE_TOO_SHORT = auto() - """ - Transaction access list storage hash < 32 bytes. - """ + """Transaction access list storage hash < 32 bytes.""" RLP_INVALID_HEADER = auto() - """ - Transaction failed to read from RLP as rlp header is invalid. - """ + """Transaction failed to read from RLP as rlp header is invalid.""" RLP_INVALID_VALUE = auto() - """ - Transaction value field is invalid rlp/structure. - """ + """Transaction value field is invalid rlp/structure.""" EC_RECOVERY_FAIL = auto() - """ - Transaction has correct signature, but ec recovery failed. - """ + """Transaction has correct signature, but ec recovery failed.""" INSUFFICIENT_ACCOUNT_FUNDS = auto() """ Transaction's sender does not have enough funds to pay for the transaction. """ INSUFFICIENT_MAX_FEE_PER_GAS = auto() - """ - Transaction's max-fee-per-gas is lower than the block base-fee. - """ + """Transaction's max-fee-per-gas is lower than the block base-fee.""" PRIORITY_OVERFLOW = auto() """ Transaction's max-priority-fee-per-gas is exceeds 2^256-1 maximum value. @@ -313,88 +249,59 @@ class TransactionException(ExceptionBase): """ PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS_2 = auto() """ - Transaction's max-priority-fee-per-gas is greater than the max-fee-per-gas (TransactionTests). + Transaction's max-priority-fee-per-gas is greater than the max-fee-per-gas + (TransactionTests). """ INSUFFICIENT_MAX_FEE_PER_BLOB_GAS = auto() """ - Transaction's max-fee-per-blob-gas is lower than the block's blob-gas price. + Transaction's max-fee-per-blob-gas is lower than the block's blob-gas + price. """ INTRINSIC_GAS_TOO_LOW = auto() - """ - Transaction's gas limit is too low. - """ + """Transaction's gas limit is too low.""" INTRINSIC_GAS_BELOW_FLOOR_GAS_COST = auto() - """ - Transaction's gas limit is below the floor gas cost. - """ + """Transaction's gas limit is below the floor gas cost.""" INITCODE_SIZE_EXCEEDED = auto() """ Transaction's initcode for a contract-creating transaction is too large. """ TYPE_3_TX_PRE_FORK = auto() - """ - Transaction type 3 included before activation fork. - """ + """Transaction type 3 included before activation fork.""" TYPE_3_TX_ZERO_BLOBS_PRE_FORK = auto() - """ - Transaction type 3, with zero blobs, included before activation fork. - """ + """Transaction type 3, with zero blobs, included before activation fork.""" TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH = auto() - """ - Transaction contains a blob versioned hash with an invalid version. - """ + """Transaction contains a blob versioned hash with an invalid version.""" TYPE_3_TX_WITH_FULL_BLOBS = auto() - """ - Transaction contains full blobs (network-version of the transaction). - """ + """Transaction contains full blobs (network-version of the transaction).""" TYPE_3_TX_BLOB_COUNT_EXCEEDED = auto() - """ - Transaction contains too many blob versioned hashes. - """ + """Transaction contains too many blob versioned hashes.""" TYPE_3_TX_CONTRACT_CREATION = auto() - """ - Transaction is a type 3 transaction and has an empty `to`. - """ + """Transaction is a type 3 transaction and has an empty `to`.""" TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED = auto() - """ - Transaction causes block to go over blob gas limit. - """ + """Transaction causes block to go over blob gas limit.""" GAS_ALLOWANCE_EXCEEDED = auto() - """ - Transaction causes block to go over blob gas limit. - """ + """Transaction causes block to go over blob gas limit.""" GAS_LIMIT_EXCEEDS_MAXIMUM = auto() """ Transaction gas limit exceeds the maximum allowed limit of 30 million. """ TYPE_3_TX_ZERO_BLOBS = auto() - """ - Transaction is type 3, but has no blobs. - """ + """Transaction is type 3, but has no blobs.""" TYPE_4_EMPTY_AUTHORIZATION_LIST = auto() - """ - Transaction is type 4, but has an empty authorization list. - """ + """Transaction is type 4, but has an empty authorization list.""" TYPE_4_INVALID_AUTHORITY_SIGNATURE = auto() - """ - Transaction authority signature is invalid - """ + """Transaction authority signature is invalid""" TYPE_4_INVALID_AUTHORITY_SIGNATURE_S_TOO_HIGH = auto() - """ - Transaction authority signature is invalid - """ + """Transaction authority signature is invalid""" TYPE_4_TX_CONTRACT_CREATION = auto() - """ - Transaction is a type 4 transaction and has an empty `to`. - """ + """Transaction is a type 4 transaction and has an empty `to`.""" TYPE_4_INVALID_AUTHORIZATION_FORMAT = auto() """ - Transaction is type 4, but contains an authorization that has an invalid format. + Transaction is type 4, but contains an authorization that has an invalid + format. """ TYPE_4_TX_PRE_FORK = auto() - """ - Transaction type 4 included before activation fork. - """ + """Transaction type 4 included before activation fork.""" @unique @@ -402,202 +309,158 @@ class BlockException(ExceptionBase): """ Exception raised when a block is invalid, but not due to a transaction. - E.g. all transactions in the block are valid, and can be applied to the state, but the - block header contains an invalid field. + E.g. all transactions in the block are valid, and can be applied to the + state, but the block header contains an invalid field. """ TOO_MANY_UNCLES = auto() - """ - Block declares too many uncles over the allowed limit. - """ + """Block declares too many uncles over the allowed limit.""" UNCLE_IN_CHAIN = auto() - """ - Block declares uncle header that is already imported into chain. - """ + """Block declares uncle header that is already imported into chain.""" UNCLE_IS_ANCESTOR = auto() - """ - Block declares uncle header that is directly a parent of this block. - """ + """Block declares uncle header that is directly a parent of this block.""" UNCLE_IS_BROTHER = auto() - """ - Block declares two similar uncle headers. - """ + """Block declares two similar uncle headers.""" UNCLE_PARENT_INCORRECT = auto() - """ - Block declares uncle header that is an outdated block to be an uncle. - """ + """Block declares uncle header that is an outdated block to be an uncle.""" EXTRA_DATA_TOO_BIG = auto() - """ - Block header's extra data >32 bytes. - """ + """Block header's extra data >32 bytes.""" EXTRA_DATA_INVALID_DAO = auto() """ Block header's extra data after dao fork must be a fixed pre defined hash. """ UNKNOWN_PARENT = auto() """ - Block header's parent hash does not correspond to any of existing blocks on chain. + Block header's parent hash does not correspond to any of existing blocks on + chain. """ UNCLE_UNKNOWN_PARENT = auto() """ - Uncle header's parent hash does not correspond to any of existing blocks on chain. + Uncle header's parent hash does not correspond to any of existing blocks on + chain. """ UNKNOWN_PARENT_ZERO = auto() - """ - Block header's parent hash is zero hash. - """ + """Block header's parent hash is zero hash.""" GASLIMIT_TOO_BIG = auto() - """ - Block header's gas limit > 0x7fffffffffffffff. - """ + """Block header's gas limit > 0x7fffffffffffffff.""" INVALID_BLOCK_NUMBER = auto() - """ - Block header's number != parent header's number + 1. - """ + """Block header's number != parent header's number + 1.""" INVALID_BLOCK_TIMESTAMP_OLDER_THAN_PARENT = auto() - """ - Block header's timestamp <= parent header's timestamp. - """ + """Block header's timestamp <= parent header's timestamp.""" INVALID_DIFFICULTY = auto() """ - Block header's difficulty does not match the difficulty formula calculated from previous block. + Block header's difficulty does not match the difficulty formula calculated + from previous block. """ INVALID_LOG_BLOOM = auto() """ - Block header's logs bloom hash does not match the actually computed log bloom. + Block header's logs bloom hash does not match the actually computed log + bloom. """ INVALID_STATE_ROOT = auto() """ - Block header's state root hash does not match the actually computed hash of the state. + Block header's state root hash does not match the actually computed hash of + the state. """ INVALID_RECEIPTS_ROOT = auto() """ - Block header's receipts root hash does not match the actually computed hash of receipts. + Block header's receipts root hash does not match the actually computed hash + of receipts. """ INVALID_TRANSACTIONS_ROOT = auto() """ - Block header's transactions root hash does not match the actually computed hash of tx tree. + Block header's transactions root hash does not match the actually computed + hash of tx tree. """ INVALID_UNCLES_HASH = auto() """ - Block header's uncle hash does not match the actually computed hash of block's uncles. + Block header's uncle hash does not match the actually computed hash of + block's uncles. """ GAS_USED_OVERFLOW = auto() - """ - Block transactions consume more gas than block header allow. - """ + """Block transactions consume more gas than block header allow.""" INVALID_GASLIMIT = auto() """ - Block header's gas limit does not match the gas limit formula calculated from previous block. + Block header's gas limit does not match the gas limit formula calculated + from previous block. """ INVALID_BASEFEE_PER_GAS = auto() - """ - Block header's base_fee_per_gas field is calculated incorrect. - """ + """Block header's base_fee_per_gas field is calculated incorrect.""" INVALID_GAS_USED = auto() """ Block header's actual gas used does not match the provided header's value """ INVALID_GAS_USED_ABOVE_LIMIT = auto() - """ - Block header's gas used value is above the gas limit field's value. - """ + """Block header's gas used value is above the gas limit field's value.""" INVALID_WITHDRAWALS_ROOT = auto() """ Block header's withdrawals root does not match calculated withdrawals root. """ INCORRECT_BLOCK_FORMAT = auto() """ - Block's format is incorrect, contains invalid fields, is missing fields, or contains fields of - a fork that is not active yet. + Block's format is incorrect, contains invalid fields, is missing fields, or + contains fields of a fork that is not active yet. """ BLOB_GAS_USED_ABOVE_LIMIT = auto() - """ - Block's blob gas used in header is above the limit. - """ + """Block's blob gas used in header is above the limit.""" INCORRECT_BLOB_GAS_USED = auto() - """ - Block's blob gas used in header is incorrect. - """ + """Block's blob gas used in header is incorrect.""" INCORRECT_EXCESS_BLOB_GAS = auto() - """ - Block's excess blob gas in header is incorrect. - """ + """Block's excess blob gas in header is incorrect.""" INVALID_VERSIONED_HASHES = auto() - """ - Incorrect number of versioned hashes in a payload. - """ + """Incorrect number of versioned hashes in a payload.""" RLP_STRUCTURES_ENCODING = auto() """ Block's rlp encoding is valid but ethereum structures in it are invalid. """ RLP_WITHDRAWALS_NOT_READ = auto() - """ - Block's rlp encoding is missing withdrawals. - """ + """Block's rlp encoding is missing withdrawals.""" RLP_INVALID_FIELD_OVERFLOW_64 = auto() - """ - One of block's fields rlp is overflow 2**64 value. - """ + """One of block's fields rlp is overflow 2**64 value.""" RLP_INVALID_ADDRESS = auto() - """ - Block withdrawals address is rlp of invalid address != 20 bytes. - """ + """Block withdrawals address is rlp of invalid address != 20 bytes.""" RLP_BLOCK_LIMIT_EXCEEDED = auto() - """ - Block's rlp encoding is larger than the allowed limit. - """ + """Block's rlp encoding is larger than the allowed limit.""" INVALID_REQUESTS = auto() - """ - Block's requests are invalid. - """ + """Block's requests are invalid.""" IMPORT_IMPOSSIBLE_LEGACY = auto() - """ - Legacy block import is impossible in this chain configuration. - """ + """Legacy block import is impossible in this chain configuration.""" IMPORT_IMPOSSIBLE_LEGACY_WRONG_PARENT = auto() """ - Legacy block import is impossible, trying to import on top of a block that is not legacy. + Legacy block import is impossible, trying to import on top of a block that + is not legacy. """ IMPORT_IMPOSSIBLE_LONDON_WRONG_PARENT = auto() """ Trying to import london (basefee) block on top of block that is not 1559. """ IMPORT_IMPOSSIBLE_PARIS_WRONG_POW = auto() - """ - Trying to import paris(merge) block with PoW enabled. - """ + """Trying to import paris(merge) block with PoW enabled.""" IMPORT_IMPOSSIBLE_PARIS_WRONG_POS = auto() """ Trying to import paris(merge) block with PoS enabled before TTD is reached. """ IMPORT_IMPOSSIBLE_LONDON_OVER_PARIS = auto() - """ - Trying to import london looking block over paris network (POS). - """ + """Trying to import london looking block over paris network (POS).""" IMPORT_IMPOSSIBLE_PARIS_OVER_SHANGHAI = auto() - """ - Trying to import paris block on top of shanghai block. - """ + """Trying to import paris block on top of shanghai block.""" IMPORT_IMPOSSIBLE_SHANGHAI = auto() - """ - Shanghai block import is impossible in this chain configuration. - """ + """Shanghai block import is impossible in this chain configuration.""" IMPORT_IMPOSSIBLE_UNCLES_OVER_PARIS = auto() """ Trying to import a block after paris fork that has not empty uncles hash. """ IMPORT_IMPOSSIBLE_DIFFICULTY_OVER_PARIS = auto() - """ - Trying to import a block after paris fork that has difficulty != 0. - """ + """Trying to import a block after paris fork that has difficulty != 0.""" SYSTEM_CONTRACT_EMPTY = auto() """ - A system contract address contains no code at the end of fork activation block. + A system contract address contains no code at the end of fork activation + block. """ SYSTEM_CONTRACT_CALL_FAILED = auto() """ - A system contract call at the end of block execution (from the system address) fails. + A system contract call at the end of block execution (from the system + address) fails. """ INVALID_BLOCK_HASH = auto() """ @@ -605,8 +468,8 @@ class BlockException(ExceptionBase): """ INVALID_DEPOSIT_EVENT_LAYOUT = auto() """ - Transaction emits a `DepositEvent` in the deposit contract (EIP-6110), but the layout - of the event does not match the required layout. + Transaction emits a `DepositEvent` in the deposit contract (EIP-6110), but + the layout of the event does not match the required layout. """ @@ -615,218 +478,122 @@ class EOFException(ExceptionBase): """Exception raised when an EOF container is invalid.""" DEFAULT_EXCEPTION = auto() - """ - Expect some exception, not yet known. - """ + """Expect some exception, not yet known.""" UNDEFINED_EXCEPTION = auto() - """ - Indicates that exception string is not mapped to an exception enum. - """ + """Indicates that exception string is not mapped to an exception enum.""" UNDEFINED_INSTRUCTION = auto() - """ - EOF container has undefined instruction in it's body code. - """ + """EOF container has undefined instruction in it's body code.""" UNKNOWN_VERSION = auto() - """ - EOF container has an unknown version. - """ + """EOF container has an unknown version.""" INCOMPLETE_MAGIC = auto() - """ - EOF container has not enough bytes to read magic. - """ + """EOF container has not enough bytes to read magic.""" INVALID_MAGIC = auto() - """ - EOF container has not allowed magic version byte. - """ + """EOF container has not allowed magic version byte.""" INVALID_VERSION = auto() - """ - EOF container version bytes mismatch. - """ + """EOF container version bytes mismatch.""" INVALID_NON_RETURNING_FLAG = auto() - """ - EOF container's section has non-returning flag set incorrectly. - """ + """EOF container's section has non-returning flag set incorrectly.""" INVALID_RJUMP_DESTINATION = auto() - """ - Code has RJUMP instruction with invalid parameters. - """ + """Code has RJUMP instruction with invalid parameters.""" MISSING_TYPE_HEADER = auto() - """ - EOF container missing types section. - """ + """EOF container missing types section.""" INVALID_TYPE_SECTION_SIZE = auto() - """ - EOF container types section has wrong size. - """ + """EOF container types section has wrong size.""" INVALID_TYPE_BODY = auto() - """ - EOF container types body section bytes are wrong. - """ + """EOF container types body section bytes are wrong.""" MISSING_CODE_HEADER = auto() - """ - EOF container missing code section. - """ + """EOF container missing code section.""" INVALID_CODE_SECTION = auto() - """ - EOF container code section bytes are incorrect. - """ + """EOF container code section bytes are incorrect.""" INCOMPLETE_CODE_HEADER = auto() - """ - EOF container code header missing bytes. - """ + """EOF container code header missing bytes.""" INCOMPLETE_DATA_HEADER = auto() - """ - EOF container data header missing bytes. - """ + """EOF container data header missing bytes.""" ZERO_SECTION_SIZE = auto() - """ - EOF container data header construction is wrong. - """ + """EOF container data header construction is wrong.""" MISSING_DATA_SECTION = auto() - """ - EOF container missing data section - """ + """EOF container missing data section""" INCOMPLETE_CONTAINER = auto() - """ - EOF container bytes are incomplete. - """ + """EOF container bytes are incomplete.""" INVALID_SECTION_BODIES_SIZE = auto() - """ - Sections bodies does not match sections headers. - """ + """Sections bodies does not match sections headers.""" TRAILING_BYTES = auto() - """ - EOF container has bytes beyond data section. - """ + """EOF container has bytes beyond data section.""" MISSING_TERMINATOR = auto() - """ - EOF container missing terminator bytes between header and body. - """ + """EOF container missing terminator bytes between header and body.""" MISSING_HEADERS_TERMINATOR = auto() - """ - Some type of another exception about missing headers terminator. - """ + """Some type of another exception about missing headers terminator.""" INVALID_FIRST_SECTION_TYPE = auto() - """ - EOF container header does not have types section first. - """ + """EOF container header does not have types section first.""" INCOMPLETE_SECTION_NUMBER = auto() - """ - EOF container header has section that is missing declaration bytes. - """ + """EOF container header has section that is missing declaration bytes.""" INCOMPLETE_SECTION_SIZE = auto() - """ - EOF container header has section that is defined incorrectly. - """ + """EOF container header has section that is defined incorrectly.""" TOO_MANY_CODE_SECTIONS = auto() - """ - EOF container header has too many code sections. - """ + """EOF container header has too many code sections.""" MISSING_STOP_OPCODE = auto() - """ - EOF container's code missing STOP bytecode at it's end. - """ + """EOF container's code missing STOP bytecode at it's end.""" INPUTS_OUTPUTS_NUM_ABOVE_LIMIT = auto() - """ - EOF container code section inputs/outputs number is above the limit - """ + """EOF container code section inputs/outputs number is above the limit""" UNREACHABLE_INSTRUCTIONS = auto() - """ - EOF container's code have instructions that are unreachable. - """ + """EOF container's code have instructions that are unreachable.""" UNREACHABLE_CODE_SECTIONS = auto() - """ - EOF container's body have code sections that are unreachable. - """ + """EOF container's body have code sections that are unreachable.""" STACK_UNDERFLOW = auto() - """ - EOF container's code produces an stack underflow. - """ + """EOF container's code produces an stack underflow.""" STACK_OVERFLOW = auto() - """ - EOF container's code produces an stack overflow. - """ + """EOF container's code produces an stack overflow.""" STACK_HEIGHT_MISMATCH = auto() - """ - EOF container section stack height mismatch. - """ + """EOF container section stack height mismatch.""" MAX_STACK_INCREASE_ABOVE_LIMIT = auto() - """ - EOF container's specified max stack increase is above the limit. - """ + """EOF container's specified max stack increase is above the limit.""" STACK_HIGHER_THAN_OUTPUTS = auto() """ - EOF container section stack height is higher than the outputs. - when returning + EOF container section stack height is higher than the outputs. when + returning """ JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS = auto() """ - EOF container section JUMPF's to a destination section with incompatible outputs. + EOF container section JUMPF's to a destination section with incompatible + outputs. """ INVALID_MAX_STACK_INCREASE = auto() """ - EOF container section's specified max stack increase does not match the actual stack height. + EOF container section's specified max stack increase does not match the + actual stack height. """ INVALID_DATALOADN_INDEX = auto() - """ - A DATALOADN instruction has out-of-bounds index for the data section. - """ + """A DATALOADN instruction has out-of-bounds index for the data section.""" TRUNCATED_INSTRUCTION = auto() - """ - EOF container's code section has truncated instruction. - """ + """EOF container's code section has truncated instruction.""" TOPLEVEL_CONTAINER_TRUNCATED = auto() - """ - Top-level EOF container has data section truncated - """ + """Top-level EOF container has data section truncated""" ORPHAN_SUBCONTAINER = auto() - """ - EOF container has an unreferenced subcontainer. - '""" + """EOF container has an unreferenced subcontainer. '""" CONTAINER_SIZE_ABOVE_LIMIT = auto() - """ - EOF container is above size limit - """ + """EOF container is above size limit""" INVALID_CONTAINER_SECTION_INDEX = auto() - """ - Instruction references container section that does not exist. - """ + """Instruction references container section that does not exist.""" INCOMPATIBLE_CONTAINER_KIND = auto() - """ - Incompatible instruction found in a container of a specific kind. - """ + """Incompatible instruction found in a container of a specific kind.""" AMBIGUOUS_CONTAINER_KIND = auto() - """ - The kind of a sub-container cannot be uniquely deduced. - """ + """The kind of a sub-container cannot be uniquely deduced.""" TOO_MANY_CONTAINERS = auto() - """ - EOF container header has too many sub-containers. - """ + """EOF container header has too many sub-containers.""" INVALID_CODE_SECTION_INDEX = auto() - """ - CALLF Operation refers to a non-existent code section - """ + """CALLF Operation refers to a non-existent code section""" UNEXPECTED_HEADER_KIND = auto() - """ - Header parsing encountered a section kind it wasn't expecting - """ + """Header parsing encountered a section kind it wasn't expecting""" CALLF_TO_NON_RETURNING = auto() - """ - CALLF instruction targeting a non-returning code section - """ + """CALLF instruction targeting a non-returning code section""" EOFCREATE_WITH_TRUNCATED_CONTAINER = auto() - """ - EOFCREATE with truncated container - """ + """EOFCREATE with truncated container""" -""" -Pydantic Annotated Types -""" +"""Pydantic Annotated Types""" ExceptionInstanceOrList = Annotated[ List[TransactionException | BlockException] | TransactionException | BlockException, diff --git a/ethereum_test_exceptions/exceptions/base.py b/ethereum_test_exceptions/exceptions/base.py index 96b52929f6..ebfb0d79e9 100644 --- a/ethereum_test_exceptions/exceptions/base.py +++ b/ethereum_test_exceptions/exceptions/base.py @@ -25,7 +25,10 @@ def __init_subclass__(cls) -> None: def __get_pydantic_core_schema__( cls, source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call class constructor without info and appends the serialization schema.""" + """ + Call class constructor without info and appends the serialization + schema. + """ return no_info_plain_validator_function( cls.from_str, serialization=to_string_ser_schema(), @@ -82,7 +85,10 @@ def __new__(cls, value: str, *, mapper_name: str | None = None) -> "UndefinedExc def __get_pydantic_core_schema__( cls, source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call class constructor without info and appends the serialization schema.""" + """ + Call class constructor without info and appends the serialization + schema. + """ return no_info_plain_validator_function( cls, serialization=to_string_ser_schema(), diff --git a/ethereum_test_exceptions/exceptions/block.py b/ethereum_test_exceptions/exceptions/block.py index 4053b1938e..8e7eae0b24 100644 --- a/ethereum_test_exceptions/exceptions/block.py +++ b/ethereum_test_exceptions/exceptions/block.py @@ -10,202 +10,158 @@ class BlockException(ExceptionBase): """ Exception raised when a block is invalid, but not due to a transaction. - E.g. all transactions in the block are valid, and can be applied to the state, but the - block header contains an invalid field. + E.g. all transactions in the block are valid, and can be applied to the + state, but the block header contains an invalid field. """ TOO_MANY_UNCLES = auto() - """ - Block declares too many uncles over the allowed limit. - """ + """Block declares too many uncles over the allowed limit.""" UNCLE_IN_CHAIN = auto() - """ - Block declares uncle header that is already imported into chain. - """ + """Block declares uncle header that is already imported into chain.""" UNCLE_IS_ANCESTOR = auto() - """ - Block declares uncle header that is directly a parent of this block. - """ + """Block declares uncle header that is directly a parent of this block.""" UNCLE_IS_BROTHER = auto() - """ - Block declares two similar uncle headers. - """ + """Block declares two similar uncle headers.""" UNCLE_PARENT_INCORRECT = auto() - """ - Block declares uncle header that is an outdated block to be an uncle. - """ + """Block declares uncle header that is an outdated block to be an uncle.""" EXTRA_DATA_TOO_BIG = auto() - """ - Block header's extra data >32 bytes. - """ + """Block header's extra data >32 bytes.""" EXTRA_DATA_INVALID_DAO = auto() """ Block header's extra data after dao fork must be a fixed pre defined hash. """ UNKNOWN_PARENT = auto() """ - Block header's parent hash does not correspond to any of existing blocks on chain. + Block header's parent hash does not correspond to any of existing blocks on + chain. """ UNCLE_UNKNOWN_PARENT = auto() """ - Uncle header's parent hash does not correspond to any of existing blocks on chain. + Uncle header's parent hash does not correspond to any of existing blocks on + chain. """ UNKNOWN_PARENT_ZERO = auto() - """ - Block header's parent hash is zero hash. - """ + """Block header's parent hash is zero hash.""" GASLIMIT_TOO_BIG = auto() - """ - Block header's gas limit > 0x7fffffffffffffff. - """ + """Block header's gas limit > 0x7fffffffffffffff.""" INVALID_BLOCK_NUMBER = auto() - """ - Block header's number != parent header's number + 1. - """ + """Block header's number != parent header's number + 1.""" INVALID_BLOCK_TIMESTAMP_OLDER_THAN_PARENT = auto() - """ - Block header's timestamp <= parent header's timestamp. - """ + """Block header's timestamp <= parent header's timestamp.""" INVALID_DIFFICULTY = auto() """ - Block header's difficulty does not match the difficulty formula calculated from previous block. + Block header's difficulty does not match the difficulty formula calculated + from previous block. """ INVALID_LOG_BLOOM = auto() """ - Block header's logs bloom hash does not match the actually computed log bloom. + Block header's logs bloom hash does not match the actually computed log + bloom. """ INVALID_STATE_ROOT = auto() """ - Block header's state root hash does not match the actually computed hash of the state. + Block header's state root hash does not match the actually computed hash of + the state. """ INVALID_RECEIPTS_ROOT = auto() """ - Block header's receipts root hash does not match the actually computed hash of receipts. + Block header's receipts root hash does not match the actually computed hash + of receipts. """ INVALID_TRANSACTIONS_ROOT = auto() """ - Block header's transactions root hash does not match the actually computed hash of tx tree. + Block header's transactions root hash does not match the actually computed + hash of tx tree. """ INVALID_UNCLES_HASH = auto() """ - Block header's uncle hash does not match the actually computed hash of block's uncles. + Block header's uncle hash does not match the actually computed hash of + block's uncles. """ GAS_USED_OVERFLOW = auto() - """ - Block transactions consume more gas than block header allow. - """ + """Block transactions consume more gas than block header allow.""" INVALID_GASLIMIT = auto() """ - Block header's gas limit does not match the gas limit formula calculated from previous block. + Block header's gas limit does not match the gas limit formula calculated + from previous block. """ INVALID_BASEFEE_PER_GAS = auto() - """ - Block header's base_fee_per_gas field is calculated incorrect. - """ + """Block header's base_fee_per_gas field is calculated incorrect.""" INVALID_GAS_USED = auto() """ Block header's actual gas used does not match the provided header's value """ INVALID_GAS_USED_ABOVE_LIMIT = auto() - """ - Block header's gas used value is above the gas limit field's value. - """ + """Block header's gas used value is above the gas limit field's value.""" INVALID_WITHDRAWALS_ROOT = auto() """ Block header's withdrawals root does not match calculated withdrawals root. """ INCORRECT_BLOCK_FORMAT = auto() """ - Block's format is incorrect, contains invalid fields, is missing fields, or contains fields of - a fork that is not active yet. + Block's format is incorrect, contains invalid fields, is missing fields, or + contains fields of a fork that is not active yet. """ BLOB_GAS_USED_ABOVE_LIMIT = auto() - """ - Block's blob gas used in header is above the limit. - """ + """Block's blob gas used in header is above the limit.""" INCORRECT_BLOB_GAS_USED = auto() - """ - Block's blob gas used in header is incorrect. - """ + """Block's blob gas used in header is incorrect.""" INCORRECT_EXCESS_BLOB_GAS = auto() - """ - Block's excess blob gas in header is incorrect. - """ + """Block's excess blob gas in header is incorrect.""" INVALID_VERSIONED_HASHES = auto() - """ - Incorrect number of versioned hashes in a payload. - """ + """Incorrect number of versioned hashes in a payload.""" RLP_STRUCTURES_ENCODING = auto() """ Block's rlp encoding is valid but ethereum structures in it are invalid. """ RLP_WITHDRAWALS_NOT_READ = auto() - """ - Block's rlp encoding is missing withdrawals. - """ + """Block's rlp encoding is missing withdrawals.""" RLP_INVALID_FIELD_OVERFLOW_64 = auto() - """ - One of block's fields rlp is overflow 2**64 value. - """ + """One of block's fields rlp is overflow 2**64 value.""" RLP_INVALID_ADDRESS = auto() - """ - Block withdrawals address is rlp of invalid address != 20 bytes. - """ + """Block withdrawals address is rlp of invalid address != 20 bytes.""" RLP_BLOCK_LIMIT_EXCEEDED = auto() - """ - Block's rlp encoding is larger than the allowed limit. - """ + """Block's rlp encoding is larger than the allowed limit.""" INVALID_REQUESTS = auto() - """ - Block's requests are invalid. - """ + """Block's requests are invalid.""" IMPORT_IMPOSSIBLE_LEGACY = auto() - """ - Legacy block import is impossible in this chain configuration. - """ + """Legacy block import is impossible in this chain configuration.""" IMPORT_IMPOSSIBLE_LEGACY_WRONG_PARENT = auto() """ - Legacy block import is impossible, trying to import on top of a block that is not legacy. + Legacy block import is impossible, trying to import on top of a block that + is not legacy. """ IMPORT_IMPOSSIBLE_LONDON_WRONG_PARENT = auto() """ Trying to import london (basefee) block on top of block that is not 1559. """ IMPORT_IMPOSSIBLE_PARIS_WRONG_POW = auto() - """ - Trying to import paris(merge) block with PoW enabled. - """ + """Trying to import paris(merge) block with PoW enabled.""" IMPORT_IMPOSSIBLE_PARIS_WRONG_POS = auto() """ Trying to import paris(merge) block with PoS enabled before TTD is reached. """ IMPORT_IMPOSSIBLE_LONDON_OVER_PARIS = auto() - """ - Trying to import london looking block over paris network (POS). - """ + """Trying to import london looking block over paris network (POS).""" IMPORT_IMPOSSIBLE_PARIS_OVER_SHANGHAI = auto() - """ - Trying to import paris block on top of shanghai block. - """ + """Trying to import paris block on top of shanghai block.""" IMPORT_IMPOSSIBLE_SHANGHAI = auto() - """ - Shanghai block import is impossible in this chain configuration. - """ + """Shanghai block import is impossible in this chain configuration.""" IMPORT_IMPOSSIBLE_UNCLES_OVER_PARIS = auto() """ Trying to import a block after paris fork that has not empty uncles hash. """ IMPORT_IMPOSSIBLE_DIFFICULTY_OVER_PARIS = auto() - """ - Trying to import a block after paris fork that has difficulty != 0. - """ + """Trying to import a block after paris fork that has difficulty != 0.""" SYSTEM_CONTRACT_EMPTY = auto() """ - A system contract address contains no code at the end of fork activation block. + A system contract address contains no code at the end of fork activation + block. """ SYSTEM_CONTRACT_CALL_FAILED = auto() """ - A system contract call at the end of block execution (from the system address) fails. + A system contract call at the end of block execution (from the system + address) fails. """ INVALID_BLOCK_HASH = auto() """ @@ -213,21 +169,18 @@ class BlockException(ExceptionBase): """ INVALID_DEPOSIT_EVENT_LAYOUT = auto() """ - Transaction emits a `DepositEvent` in the deposit contract (EIP-6110), but the layout - of the event does not match the required layout. + Transaction emits a `DepositEvent` in the deposit contract (EIP-6110), but + the layout of the event does not match the required layout. """ # --- Block-Level Access Lists (EIP-7928) --- # INVALID_BLOCK_ACCESS_LIST = auto() - """ - Block's access list is invalid. - """ + """Block's access list is invalid.""" INVALID_BAL_HASH = auto() - """ - Block header's BAL hash does not match the computed BAL hash. - """ + """Block header's BAL hash does not match the computed BAL hash.""" INVALID_BAL_EXTRA_ACCOUNT = auto() """ - Block BAL contains an account change that is not present in the computed BAL. + Block BAL contains an account change that is not present in the computed + BAL. """ INVALID_BAL_MISSING_ACCOUNT = auto() """ diff --git a/ethereum_test_exceptions/exceptions/eof.py b/ethereum_test_exceptions/exceptions/eof.py index 03df7faf64..0e9c0c5f6c 100644 --- a/ethereum_test_exceptions/exceptions/eof.py +++ b/ethereum_test_exceptions/exceptions/eof.py @@ -10,210 +10,116 @@ class EOFException(ExceptionBase): """Exception raised when an EOF container is invalid.""" DEFAULT_EXCEPTION = auto() - """ - Expect some exception, not yet known. - """ + """Expect some exception, not yet known.""" UNDEFINED_EXCEPTION = auto() - """ - Indicates that exception string is not mapped to an exception enum. - """ + """Indicates that exception string is not mapped to an exception enum.""" UNDEFINED_INSTRUCTION = auto() - """ - EOF container has undefined instruction in it's body code. - """ + """EOF container has undefined instruction in it's body code.""" UNKNOWN_VERSION = auto() - """ - EOF container has an unknown version. - """ + """EOF container has an unknown version.""" INCOMPLETE_MAGIC = auto() - """ - EOF container has not enough bytes to read magic. - """ + """EOF container has not enough bytes to read magic.""" INVALID_MAGIC = auto() - """ - EOF container has not allowed magic version byte. - """ + """EOF container has not allowed magic version byte.""" INVALID_VERSION = auto() - """ - EOF container version bytes mismatch. - """ + """EOF container version bytes mismatch.""" INVALID_NON_RETURNING_FLAG = auto() - """ - EOF container's section has non-returning flag set incorrectly. - """ + """EOF container's section has non-returning flag set incorrectly.""" INVALID_RJUMP_DESTINATION = auto() - """ - Code has RJUMP instruction with invalid parameters. - """ + """Code has RJUMP instruction with invalid parameters.""" MISSING_TYPE_HEADER = auto() - """ - EOF container missing types section. - """ + """EOF container missing types section.""" INVALID_TYPE_SECTION_SIZE = auto() - """ - EOF container types section has wrong size. - """ + """EOF container types section has wrong size.""" INVALID_TYPE_BODY = auto() - """ - EOF container types body section bytes are wrong. - """ + """EOF container types body section bytes are wrong.""" MISSING_CODE_HEADER = auto() - """ - EOF container missing code section. - """ + """EOF container missing code section.""" INVALID_CODE_SECTION = auto() - """ - EOF container code section bytes are incorrect. - """ + """EOF container code section bytes are incorrect.""" INCOMPLETE_CODE_HEADER = auto() - """ - EOF container code header missing bytes. - """ + """EOF container code header missing bytes.""" INCOMPLETE_DATA_HEADER = auto() - """ - EOF container data header missing bytes. - """ + """EOF container data header missing bytes.""" ZERO_SECTION_SIZE = auto() - """ - EOF container data header construction is wrong. - """ + """EOF container data header construction is wrong.""" MISSING_DATA_SECTION = auto() - """ - EOF container missing data section - """ + """EOF container missing data section""" INCOMPLETE_CONTAINER = auto() - """ - EOF container bytes are incomplete. - """ + """EOF container bytes are incomplete.""" INVALID_SECTION_BODIES_SIZE = auto() - """ - Sections bodies does not match sections headers. - """ + """Sections bodies does not match sections headers.""" TRAILING_BYTES = auto() - """ - EOF container has bytes beyond data section. - """ + """EOF container has bytes beyond data section.""" MISSING_TERMINATOR = auto() - """ - EOF container missing terminator bytes between header and body. - """ + """EOF container missing terminator bytes between header and body.""" MISSING_HEADERS_TERMINATOR = auto() - """ - Some type of another exception about missing headers terminator. - """ + """Some type of another exception about missing headers terminator.""" INVALID_FIRST_SECTION_TYPE = auto() - """ - EOF container header does not have types section first. - """ + """EOF container header does not have types section first.""" INCOMPLETE_SECTION_NUMBER = auto() - """ - EOF container header has section that is missing declaration bytes. - """ + """EOF container header has section that is missing declaration bytes.""" INCOMPLETE_SECTION_SIZE = auto() - """ - EOF container header has section that is defined incorrectly. - """ + """EOF container header has section that is defined incorrectly.""" TOO_MANY_CODE_SECTIONS = auto() - """ - EOF container header has too many code sections. - """ + """EOF container header has too many code sections.""" MISSING_STOP_OPCODE = auto() - """ - EOF container's code missing STOP bytecode at it's end. - """ + """EOF container's code missing STOP bytecode at it's end.""" INPUTS_OUTPUTS_NUM_ABOVE_LIMIT = auto() - """ - EOF container code section inputs/outputs number is above the limit - """ + """EOF container code section inputs/outputs number is above the limit""" UNREACHABLE_INSTRUCTIONS = auto() - """ - EOF container's code have instructions that are unreachable. - """ + """EOF container's code have instructions that are unreachable.""" UNREACHABLE_CODE_SECTIONS = auto() - """ - EOF container's body have code sections that are unreachable. - """ + """EOF container's body have code sections that are unreachable.""" STACK_UNDERFLOW = auto() - """ - EOF container's code produces an stack underflow. - """ + """EOF container's code produces an stack underflow.""" STACK_OVERFLOW = auto() - """ - EOF container's code produces an stack overflow. - """ + """EOF container's code produces an stack overflow.""" STACK_HEIGHT_MISMATCH = auto() - """ - EOF container section stack height mismatch. - """ + """EOF container section stack height mismatch.""" MAX_STACK_INCREASE_ABOVE_LIMIT = auto() - """ - EOF container's specified max stack increase is above the limit. - """ + """EOF container's specified max stack increase is above the limit.""" STACK_HIGHER_THAN_OUTPUTS = auto() """ - EOF container section stack height is higher than the outputs. - when returning + EOF container section stack height is higher than the outputs. when + returning """ JUMPF_DESTINATION_INCOMPATIBLE_OUTPUTS = auto() """ - EOF container section JUMPF's to a destination section with incompatible outputs. + EOF container section JUMPF's to a destination section with incompatible + outputs. """ INVALID_MAX_STACK_INCREASE = auto() """ - EOF container section's specified max stack increase does not match the actual stack height. + EOF container section's specified max stack increase does not match the + actual stack height. """ INVALID_DATALOADN_INDEX = auto() - """ - A DATALOADN instruction has out-of-bounds index for the data section. - """ + """A DATALOADN instruction has out-of-bounds index for the data section.""" TRUNCATED_INSTRUCTION = auto() - """ - EOF container's code section has truncated instruction. - """ + """EOF container's code section has truncated instruction.""" TOPLEVEL_CONTAINER_TRUNCATED = auto() - """ - Top-level EOF container has data section truncated - """ + """Top-level EOF container has data section truncated""" ORPHAN_SUBCONTAINER = auto() - """ - EOF container has an unreferenced subcontainer. - '""" + """EOF container has an unreferenced subcontainer. '""" CONTAINER_SIZE_ABOVE_LIMIT = auto() - """ - EOF container is above size limit - """ + """EOF container is above size limit""" INVALID_CONTAINER_SECTION_INDEX = auto() - """ - Instruction references container section that does not exist. - """ + """Instruction references container section that does not exist.""" INCOMPATIBLE_CONTAINER_KIND = auto() - """ - Incompatible instruction found in a container of a specific kind. - """ + """Incompatible instruction found in a container of a specific kind.""" AMBIGUOUS_CONTAINER_KIND = auto() - """ - The kind of a sub-container cannot be uniquely deduced. - """ + """The kind of a sub-container cannot be uniquely deduced.""" TOO_MANY_CONTAINERS = auto() - """ - EOF container header has too many sub-containers. - """ + """EOF container header has too many sub-containers.""" INVALID_CODE_SECTION_INDEX = auto() - """ - CALLF Operation refers to a non-existent code section - """ + """CALLF Operation refers to a non-existent code section""" UNEXPECTED_HEADER_KIND = auto() - """ - Header parsing encountered a section kind it wasn't expecting - """ + """Header parsing encountered a section kind it wasn't expecting""" CALLF_TO_NON_RETURNING = auto() - """ - CALLF instruction targeting a non-returning code section - """ + """CALLF instruction targeting a non-returning code section""" EOFCREATE_WITH_TRUNCATED_CONTAINER = auto() - """ - EOFCREATE with truncated container - """ + """EOFCREATE with truncated container""" diff --git a/ethereum_test_exceptions/exceptions/transaction.py b/ethereum_test_exceptions/exceptions/transaction.py index 4d3bbc97b8..ee67b0d55e 100644 --- a/ethereum_test_exceptions/exceptions/transaction.py +++ b/ethereum_test_exceptions/exceptions/transaction.py @@ -8,195 +8,125 @@ @unique class TransactionException(ExceptionBase): """ - Exception raised when a transaction is invalid, and thus cannot be executed. + Exception raised when a transaction is invalid, and thus cannot be + executed. - If a transaction with any of these exceptions is included in a block, the block is invalid. + If a transaction with any of these exceptions is included in a block, the + block is invalid. """ TYPE_NOT_SUPPORTED = auto() - """ - Transaction type is not supported on this chain configuration. - """ + """Transaction type is not supported on this chain configuration.""" SENDER_NOT_EOA = auto() - """ - Transaction is coming from address that is not exist anymore. - """ + """Transaction is coming from address that is not exist anymore.""" ADDRESS_TOO_SHORT = auto() - """ - Transaction `to` is not allowed to be less than 20 bytes. - """ + """Transaction `to` is not allowed to be less than 20 bytes.""" ADDRESS_TOO_LONG = auto() - """ - Transaction `to` is not allowed to be more than 20 bytes. - """ + """Transaction `to` is not allowed to be more than 20 bytes.""" NONCE_MISMATCH_TOO_HIGH = auto() - """ - Transaction nonce > sender.nonce. - """ + """Transaction nonce > sender.nonce.""" NONCE_MISMATCH_TOO_LOW = auto() - """ - Transaction nonce < sender.nonce. - """ + """Transaction nonce < sender.nonce.""" NONCE_TOO_BIG = auto() """ - Transaction `nonce` is not allowed to be max_uint64 - 1 (this is probably TransactionTest). + Transaction `nonce` is not allowed to be max_uint64 - 1 (this is probably + TransactionTest). """ NONCE_IS_MAX = auto() """ - Transaction `nonce` is not allowed to be max_uint64 - 1 (this is StateTests). + Transaction `nonce` is not allowed to be max_uint64 - 1 (this is + StateTests). """ NONCE_OVERFLOW = auto() - """ - Transaction `nonce` is not allowed to be more than uint64. - """ + """Transaction `nonce` is not allowed to be more than uint64.""" GASLIMIT_OVERFLOW = auto() - """ - Transaction gaslimit exceeds 2^64-1 maximum value. - """ + """Transaction gaslimit exceeds 2^64-1 maximum value.""" VALUE_OVERFLOW = auto() - """ - Transaction value exceeds 2^256-1 maximum value. - """ + """Transaction value exceeds 2^256-1 maximum value.""" GASPRICE_OVERFLOW = auto() - """ - Transaction gasPrice exceeds 2^256-1 maximum value. - """ + """Transaction gasPrice exceeds 2^256-1 maximum value.""" GASLIMIT_PRICE_PRODUCT_OVERFLOW = auto() - """ - Transaction gasPrice * gasLimit exceeds 2^256-1 maximum value. - """ + """Transaction gasPrice * gasLimit exceeds 2^256-1 maximum value.""" INVALID_SIGNATURE_VRS = auto() - """ - Invalid transaction v, r, s values. - """ + """Invalid transaction v, r, s values.""" RLP_INVALID_SIGNATURE_R = auto() - """ - Error reading transaction signature R value. - """ + """Error reading transaction signature R value.""" RLP_INVALID_SIGNATURE_S = auto() - """ - Error reading transaction signature S value. - """ + """Error reading transaction signature S value.""" RLP_LEADING_ZEROS_GASLIMIT = auto() - """ - Error reading transaction gaslimit field RLP. - """ + """Error reading transaction gaslimit field RLP.""" RLP_LEADING_ZEROS_GASPRICE = auto() - """ - Error reading transaction gasprice field RLP. - """ + """Error reading transaction gasprice field RLP.""" RLP_LEADING_ZEROS_VALUE = auto() - """ - Error reading transaction value field RLP. - """ + """Error reading transaction value field RLP.""" RLP_LEADING_ZEROS_NONCE = auto() - """ - Error reading transaction nonce field RLP. - """ + """Error reading transaction nonce field RLP.""" RLP_LEADING_ZEROS_R = auto() - """ - Error reading transaction signature R field RLP. - """ + """Error reading transaction signature R field RLP.""" RLP_LEADING_ZEROS_S = auto() - """ - Error reading transaction signature S field RLP. - """ + """Error reading transaction signature S field RLP.""" RLP_LEADING_ZEROS_V = auto() - """ - Error reading transaction signature V field RLP. - """ + """Error reading transaction signature V field RLP.""" RLP_LEADING_ZEROS_BASEFEE = auto() - """ - Error reading transaction basefee field RLP. - """ + """Error reading transaction basefee field RLP.""" RLP_LEADING_ZEROS_PRIORITY_FEE = auto() - """ - Error reading transaction priority fee field RLP. - """ + """Error reading transaction priority fee field RLP.""" RLP_LEADING_ZEROS_DATA_SIZE = auto() """ - Error reading transaction data field RLP, (rlp field length has leading zeros). + Error reading transaction data field RLP, (rlp field length has leading + zeros). """ RLP_LEADING_ZEROS_NONCE_SIZE = auto() """ - Error reading transaction nonce field RLP, (rlp field length has leading zeros). + Error reading transaction nonce field RLP, (rlp field length has leading + zeros). """ RLP_TOO_FEW_ELEMENTS = auto() """ - Error reading transaction RLP, structure has too few elements than expected. + Error reading transaction RLP, structure has too few elements than + expected. """ RLP_TOO_MANY_ELEMENTS = auto() """ - Error reading transaction RLP, structure has too many elements than expected. + Error reading transaction RLP, structure has too many elements than + expected. """ RLP_ERROR_EOF = auto() - """ - Error reading transaction RLP, rlp stream unexpectedly finished. - """ + """Error reading transaction RLP, rlp stream unexpectedly finished.""" RLP_ERROR_SIZE = auto() - """ - Error reading transaction RLP, rlp size is invalid. - """ + """Error reading transaction RLP, rlp size is invalid.""" RLP_ERROR_SIZE_LEADING_ZEROS = auto() - """ - Error reading transaction RLP, field size has leading zeros. - """ + """Error reading transaction RLP, field size has leading zeros.""" INVALID_CHAINID = auto() - """ - Transaction chain id encoding is incorrect. - """ + """Transaction chain id encoding is incorrect.""" RLP_INVALID_DATA = auto() - """ - Transaction data field is invalid rlp. - """ + """Transaction data field is invalid rlp.""" RLP_INVALID_GASLIMIT = auto() - """ - Transaction gaslimit field is invalid rlp. - """ + """Transaction gaslimit field is invalid rlp.""" RLP_INVALID_NONCE = auto() - """ - Transaction nonce field is invalid rlp. - """ + """Transaction nonce field is invalid rlp.""" RLP_INVALID_TO = auto() - """ - Transaction to field is invalid rlp. - """ + """Transaction to field is invalid rlp.""" RLP_INVALID_ACCESS_LIST_ADDRESS_TOO_LONG = auto() - """ - Transaction access list address is > 20 bytes. - """ + """Transaction access list address is > 20 bytes.""" RLP_INVALID_ACCESS_LIST_ADDRESS_TOO_SHORT = auto() - """ - Transaction access list address is < 20 bytes. - """ + """Transaction access list address is < 20 bytes.""" RLP_INVALID_ACCESS_LIST_STORAGE_TOO_LONG = auto() - """ - Transaction access list storage hash > 32 bytes. - """ + """Transaction access list storage hash > 32 bytes.""" RLP_INVALID_ACCESS_LIST_STORAGE_TOO_SHORT = auto() - """ - Transaction access list storage hash < 32 bytes. - """ + """Transaction access list storage hash < 32 bytes.""" RLP_INVALID_HEADER = auto() - """ - Transaction failed to read from RLP as rlp header is invalid. - """ + """Transaction failed to read from RLP as rlp header is invalid.""" RLP_INVALID_VALUE = auto() - """ - Transaction value field is invalid rlp/structure. - """ + """Transaction value field is invalid rlp/structure.""" EC_RECOVERY_FAIL = auto() - """ - Transaction has correct signature, but ec recovery failed. - """ + """Transaction has correct signature, but ec recovery failed.""" INSUFFICIENT_ACCOUNT_FUNDS = auto() """ Transaction's sender does not have enough funds to pay for the transaction. """ INSUFFICIENT_MAX_FEE_PER_GAS = auto() - """ - Transaction's max-fee-per-gas is lower than the block base-fee. - """ + """Transaction's max-fee-per-gas is lower than the block base-fee.""" PRIORITY_OVERFLOW = auto() """ Transaction's max-priority-fee-per-gas is exceeds 2^256-1 maximum value. @@ -207,85 +137,56 @@ class TransactionException(ExceptionBase): """ PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS_2 = auto() """ - Transaction's max-priority-fee-per-gas is greater than the max-fee-per-gas (TransactionTests). + Transaction's max-priority-fee-per-gas is greater than the max-fee-per-gas + (TransactionTests). """ INSUFFICIENT_MAX_FEE_PER_BLOB_GAS = auto() """ - Transaction's max-fee-per-blob-gas is lower than the block's blob-gas price. + Transaction's max-fee-per-blob-gas is lower than the block's blob-gas + price. """ INTRINSIC_GAS_TOO_LOW = auto() - """ - Transaction's gas limit is too low. - """ + """Transaction's gas limit is too low.""" INTRINSIC_GAS_BELOW_FLOOR_GAS_COST = auto() - """ - Transaction's gas limit is below the floor gas cost. - """ + """Transaction's gas limit is below the floor gas cost.""" INITCODE_SIZE_EXCEEDED = auto() """ Transaction's initcode for a contract-creating transaction is too large. """ TYPE_3_TX_PRE_FORK = auto() - """ - Transaction type 3 included before activation fork. - """ + """Transaction type 3 included before activation fork.""" TYPE_3_TX_ZERO_BLOBS_PRE_FORK = auto() - """ - Transaction type 3, with zero blobs, included before activation fork. - """ + """Transaction type 3, with zero blobs, included before activation fork.""" TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH = auto() - """ - Transaction contains a blob versioned hash with an invalid version. - """ + """Transaction contains a blob versioned hash with an invalid version.""" TYPE_3_TX_WITH_FULL_BLOBS = auto() - """ - Transaction contains full blobs (network-version of the transaction). - """ + """Transaction contains full blobs (network-version of the transaction).""" TYPE_3_TX_BLOB_COUNT_EXCEEDED = auto() - """ - Transaction contains too many blob versioned hashes. - """ + """Transaction contains too many blob versioned hashes.""" TYPE_3_TX_CONTRACT_CREATION = auto() - """ - Transaction is a type 3 transaction and has an empty `to`. - """ + """Transaction is a type 3 transaction and has an empty `to`.""" TYPE_3_TX_MAX_BLOB_GAS_ALLOWANCE_EXCEEDED = auto() - """ - Transaction causes block to go over blob gas limit. - """ + """Transaction causes block to go over blob gas limit.""" GAS_ALLOWANCE_EXCEEDED = auto() - """ - Transaction causes block to go over blob gas limit. - """ + """Transaction causes block to go over blob gas limit.""" GAS_LIMIT_EXCEEDS_MAXIMUM = auto() """ Transaction gas limit exceeds the maximum allowed limit of 30 million. """ TYPE_3_TX_ZERO_BLOBS = auto() - """ - Transaction is type 3, but has no blobs. - """ + """Transaction is type 3, but has no blobs.""" TYPE_4_EMPTY_AUTHORIZATION_LIST = auto() - """ - Transaction is type 4, but has an empty authorization list. - """ + """Transaction is type 4, but has an empty authorization list.""" TYPE_4_INVALID_AUTHORITY_SIGNATURE = auto() - """ - Transaction authority signature is invalid - """ + """Transaction authority signature is invalid""" TYPE_4_INVALID_AUTHORITY_SIGNATURE_S_TOO_HIGH = auto() - """ - Transaction authority signature is invalid - """ + """Transaction authority signature is invalid""" TYPE_4_TX_CONTRACT_CREATION = auto() - """ - Transaction is a type 4 transaction and has an empty `to`. - """ + """Transaction is a type 4 transaction and has an empty `to`.""" TYPE_4_INVALID_AUTHORIZATION_FORMAT = auto() """ - Transaction is type 4, but contains an authorization that has an invalid format. + Transaction is type 4, but contains an authorization that has an invalid + format. """ TYPE_4_TX_PRE_FORK = auto() - """ - Transaction type 4 included before activation fork. - """ + """Transaction type 4 included before activation fork.""" diff --git a/ethereum_test_exceptions/tests/test_exceptions.py b/ethereum_test_exceptions/tests/test_exceptions.py index 925d76f9c6..a09381be22 100644 --- a/ethereum_test_exceptions/tests/test_exceptions.py +++ b/ethereum_test_exceptions/tests/test_exceptions.py @@ -34,7 +34,10 @@ def test_exceptions_string_conversion( exception: BlockException | TransactionException, expected: str ): - """Test that the exceptions are unique and have the correct string representation.""" + """ + Test that the exceptions are unique and have the correct string + representation. + """ assert str(exception) == expected diff --git a/ethereum_test_execution/base.py b/ethereum_test_execution/base.py index 1bf1d00437..58a3411443 100644 --- a/ethereum_test_execution/base.py +++ b/ethereum_test_execution/base.py @@ -44,8 +44,8 @@ class LabeledExecuteFormat: """ Represents an execution format with a custom label. - This label will be used in the test id and also will be added as a marker to the - generated test case when executing the test. + This label will be used in the test id and also will be added as a marker + to the generated test case when executing the test. """ format: Type[BaseExecute] @@ -85,8 +85,8 @@ def __eq__(self, other: Any) -> bool: """ Check if two labeled execute formats are equal. - If the other object is a ExecuteFormat type, the format of the labeled execute - format will be compared with the format of the other object. + If the other object is a ExecuteFormat type, the format of the labeled + execute format will be compared with the format of the other object. """ if isinstance(other, LabeledExecuteFormat): return self.format == other.format diff --git a/ethereum_test_execution/blob_transaction.py b/ethereum_test_execution/blob_transaction.py index 6c7f6a90d0..21bedbf4dd 100644 --- a/ethereum_test_execution/blob_transaction.py +++ b/ethereum_test_execution/blob_transaction.py @@ -47,8 +47,9 @@ def versioned_hashes_with_blobs_and_proofs( class BlobTransaction(BaseExecute): """ - Represents a test execution format to send blob transactions to the client and then - use `engine_getBlobsV*` end points to validate the proofs generated by the execution client. + Represents a test execution format to send blob transactions to the client + and then use `engine_getBlobsV*` end points to validate the proofs + generated by the execution client. """ format_name: ClassVar[str] = "blob_transaction_test" @@ -94,16 +95,18 @@ def execute( version = fork.engine_get_blobs_version() assert version is not None, "Engine get blobs version is not supported by the fork." - # ensure that clients respond 'null' when they have no access to at least one blob + # ensure that clients respond 'null' when they have no access to at + # least one blob list_versioned_hashes = list(versioned_hashes.keys()) if self.nonexisting_blob_hashes is not None: list_versioned_hashes.extend(self.nonexisting_blob_hashes) blob_response: GetBlobsResponse | None = engine_rpc.get_blobs( list_versioned_hashes, version=version - ) # noqa: E501 + ) - # if non-existing blob hashes were request then the response must be 'null' + # if non-existing blob hashes were request then the response must be + # 'null' if self.nonexisting_blob_hashes is not None: if blob_response is not None: raise ValueError( @@ -121,8 +124,9 @@ def execute( assert blob_response is not None local_blobs_and_proofs = list(versioned_hashes.values()) - assert len(blob_response) == len(local_blobs_and_proofs), "Expected " - f"{len(local_blobs_and_proofs)} blobs and proofs, got {len(blob_response)}." + assert len(blob_response) == len(local_blobs_and_proofs), ( + f"Expected {len(local_blobs_and_proofs)} blobs and proofs, got {len(blob_response)}." + ) for expected_blob, received_blob in zip( local_blobs_and_proofs, blob_response.root, strict=True diff --git a/ethereum_test_execution/transaction_post.py b/ethereum_test_execution/transaction_post.py index fce6b2bbcb..5c97eb045b 100644 --- a/ethereum_test_execution/transaction_post.py +++ b/ethereum_test_execution/transaction_post.py @@ -14,7 +14,9 @@ class TransactionPost(BaseExecute): - """Represents a simple transaction-send then post-check execution format.""" + """ + Represents a simple transaction-send then post-check execution format. + """ blocks: List[List[Transaction]] post: Alloc diff --git a/ethereum_test_fixtures/base.py b/ethereum_test_fixtures/base.py index b4531e4580..e0670b7b34 100644 --- a/ethereum_test_fixtures/base.py +++ b/ethereum_test_fixtures/base.py @@ -64,7 +64,10 @@ class BaseFixture(CamelModel): @classmethod def output_base_dir_name(cls) -> str: - """Return name of the subdirectory where this type of fixture should be dumped to.""" + """ + Return name of the subdirectory where this type of fixture should be + dumped to. + """ return cls.format_name.replace("test", "tests") @classmethod @@ -161,7 +164,10 @@ def discard_fixture_format_by_marks( fork: Fork, markers: List[pytest.Mark], ) -> bool: - """Discard a fixture format from filling if the appropriate marker is used.""" + """ + Discard a fixture format from filling if the appropriate marker is + used. + """ return False @@ -169,8 +175,8 @@ class LabeledFixtureFormat: """ Represents a fixture format with a custom label. - This label will be used in the test id and also will be added as a marker to the - generated test case when filling the test. + This label will be used in the test id and also will be added as a marker + to the generated test case when filling the test. """ format: Type[BaseFixture] @@ -210,8 +216,8 @@ def __eq__(self, other: Any) -> bool: """ Check if two labeled fixture formats are equal. - If the other object is a FixtureFormat type, the format of the labeled fixture - format will be compared with the format of the other object. + If the other object is a FixtureFormat type, the format of the labeled + fixture format will be compared with the format of the other object. """ if isinstance(other, LabeledFixtureFormat): return self.format == other.format diff --git a/ethereum_test_fixtures/blockchain.py b/ethereum_test_fixtures/blockchain.py index 74d60f16bb..b5ef43cb40 100644 --- a/ethereum_test_fixtures/blockchain.py +++ b/ethereum_test_fixtures/blockchain.py @@ -55,10 +55,8 @@ def post_state_validator(alternate_field: str | None = None, mode: str = "after" """ Create a validator to ensure exactly one post-state field is provided. - Args: - alternate_field: Alternative field name to post_state_hash (e.g., 'post_state_diff'). - mode: Pydantic validation mode. - + Args: alternate_field: Alternative field name to post_state_hash (e.g., + 'post_state_diff'). mode: Pydantic validation mode. """ def decorator(cls): @@ -68,10 +66,12 @@ def validate_post_state_fields(self): if mode == "after": # Determine which fields to check if alternate_field: - # For engine x fixtures: check post_state vs post_state_diff + # For engine x fixtures: check post_state vs + # post_state_diff field1_name, field2_name = "post_state", alternate_field else: - # For standard fixtures: check post_state vs post_state_hash + # For standard fixtures: check post_state vs + # post_state_hash field1_name, field2_name = "post_state", "post_state_hash" field1_value = getattr(self, field1_name, None) @@ -93,8 +93,8 @@ def validate_post_state_fields(self): class HeaderForkRequirement(str): """ - Fork requirement class that specifies the name of the method that should be called - to check if the field is required. + Fork requirement class that specifies the name of the method that should be + called to check if the field is required. """ def __new__(cls, value: str) -> "HeaderForkRequirement": @@ -173,7 +173,10 @@ class FixtureHeader(CamelModel): fork: Fork | None = Field(None, exclude=True) def model_post_init(self, __context): - """Model post init method used to check for required fields of a given fork.""" + """ + Model post init method used to check for required fields of a given + fork. + """ super().model_post_init(__context) if self.fork is None: @@ -184,8 +187,9 @@ def model_post_init(self, __context): block_number = self.number timestamp = self.timestamp - # For each field, check if any of the annotations are of type HeaderForkRequirement and - # if so, check if the field is required for the given fork. + # For each field, check if any of the annotations are of type + # HeaderForkRequirement and if so, check if the field is required for + # the given fork. annotated_hints = get_type_hints(self, include_extras=True) for field in self.__class__.model_fields: @@ -244,7 +248,9 @@ def genesis(cls, fork: Fork, env: Environment, state_root: Hash) -> "FixtureHead class FixtureExecutionPayload(CamelModel): - """Representation of an Ethereum execution payload within a test Fixture.""" + """ + Representation of an Ethereum execution payload within a test Fixture. + """ parent_hash: Hash fee_recipient: Address @@ -282,8 +288,8 @@ def from_fixture_header( block_access_list: Bytes | None = None, ) -> "FixtureExecutionPayload": """ - Return FixtureExecutionPayload from a FixtureHeader, a list - of transactions, a list of withdrawals, and an optional block access list. + Return FixtureExecutionPayload from a FixtureHeader, a list of + transactions, a list of withdrawals, and an optional block access list. """ return cls( **header.model_dump(exclude={"rlp"}, exclude_none=True), @@ -303,8 +309,8 @@ def from_fixture_header( ] EngineNewPayloadV5Parameters = EngineNewPayloadV4Parameters -# Important: We check EngineNewPayloadV3Parameters first as it has more fields, and pydantic -# has a weird behavior when the smaller tuple is checked first. +# Important: We check EngineNewPayloadV3Parameters first as it has more fields, +# and pydantic has a weird behavior when the smaller tuple is checked first. EngineNewPayloadParameters = Union[ EngineNewPayloadV5Parameters, EngineNewPayloadV4Parameters, @@ -315,8 +321,8 @@ def from_fixture_header( class FixtureEngineNewPayload(CamelModel): """ - Representation of the `engine_newPayloadVX` information to be - sent using the block information. + Representation of the `engine_newPayloadVX` information to be sent using + the block information. """ params: EngineNewPayloadParameters @@ -445,7 +451,10 @@ def parse_witness_chunks(cls, s: str) -> List["WitnessChunk"]: class FixtureBlockBase(CamelModel): - """Representation of an Ethereum block within a test Fixture without RLP bytes.""" + """ + Representation of an Ethereum block within a test Fixture without RLP + bytes. + """ header: FixtureHeader = Field(..., alias="blockHeader") txs: List[FixtureTransaction] = Field(default_factory=list, alias="transactions") @@ -467,7 +476,9 @@ def with_rlp(self, txs: List[Transaction]) -> "FixtureBlock": block = [ self.header.rlp_encode_list, [tx.serializable_list for tx in txs], - self.ommers, # TODO: This is incorrect, and we probably need to serialize the ommers + # TODO: This is incorrect, and we probably + # need to serialize the ommers + self.ommers, ] if self.withdrawals is not None: @@ -519,15 +530,16 @@ class BlockchainFixtureCommon(BaseFixture): pre: Alloc post_state: Alloc | None = Field(None) post_state_hash: Hash | None = Field(None) - last_block_hash: Hash = Field(..., alias="lastblockhash") # FIXME: lastBlockHash + # FIXME: lastBlockHash + last_block_hash: Hash = Field(..., alias="lastblockhash") config: FixtureConfig @model_validator(mode="before") @classmethod def config_defaults_for_backwards_compatibility(cls, data: Any) -> Any: """ - Check if the config field is populated, otherwise use the root-level field values for - backwards compatibility. + Check if the config field is populated, otherwise use the root-level + field values for backwards compatibility. """ if isinstance(data, dict): if "config" not in data: @@ -566,7 +578,8 @@ class BlockchainEngineFixtureCommon(BaseFixture): fork: Fork = Field(..., alias="network") post_state_hash: Hash | None = Field(None) - last_block_hash: Hash = Field(..., alias="lastblockhash") # FIXME: lastBlockHash + # FIXME: lastBlockHash + last_block_hash: Hash = Field(..., alias="lastblockhash") config: FixtureConfig def get_fork(self) -> Fork | None: @@ -616,7 +629,10 @@ class BlockchainEngineXFixture(BlockchainEngineFixtureCommon): """Hash of the pre-allocation group this test belongs to.""" post_state_diff: Alloc | None = None - """State difference from genesis after test execution (efficiency optimization).""" + """ + State difference from genesis after test execution (efficiency + optimization). + """ payloads: List[FixtureEngineNewPayload] = Field(..., alias="engineNewPayloads") """Engine API payloads for blockchain execution.""" diff --git a/ethereum_test_fixtures/collector.py b/ethereum_test_fixtures/collector.py index e13e043125..10606bfefc 100644 --- a/ethereum_test_fixtures/collector.py +++ b/ethereum_test_fixtures/collector.py @@ -1,6 +1,6 @@ """ -Fixture collector class used to collect, sort and combine the different types of generated -fixtures. +Fixture collector class used to collect, sort and combine the different types +of generated fixtures. """ import json @@ -23,9 +23,11 @@ class TestInfo: """Contains test information from the current node.""" name: str # pytest: Item.name, e.g. test_paris_one[fork_Paris-state_test] - id: str # pytest: Item.nodeid, e.g. tests/paris/test_module_paris.py::test_paris_one[...] + id: str # pytest: Item.nodeid, e.g. + # tests/paris/test_module_paris.py::test_paris_one[...] original_name: str # pytest: Item.originalname, e.g. test_paris_one - module_path: Path # pytest: Item.path, e.g. .../tests/paris/test_module_paris.py + module_path: Path # pytest: Item.path, e.g. + # .../tests/paris/test_module_paris.py test_prefix: ClassVar[str] = "test_" # Python test prefix filler_suffix: ClassVar[str] = "Filler" # Static test suffix @@ -41,11 +43,11 @@ def strip_test_name(cls, name: str) -> str: def get_name_and_parameters(self) -> Tuple[str, str]: """ - Convert test name to a tuple containing the test name and test parameters. - - Example: - test_push0_key_sstore[fork_Shanghai] -> test_push0_key_sstore, fork_Shanghai + Convert test name to a tuple containing the test name and test + parameters. + Example: test_push0_key_sstore[fork_Shanghai] -> test_push0_key_sstore, + fork_Shanghai """ test_name, parameters = self.name.split("[") return test_name, re.sub(r"[\[\-]", "_", parameters).replace("]", "") @@ -91,9 +93,8 @@ def get_module_relative_output_dir(self, filler_path: Path) -> Path: base ./tests directory) that can be used for output (within the configured fixtures output path or the base_dump_dir directory). - Example: - tests/shanghai/eip3855_push0/test_push0.py -> shanghai/eip3855_push0/test_push0 - + Example: tests/shanghai/eip3855_push0/test_push0.py -> + shanghai/eip3855_push0/test_push0 """ basename = self.module_path.with_suffix("").absolute() basename_relative = basename.relative_to( @@ -122,8 +123,9 @@ def get_fixture_basename(self, info: TestInfo) -> Path: """Return basename of the fixture file for a given test case.""" module_relative_output_dir = info.get_module_relative_output_dir(self.filler_path) - # Each legacy test filler has only 1 test per file if it's a !state test! - # So no need to create directory Add11/add11.json it can be plain add11.json + # Each legacy test filler has only 1 test per file if it's a !state + # test! So no need to create directory Add11/add11.json it can be plain + # add11.json if self.fill_static_tests: return module_relative_output_dir.parent / info.original_name @@ -140,7 +142,8 @@ def add_fixture(self, info: TestInfo, fixture: BaseFixture) -> Path: / fixture.output_base_dir_name() / fixture_basename.with_suffix(fixture.output_file_extension) ) - if fixture_path not in self.all_fixtures.keys(): # relevant when we group by test function + # relevant when we group by test function + if fixture_path not in self.all_fixtures.keys(): self.all_fixtures[fixture_path] = Fixtures(root={}) self.json_path_to_test_item[fixture_path] = info diff --git a/ethereum_test_fixtures/consume.py b/ethereum_test_fixtures/consume.py index dcec641b3a..b55f35efd4 100644 --- a/ethereum_test_fixtures/consume.py +++ b/ethereum_test_fixtures/consume.py @@ -34,7 +34,10 @@ def consume_fixture( fixture_name: str | None = None, debug_output_path: Path | None = None, ): - """Test the client with the specified fixture using its direct consumer interface.""" + """ + Test the client with the specified fixture using its direct consumer + interface. + """ raise NotImplementedError( "The `consume_fixture()` function is not supported by this tool." ) @@ -59,7 +62,9 @@ class TestCaseStream(TestCaseBase): class TestCaseIndexFile(TestCaseBase): - """The test case model used to save/load test cases to/from an index file.""" + """ + The test case model used to save/load test cases to/from an index file. + """ json_path: Path __test__ = False # stop pytest from collecting this class as a test diff --git a/ethereum_test_fixtures/file.py b/ethereum_test_fixtures/file.py index 2f74e06b37..8679cfabcf 100644 --- a/ethereum_test_fixtures/file.py +++ b/ethereum_test_fixtures/file.py @@ -15,13 +15,14 @@ class Fixtures(EthereumTestRootModel): """ A base class for defining top-level models that encapsulate multiple test - fixtures. Each fixture is stored in a dictionary, where each key is a string - (typically the fixture name) and its corresponding value is a fixture object. - This is the structure used for blockchain and state JSON fixture files. - - This class implements dunder methods and other common functionality to allow - interaction with the model's fixtures as if they were being accessed directly - from a dictionary. + fixtures. Each fixture is stored in a dictionary, where each key is a + string (typically the fixture name) and its corresponding value is a + fixture object. This is the structure used for blockchain and state JSON + fixture files. + + This class implements dunder methods and other common functionality to + allow interaction with the model's fixtures as if they were being accessed + directly from a dictionary. """ root: Dict[str, SerializeAsAny[BaseFixture]] @@ -54,8 +55,8 @@ def collect_into_file(self, file_path: Path): """ For all formats, we join the fixtures as json into a single file. - Note: We don't use pydantic model_dump_json() on the Fixtures object as we - add the hash to the info field on per-fixture basis. + Note: We don't use pydantic model_dump_json() on the Fixtures object as + we add the hash to the info field on per-fixture basis. """ json_fixtures: Dict[str, Dict[str, Any]] = {} lock_file_path = file_path.with_suffix(".lock") diff --git a/ethereum_test_fixtures/pre_alloc_groups.py b/ethereum_test_fixtures/pre_alloc_groups.py index c358b75709..25173760d0 100644 --- a/ethereum_test_fixtures/pre_alloc_groups.py +++ b/ethereum_test_fixtures/pre_alloc_groups.py @@ -22,7 +22,8 @@ class PreAllocGroup(CamelModel): pre-allocation group optimization. """ - model_config = {"populate_by_name": True} # Allow both field names and aliases + # Allow both field names and aliases + model_config = {"populate_by_name": True} test_ids: List[str] = Field(default_factory=list) environment: Environment = Field(..., description="Grouping environment for this test group") @@ -65,9 +66,10 @@ def to_file(self, file: Path) -> None: else: new_account = self.pre[account] if new_account != existing_account: - # This procedure fails during xdist worker's pytest_sessionfinish - # and is not reported to the master thread. - # We signal here that the groups created contain a collision. + # This procedure fails during xdist worker's + # pytest_sessionfinish and is not reported to the + # master thread. We signal here that the groups + # created contain a collision. collision_file_path = file.with_suffix(".fail") collision_exception = Alloc.CollisionError( address=account, @@ -87,7 +89,8 @@ class PreAllocGroups(EthereumTestRootModel): """ Root model mapping pre-allocation group hashes to test groups. - If lazy_load is True, the groups are not loaded from the folder until they are accessed. + If lazy_load is True, the groups are not loaded from the folder until they + are accessed. Iterating will fail if lazy_load is True. """ diff --git a/ethereum_test_fixtures/state.py b/ethereum_test_fixtures/state.py index 8d389db57f..3dfb6ba29c 100644 --- a/ethereum_test_fixtures/state.py +++ b/ethereum_test_fixtures/state.py @@ -64,7 +64,9 @@ def from_transaction(cls, tx: Transaction) -> "FixtureTransaction": class FixtureForkPostIndexes(BaseModel): - """Type used to describe the indexes of a single post state of a single Fork.""" + """ + Type used to describe the indexes of a single post state of a single Fork. + """ data: int = 0 gas: int = 0 diff --git a/ethereum_test_fixtures/tests/test_blockchain.py b/ethereum_test_fixtures/tests/test_blockchain.py index c2917a2ccf..944f2ece29 100644 --- a/ethereum_test_fixtures/tests/test_blockchain.py +++ b/ethereum_test_fixtures/tests/test_blockchain.py @@ -531,8 +531,9 @@ id="invalid_fixture_block_2", ), pytest.param( - False, # Can not be deserialized: A single expect_exception str will not be - # deserialized as a list and therefore will not match the model_instance definition. + False, # Can not be deserialized: A single expect_exception str + # will not be deserialized as a list and therefore will not + # match the model_instance definition. InvalidFixtureBlock( rlp="0x00", expect_exception=[TransactionException.INTRINSIC_GAS_TOO_LOW], diff --git a/ethereum_test_fixtures/tests/test_state.py b/ethereum_test_fixtures/tests/test_state.py index e4b3ab50ce..b1881065b2 100644 --- a/ethereum_test_fixtures/tests/test_state.py +++ b/ethereum_test_fixtures/tests/test_state.py @@ -50,8 +50,9 @@ id="state_fixture_fork_post_exception", ), pytest.param( - False, # Can not be deserialized: A single expect_exception str will not be - # deserialized as a list and therefore will not match the model_instance definition. + False, # Can not be deserialized: A single expect_exception str + # will not be deserialized as a list and therefore will not + # match the model_instance definition. FixtureForkPost( state_root=0, logs_hash=1, diff --git a/ethereum_test_forks/base_fork.py b/ethereum_test_forks/base_fork.py index 74840c55e1..69af59800d 100644 --- a/ethereum_test_forks/base_fork.py +++ b/ethereum_test_forks/base_fork.py @@ -26,15 +26,22 @@ class ForkAttribute(Protocol): - """A protocol to get the attribute of a fork at a given block number and timestamp.""" + """ + A protocol to get the attribute of a fork at a given block number and + timestamp. + """ def __call__(self, block_number: int = 0, timestamp: int = 0) -> Any: - """Return value of the attribute at the given block number and timestamp.""" + """ + Return value of the attribute at the given block number and timestamp. + """ pass class MemoryExpansionGasCalculator(Protocol): - """A protocol to calculate the gas cost of memory expansion at a given fork.""" + """ + A protocol to calculate the gas cost of memory expansion at a given fork. + """ def __call__(self, *, new_bytes: int, previous_bytes: int = 0) -> int: """Return gas cost of expanding the memory by the given length.""" @@ -42,7 +49,10 @@ def __call__(self, *, new_bytes: int, previous_bytes: int = 0) -> int: class CalldataGasCalculator(Protocol): - """A protocol to calculate the transaction gas cost of calldata at a given fork.""" + """ + A protocol to calculate the transaction gas cost of calldata at a given + fork. + """ def __call__(self, *, data: BytesConvertible, floor: bool = False) -> int: """Return the transaction gas cost of calldata given its contents.""" @@ -50,7 +60,9 @@ def __call__(self, *, data: BytesConvertible, floor: bool = False) -> int: class TransactionDataFloorCostCalculator(Protocol): - """Calculate the transaction floor cost due to its calldata for a given fork.""" + """ + Calculate the transaction floor cost due to its calldata for a given fork. + """ def __call__(self, *, data: BytesConvertible) -> int: """Return transaction gas cost of calldata given its contents.""" @@ -68,7 +80,10 @@ def __call__( class BaseFeeChangeCalculator(Protocol): - """A protocol to calculate the gas that needs to be used to change the base fee.""" + """ + A protocol to calculate the gas that needs to be used to change the base + fee. + """ def __call__( self, @@ -82,7 +97,10 @@ def __call__( class TransactionIntrinsicCostCalculator(Protocol): - """A protocol to calculate the intrinsic gas cost of a transaction at a given fork.""" + """ + A protocol to calculate the intrinsic gas cost of a transaction at a given + fork. + """ def __call__( self, @@ -97,25 +115,32 @@ def __call__( Return the intrinsic gas cost of a transaction given its properties. Args: - calldata: The data of the transaction. - contract_creation: Whether the transaction creates a contract. - access_list: The list of access lists for the transaction. - authorization_list_or_count: The list of authorizations or the count of authorizations - for the transaction. - return_cost_deducted_prior_execution: If set to False, the returned value is equal to - the minimum gas required for the transaction to be valid. If set to True, the - returned value is equal to the cost that is deducted from the gas limit before - the transaction starts execution. - - Returns: - Gas cost of a transaction + calldata: The data of the transaction. + contract_creation: Whether the transaction creates a contract. + access_list: The list of access lists for the transaction. + authorization_list_or_count: The list of authorizations or the count + of authorizations for the transaction. + return_cost_deducted_prior_execution: If set to False, the returned + value is equal to the minimum + gas required for the + transaction to be valid. If + set to True, the returned + value is equal to the cost + that is deducted from the gas + limit before the transaction + starts execution. + + Returns: Gas cost of a transaction """ pass class BlobGasPriceCalculator(Protocol): - """A protocol to calculate the blob gas price given the excess blob gas at a given fork.""" + """ + A protocol to calculate the blob gas price given the excess blob gas at a + given fork. + """ def __call__(self, *, excess_blob_gas: int) -> int: """Return the blob gas price given the excess blob gas.""" @@ -123,7 +148,9 @@ def __call__(self, *, excess_blob_gas: int) -> int: class ExcessBlobGasCalculator(Protocol): - """A protocol to calculate the excess blob gas for a block at a given fork.""" + """ + A protocol to calculate the excess blob gas for a block at a given fork. + """ def __call__( self, @@ -134,7 +161,10 @@ def __call__( parent_blob_count: int | None = None, parent_base_fee_per_gas: int, ) -> int: - """Return the excess blob gas given the parent's excess blob gas and blob gas used.""" + """ + Return the excess blob gas given the parent's excess blob gas and blob + gas used. + """ pass @@ -143,7 +173,10 @@ class BaseForkMeta(ABCMeta): @abstractmethod def name(cls) -> str: - """Return the name of the fork (e.g., Berlin), must be implemented by subclasses.""" + """ + Return the name of the fork (e.g., Berlin), must be implemented by + subclasses. + """ pass def __repr__(cls) -> str: @@ -152,12 +185,18 @@ def __repr__(cls) -> str: @staticmethod def _maybe_transitioned(fork_cls: "BaseForkMeta") -> "BaseForkMeta": - """Return the transitioned fork, if a transition fork, otherwise return `fork_cls`.""" + """ + Return the transitioned fork, if a transition fork, otherwise return + `fork_cls`. + """ return fork_cls.transitions_to() if hasattr(fork_cls, "transitions_to") else fork_cls @staticmethod def _is_subclass_of(a: "BaseForkMeta", b: "BaseForkMeta") -> bool: - """Check if `a` is a subclass of `b`, taking fork transitions into account.""" + """ + Check if `a` is a subclass of `b`, taking fork transitions into + account. + """ a = BaseForkMeta._maybe_transitioned(a) b = BaseForkMeta._maybe_transitioned(b) return issubclass(a, b) @@ -167,7 +206,10 @@ def __gt__(cls, other: "BaseForkMeta") -> bool: return cls is not other and BaseForkMeta._is_subclass_of(cls, other) def __ge__(cls, other: "BaseForkMeta") -> bool: - """Compare if a fork is newer than or equal to some other fork (cls >= other).""" + """ + Compare if a fork is newer than or equal to some other fork (cls >= + other). + """ return cls is other or BaseForkMeta._is_subclass_of(cls, other) def __lt__(cls, other: "BaseForkMeta") -> bool: @@ -176,7 +218,10 @@ def __lt__(cls, other: "BaseForkMeta") -> bool: return cls is not other and BaseForkMeta._is_subclass_of(other, cls) def __le__(cls, other: "BaseForkMeta") -> bool: - """Compare if a fork is older than or equal to some other fork (cls <= other).""" + """ + Compare if a fork is older than or equal to some other fork (cls <= + other). + """ return cls is other or BaseForkMeta._is_subclass_of(other, cls) @@ -209,7 +254,10 @@ def __init_subclass__( ignore: bool = False, bpo_fork: bool = False, ) -> None: - """Initialize new fork with values that don't carry over to subclass forks.""" + """ + Initialize new fork with values that don't carry over to subclass + forks. + """ cls._transition_tool_name = transition_tool_name cls._solc_name = solc_name cls._ignore = ignore @@ -288,7 +336,10 @@ def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: def memory_expansion_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> MemoryExpansionGasCalculator: - """Return a callable that calculates the gas cost of memory expansion for the fork.""" + """ + Return a callable that calculates the gas cost of memory expansion for + the fork. + """ pass @classmethod @@ -297,8 +348,8 @@ def calldata_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> CalldataGasCalculator: """ - Return callable that calculates the transaction gas cost for its calldata - depending on its contents. + Return callable that calculates the transaction gas cost for its + calldata depending on its contents. """ pass @@ -307,7 +358,9 @@ def calldata_gas_calculator( def base_fee_per_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> BaseFeePerGasCalculator: - """Return a callable that calculates the base fee per gas at a given fork.""" + """ + Return a callable that calculates the base fee per gas at a given fork. + """ pass @classmethod @@ -316,8 +369,8 @@ def base_fee_change_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> BaseFeeChangeCalculator: """ - Return a callable that calculates the gas that needs to be used to change the - base fee. + Return a callable that calculates the gas that needs to be used to + change the base fee. """ pass @@ -344,7 +397,10 @@ def max_refund_quotient(cls) -> int: def transaction_data_floor_cost_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> TransactionDataFloorCostCalculator: - """Return a callable that calculates the transaction floor cost due to its calldata.""" + """ + Return a callable that calculates the transaction floor cost due to its + calldata. + """ pass @classmethod @@ -352,7 +408,10 @@ def transaction_data_floor_cost_calculator( def transaction_intrinsic_cost_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> TransactionIntrinsicCostCalculator: - """Return callable that calculates the intrinsic gas cost of a transaction for the fork.""" + """ + Return callable that calculates the intrinsic gas cost of a transaction + for the fork. + """ pass @classmethod @@ -360,7 +419,9 @@ def transaction_intrinsic_cost_calculator( def blob_gas_price_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> BlobGasPriceCalculator: - """Return a callable that calculates the blob gas price at a given fork.""" + """ + Return a callable that calculates the blob gas price at a given fork. + """ pass @classmethod @@ -368,7 +429,10 @@ def blob_gas_price_calculator( def excess_blob_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> ExcessBlobGasCalculator: - """Return a callable that calculates the excess blob gas for a block at a given fork.""" + """ + Return a callable that calculates the excess blob gas for a block at a + given fork. + """ pass @classmethod @@ -416,7 +480,10 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: @classmethod @abstractmethod def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> bool: - """Return whether the fork uses a reserve price mechanism for blobs or not.""" + """ + Return whether the fork uses a reserve price mechanism for blobs or + not. + """ pass @classmethod @@ -428,7 +495,10 @@ def blob_base_cost(cls, block_number: int = 0, timestamp: int = 0) -> int: @classmethod @abstractmethod def full_blob_tx_wrapper_version(cls, block_number: int = 0, timestamp: int = 0) -> int | None: - """Return the version of the full blob transaction wrapper at a given fork.""" + """ + Return the version of the full blob transaction wrapper at a given + fork. + """ pass @classmethod @@ -455,19 +525,27 @@ def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: @classmethod @abstractmethod def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: - """Return list of the transaction types supported by the fork that can create contracts.""" + """ + Return list of the transaction types supported by the fork that can + create contracts. + """ pass @classmethod @abstractmethod def transaction_gas_limit_cap(cls, block_number: int = 0, timestamp: int = 0) -> int | None: - """Return the transaction gas limit cap, or None if no limit is imposed.""" + """ + Return the transaction gas limit cap, or None if no limit is imposed. + """ pass @classmethod @abstractmethod def block_rlp_size_limit(cls, block_number: int = 0, timestamp: int = 0) -> int | None: - """Return the maximum RLP size of a block in bytes, or None if no limit is imposed.""" + """ + Return the maximum RLP size of a block in bytes, or None if no limit is + imposed. + """ pass @classmethod @@ -489,8 +567,9 @@ def pre_allocation(cls) -> Mapping: """ Return required pre-allocation of accounts for any kind of test. - This method must always call the `fork_to` method when transitioning, because the - allocation can only be set at genesis, and thus cannot be changed at transition time. + This method must always call the `fork_to` method when transitioning, + because the allocation can only be set at genesis, and thus cannot be + changed at transition time. """ pass @@ -501,8 +580,9 @@ def pre_allocation_blockchain(cls) -> Mapping: """ Return required pre-allocation of accounts for any blockchain tests. - This method must always call the `fork_to` method when transitioning, because the - allocation can only be set at genesis, and thus cannot be changed at transition time. + This method must always call the `fork_to` method when transitioning, + because the allocation can only be set at genesis, and thus cannot be + changed at transition time. """ pass @@ -513,8 +593,8 @@ def engine_new_payload_version( cls, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """ - Return `None` if this fork's payloads cannot be sent over the engine API, - or the payload version if it can. + Return `None` if this fork's payloads cannot be sent over the engine + API, or the payload version if it can. """ pass @@ -522,8 +602,8 @@ def engine_new_payload_version( @abstractmethod def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = 0) -> bool: """ - Return true if the engine api version requires new payload calls to include - blob hashes. + Return true if the engine api version requires new payload calls to + include blob hashes. """ pass @@ -531,15 +611,18 @@ def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = @abstractmethod def engine_new_payload_beacon_root(cls, block_number: int = 0, timestamp: int = 0) -> bool: """ - Return true if the engine api version requires new payload calls to include a parent - beacon block root. + Return true if the engine api version requires new payload calls to + include a parent beacon block root. """ pass @classmethod @abstractmethod def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) -> bool: - """Return true if the engine api version requires new payload calls to include requests.""" + """ + Return true if the engine api version requires new payload calls to + include requests. + """ pass @classmethod @@ -548,8 +631,8 @@ def engine_new_payload_target_blobs_per_block( cls, block_number: int = 0, timestamp: int = 0 ) -> bool: """ - Return true if the engine api version requires new payload calls to include - target blobs per block. + Return true if the engine api version requires new payload calls to + include target blobs per block. """ pass @@ -559,8 +642,8 @@ def engine_execution_payload_block_access_list( cls, block_number: int = 0, timestamp: int = 0 ) -> bool: """ - Return `True` if the engine api version requires execution payload to include a - `block_access_list`. + Return `True` if the engine api version requires execution payload to + include a `block_access_list`. """ pass @@ -569,7 +652,10 @@ def engine_execution_payload_block_access_list( def engine_payload_attribute_target_blobs_per_block( cls, block_number: int = 0, timestamp: int = 0 ) -> bool: - """Return true if the payload attributes include the target blobs per block.""" + """ + Return true if the payload attributes include the target blobs per + block. + """ pass @classmethod @@ -577,7 +663,9 @@ def engine_payload_attribute_target_blobs_per_block( def engine_payload_attribute_max_blobs_per_block( cls, block_number: int = 0, timestamp: int = 0 ) -> bool: - """Return true if the payload attributes include the max blobs per block.""" + """ + Return true if the payload attributes include the max blobs per block. + """ pass @classmethod @@ -585,7 +673,10 @@ def engine_payload_attribute_max_blobs_per_block( def engine_forkchoice_updated_version( cls, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: - """Return `None` if the forks canonical chain cannot be set using the forkchoice method.""" + """ + Return `None` if the forks canonical chain cannot be set using the + forkchoice method. + """ pass @classmethod @@ -594,15 +685,18 @@ def engine_get_payload_version( cls, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """ - Return `None` if the forks canonical chain cannot build a payload using the engine - API. + Return `None` if the forks canonical chain cannot build a payload using + the engine API. """ pass @classmethod @abstractmethod def engine_get_blobs_version(cls, block_number: int = 0, timestamp: int = 0) -> Optional[int]: - """Return `None` if the fork does not support the engine get blobs version.""" + """ + Return `None` if the fork does not support the engine get blobs + version. + """ pass # EVM information abstract methods @@ -615,7 +709,10 @@ def evm_code_types(cls, block_number: int = 0, timestamp: int = 0) -> List[EVMCo @classmethod @abstractmethod def max_code_size(cls) -> int: - """Return the maximum code size allowed to be deployed in a contract creation.""" + """ + Return the maximum code size allowed to be deployed in a contract + creation. + """ pass @classmethod @@ -627,7 +724,10 @@ def max_stack_height(cls) -> int: @classmethod @abstractmethod def max_initcode_size(cls) -> int: - """Return the maximum initcode size allowed to be used in a contract creation.""" + """ + Return the maximum initcode size allowed to be used in a contract + creation. + """ pass @classmethod @@ -635,7 +735,10 @@ def max_initcode_size(cls) -> int: def call_opcodes( cls, block_number: int = 0, timestamp: int = 0 ) -> List[Tuple[Opcodes, EVMCodeType]]: - """Return list of tuples with the call opcodes and its corresponding EVM code type.""" + """ + Return list of tuples with the call opcodes and its corresponding EVM + code type. + """ pass @classmethod @@ -651,7 +754,10 @@ def valid_opcodes( def create_opcodes( cls, block_number: int = 0, timestamp: int = 0 ) -> List[Tuple[Opcodes, EVMCodeType]]: - """Return list of tuples with the create opcodes and its corresponding EVM code type.""" + """ + Return list of tuples with the create opcodes and its corresponding EVM + code type. + """ pass @classmethod @@ -669,15 +775,18 @@ def name(cls) -> str: @classmethod def fork_at(cls, block_number: int = 0, timestamp: int = 0) -> Type["BaseFork"]: """ - Return fork at the given block number and timestamp. - Useful only for transition forks, and it's a no-op for normal forks. + Return fork at the given block number and timestamp. Useful only for + transition forks, and it's a no-op for normal forks. """ return cls @classmethod @abstractmethod def transition_tool_name(cls, block_number: int = 0, timestamp: int = 0) -> str: - """Return fork name as it's meant to be passed to the transition tool for execution.""" + """ + Return fork name as it's meant to be passed to the transition tool for + execution. + """ pass @classmethod diff --git a/ethereum_test_forks/forks/forks.py b/ethereum_test_forks/forks/forks.py index c40484a34d..3287a1ec1b 100644 --- a/ethereum_test_forks/forks/forks.py +++ b/ethereum_test_forks/forks/forks.py @@ -34,7 +34,10 @@ class Frontier(BaseFork, solc_name="homestead"): @classmethod def transition_tool_name(cls, block_number: int = 0, timestamp: int = 0) -> str: - """Return fork name as it's meant to be passed to the transition tool for execution.""" + """ + Return fork name as it's meant to be passed to the transition tool for + execution. + """ if cls._transition_tool_name is not None: return cls._transition_tool_name return cls.name() @@ -78,7 +81,9 @@ def header_blob_gas_used_required(cls, block_number: int = 0, timestamp: int = 0 @classmethod def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: - """Return dataclass with the defined gas costs constants for genesis.""" + """ + Return dataclass with the defined gas costs constants for genesis. + """ return GasCosts( G_JUMPDEST=1, G_BASE=2, @@ -126,7 +131,10 @@ def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: def memory_expansion_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> MemoryExpansionGasCalculator: - """Return callable that calculates the gas cost of memory expansion for the fork.""" + """ + Return callable that calculates the gas cost of memory expansion for + the fork. + """ gas_costs = cls.gas_costs(block_number, timestamp) def fn(*, new_bytes: int, previous_bytes: int = 0) -> int: @@ -147,8 +155,8 @@ def calldata_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> CalldataGasCalculator: """ - Return callable that calculates the transaction gas cost for its calldata - depending on its contents. + Return callable that calculates the transaction gas cost for its + calldata depending on its contents. """ gas_costs = cls.gas_costs(block_number, timestamp) @@ -169,7 +177,9 @@ def fn(*, data: BytesConvertible, floor: bool = False) -> int: def base_fee_per_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> BaseFeePerGasCalculator: - """Return a callable that calculates the base fee per gas at a given fork.""" + """ + Return a callable that calculates the base fee per gas at a given fork. + """ raise NotImplementedError(f"Base fee per gas calculator is not supported in {cls.name()}") @classmethod @@ -177,8 +187,8 @@ def base_fee_change_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> BaseFeeChangeCalculator: """ - Return a callable that calculates the gas that needs to be used to change the - base fee. + Return a callable that calculates the gas that needs to be used to + change the base fee. """ raise NotImplementedError(f"Base fee change calculator is not supported in {cls.name()}") @@ -212,7 +222,10 @@ def fn(*, data: BytesConvertible) -> int: def transaction_intrinsic_cost_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> TransactionIntrinsicCostCalculator: - """Return callable that calculates the intrinsic gas cost of a transaction for the fork.""" + """ + Return callable that calculates the intrinsic gas cost of a transaction + for the fork. + """ gas_costs = cls.gas_costs(block_number, timestamp) calldata_gas_calculator = cls.calldata_gas_calculator(block_number, timestamp) @@ -246,14 +259,19 @@ def fn( def blob_gas_price_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> BlobGasPriceCalculator: - """Return a callable that calculates the blob gas price at a given fork.""" + """ + Return a callable that calculates the blob gas price at a given fork. + """ raise NotImplementedError(f"Blob gas price calculator is not supported in {cls.name()}") @classmethod def excess_blob_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> ExcessBlobGasCalculator: - """Return a callable that calculates the excess blob gas for a block at a given fork.""" + """ + Return a callable that calculates the excess blob gas for a block at a + given fork. + """ raise NotImplementedError(f"Excess blob gas calculator is not supported in {cls.name()}") @classmethod @@ -290,7 +308,10 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: @classmethod def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> bool: - """Return whether the fork uses a reserve price mechanism for blobs or not.""" + """ + Return whether the fork uses a reserve price mechanism for blobs or + not. + """ raise NotImplementedError(f"Blob reserve price is not supported in {cls.name()}") @classmethod @@ -372,21 +393,28 @@ def engine_new_payload_target_blobs_per_block( def engine_payload_attribute_target_blobs_per_block( cls, block_number: int = 0, timestamp: int = 0 ) -> bool: - """At genesis, payload attributes do not include the target blobs per block.""" + """ + At genesis, payload attributes do not include the target blobs per + block. + """ return False @classmethod def engine_payload_attribute_max_blobs_per_block( cls, block_number: int = 0, timestamp: int = 0 ) -> bool: - """At genesis, payload attributes do not include the max blobs per block.""" + """ + At genesis, payload attributes do not include the max blobs per block. + """ return False @classmethod def engine_forkchoice_updated_version( cls, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: - """At genesis, forkchoice updates cannot be sent through the engine API.""" + """ + At genesis, forkchoice updates cannot be sent through the engine API. + """ return cls.engine_new_payload_version(block_number, timestamp) @classmethod @@ -446,8 +474,12 @@ def evm_code_types(cls, block_number: int = 0, timestamp: int = 0) -> List[EVMCo @classmethod def max_code_size(cls) -> int: - """At genesis, there is no upper bound for code size (bounded by block gas limit).""" - """However, the default is set to the limit of EIP-170 (Spurious Dragon)""" + """ + At genesis, there is no upper bound for code size (bounded by block gas + limit). + + However, the default is set to the limit of EIP-170 (Spurious Dragon) + """ return 0x6000 @classmethod @@ -738,17 +770,17 @@ class Byzantium(Homestead): @classmethod def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: """ - At Byzantium, the block reward is reduced to - 3_000_000_000_000_000_000 wei. + At Byzantium, the block reward is reduced to 3_000_000_000_000_000_000 + wei. """ return 3_000_000_000_000_000_000 @classmethod def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: """ - At Byzantium, pre-compiles for bigint modular exponentiation, addition and scalar - multiplication on elliptic curve alt_bn128, and optimal ate pairing check on - elliptic curve alt_bn128 are introduced. + At Byzantium, pre-compiles for bigint modular exponentiation, addition + and scalar multiplication on elliptic curve alt_bn128, and optimal ate + pairing check on elliptic curve alt_bn128 are introduced. """ return [ Address(5, label="MODEXP"), @@ -759,8 +791,12 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address] @classmethod def max_code_size(cls) -> int: - # NOTE: Move this to Spurious Dragon once this fork is introduced. See EIP-170. - """At Spurious Dragon, an upper bound was introduced for max contract code size.""" + # NOTE: Move this to Spurious Dragon once this fork is introduced. See + # EIP-170. + """ + At Spurious Dragon, an upper bound was introduced for max contract code + size. + """ return 0x6000 @classmethod @@ -845,8 +881,8 @@ def valid_opcodes( @classmethod def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: """ - On Istanbul, the non-zero transaction data byte cost is reduced to 16 due to - EIP-2028. + On Istanbul, the non-zero transaction data byte cost is reduced to 16 + due to EIP-2028. """ return replace( super(Istanbul, cls).gas_costs(block_number, timestamp), @@ -878,7 +914,10 @@ def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) - def transaction_intrinsic_cost_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> TransactionIntrinsicCostCalculator: - """At Berlin, the transaction intrinsic cost needs to take the access list into account.""" + """ + At Berlin, the transaction intrinsic cost needs to take the access list + into account. + """ super_fn = super(Berlin, cls).transaction_intrinsic_cost_calculator( block_number, timestamp ) @@ -964,19 +1003,20 @@ def base_fee_per_gas_calculator( expected_base_fee_per_gas = parent_base_fee_per_gas elif parent_gas_used > parent_gas_target: gas_used_delta = parent_gas_used - parent_gas_target - base_fee_per_gas_delta = max( - parent_base_fee_per_gas * gas_used_delta // parent_gas_target \ - // BASE_FEE_MAX_CHANGE_DENOMINATOR, - 1, - ) - expected_base_fee_per_gas = parent_base_fee_per_gas + base_fee_per_gas_delta + base_fee_per_gas_delta = max( parent_base_fee_per_gas + * gas_used_delta // parent_gas_target // + BASE_FEE_MAX_CHANGE_DENOMINATOR, 1, ) + expected_base_fee_per_gas = parent_base_fee_per_gas + + base_fee_per_gas_delta else: gas_used_delta = parent_gas_target - parent_gas_used base_fee_per_gas_delta = ( - parent_base_fee_per_gas * gas_used_delta // \ - parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR - ) - expected_base_fee_per_gas = parent_base_fee_per_gas - base_fee_per_gas_delta + parent_base_fee_per_gas * gas_used_delta // + parent_gas_target // + BASE_FEE_MAX_CHANGE_DENOMINATOR + ) + expected_base_fee_per_gas = parent_base_fee_per_gas - + base_fee_per_gas_delta """ base_fee_max_change_denominator = cls.base_fee_max_change_denominator( block_number, timestamp @@ -1016,8 +1056,8 @@ def base_fee_change_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> BaseFeeChangeCalculator: """ - Return a callable that calculates the gas that needs to be used to change the - base fee. + Return a callable that calculates the gas that needs to be used to + change the base fee. """ base_fee_max_change_denominator = cls.base_fee_max_change_denominator( block_number, timestamp @@ -1150,8 +1190,12 @@ class Cancun(Shanghai): "FIELD_ELEMENTS_PER_BLOB": 4096, "BYTES_PER_FIELD_ELEMENT": 32, "CELL_LENGTH": 2048, - "BLS_MODULUS": 0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001, # EIP-2537: Main subgroup order = q, due to this BLS_MODULUS every blob byte (uint256) must be smaller than 116 # noqa: E501 - # https://github.com/ethereum/consensus-specs/blob/cc6996c22692d70e41b7a453d925172ee4b719ad/specs/deneb/polynomial-commitments.md?plain=1#L78 + # EIP-2537: Main subgroup order = q, due to this BLS_MODULUS + # every blob byte (uint256) must be smaller than 116 + "BLS_MODULUS": 0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001, + # https://github.com/ethereum/consensus-specs/blob/ + # cc6996c22692d70e41b7a453d925172ee4b719ad/specs/deneb/ + # polynomial-commitments.md?plain=1#L78 "BYTES_PER_PROOF": 48, "BYTES_PER_COMMITMENT": 48, "KZG_ENDIANNESS": "big", @@ -1203,7 +1247,10 @@ def fn(*, excess_blob_gas) -> int: def excess_blob_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> ExcessBlobGasCalculator: - """Return a callable that calculates the excess blob gas for a block at Cancun.""" + """ + Return a callable that calculates the excess blob gas for a block at + Cancun. + """ target_blobs_per_block = cls.target_blobs_per_block(block_number, timestamp) blob_gas_per_blob = cls.blob_gas_per_blob(block_number, timestamp) target_blob_gas_per_block = target_blobs_per_block * blob_gas_per_blob @@ -1214,7 +1261,8 @@ def fn( parent_excess_blobs: int | None = None, parent_blob_gas_used: int | None = None, parent_blob_count: int | None = None, - parent_base_fee_per_gas: int, # Required for Osaka as using this as base + # Required for Osaka as using this as base + parent_base_fee_per_gas: int, ) -> int: del parent_base_fee_per_gas @@ -1253,12 +1301,18 @@ def supports_blobs(cls, block_number: int = 0, timestamp: int = 0) -> bool: @classmethod def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: - """Blobs are enabled starting from Cancun, with a static target of 3 blobs per block.""" + """ + Blobs are enabled starting from Cancun, with a static target of 3 blobs + per block. + """ return 3 @classmethod def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: - """Blobs are enabled starting from Cancun, with a static max of 6 blobs per block.""" + """ + Blobs are enabled starting from Cancun, with a static max of 6 blobs + per block. + """ return 6 @classmethod @@ -1268,12 +1322,18 @@ def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> @classmethod def full_blob_tx_wrapper_version(cls, block_number: int = 0, timestamp: int = 0) -> int | None: - """Pre-Osaka forks don't use tx wrapper versions for full blob transactions.""" + """ + Pre-Osaka forks don't use tx wrapper versions for full blob + transactions. + """ return None @classmethod def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int: - """Blobs are enabled starting from Cancun, with a static max equal to the max per block.""" + """ + Blobs are enabled starting from Cancun, with a static max equal to the + max per block. + """ return cls.max_blobs_per_block(block_number, timestamp) @classmethod @@ -1313,8 +1373,8 @@ def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Add @classmethod def pre_allocation_blockchain(cls) -> Mapping: """ - Cancun requires pre-allocation of the beacon root contract for EIP-4788 on blockchain - type tests. + Cancun requires pre-allocation of the beacon root contract for EIP-4788 + on blockchain type tests. """ new_allocation = { 0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02: { @@ -1406,8 +1466,8 @@ def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: @classmethod def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: """ - On Prague, the standard token cost and the floor token costs are introduced due to - EIP-7623. + On Prague, the standard token cost and the floor token costs are + introduced due to EIP-7623. """ return replace( super(Prague, cls).gas_costs(block_number, timestamp), @@ -1419,7 +1479,10 @@ def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: @classmethod def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: - """Prague introduces the system contracts for EIP-6110, EIP-7002, EIP-7251 and EIP-2935.""" + """ + Prague introduces the system contracts for EIP-6110, EIP-7002, EIP-7251 + and EIP-2935. + """ return [ Address( 0x00000000219AB540356CBB839CBE05303D7705FA, @@ -1441,7 +1504,10 @@ def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Add @classmethod def max_request_type(cls, block_number: int = 0, timestamp: int = 0) -> int: - """At Prague, three request types are introduced, hence the max request type is 2.""" + """ + At Prague, three request types are introduced, hence the max request + type is 2. + """ return 2 @classmethod @@ -1449,8 +1515,8 @@ def calldata_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> CalldataGasCalculator: """ - Return a callable that calculates the transaction gas cost for its calldata - depending on its contents. + Return a callable that calculates the transaction gas cost for its + calldata depending on its contents. """ gas_costs = cls.gas_costs(block_number, timestamp) @@ -1471,7 +1537,10 @@ def fn(*, data: BytesConvertible, floor: bool = False) -> int: def transaction_data_floor_cost_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> TransactionDataFloorCostCalculator: - """On Prague, due to EIP-7623, the transaction data floor cost is introduced.""" + """ + On Prague, due to EIP-7623, the transaction data floor cost is + introduced. + """ calldata_gas_calculator = cls.calldata_gas_calculator(block_number, timestamp) gas_costs = cls.gas_costs(block_number, timestamp) @@ -1541,8 +1610,9 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: @classmethod def pre_allocation_blockchain(cls) -> Mapping: """ - Prague requires pre-allocation of the beacon chain deposit contract for EIP-6110, - the exits contract for EIP-7002, and the history storage contract for EIP-2935. + Prague requires pre-allocation of the beacon chain deposit contract for + EIP-6110, the exits contract for EIP-7002, and the history storage + contract for EIP-2935. """ new_allocation = {} @@ -1610,7 +1680,9 @@ def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> @classmethod def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) -> bool: - """From Prague, new payloads include the requests hash as a parameter.""" + """ + From Prague, new payloads include the requests hash as a parameter. + """ return True @classmethod @@ -1624,7 +1696,9 @@ def engine_new_payload_version( def engine_forkchoice_updated_version( cls, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: - """At Prague, version number of NewPayload and ForkchoiceUpdated diverge.""" + """ + At Prague, version number of NewPayload and ForkchoiceUpdated diverge. + """ return 3 @@ -1698,7 +1772,9 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address] def excess_blob_gas_calculator( cls, block_number: int = 0, timestamp: int = 0 ) -> ExcessBlobGasCalculator: - """Return a callable that calculates the excess blob gas for a block.""" + """ + Return a callable that calculates the excess blob gas for a block. + """ target_blobs_per_block = cls.target_blobs_per_block(block_number, timestamp) blob_gas_per_blob = cls.blob_gas_per_blob(block_number, timestamp) target_blob_gas_per_block = target_blobs_per_block * blob_gas_per_blob @@ -1722,7 +1798,8 @@ def fn( if parent_excess_blob_gas + parent_blob_gas_used < target_blob_gas_per_block: return 0 - # EIP-7918: Apply reserve price when execution costs dominate blob costs + # EIP-7918: Apply reserve price when execution costs dominate blob + # costs current_blob_base_fee = cls.blob_gas_price_calculator()( excess_blob_gas=parent_excess_blob_gas ) @@ -1745,7 +1822,10 @@ def fn( @classmethod def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int: - """Blobs in Osaka, have a static max of 6 blobs per tx. Differs from the max per block.""" + """ + Blobs in Osaka, have a static max of 6 blobs per tx. Differs from the + max per block. + """ return 6 @classmethod @@ -1836,7 +1916,10 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: class BPO5(BPO4, bpo_fork=True): - """BPO5 fork - Blob Parameter Only fork 5 (Required to parse Fusaka devnet genesis files).""" + """ + BPO5 fork - Blob Parameter Only fork 5 (Required to parse Fusaka devnet + genesis files). + """ pass @@ -1846,7 +1929,9 @@ class Amsterdam(Osaka): @classmethod def header_bal_hash_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: - """From Amsterdam, header must contain block access list hash (EIP-7928).""" + """ + From Amsterdam, header must contain block access list hash (EIP-7928). + """ return True @classmethod @@ -1866,8 +1951,8 @@ def engine_execution_payload_block_access_list( cls, block_number: int = 0, timestamp: int = 0 ) -> bool: """ - From Amsterdam, engine execution payload includes `block_access_list` as - a parameter. + From Amsterdam, engine execution payload includes `block_access_list` + as a parameter. """ return True diff --git a/ethereum_test_forks/helpers.py b/ethereum_test_forks/helpers.py index 62796f3f53..3b13834280 100644 --- a/ethereum_test_forks/helpers.py +++ b/ethereum_test_forks/helpers.py @@ -20,7 +20,10 @@ class InvalidForkError(Exception): - """Invalid fork error raised when the fork specified is not found or incompatible.""" + """ + Invalid fork error raised when the fork specified is not found or + incompatible. + """ def __init__(self, message): """Initialize the InvalidForkError exception.""" @@ -54,8 +57,8 @@ def __init__(self, message): def get_forks() -> List[Type[BaseFork]]: """ - Return list of all the fork classes implemented by - `ethereum_test_forks` ordered chronologically by deployment. + Return list of all the fork classes implemented by `ethereum_test_forks` + ordered chronologically by deployment. """ return all_forks[:] @@ -177,8 +180,8 @@ def get_selected_fork_set( transition_forks: bool = True, ) -> Set[Type[BaseFork]]: """ - Process sets derived from `--fork`, `--until` and `--from` to return an unified fork - set. + Process sets derived from `--fork`, `--until` and `--from` to return an + unified fork set. """ selected_fork_set = set() if single_fork: @@ -200,8 +203,7 @@ def transition_fork_from_to( fork_from: Type[BaseFork], fork_to: Type[BaseFork] ) -> Type[BaseFork] | None: """ - Return transition fork that transitions to and from the specified - forks. + Return transition fork that transitions to and from the specified forks. """ for transition_fork in get_transition_forks(): if not issubclass(transition_fork, TransitionBaseClass): @@ -231,8 +233,8 @@ def forks_from_until( fork_from: Type[BaseFork], fork_until: Type[BaseFork] ) -> List[Type[BaseFork]]: """ - Return specified fork and all forks after it until and including the - second specified fork. + Return specified fork and all forks after it until and including the second + specified fork. """ prev_fork = fork_until @@ -266,13 +268,13 @@ def get_relative_fork_markers( """ Return a list of marker names for a given fork. - For a base fork (e.g. `Shanghai`), return [ `Shanghai` ]. - For a transition fork (e.g. `ShanghaiToCancunAtTime15k` which transitions to `Cancun`), + For a base fork (e.g. `Shanghai`), return [ `Shanghai` ]. For a transition + fork (e.g. `ShanghaiToCancunAtTime15k` which transitions to `Cancun`), return [ `ShanghaiToCancunAtTime15k`, `Cancun` ]. - If `strict_mode` is set to `True`, raise an `InvalidForkError` if the fork is not found, - otherwise, simply return the provided (str) `fork_identifier` (this is required to run - `consume` with forks that are unknown to EEST). + If `strict_mode` is set to `True`, raise an `InvalidForkError` if the fork + is not found, otherwise, simply return the provided (str) `fork_identifier` + (this is required to run `consume` with forks that are unknown to EEST). """ all_forks = set(get_forks()) | set(get_transition_forks()) if isinstance(fork_identifier, str): @@ -302,7 +304,10 @@ def get_fork_by_name(fork_name: str) -> Type[BaseFork] | None: class ForkRangeDescriptor(BaseModel): - """Fork descriptor parsed from string normally contained in ethereum/tests fillers.""" + """ + Fork descriptor parsed from string normally contained in ethereum/tests + fillers. + """ greater_equal: Type[BaseFork] | None = None less_than: Type[BaseFork] | None = None @@ -323,8 +328,10 @@ def validate_fork_range_descriptor(cls, v: Any, handler: ValidatorFunctionWrapHa Validate the fork range descriptor from a string. Examples: - - ">=Osaka" validates to {greater_equal=Osaka, less_than=None} - - ">=Prague=Osaka" validates to {greater_equal=Osaka, less_than=None} + + - ">=PragueB, when filling, and given the from/until markers, - we expect the following logic: + E.g. given transition fork A->B, when filling, and given the from/until + markers, we expect the following logic: Marker Comparison A->B Included --------- ------------ --------------- @@ -223,7 +224,8 @@ def test_transition_fork_comparison(): assert BerlinToLondonAt5 >= London assert BerlinToLondonAt5 <= London - # Comparisons between transition forks is done against the `transitions_to` fork + # Comparisons between transition forks is done against the `transitions_to` + # fork assert BerlinToLondonAt5 < ParisToShanghaiAtTime15k assert ParisToShanghaiAtTime15k > BerlinToLondonAt5 assert BerlinToLondonAt5 == BerlinToLondonAt5 @@ -353,8 +355,9 @@ class FutureFork(Osaka): """ Dummy fork used for testing. - Contains no changes to the blob parameters from the parent fork in order to confirm that - it's added to the blob schedule even if it doesn't have any changes. + Contains no changes to the blob parameters from the parent fork in order to + confirm that it's added to the blob schedule even if it doesn't have any + changes. """ pass diff --git a/ethereum_test_forks/transition_base_fork.py b/ethereum_test_forks/transition_base_fork.py index 81c3e3f657..60b43b63a9 100644 --- a/ethereum_test_forks/transition_base_fork.py +++ b/ethereum_test_forks/transition_base_fork.py @@ -24,7 +24,9 @@ def transitions_from(cls) -> Type[BaseFork]: def base_fork_abstract_methods() -> List[str]: - """Return list of all abstract methods that must be implemented by a fork.""" + """ + Return list of all abstract methods that must be implemented by a fork. + """ return list(BaseFork.__abstractmethods__) diff --git a/ethereum_test_rpc/__init__.py b/ethereum_test_rpc/__init__.py index 85e533d89b..888cdf3c63 100644 --- a/ethereum_test_rpc/__init__.py +++ b/ethereum_test_rpc/__init__.py @@ -1,4 +1,6 @@ -"""JSON-RPC methods and helper functions for EEST consume based hive simulators.""" +""" +JSON-RPC methods and helper functions for EEST consume based hive simulators. +""" from .rpc import ( AdminRPC, diff --git a/ethereum_test_rpc/rpc.py b/ethereum_test_rpc/rpc.py index 1f289b628f..a09055ba12 100644 --- a/ethereum_test_rpc/rpc.py +++ b/ethereum_test_rpc/rpc.py @@ -1,4 +1,6 @@ -"""JSON-RPC methods and helper functions for EEST consume based hive simulators.""" +""" +JSON-RPC methods and helper functions for EEST consume based hive simulators. +""" import time from itertools import count @@ -30,13 +32,18 @@ class SendTransactionExceptionError(Exception): - """Represent an exception that is raised when a transaction fails to be sent.""" + """ + Represent an exception that is raised when a transaction fails to be sent. + """ tx: Transaction | None = None tx_rlp: Bytes | None = None def __init__(self, *args, tx: Transaction | None = None, tx_rlp: Bytes | None = None): - """Initialize SendTransactionExceptionError class with the given transaction.""" + """ + Initialize SendTransactionExceptionError class with the given + transaction. + """ super().__init__(*args) self.tx = tx self.tx_rlp = tx_rlp @@ -51,7 +58,10 @@ def __str__(self): class BaseRPC: - """Represents a base RPC class for every RPC call used within EEST based hive simulators.""" + """ + Represents a base RPC class for every RPC call used within EEST based hive + simulators. + """ namespace: ClassVar[str] response_validation_context: Any | None @@ -68,7 +78,9 @@ def __init__( self.response_validation_context = response_validation_context def __init_subclass__(cls, namespace: str | None = None) -> None: - """Set namespace of the RPC class to the lowercase of the class name.""" + """ + Set namespace of the RPC class to the lowercase of the class name. + """ if namespace is None: namespace = cls.__name__ if namespace.endswith("RPC"): @@ -85,7 +97,10 @@ def post_request( request_id: int | str | None = None, timeout: int | None = None, ) -> Any: - """Send JSON-RPC POST request to the client RPC server at port defined in the url.""" + """ + Send JSON-RPC POST request to the client RPC server at port defined in + the url. + """ if extra_headers is None: extra_headers = {} if params is None: @@ -123,8 +138,8 @@ def post_request( class EthRPC(BaseRPC): """ - Represents an `eth_X` RPC class for every default ethereum RPC method used within EEST based - hive simulators. + Represents an `eth_X` RPC class for every default ethereum RPC method used + within EEST based hive simulators. """ transaction_wait_timeout: int = 60 @@ -137,12 +152,18 @@ def __init__( transaction_wait_timeout: int = 60, **kwargs, ): - """Initialize EthRPC class with the given url and transaction wait timeout.""" + """ + Initialize EthRPC class with the given url and transaction wait + timeout. + """ super().__init__(*args, **kwargs) self.transaction_wait_timeout = transaction_wait_timeout def config(self, timeout: int | None = None): - """`eth_config`: Returns information about a fork configuration of the client.""" + """ + `eth_config`: Returns information about a fork configuration of the + client. + """ try: response = self.post_request(method="config", timeout=timeout) if response is None: @@ -165,7 +186,10 @@ def chain_id(self) -> int: return int(response, 16) def get_block_by_number(self, block_number: BlockNumberType = "latest", full_txs: bool = True): - """`eth_getBlockByNumber`: Returns information about a block by block number.""" + """ + `eth_getBlockByNumber`: Returns information about a block by block + number. + """ block = hex(block_number) if isinstance(block_number, int) else block_number params = [block, full_txs] response = self.post_request(method="getBlockByNumber", params=params) @@ -180,7 +204,9 @@ def get_block_by_hash(self, block_hash: Hash, full_txs: bool = True): return response def get_balance(self, address: Address, block_number: BlockNumberType = "latest") -> int: - """`eth_getBalance`: Returns the balance of the account of given address.""" + """ + `eth_getBalance`: Returns the balance of the account of given address. + """ block = hex(block_number) if isinstance(block_number, int) else block_number params = [f"{address}", block] @@ -200,7 +226,10 @@ def get_code(self, address: Address, block_number: BlockNumberType = "latest") - def get_transaction_count( self, address: Address, block_number: BlockNumberType = "latest" ) -> int: - """`eth_getTransactionCount`: Returns the number of transactions sent from an address.""" + """ + `eth_getTransactionCount`: Returns the number of transactions sent from + an address. + """ block = hex(block_number) if isinstance(block_number, int) else block_number params = [f"{address}", block] @@ -226,7 +255,10 @@ def get_transaction_by_hash(self, transaction_hash: Hash) -> TransactionByHashRe def get_storage_at( self, address: Address, position: Hash, block_number: BlockNumberType = "latest" ) -> Hash: - """`eth_getStorageAt`: Returns the value from a storage position at a given address.""" + """ + `eth_getStorageAt`: Returns the value from a storage position at a + given address. + """ block = hex(block_number) if isinstance(block_number, int) else block_number params = [f"{address}", f"{position}", block] @@ -234,7 +266,10 @@ def get_storage_at( return Hash(response) def gas_price(self) -> int: - """`eth_gasPrice`: Returns the number of transactions sent from an address.""" + """ + `eth_gasPrice`: Returns the number of transactions sent from an + address. + """ response = self.post_request(method="gasPrice") return int(response, 16) @@ -247,7 +282,7 @@ def send_raw_transaction( response = self.post_request( method="sendRawTransaction", params=[transaction_rlp.hex()], - request_id=request_id, # noqa: E501 + request_id=request_id, ) result_hash = Hash(response) @@ -263,7 +298,7 @@ def send_transaction(self, transaction: Transaction) -> Hash: response = self.post_request( method="sendRawTransaction", params=[transaction.rlp().hex()], - request_id=transaction.metadata_string(), # noqa: E501 + request_id=transaction.metadata_string(), ) result_hash = Hash(response) @@ -274,15 +309,18 @@ def send_transaction(self, transaction: Transaction) -> Hash: raise SendTransactionExceptionError(str(e), tx=transaction) from e def send_transactions(self, transactions: List[Transaction]) -> List[Hash]: - """Use `eth_sendRawTransaction` to send a list of transactions to the client.""" + """ + Use `eth_sendRawTransaction` to send a list of transactions to the + client. + """ return [self.send_transaction(tx) for tx in transactions] def storage_at_keys( self, account: Address, keys: List[Hash], block_number: BlockNumberType = "latest" ) -> Dict[Hash, Hash]: """ - Retrieve the storage values for the specified keys at a given address and block - number. + Retrieve the storage values for the specified keys at a given address + and block number. """ results: Dict[Hash, Hash] = {} for key in keys: @@ -291,7 +329,10 @@ def storage_at_keys( return results def wait_for_transaction(self, transaction: Transaction) -> TransactionByHashResponse: - """Use `eth_getTransactionByHash` to wait until a transaction is included in a block.""" + """ + Use `eth_getTransactionByHash` to wait until a transaction is included + in a block. + """ tx_hash = transaction.hash start_time = time.time() while True: @@ -310,8 +351,8 @@ def wait_for_transactions( self, transactions: List[Transaction] ) -> List[TransactionByHashResponse]: """ - Use `eth_getTransactionByHash` to wait until all transactions in list are included in a - block. + Use `eth_getTransactionByHash` to wait until all transactions in list + are included in a block. """ tx_hashes = [tx.hash for tx in transactions] responses: List[TransactionByHashResponse] = [] @@ -345,15 +386,18 @@ def send_wait_transaction(self, transaction: Transaction): return self.wait_for_transaction(transaction) def send_wait_transactions(self, transactions: List[Transaction]): - """Send list of transactions and waits until all of them are included in a block.""" + """ + Send list of transactions and waits until all of them are included in a + block. + """ self.send_transactions(transactions) return self.wait_for_transactions(transactions) class DebugRPC(EthRPC): """ - Represents an `debug_X` RPC class for every default ethereum RPC method used within EEST based - hive simulators. + Represents an `debug_X` RPC class for every default ethereum RPC method + used within EEST based hive simulators. """ def trace_call(self, tr: dict[str, str], block_number: str): @@ -364,8 +408,8 @@ def trace_call(self, tr: dict[str, str], block_number: str): class EngineRPC(BaseRPC): """ - Represents an Engine API RPC class for every Engine API method used within EEST based hive - simulators. + Represents an Engine API RPC class for every Engine API method used within + EEST based hive simulators. """ jwt_secret: bytes @@ -389,7 +433,10 @@ def post_request( request_id: int | str | None = None, timeout: int | None = None, ) -> Any: - """Send JSON-RPC POST request to the client RPC server at port defined in the url.""" + """ + Send JSON-RPC POST request to the client RPC server at port defined in + the url. + """ if extra_headers is None: extra_headers = {} jwt_token = encode( @@ -410,7 +457,10 @@ def post_request( ) def new_payload(self, *params: Any, version: int) -> PayloadStatus: - """`engine_newPayloadVX`: Attempts to execute the given payload on an execution client.""" + """ + `engine_newPayloadVX`: Attempts to execute the given payload on an + execution client. + """ method = f"newPayloadV{version}" params_list = [to_json(param) for param in params] @@ -426,7 +476,10 @@ def forkchoice_updated( *, version: int, ) -> ForkchoiceUpdateResponse: - """`engine_forkchoiceUpdatedVX`: Updates the forkchoice state of the execution client.""" + """ + `engine_forkchoiceUpdatedVX`: Updates the forkchoice state of the + execution client. + """ method = f"forkchoiceUpdatedV{version}" if payload_attributes is None: @@ -468,7 +521,9 @@ def get_blobs( *, version: int, ) -> GetBlobsResponse | None: - """`engine_getBlobsVX`: Retrieves blobs from an execution layers tx pool.""" + """ + `engine_getBlobsVX`: Retrieves blobs from an execution layers tx pool. + """ method = f"getBlobsV{version}" params = [f"{h}" for h in versioned_hashes] diff --git a/ethereum_test_rpc/rpc_types.py b/ethereum_test_rpc/rpc_types.py index 8d874d07fb..d904d441cc 100644 --- a/ethereum_test_rpc/rpc_types.py +++ b/ethereum_test_rpc/rpc_types.py @@ -55,7 +55,8 @@ class TransactionByHashResponse(Transaction): transaction_hash: Hash = Field(..., alias="hash") sender: EOA | None = Field(None, alias="from") - # The to field can have different names in different clients, so we use AliasChoices. + # The to field can have different names in different clients, so we use + # AliasChoices. to: Address | None = Field(..., validation_alias=AliasChoices("to_address", "to", "toAddress")) v: HexNumber = Field(0, validation_alias=AliasChoices("v", "yParity")) # type: ignore @@ -64,8 +65,8 @@ class TransactionByHashResponse(Transaction): @classmethod def adapt_clients_response(cls, data: Any) -> Any: """ - Perform modifications necessary to adapt the response returned by clients - so it can be parsed by our model. + Perform modifications necessary to adapt the response returned by + clients so it can be parsed by our model. """ if isinstance(data, dict): if "gasPrice" in data and "maxFeePerGas" in data: @@ -75,8 +76,8 @@ def adapt_clients_response(cls, data: Any) -> Any: def model_post_init(self, __context): """ - Check that the transaction hash returned by the client matches the one calculated by - us. + Check that the transaction hash returned by the client matches the one + calculated by us. """ Transaction.model_post_init(self, __context) assert self.transaction_hash == self.hash diff --git a/ethereum_test_rpc/tests/test_types.py b/ethereum_test_rpc/tests/test_types.py index c0a6892e9a..0a42a078b3 100644 --- a/ethereum_test_rpc/tests/test_types.py +++ b/ethereum_test_rpc/tests/test_types.py @@ -99,7 +99,9 @@ @pytest.fixture def eth_config_response() -> EthConfigResponse: - """Get the `eth_config` response from the client to be verified by all tests.""" + """ + Get the `eth_config` response from the client to be verified by all tests. + """ return EthConfigResponse.model_validate(eth_config_dict) diff --git a/ethereum_test_specs/base.py b/ethereum_test_specs/base.py index a82c0d9456..3fee6ba4bc 100644 --- a/ethereum_test_specs/base.py +++ b/ethereum_test_specs/base.py @@ -1,4 +1,6 @@ -"""Base test class and helper functions for Ethereum state and blockchain tests.""" +""" +Base test class and helper functions for Ethereum state and blockchain tests. +""" import hashlib from abc import abstractmethod @@ -43,8 +45,8 @@ def __str__(self): def verify_result(result: Result, env: Environment): """ - Verify that values in the t8n result match the expected values. - Raises exception on unexpected values. + Verify that values in the t8n result match the expected values. Raises + exception on unexpected values. """ if env.withdrawals is not None: assert result.withdrawals_root == to_hex(Withdrawal.list_root(env.withdrawals)) @@ -61,7 +63,9 @@ class OpMode(StrEnum): class BaseTest(BaseModel): - """Represents a base Ethereum test which must return a single test fixture.""" + """ + Represents a base Ethereum test which must return a single test fixture. + """ model_config = ConfigDict(extra="forbid") @@ -93,7 +97,10 @@ def discard_fixture_format_by_marks( fork: Fork, markers: List[pytest.Mark], ) -> bool: - """Discard a fixture format from filling if the appropriate marker is used.""" + """ + Discard a fixture format from filling if the appropriate marker is + used. + """ return False @classmethod @@ -132,7 +139,10 @@ def discard_execute_format_by_marks( fork: Fork, markers: List[pytest.Mark], ) -> bool: - """Discard an execute format from executing if the appropriate marker is used.""" + """ + Discard an execute format from executing if the appropriate marker is + used. + """ return False @abstractmethod @@ -189,10 +199,11 @@ def is_tx_gas_heavy_test(self) -> bool: def is_exception_test(self) -> bool | None: """ - Check if the test is an exception test (invalid block, invalid transaction). + Check if the test is an exception test (invalid block, invalid + transaction). - `None` is returned if it's not possible to determine if the test is negative or not. - This is the case when the test is not run in pytest. + `None` is returned if it's not possible to determine if the test is + negative or not. This is the case when the test is not run in pytest. """ if self._request is not None and hasattr(self._request, "node"): return self._request.node.get_closest_marker("exception_test") is not None @@ -231,7 +242,8 @@ def get_genesis_environment(self, fork: Fork) -> Environment: """ Get the genesis environment for pre-allocation groups. - Must be implemented by subclasses to provide the appropriate environment. + Must be implemented by subclasses to provide the appropriate + environment. """ raise NotImplementedError( f"{self.__class__.__name__} must implement genesis environment access for use with " @@ -241,7 +253,10 @@ def get_genesis_environment(self, fork: Fork) -> Environment: def update_pre_alloc_groups( self, pre_alloc_groups: PreAllocGroups, fork: Fork, test_id: str ) -> PreAllocGroups: - """Create or update the pre-allocation group with the pre from the current spec.""" + """ + Create or update the pre-allocation group with the pre from the current + spec. + """ if not hasattr(self, "pre"): raise AttributeError( f"{self.__class__.__name__} does not have a 'pre' field. Pre-allocation groups " @@ -261,7 +276,8 @@ def update_pre_alloc_groups( group.test_ids.append(str(test_id)) pre_alloc_groups[pre_alloc_hash] = group else: - # Create new group - use Environment instead of expensive genesis generation + # Create new group - use Environment instead of expensive genesis + # generation genesis_env = self.get_genesis_environment(fork) pre_alloc = Alloc.merge( Alloc.model_validate(fork.pre_allocation_blockchain()), diff --git a/ethereum_test_specs/base_static.py b/ethereum_test_specs/base_static.py index cdd60d6164..3dd61bbebc 100644 --- a/ethereum_test_specs/base_static.py +++ b/ethereum_test_specs/base_static.py @@ -1,4 +1,6 @@ -"""Base class to parse test cases written in static formats.""" +""" +Base class to parse test cases written in static formats. +""" import re from abc import abstractmethod @@ -25,8 +27,8 @@ class BaseStaticTest(BaseModel): @classmethod def __pydantic_init_subclass__(cls, **kwargs): """ - Register all subclasses of BaseStaticTest with a static test format name set - as possible static test format. + Register all subclasses of BaseStaticTest with a static test format + name set as possible static test format. """ if cls.format_name: # Register the new fixture format @@ -55,8 +57,9 @@ def fill_function(self) -> Callable: This method should be implemented by the subclasses. - The function returned can be optionally decorated with the `@pytest.mark.parametrize` - decorator to parametrize the test with the number of sub test cases. + The function returned can be optionally decorated with the + `@pytest.mark.parametrize` decorator to parametrize the test with the + number of sub test cases. Example: ``` @@ -68,7 +71,7 @@ def test_state_filler( fork: Fork, pre: Alloc, n: int, - m: int, + m: int ): \"\"\"Generate a test from a static state filler.\"\"\" assert n == 1 @@ -85,35 +88,46 @@ def test_state_filler( sender=sender, ) state_test(env=env, pre=pre, post={}, tx=tx) - - return test_state_filler ``` - To aid the generation of the test, the function can be defined and then the decorator be - applied after defining the function: + To aid the generation of the test, the function can be defined and then + the decorator be applied after defining the function: ``` def test_state_filler( - state_test: StateTestFiller, + state_test: StateTestFiller, fork: Fork, pre: Alloc, n: int, m: int, ): - ... - test_state_filler = pytest.mark.parametrize("n", [1])(test_state_filler) - test_state_filler = pytest.mark.parametrize("m", [1, 2])(test_state_filler) + + ... + + test_state_filler = pytest.mark.parametrize("n", + [1])(test_state_filler + ) + test_state_filler = pytest.mark.parametrize("m", + [1, 2])(test_state_filler + ) + if self.valid_from: - test_state_filler = pytest.mark.valid_from(self.valid_from)(test_state_filler) + test_state_filler = pytest.mark.valid_from( + self.valid_from + )(test_state_filler) + if self.valid_until: - test_state_filler = pytest.mark.valid_until(self.valid_until)(test_state_filler) + test_state_filler = pytest.mark.valid_until( + self.valid_until + )(test_state_filler) + return test_state_filler ``` - The function can contain the following parameters on top of the spec type parameter - (`state_test` in the example above): - - `fork`: The fork for which the test is currently being filled. - - `pre`: The pre-state of the test. + The function can contain the following parameters on top of the spec + type parameter (`state_test` in the example above): - `fork`: The fork + for which the test is currently being filled. - `pre`: The pre-state of + the test. """ raise NotImplementedError @@ -143,8 +157,8 @@ def remove_comments_from_model(cls, data: Any) -> Any: def remove_comments(v: str) -> str: """ - Split by line and then remove the comments (starting with #) at the end of each line if - any. + Split by line and then remove the comments (starting with #) at the end of + each line if any. """ return "\n".join([line.split("#")[0].strip() for line in v.splitlines()]) diff --git a/ethereum_test_specs/benchmark.py b/ethereum_test_specs/benchmark.py index 440faa8b84..c6fdd1b644 100644 --- a/ethereum_test_specs/benchmark.py +++ b/ethereum_test_specs/benchmark.py @@ -54,7 +54,10 @@ def generate_transaction(self, pre: Alloc, gas_limit: int, fork: Fork) -> Transa def generate_repeated_code( self, repeated_code: Bytecode, setup: Bytecode, fork: Fork ) -> Bytecode: - """Calculate the maximum number of iterations that can fit in the code size limit.""" + """ + Calculate the maximum number of iterations that + can fit in the code size limit. + """ assert len(repeated_code) > 0, "repeated_code cannot be empty" max_code_size = fork.max_code_size() @@ -114,7 +117,10 @@ class BenchmarkTest(BaseTest): @classmethod def pytest_parameter_name(cls) -> str: - """Return the parameter name used in pytest to select this spec type.""" + """ + Return the parameter name used in pytest + to select this spec type. + """ return "benchmark_test" @classmethod @@ -124,7 +130,10 @@ def discard_fixture_format_by_marks( fork: Fork, markers: List[pytest.Mark], ) -> bool: - """Discard a fixture format from filling if the appropriate marker is used.""" + """ + Discard a fixture format from filling if the + appropriate marker is used. + """ if "blockchain_test_only" in [m.name for m in markers]: return fixture_format != BlockchainFixture if "blockchain_test_engine_only" in [m.name for m in markers]: @@ -136,7 +145,10 @@ def get_genesis_environment(self, fork: Fork) -> Environment: return self.env def split_transaction(self, tx: Transaction, gas_limit_cap: int | None) -> List[Transaction]: - """Split a transaction that exceeds the gas limit cap into multiple transactions.""" + """ + Split a transaction that exceeds the gas + limit cap into multiple transactions. + """ if gas_limit_cap is None: tx.gas_limit = HexNumber(self.gas_benchmark_value) return [tx] diff --git a/ethereum_test_specs/blockchain.py b/ethereum_test_specs/blockchain.py index 796a34ce4d..6669ab2f27 100644 --- a/ethereum_test_specs/blockchain.py +++ b/ethereum_test_specs/blockchain.py @@ -130,27 +130,22 @@ class Header(CamelModel): """ EMPTY_FIELD: ClassVar[Removable] = Removable() """ - Sentinel object used to specify that a header field must be empty during verification. + Sentinel object used to specify that a header field must be empty during + verification. - This can be used in a test to explicitly skip a field in a block's RLP encoding. - included in the (json) output when the model is serialized. For example: - ``` - header_modifier = Header( - excess_blob_gas=Header.REMOVE_FIELD, - ) - block = Block( - timestamp=TIMESTAMP, - rlp_modifier=header_modifier, - exception=BlockException.INCORRECT_BLOCK_FORMAT, - engine_api_error_code=EngineAPIError.InvalidParams, - ) - ``` + This can be used in a test to explicitly skip a field in a block's RLP + encoding. included in the (json) output when the model is serialized. For + example: ``` header_modifier = Header( excess_blob_gas=Header.REMOVE_FIELD, + ) block = Block( timestamp=TIMESTAMP, rlp_modifier=header_modifier, + exception=BlockException.INCORRECT_BLOCK_FORMAT, + engine_api_error_code=EngineAPIError.InvalidParams, ) ``` """ model_config = ConfigDict( arbitrary_types_allowed=True, - # explicitly set Removable items to None so they are not included in the serialization - # (in combination with exclude_None=True in model.dump()). + # explicitly set Removable items to None so they are not included in + # the serialization (in combination with exclude_None=True in + # model.dump()). json_encoders={ Removable: lambda x: None, }, @@ -165,7 +160,9 @@ def validate_withdrawals_root(cls, value): return value def apply(self, target: FixtureHeader) -> FixtureHeader: - """Produce a fixture header copy with the set values from the modifier.""" + """ + Produce a fixture header copy with the set values from the modifier. + """ return target.copy( **{ k: (v if v is not Header.REMOVE_FIELD else None) @@ -200,9 +197,7 @@ class Block(Header): """Block type used to describe block properties in test specs.""" header_verify: Header | None = None - """ - If set, the block header will be verified against the specified values. - """ + # If set, the block header will be verified against the specified values. rlp_modifier: Header | None = None """ An RLP modifying header which values would be used to override the ones @@ -210,46 +205,34 @@ class Block(Header): """ expected_block_access_list: BlockAccessListExpectation | None = None """ - If set, the block access list will be verified and potentially corrupted for invalid tests. + If set, the block access list will be verified and potentially corrupted + for invalid tests. """ exception: BLOCK_EXCEPTION_TYPE = None - """ - If set, the block is expected to be rejected by the client. - """ + # If set, the block is expected to be rejected by the client. skip_exception_verification: bool = False """ - Skip verifying that the exception is returned by the transition tool. - This could be because the exception is inserted in the block after the transition tool - evaluates it. + Skip verifying that the exception is returned by the transition tool. This + could be because the exception is inserted in the block after the + transition tool evaluates it. """ engine_api_error_code: EngineAPIError | None = None """ - If set, the block is expected to produce an error response from the Engine API. + If set, the block is expected to produce an error response from the Engine + API. """ txs: List[Transaction] = Field(default_factory=list) - """ - List of transactions included in the block. - """ + """List of transactions included in the block.""" ommers: List[Header] | None = None - """ - List of ommer headers included in the block. - """ + """List of ommer headers included in the block.""" withdrawals: List[Withdrawal] | None = None - """ - List of withdrawals to perform for this block. - """ + """List of withdrawals to perform for this block.""" requests: List[Bytes] | None = None - """ - Custom list of requests to embed in this block. - """ + """Custom list of requests to embed in this block.""" expected_post_state: Alloc | None = None - """ - Post state for verification after block execution in BlockchainTest - """ + """Post state for verification after block execution in BlockchainTest""" block_access_list: Bytes | None = Field(None) - """ - EIP-7928: Block-level access lists (serialized). - """ + """EIP-7928: Block-level access lists (serialized).""" def set_environment(self, env: Environment) -> Environment: """ @@ -259,8 +242,8 @@ def set_environment(self, env: Environment) -> Environment: new_env_values: Dict[str, Any] = {} """ - Values that need to be set in the environment and are `None` for - this block need to be set to their defaults. + Values that need to be set in the environment and are `None` for this + block need to be set to their defaults. """ new_env_values["difficulty"] = self.difficulty new_env_values["prev_randao"] = self.prev_randao @@ -310,10 +293,7 @@ def set_environment(self, env: Environment) -> Environment: class BuiltBlock(CamelModel): - """ - Model that contains all properties to build a full block or - payload. - """ + """Model that contains all properties to build a full block or payload.""" header: FixtureHeader env: Environment @@ -414,7 +394,8 @@ def verify_block_exception(self, transition_tool_exceptions_reliable: bool): "prev_randao": 0, } """ -Default values for the genesis environment that are used to create all genesis headers. +Default values for the genesis environment that are used to create all genesis +headers. """ @@ -428,8 +409,8 @@ class BlockchainTest(BaseTest): chain_id: int = 1 exclude_full_post_state_in_output: bool = False """ - Exclude the post state from the fixture output. - In this case, the state verification is only performed based on the state root. + Exclude the post state from the fixture output. In this case, the state + verification is only performed based on the state root. """ supported_fixture_formats: ClassVar[Sequence[FixtureFormat | LabeledFixtureFormat]] = [ @@ -458,7 +439,10 @@ def discard_fixture_format_by_marks( fork: Fork, markers: List[pytest.Mark], ) -> bool: - """Discard a fixture format from filling if the appropriate marker is used.""" + """ + Discard a fixture format from filling if the appropriate marker is + used. + """ marker_names = [m.name for m in markers] if fixture_format != BlockchainFixture and "blockchain_test_only" in marker_names: return True @@ -516,7 +500,9 @@ def generate_block_data( previous_alloc: Alloc, last_block: bool, ) -> BuiltBlock: - """Generate common block data for both make_fixture and make_hive_fixture.""" + """ + Generate common block data for both make_fixture and make_hive_fixture. + """ env = block.set_environment(previous_env) env = env.set_fork_requirements(fork) txs = [tx.with_signature_and_sender() for tx in block.txs] @@ -546,10 +532,11 @@ def generate_block_data( slow_request=self.is_tx_gas_heavy_test(), ) - # One special case of the invalid transactions is the blob gas used, since this value - # is not included in the transition tool result, but it is included in the block header, - # and some clients check it before executing the block by simply counting the type-3 txs, - # we need to set the correct value by default. + # One special case of the invalid transactions is the blob gas used, + # since this value is not included in the transition tool result, but + # it is included in the block header, and some clients check it before + # executing the block by simply counting the type-3 txs, we need to set + # the correct value by default. blob_gas_used: int | None = None if (blob_gas_per_blob := fork.blob_gas_per_blob(env.number, env.timestamp)) > 0: blob_gas_used = blob_gas_per_blob * count_blobs(txs) @@ -628,7 +615,8 @@ def generate_block_data( header = block.rlp_modifier.apply(header) header.fork = fork # Deleted during `apply` because `exclude=True` - # Process block access list - apply transformer if present for invalid tests + # Process block access list - apply transformer if present for invalid + # tests t8n_bal = transition_tool_output.result.block_access_list bal = t8n_bal if block.expected_block_access_list is not None and t8n_bal is not None: @@ -668,15 +656,14 @@ def generate_block_data( and block.expected_block_access_list._modifier is not None ) ): - # Only verify block level exception if: - # - No transaction exception was raised, because these are not - # reported as block exceptions. - # - No RLP modifier was specified, because the modifier is what - # normally produces the block exception. - # - No requests were specified, because modified requests are also - # what normally produces the block exception. - # - No BAL modifier was specified, because modified BAL also - # produces block exceptions. + # Only verify block level exception if: - No transaction + # exception was raised, because these are not reported as block + # exceptions. - No RLP modifier was specified, because the + # modifier is what normally produces the block exception. - No + # requests were specified, because modified requests are also + # what normally produces the block exception. - No BAL modifier + # was specified, because modified BAL also produces block + # exceptions. built_block.verify_block_exception( transition_tool_exceptions_reliable=t8n.exception_mapper.reliable, ) @@ -739,7 +726,8 @@ def make_fixture( ) fixture_blocks.append(built_block.get_fixture_block()) - # BAL verification already done in to_fixture_bal() if expected_block_access_list set + # BAL verification already done in to_fixture_bal() if + # expected_block_access_list set if block.exception is None: # Update env, alloc and last block hash for the next block. @@ -838,8 +826,8 @@ def make_hive_fixture( # Add format-specific fields if fixture_format == BlockchainEngineXFixture: - # For Engine X format, exclude pre (will be provided via shared state) - # and prepare for state diff optimization + # For Engine X format, exclude pre (will be provided via shared + # state) and prepare for state diff optimization fixture_data.update( { "post_state": alloc if not self.exclude_full_post_state_in_output else None, @@ -852,9 +840,9 @@ def make_hive_fixture( assert genesis.header.block_hash != head_hash, ( "Invalid payload tests negative test via sync is not supported yet." ) - # Most clients require the header to start the sync process, so we create an empty - # block on top of the last block of the test to send it as new payload and trigger the - # sync process. + # Most clients require the header to start the sync process, so we + # create an empty block on top of the last block of the test to + # send it as new payload and trigger the sync process. sync_built_block = self.generate_block_data( t8n=t8n, fork=fork, diff --git a/ethereum_test_specs/eof.py b/ethereum_test_specs/eof.py index 35f5898489..d64a98cde1 100644 --- a/ethereum_test_specs/eof.py +++ b/ethereum_test_specs/eof.py @@ -53,7 +53,9 @@ def __init__(self, message): @staticmethod def format_code(code: Bytes, max_length=60) -> str: - """Avoid printing long bytecode strings in the terminal upon test failure.""" + """ + Avoid printing long bytecode strings in the terminal upon test failure. + """ if len(code) > max_length: half_length = max_length // 2 - 5 # Floor; adjust for ellipsis return f"{code[:half_length].hex()}...{code[-half_length:].hex()}" @@ -84,7 +86,10 @@ class ExpectedEOFExceptionError(EOFBaseExceptionError): """ def __init__(self, *, code: Bytes, expected: str): - """Initialize the exception with the code and the expected exception message.""" + """ + Initialize the exception with the code and the expected exception + message. + """ message = ( "Expected EOF code to be invalid, but no exception was raised:\n" f" Code: {self.format_code(code)}\n" @@ -95,10 +100,15 @@ def __init__(self, *, code: Bytes, expected: str): class EOFExceptionMismatchError(EOFBaseExceptionError): - """Exception used when the actual EOF exception differs from the expected one.""" + """ + Exception used when the actual EOF exception differs from the expected one. + """ def __init__(self, code: Bytes, expected: str, got: str): - """Initialize the exception with the code, the expected/actual exception message.""" + """ + Initialize the exception with the code, the expected/actual exception + message. + """ message = ( "EOF code raised a different exception than expected:\n" f" Code: {self.format_code(code)}\n" @@ -166,88 +176,92 @@ class EOFTest(BaseTest): """ Filler type that generates a test for EOF container validation. - A state test is also automatically generated where the container is wrapped in a - contract-creating transaction to test deployment/validation on the instantiated blockchain. + A state test is also automatically generated where the container is wrapped + in a contract-creating transaction to test deployment/validation on the + instantiated blockchain. """ container: Container """ EOF container that will be tested for validity. - The only supported type at the moment is `ethereum_test_types.eof.v1.Container`. + The only supported type at the moment is + `ethereum_test_types.eof.v1.Container`. - If an invalid container needs to be tested, and it cannot be generated using the - Container class features, the `raw_bytes` field can be used to provide the raw - container bytes. + If an invalid container needs to be tested, and it cannot be generated + using the Container class features, the `raw_bytes` field can be used to + provide the raw container bytes. """ expect_exception: EOFExceptionInstanceOrList | None = None """ - Expected exception that the container should raise when parsed by an EOF parser. + Expected exception that the container should raise when parsed by an EOF + parser. - Can be a single exception or a list of exceptions that the container is expected to raise, - in which case the test will pass if any of the exceptions are raised. + Can be a single exception or a list of exceptions that the container is + expected to raise, in which case the test will pass if any of the + exceptions are raised. - The list of supported exceptions can be found in the `ethereum_test_exceptions.EOFException` - class. + The list of supported exceptions can be found in the + `ethereum_test_exceptions.EOFException` class. """ container_kind: ContainerKind = ContainerKind.RUNTIME """ Container kind type that the container should be treated as. - The container kind can be one of the following: - - `ContainerKind.INITCODE`: The container is an initcode container. - - `ContainerKind.RUNTIME`: The container is a runtime container. + The container kind can be one of the following: - `ContainerKind.INITCODE`: + The container is an initcode container. - `ContainerKind.RUNTIME`: The + container is a runtime container. The default value is `ContainerKind.RUNTIME`. """ deployed_container: Container | None = None """ - To be used when the container is an initcode container and the expected deployed container is - known. - - The value is only used when a State Test is generated from this EOF test to set the expected - deployed container that should be found in the post state. - - If this field is not set, and the container is valid: - - If the container kind is `ContainerKind.RUNTIME`, the deployed container is assumed to be - the container itself, and an initcode container that wraps the container is generated - automatically. - - If the container kind is `ContainerKind.INITCODE`, `model_post_init` will attempt to infer - the deployed container from the sections of the init-container, and the first - container-type section will be used. An error will be raised if the deployed container - cannot be inferred. - - If the value is set to `None`, it is assumed that the container is invalid and the test will - expect that no contract is created. - - It is considered an error if: - - The `deployed_container` field is set and the `container_kind` field is not set to - `ContainerKind.INITCODE`. - - The `deployed_container` field is set and the `expect_exception` is not `None`. - - The deployed container is **not** executed at any point during the EOF validation test nor - the generated State Test. For container runtime testing use the `EOFStateTest` class. + To be used when the container is an initcode container and the expected + deployed container is known. + + The value is only used when a State Test is generated from this EOF test to + set the expected deployed container that should be found in the post state. + + If this field is not set, and the container is valid: - If the container + kind is `ContainerKind.RUNTIME`, the deployed container is assumed to be + the container itself, and an initcode container that wraps the container is + generated automatically. - If the container kind is + `ContainerKind.INITCODE`, `model_post_init` will attempt to infer the + deployed container from the sections of the init-container, and the first + container-type section will be used. An error will be raised if the + deployed container cannot be inferred. + + If the value is set to `None`, it is assumed that the container is invalid + and the test will expect that no contract is created. + + It is considered an error if: - The `deployed_container` field is set and + the `container_kind` field is not set to `ContainerKind.INITCODE`. - The + `deployed_container` field is set and the `expect_exception` is not `None`. + + The deployed container is **not** executed at any point during the EOF + validation test nor the generated State Test. For container runtime testing + use the `EOFStateTest` class. """ pre: Alloc | None = None """ Pre alloc object that is used during State Test generation. - This field is automatically set by the test filler when generating a State Test from this EOF - test and should otherwise be left unset. + This field is automatically set by the test filler when generating a State + Test from this EOF test and should otherwise be left unset. """ post: Alloc | None = None """ Post alloc object that is used during State Test generation. - This field is automatically set by the test filler when generating a State Test from this EOF - test and is normally not set by the user. + This field is automatically set by the test filler when generating a State + Test from this EOF test and is normally not set by the user. """ sender: EOA | None = None """ Sender EOA object that is used during State Test generation. - This field is automatically set by the `model_post_init` method and should otherwise be left - unset. + This field is automatically set by the `model_post_init` method and should + otherwise be left unset. """ supported_fixture_formats: ClassVar[Sequence[FixtureFormat | LabeledFixtureFormat]] = [ @@ -281,7 +295,10 @@ def discard_fixture_format_by_marks( fork: Fork, markers: List[pytest.Mark], ) -> bool: - """Discard a fixture format from filling if the appropriate marker is used.""" + """ + Discard a fixture format from filling if the appropriate marker is + used. + """ if "eof_test_only" in [m.name for m in markers]: return fixture_format != EOFFixture return False @@ -369,7 +386,9 @@ def make_eof_test_fixture( return fixture def verify_result(self, result: CompletedProcess, expected_result: Result, code: Bytes): - """Check that the reported exception string matches the expected error.""" + """ + Check that the reported exception string matches the expected error. + """ evmone_exception_mapper = EvmoneExceptionMapper() actual_exception_str = result.stdout.strip() actual_exception: EOFExceptionWithMessage | UndefinedException | None = None @@ -409,12 +428,13 @@ def generate_eof_contract_create_transaction(self) -> Transaction: if self.container_kind == ContainerKind.INITCODE: initcode = self.container if "deployed_container" in self.model_fields_set: - # In the case of an initcontainer where we know the deployed container, - # we can use the initcontainer as-is. + # In the case of an initcontainer where we know the deployed + # container, we can use the initcontainer as-is. deployed_container = self.deployed_container elif self.expect_exception is None: - # We have a valid init-container, but we don't know the deployed container. - # Try to infer the deployed container from the sections of the init-container. + # We have a valid init-container, but we don't know the + # deployed container. Try to infer the deployed container from + # the sections of the init-container. assert self.container.raw_bytes is None, ( "deployed_container must be set for initcode containers with raw_bytes." ) @@ -505,34 +525,28 @@ def execute( class EOFStateTest(EOFTest, Transaction): """ - Filler type that generates an EOF test for container validation, and also tests the container - during runtime using a state test (and blockchain test). + Filler type that generates an EOF test for container validation, and also + tests the container during runtime using a state test (and blockchain + test). - In the state or blockchain test, the container is first deployed to the pre-allocation and - then a transaction is sent to the deployed container. + In the state or blockchain test, the container is first deployed to the + pre-allocation and then a transaction is sent to the deployed container. - Container deployment/validation is **not** tested like in the `EOFTest` unless the container - under test is an initcode container. + Container deployment/validation is **not** tested like in the `EOFTest` + unless the container under test is an initcode container. - All fields from `ethereum_test_types.Transaction` are available for use in the test. + All fields from `ethereum_test_types.Transaction` are available for use in + the test. """ gas_limit: HexNumber = Field(HexNumber(10_000_000), serialization_alias="gas") - """ - Gas limit for the transaction that deploys the container. - """ + """Gas limit for the transaction that deploys the container.""" tx_sender_funding_amount: int = 1_000_000_000_000_000_000_000 - """ - Amount of funds to send to the sender EOA before the transaction. - """ + """Amount of funds to send to the sender EOA before the transaction.""" env: Environment = Field(default_factory=Environment) - """ - Environment object that is used during State Test generation. - """ + """Environment object that is used during State Test generation.""" container_post: Account = Field(default_factory=Account) - """ - Account object used to verify the container post state. - """ + """Account object used to verify the container post state.""" supported_fixture_formats: ClassVar[Sequence[FixtureFormat | LabeledFixtureFormat]] = [ EOFFixture @@ -580,7 +594,8 @@ def model_post_init(self, __context): # Run transaction model validation Transaction.model_post_init(self, __context) - self.post[compute_eofcreate_address(self.to, 0)] = None # Expect failure. + self.post[compute_eofcreate_address(self.to, 0)] = None # Expect + # failure. elif self.expect_exception is not None and self.container_kind == ContainerKind.INITCODE: # Invalid EOF initcode self.to = self.pre.deploy_contract( @@ -591,7 +606,8 @@ def model_post_init(self, __context): # Run transaction model validation Transaction.model_post_init(self, __context) - self.post[compute_eofcreate_address(self.to, 0)] = None # Expect failure. + self.post[compute_eofcreate_address(self.to, 0)] = None # Expect + # failure. elif self.container_kind == ContainerKind.INITCODE: self.to = self.pre.deploy_contract( Op.TXCREATE(tx_initcode_hash=self.container.hash) + Op.STOP @@ -634,8 +650,8 @@ def generate( """Generate the BlockchainTest fixture.""" if fixture_format == EOFFixture: if Bytes(self.container) in existing_tests: - # Gracefully skip duplicate tests because one EOFStateTest can generate multiple - # state fixtures with the same data. + # Gracefully skip duplicate tests because one EOFStateTest can + # generate multiple state fixtures with the same data. pytest.skip(f"Duplicate EOF container on EOFStateTest: {self.node_id()}") return self.make_eof_test_fixture(fork=fork) elif fixture_format in StateTest.supported_fixture_formats: diff --git a/ethereum_test_specs/helpers.py b/ethereum_test_specs/helpers.py index 1f877f21d3..27b0979310 100644 --- a/ethereum_test_specs/helpers.py +++ b/ethereum_test_specs/helpers.py @@ -23,7 +23,9 @@ class ExecutionContext(StrEnum): class UnexpectedExecutionSuccessError(Exception): - """Exception used when the transaction expected to fail succeeded instead.""" + """ + Exception used when the transaction expected to fail succeeded instead. + """ def __init__(self, execution_context: ExecutionContext, **kwargs): """Initialize the unexpected success exception.""" @@ -35,7 +37,9 @@ def __init__(self, execution_context: ExecutionContext, **kwargs): class UnexpectedExecutionFailError(Exception): - """Exception used when a transaction/block expected to succeed failed instead.""" + """ + Exception used when a transaction/block expected to succeed failed instead. + """ def __init__( self, @@ -54,7 +58,10 @@ def __init__( class UndefinedExecutionExceptionError(Exception): - """Exception used when a client's exception message isn't present in its `ExceptionMapper`.""" + """ + Exception used when a client's exception message isn't present in its + `ExceptionMapper`. + """ def __init__( self, @@ -100,7 +107,10 @@ def __init__( class TransactionReceiptMismatchError(Exception): - """Exception used when the actual transaction receipt differs from the expected one.""" + """ + Exception used when the actual transaction receipt differs from the + expected one. + """ def __init__( self, @@ -259,9 +269,9 @@ def verify_transactions( transition_tool_exceptions_reliable: bool, ) -> List[int]: """ - Verify accepted and rejected (if any) transactions against the expected outcome. - Raises exception on unexpected rejections, unexpected successful txs, or successful txs with - unexpected receipt values. + Verify accepted and rejected (if any) transactions against the expected + outcome. Raises exception on unexpected rejections, unexpected successful + txs, or successful txs with unexpected receipt values. """ rejected_txs: Dict[int, ExceptionWithMessage | UndefinedException] = { rejected_tx.index: rejected_tx.error for rejected_tx in result.rejected_transactions diff --git a/ethereum_test_specs/state.py b/ethereum_test_specs/state.py index b368b41298..24b0cb0816 100644 --- a/ethereum_test_specs/state.py +++ b/ethereum_test_specs/state.py @@ -46,7 +46,9 @@ class StateTest(BaseTest): - """Filler type that tests transactions over the period of a single block.""" + """ + Filler type that tests transactions over the period of a single block. + """ env: Environment = Field(default_factory=Environment) pre: Alloc @@ -70,7 +72,8 @@ class StateTest(BaseTest): f"A {fixture_format.format_name} generated from a state_test", ) for fixture_format in BlockchainTest.supported_fixture_formats - # Exclude sync fixtures from state tests - they don't make sense for state tests + # Exclude sync fixtures from state tests - they don't make sense for + # state tests if not ( (hasattr(fixture_format, "__name__") and "Sync" in fixture_format.__name__) or (hasattr(fixture_format, "format") and "Sync" in fixture_format.format.__name__) @@ -173,26 +176,33 @@ def discard_fixture_format_by_marks( fork: Fork, markers: List[pytest.Mark], ) -> bool: - """Discard a fixture format from filling if the appropriate marker is used.""" + """ + Discard a fixture format from filling if the appropriate marker is + used. + """ if "state_test_only" in [m.name for m in markers]: return fixture_format != StateFixture return False def _generate_blockchain_genesis_environment(self, *, fork: Fork) -> Environment: - """Generate the genesis environment for the BlockchainTest formatted test.""" + """ + Generate the genesis environment for the BlockchainTest formatted test. + """ assert self.env.number >= 1, ( "genesis block number cannot be negative, set state test env.number to at least 1" ) assert self.env.timestamp >= 1, ( "genesis timestamp cannot be negative, set state test env.timestamp to at least 1" ) - # There's only a handful of values that we need to set in the genesis for the - # environment values at block 1 to make sense: + # There's only a handful of values that we need to set in the genesis + # for the environment values at block 1 to make sense: # - Number: Needs to be N minus 1 - # - Timestamp: Needs to be zero, because the subsequent block can come at any time. + # - Timestamp: Needs to be zero, because the subsequent + # block can come at any time. # - Gas Limit: Changes from parent to child, needs to be set in genesis # - Base Fee Per Gas: Block's base fee depends on the parent's value - # - Excess Blob Gas: Block's excess blob gas value depends on the parent's value + # - Excess Blob Gas: Block's excess blob gas value depends on + # the parent's value kwargs: Dict[str, Any] = { "number": self.env.number - 1, "timestamp": 0, @@ -208,11 +218,13 @@ def _generate_blockchain_genesis_environment(self, *, fork: Fork) -> Environment ) if self.env.excess_blob_gas: - # The excess blob gas environment value means the value of the context (block header) - # where the transaction is executed. In a blockchain test, we need to indirectly - # set the excess blob gas by setting the excess blob gas of the genesis block - # to the expected value plus the TARGET_BLOB_GAS_PER_BLOCK, which is the value - # that will be subtracted from the excess blob gas when the first block is mined. + # The excess blob gas environment value means the value of the + # context (block header) where the transaction is executed. In a + # blockchain test, we need to indirectly set the excess blob gas by + # setting the excess blob gas of the genesis block to the expected + # value plus the TARGET_BLOB_GAS_PER_BLOCK, which is the value that + # will be subtracted from the excess blob gas when the first block + # is mined. kwargs["excess_blob_gas"] = self.env.excess_blob_gas + ( fork.target_blobs_per_block() * fork.blob_gas_per_blob() ) @@ -220,7 +232,10 @@ def _generate_blockchain_genesis_environment(self, *, fork: Fork) -> Environment return Environment(**kwargs) def _generate_blockchain_blocks(self, *, fork: Fork) -> List[Block]: - """Generate the single block that represents this state test in a BlockchainTest format.""" + """ + Generate the single block that represents this state test in a + BlockchainTest format. + """ kwargs = { "number": self.env.number, "timestamp": self.env.timestamp, @@ -261,7 +276,8 @@ def make_state_test_fixture( ) -> StateFixture: """Create a fixture from the state test definition.""" # We can't generate a state test fixture that names a transition fork, - # so we get the fork at the block number and timestamp of the state test + # so we get the fork at the block number and timestamp of the state + # test fork = fork.fork_at(self.env.number, self.env.timestamp) env = self.env.set_fork_requirements(fork) @@ -315,8 +331,9 @@ def make_state_test_fixture( assert base_tool_output.result.traces is not None, "Traces not found." - # First try reducing the gas limit only by one, if the validation fails, it means - # that the traces change even with the slightest modification to the gas. + # First try reducing the gas limit only by one, if the validation + # fails, it means that the traces change even with the slightest + # modification to the gas. if self.verify_modified_gas_limit( t8n=t8n, base_tool_output=base_tool_output, diff --git a/ethereum_test_specs/static_state/account.py b/ethereum_test_specs/static_state/account.py index 81f16cdee1..978312f9b2 100644 --- a/ethereum_test_specs/static_state/account.py +++ b/ethereum_test_specs/static_state/account.py @@ -169,7 +169,8 @@ def setup(self, pre: Alloc, all_dependencies: Dict[str, Tag]) -> TagDict: # Step 3: Get topological order resolution_order = self._topological_sort(dep_graph) - # Step 4: Pre-deploy all contract tags and pre-fund EOAs to get addresses + # Step 4: Pre-deploy all contract tags and pre-fund EOAs to get + # addresses for tag_name in resolution_order: if tag_name in tag_to_address: tag = tag_to_address[tag_name] @@ -181,7 +182,8 @@ def setup(self, pre: Alloc, all_dependencies: Dict[str, Tag]) -> TagDict: ) resolved_accounts[tag_name] = deployed_address elif isinstance(tag, SenderTag): - # Create EOA to get address - use amount=1 to ensure account is created + # Create EOA to get address - use amount=1 to ensure + # account is created eoa = pre.fund_eoa(amount=1, label=tag_name) # Store the EOA object for SenderKeyTag resolution resolved_accounts[tag_name] = eoa @@ -247,7 +249,8 @@ def setup(self, pre: Alloc, all_dependencies: Dict[str, Tag]) -> TagDict: if all_dependencies[extra_dependency].type != "eoa": raise ValueError(f"Contract dependency {extra_dependency} not found in pre") - # Create new EOA - this will have a dynamically generated key and address + # Create new EOA - this will have a dynamically generated key + # and address eoa = pre.fund_eoa(amount=0, label=extra_dependency) resolved_accounts[extra_dependency] = eoa diff --git a/ethereum_test_specs/static_state/common/common.py b/ethereum_test_specs/static_state/common/common.py index 340f08971d..d10e6f254e 100644 --- a/ethereum_test_specs/static_state/common/common.py +++ b/ethereum_test_specs/static_state/common/common.py @@ -69,7 +69,8 @@ def validate_from_string(cls, code: Any) -> Any: """Validate from string, separating label from code source.""" if isinstance(code, str): label_marker = ":label" - # Only look for label at the beginning of the string (possibly after whitespace) + # Only look for label at the beginning of the string (possibly + # after whitespace) stripped_code = code.lstrip() # Parse :label into code options @@ -123,7 +124,8 @@ def replace_tags(raw_code, keep_prefix: bool) -> str: substitution_address = f"{tag.resolve(tags)}" if not keep_prefix and substitution_address.startswith("0x"): substitution_address = substitution_address[2:] - # Use the original string if available, otherwise construct a pattern + # Use the original string if available, otherwise construct a + # pattern if hasattr(tag, "original_string") and tag.original_string: raw_code = raw_code.replace(tag.original_string, substitution_address) else: @@ -192,9 +194,11 @@ def replace_tags(raw_code, keep_prefix: bool) -> str: [parameter_str], [ [ - int(t.lower(), 0) & ((1 << 256) - 1) # treat big ints as 256bits + # treat big ints as 256bits + int(t.lower(), 0) & ((1 << 256) - 1) if parameter_types[t_index] == "uint" - else int(t.lower(), 0) > 0 # treat positive values as True + # treat positive values as True + else int(t.lower(), 0) > 0 if parameter_types[t_index] == "bool" else False and ValueError("unhandled parameter_types") for t_index, t in enumerate(tokens[1:]) @@ -217,15 +221,18 @@ def replace_tags(raw_code, keep_prefix: bool) -> str: # - using lllc result = subprocess.run(["lllc", tmp_path], capture_output=True, text=True) - # - using docker: - # If the running machine does not have lllc installed, we can use docker to - # run lllc, but we need to start a container first, and the process is generally - # slower. + # - using docker: If the running machine does not have lllc + # installed, we can use docker to run lllc, but we need to + # start a container first, and the process is generally slower. + # # from .docker import get_lllc_container_id - # result = subprocess.run( - # ["docker", "exec", get_lllc_container_id(), "lllc", tmp_path[5:]], + # result = subprocess.run( ["docker", + # "exec", + # get_lllc_container_id(), + # "lllc", + # tmp_path[5:]], # capture_output=True, - # text=True, + # text=True # ) compiled_code = "".join(result.stdout.splitlines()) @@ -245,15 +252,16 @@ def tag_dependencies(self) -> Mapping[str, Tag]: class AddressTag: """ Represents an address tag like: - - . - - . - - . + - . + - . + - . """ def __init__(self, tag_type: str, tag_name: str, original_string: str): """Initialize address tag.""" self.tag_type = tag_type # "eoa", "contract", or "coinbase" - self.tag_name = tag_name # e.g., "sender", "target", or address for 2-part tags + # e.g., "sender", "target", or address for 2-part tags + self.tag_name = tag_name self.original_string = original_string def __str__(self) -> str: @@ -317,8 +325,8 @@ def parse_address_or_tag(value: Any) -> Union[Address, AddressTag]: def parse_address_or_tag_for_access_list(value: Any) -> Union[Address, str]: """ - Parse either a regular address or an address tag, keeping tags as strings for later - resolution. + Parse either a regular address or an address tag, keeping tags as strings + for later resolution. """ if not isinstance(value, str): # Non-string values should be converted to Address normally @@ -344,7 +352,9 @@ def parse_address_or_tag_for_access_list(value: Any) -> Union[Address, str]: class AccessListInFiller(CamelModel, TagDependentData): - """Access List for transactions in fillers that can contain address tags.""" + """ + Access List for transactions in fillers that can contain address tags. + """ address: AddressOrTagInFiller storage_keys: List[Hash] = Field(default_factory=list) diff --git a/ethereum_test_specs/static_state/common/compile_yul.py b/ethereum_test_specs/static_state/common/compile_yul.py index 6e548d46b2..632d0cd31a 100644 --- a/ethereum_test_specs/static_state/common/compile_yul.py +++ b/ethereum_test_specs/static_state/common/compile_yul.py @@ -51,19 +51,21 @@ def safe_solc_command( def compile_yul(source_file: str, evm_version: str | None = None, optimize: str | None = None): """ - Compiles a Yul source file using solc and returns the binary representation. + Compiles a Yul source file using solc and returns the binary + representation. - Parameters_: - source_file (str): Path to the Yul source file. - evm_version (str, optional): The EVM version to use (e.g., 'istanbul'). Defaults to None. - optimize (any, optional): If provided (non-None), optimization flags are not added. - If None, additional optimization flags will be included. + Arguments: + source_file (str): Path to the Yul source file. + evm_version(str, optional): The EVM version to use (e.g., 'istanbul'). + Defaults to None. + optimize (any, optional): If provided (non-None), optimization flags + are not added. If None, additional + optimization flags will be included. - Returns_: - str: The binary representation prefixed with "0x". + Returns: str: The binary representation prefixed with "0x". + + Raises: Exception: If the solc output contains an error message. - Raises_: - Exception: If the solc output contains an error message. """ cmd = safe_solc_command(source_file, evm_version, optimize) @@ -77,7 +79,8 @@ def compile_yul(source_file: str, evm_version: str | None = None, optimize: str if "Error" in out: raise Exception(f"Yul compilation error:\n{out}") - # Search for the "Binary representation:" line and get the following line as the binary + # Search for the "Binary representation:" line and get the following line + # as the binary lines = out.splitlines() binary_line = "" for i, line in enumerate(lines): diff --git a/ethereum_test_specs/static_state/common/tags.py b/ethereum_test_specs/static_state/common/tags.py index d1c75dc888..100ae06107 100644 --- a/ethereum_test_specs/static_state/common/tags.py +++ b/ethereum_test_specs/static_state/common/tags.py @@ -20,7 +20,8 @@ class Tag(BaseModel, Generic[T]): name: str type: ClassVar[str] = "" regex_pattern: ClassVar[re.Pattern] = re.compile(r"<\w+:(\w+)(:[^>]+)?") - original_string: str | None = None # Store the original tag string for replacement + # Store the original tag string for replacement + original_string: str | None = None def __hash__(self) -> int: """Hash based on original string for use as dict key.""" @@ -64,12 +65,18 @@ class ContractTag(AddressTag): type: ClassVar[str] = "contract" regex_pattern: ClassVar[re.Pattern] = re.compile(r"]+)(?::(0x[a-fA-F0-9]+))?>") - debug_address: Address | None = None # Optional hard-coded address for debugging + # Optional hard-coded address for debugging + debug_address: Address | None = None @model_validator(mode="before") @classmethod def validate_from_string(cls, data: Any) -> Any: - """Validate the contract tag from string: or .""" + """ + Validate the contract tag from string: + + or + . + """ if isinstance(data, str): if m := cls.regex_pattern.match(data): name_or_addr = m.group(1) @@ -77,8 +84,9 @@ def validate_from_string(cls, data: Any) -> Any: # Check if it's a 2-part format with an address if name_or_addr.startswith("0x") and len(name_or_addr) == 42: - # For 2-part format, use the full address as the name - # This ensures all references to the same address get the same tag name + # For 2-part format, use the full address as the name This + # ensures all references to the same address get the same + # tag name return { "name": name_or_addr, "debug_address": Address(name_or_addr), @@ -146,7 +154,8 @@ class SenderTag(AddressTag): type: ClassVar[str] = "eoa" regex_pattern: ClassVar[re.Pattern] = re.compile(r"") - debug_address: Address | None = None # Optional hard-coded address for debugging + # Optional hard-coded address for debugging + debug_address: Address | None = None @model_validator(mode="before") @classmethod diff --git a/ethereum_test_specs/static_state/expect_section.py b/ethereum_test_specs/static_state/expect_section.py index 226b3311be..ccd7f7aa45 100644 --- a/ethereum_test_specs/static_state/expect_section.py +++ b/ethereum_test_specs/static_state/expect_section.py @@ -106,7 +106,10 @@ class AccountInExpectSection(BaseModel, TagDependentData): @model_validator(mode="wrap") @classmethod def validate_should_not_exist(cls, v: Any, handler: ValidatorFunctionWrapHandler): - """Validate the "shouldnotexist" field, which makes this validator return `None`.""" + """ + Validate the "shouldnotexist" field, which makes this validator return + `None`. + """ if isinstance(v, dict): if "shouldnotexist" in v: return None @@ -251,8 +254,8 @@ class ResultInFiller(EthereumTestRootModel, TagDependentData): """ Post section in state test filler. - A value of `None` for an address means that the account should not be in the state trie - at the end of the test. + A value of `None` for an address means that the account should not be in + the state trie at the end of the test. """ root: Dict[AddressOrCreateTagInFiller, AccountInExpectSection | None] diff --git a/ethereum_test_specs/static_state/general_transaction.py b/ethereum_test_specs/static_state/general_transaction.py index e3e44be62e..cafec7778c 100644 --- a/ethereum_test_specs/static_state/general_transaction.py +++ b/ethereum_test_specs/static_state/general_transaction.py @@ -86,7 +86,9 @@ def __getitem__(self, label_or_index: int | str): raise KeyError(f"Label/index {label_or_index} not found in data indexes") def __contains__(self, label_or_index: int | str): - """Return True if the LabeledDataList contains the given label/index.""" + """ + Return True if the LabeledDataList contains the given label/index. + """ if isinstance(label_or_index, int): return label_or_index < len(self.root) if isinstance(label_or_index, str): diff --git a/ethereum_test_specs/static_state/state_static.py b/ethereum_test_specs/static_state/state_static.py index 7801d404b9..322691b4cf 100644 --- a/ethereum_test_specs/static_state/state_static.py +++ b/ethereum_test_specs/static_state/state_static.py @@ -69,7 +69,9 @@ def parse_indexes( indexes: Union[int, str, list[Union[int, str]], list[str], list[int]], do_hint: bool = False, ) -> List[int] | int: - """Parse indexes and replace all ranges and labels into tx indexes.""" + """ + Parse indexes and replace all ranges and labels into tx indexes. + """ result: List[int] | int = [] if do_hint: @@ -129,8 +131,9 @@ def fill_function(self) -> Callable: for expect in self.expect: if expect.has_index(d.index, g, v) and expect.expect_exception is not None: exception_test = True - # TODO: This does not take into account exceptions that only happen on - # specific forks, but this requires a covariant parametrize + # TODO: This does not take into account exceptions that + # only happen on specific forks, but this requires a + # covariant parametrize marks = [pytest.mark.exception_test] if exception_test else [] id_label = "" if len(self.transaction.data) > 1 or d.label is not None: diff --git a/ethereum_test_specs/tests/test_benchmark.py b/ethereum_test_specs/tests/test_benchmark.py index bd4a699720..6511e427fc 100644 --- a/ethereum_test_specs/tests/test_benchmark.py +++ b/ethereum_test_specs/tests/test_benchmark.py @@ -1,4 +1,7 @@ -"""Tests for the BenchmarkTest class and its transaction splitting functionality.""" +""" +Tests for the BenchmarkTest class and its +transaction splitting functionality. +""" import pytest @@ -20,7 +23,10 @@ ], ) def test_split_transaction(gas_benchmark_value_millions: int, expected_splits: int): - """Test that transaction splitting works correctly for Osaka fork gas cap.""" + """ + Test that transaction splitting works + correctly for Osaka fork gas cap. + """ gas_benchmark_value = gas_benchmark_value_millions * 1_000_000 gas_limit_cap = 16_000_000 # Osaka's transaction gas limit cap @@ -100,6 +106,7 @@ def test_split_transaction_edge_cases(gas_benchmark_value: int, gas_limit_cap: i # When no cap, gas_limit should be benchmark value assert split_txs[0].gas_limit == gas_benchmark_value else: - # When cap > benchmark, gas_limit should be min of tx.gas_limit and benchmark + # When cap > benchmark, gas_limit should be + # min of tx.gas_limit and benchmark assert benchmark_test.tx is not None, "Transaction should not be None" assert split_txs[0].gas_limit == min(benchmark_test.tx.gas_limit, gas_benchmark_value) diff --git a/ethereum_test_specs/tests/test_expect.py b/ethereum_test_specs/tests/test_expect.py index 9f2b00acaf..0009064fc1 100644 --- a/ethereum_test_specs/tests/test_expect.py +++ b/ethereum_test_specs/tests/test_expect.py @@ -118,7 +118,10 @@ def state_test( # noqa: D103 indirect=["pre", "post"], ) def test_post_storage_value_mismatch(expected_exception, state_test, default_t8n, fork): - """Test post state `Account.storage` exceptions during state test fixture generation.""" + """ + Test post state `Account.storage` exceptions during state test fixture + generation. + """ with pytest.raises(Storage.KeyValueMismatchError) as e_info: state_test.generate(t8n=default_t8n, fork=fork, fixture_format=StateFixture) assert e_info.value == expected_exception @@ -136,8 +139,8 @@ def test_post_storage_value_mismatch(expected_exception, state_test, default_t8n ) def test_post_nonce_value_mismatch(pre: Alloc, post: Alloc, state_test, default_t8n, fork): """ - Test post state `Account.nonce` verification and exceptions during state test - fixture generation. + Test post state `Account.nonce` verification and exceptions during state + test fixture generation. """ pre_account = pre[ADDRESS_UNDER_TEST] post_account = post[ADDRESS_UNDER_TEST] @@ -167,8 +170,8 @@ def test_post_nonce_value_mismatch(pre: Alloc, post: Alloc, state_test, default_ ) def test_post_code_value_mismatch(pre: Alloc, post: Alloc, state_test, default_t8n, fork): """ - Test post state `Account.code` verification and exceptions during state test - fixture generation. + Test post state `Account.code` verification and exceptions during state + test fixture generation. """ pre_account = pre[ADDRESS_UNDER_TEST] post_account = post[ADDRESS_UNDER_TEST] @@ -198,8 +201,8 @@ def test_post_code_value_mismatch(pre: Alloc, post: Alloc, state_test, default_t ) def test_post_balance_value_mismatch(pre: Alloc, post: Alloc, state_test, default_t8n, fork): """ - Test post state `Account.balance` verification and exceptions during state test - fixture generation. + Test post state `Account.balance` verification and exceptions during state + test fixture generation. """ pre_account = pre[ADDRESS_UNDER_TEST] post_account = post[ADDRESS_UNDER_TEST] @@ -332,8 +335,8 @@ def test_transaction_expectation( fixture_format: FixtureFormat, ): """ - Test a transaction that has an unexpected error, expected error, or expected a specific - value in its receipt. + Test a transaction that has an unexpected error, expected error, or + expected a specific value in its receipt. """ if ( exception_type == ExecutionExceptionMismatchError diff --git a/ethereum_test_specs/tests/test_fixtures.py b/ethereum_test_specs/tests/test_fixtures.py index 665b37b067..45afb3864c 100644 --- a/ethereum_test_specs/tests/test_fixtures.py +++ b/ethereum_test_specs/tests/test_fixtures.py @@ -42,8 +42,8 @@ def fixture_hash(fork: Fork) -> bytes: def test_check_helper_fixtures(): """ Test that the framework's pydantic models serialization and deserialization - work correctly and that they are compatible with the helper fixtures defined - in ./fixtures/ by using the check_fixtures.py script. + work correctly and that they are compatible with the helper fixtures + defined in ./fixtures/ by using the check_fixtures.py script. """ runner = CliRunner() args = [ diff --git a/ethereum_test_specs/transaction.py b/ethereum_test_specs/transaction.py index 0dbf927201..0511891e57 100644 --- a/ethereum_test_specs/transaction.py +++ b/ethereum_test_specs/transaction.py @@ -23,7 +23,9 @@ class TransactionTest(BaseTest): - """Filler type that tests the transaction over the period of a single block.""" + """ + Filler type that tests the transaction over the period of a single block. + """ tx: Transaction pre: Alloc | None = None diff --git a/ethereum_test_tools/tests/test_code.py b/ethereum_test_tools/tests/test_code.py index 40d4782142..37040cfbb2 100644 --- a/ethereum_test_tools/tests/test_code.py +++ b/ethereum_test_tools/tests/test_code.py @@ -185,7 +185,9 @@ def test_initcode(initcode: Initcode, bytecode: bytes): # noqa: D103 ], ) def test_opcodes_if(conditional_bytecode: bytes, expected: bytes): - """Test that the if opcode macro is transformed into bytecode as expected.""" + """ + Test that the if opcode macro is transformed into bytecode as expected. + """ assert bytes(conditional_bytecode) == expected @@ -514,7 +516,9 @@ def test_opcodes_if(conditional_bytecode: bytes, expected: bytes): def test_switch( tx_data: bytes, switch_bytecode: bytes, expected_storage: Mapping, default_t8n: TransitionTool ): - """Test that the switch opcode macro gets executed as using the t8n tool.""" + """ + Test that the switch opcode macro gets executed as using the t8n tool. + """ code_address = Address(0x1000) pre = Alloc( { diff --git a/ethereum_test_tools/tools_code/generators.py b/ethereum_test_tools/tools_code/generators.py index 7af682ab6c..350eb9b0f3 100644 --- a/ethereum_test_tools/tools_code/generators.py +++ b/ethereum_test_tools/tools_code/generators.py @@ -18,12 +18,11 @@ class Initcode(Bytecode): The execution gas cost of the initcode is calculated, and also the deployment gas costs for the deployed code. - The initcode can be padded to a certain length if necessary, which - does not affect the deployed code. + The initcode can be padded to a certain length if necessary, which does not + affect the deployed code. - Other costs such as the CREATE2 hashing costs or the initcode_word_cost - of EIP-3860 are *not* taken into account by any of these calculated - costs. + Other costs such as the CREATE2 hashing costs or the initcode_word_cost of + EIP-3860 are *not* taken into account by any of these calculated costs. """ deploy_code: SupportsBytes | Bytes @@ -131,8 +130,8 @@ class CodeGasMeasure(Bytecode): """ Helper class used to generate bytecode that measures gas usage of a bytecode, taking into account and subtracting any extra overhead gas costs - required to execute. - By default, the result gas calculation is saved to storage key 0. + required to execute. By default, the result gas calculation is saved to + storage key 0. """ code: Bytecode @@ -199,8 +198,8 @@ def __new__( ): """ Assemble the conditional bytecode by generating the necessary jump and - jumpdest opcodes surrounding the condition and the two possible execution - paths. + jumpdest opcodes surrounding the condition and the two possible + execution paths. In the future, PC usage should be replaced by using RJUMP and RJUMPI """ @@ -213,15 +212,16 @@ def __new__( # First we append a jumpdest to the start of the true branch if_true = Op.JUMPDEST + if_true - # Then we append the unconditional jump to the end of the false branch, used to skip - # the true branch + # Then we append the unconditional jump to the end of the false + # branch, used to skip the true branch if_false += Op.JUMP(Op.ADD(Op.PC, len(if_true) + 3)) - # Then we need to do the conditional jump by skipping the false branch + # Then we need to do the conditional jump by skipping the false + # branch condition = Op.JUMPI(Op.ADD(Op.PC, len(if_false) + 3), condition) - # Finally we append the condition, false and true branches, plus the jumpdest at the - # very end + # Finally we append the condition, false and true branches, plus + # the jumpdest at the very end bytecode = condition + if_false + if_true + Op.JUMPDEST elif evm_code_type == EVMCodeType.EOF_V1: @@ -284,8 +284,8 @@ def is_terminating(self) -> bool: class CalldataCase(Case): """ - Small helper class to represent a single case whose condition depends - on the value of the contract's calldata in a Switch case statement. + Small helper class to represent a single case whose condition depends on + the value of the contract's calldata in a Switch case statement. By default the calldata is read from position zero, but this can be overridden using `position`. @@ -305,12 +305,14 @@ class Switch(Bytecode): Helper class used to generate switch-case expressions in EVM bytecode. Switch-case behavior: - - If no condition is met in the list of BytecodeCases conditions, - the `default_action` bytecode is executed. - - If multiple conditions are met, the action from the first valid - condition is the only one executed. - - There is no fall through; it is not possible to execute multiple - actions. + - If no condition is met in the list of BytecodeCases + conditions, the `default_action` bytecode is executed. + + - If multiple conditions are met, the action from the first valid + condition is the only one executed. + + - There is no fall through; it is not possible to execute + multiple actions. """ default_action: Bytecode | Op | None @@ -338,55 +340,57 @@ def __new__( evm_code_type: EVMCodeType = EVMCodeType.LEGACY, ): """ - Assemble the bytecode by looping over the list of cases and adding - the necessary [R]JUMPI and JUMPDEST opcodes in order to replicate + Assemble the bytecode by looping over the list of cases and adding the + necessary [R]JUMPI and JUMPDEST opcodes in order to replicate switch-case behavior. """ - # The length required to jump over subsequent actions to the final JUMPDEST at the end - # of the switch-case block: - # - add 6 per case for the length of the JUMPDEST and JUMP(ADD(PC, action_jump_length)) - # bytecode - # - add 3 to the total to account for this action's JUMP; the PC within the call - # requires a "correction" of 3. + # The length required to jump over subsequent actions to the final + # JUMPDEST at the end of the switch-case block: + # - add 6 per case for the length of the JUMPDEST and + # JUMP(ADD(PC, action_jump_length)) bytecode + # + # - add 3 to the total to account for this action's JUMP; + # the PC within the call requires a "correction" of 3. bytecode = Bytecode() - # All conditions get prepended to this bytecode; if none are met, we reach the default + # All conditions get prepended to this bytecode; if none are met, we + # reach the default if evm_code_type == EVMCodeType.LEGACY: action_jump_length = sum(len(case.action) + 6 for case in cases) + 3 bytecode = default_action + Op.JUMP(Op.ADD(Op.PC, action_jump_length)) - # The length required to jump over the default action and its JUMP bytecode + # The length required to jump over the default action and its JUMP + # bytecode condition_jump_length = len(bytecode) + 3 elif evm_code_type == EVMCodeType.EOF_V1: action_jump_length = sum( len(case.action) + (len(Op.RJUMP[0]) if not case.is_terminating else 0) for case in cases - # On not terminating cases, we need to add 3 bytes for the RJUMP + # On not terminating cases, we need to add 3 bytes for the + # RJUMP ) bytecode = default_action + Op.RJUMP[action_jump_length] - # The length required to jump over the default action and its JUMP bytecode + # The length required to jump over the default action and its JUMP + # bytecode condition_jump_length = len(bytecode) - # Reversed: first case in the list has priority; it will become the outer-most onion layer. - # We build up layers around the default_action, after 1 iteration of the loop, a simplified - # representation of the bytecode is: + # Reversed: first case in the list has priority; it will become the + # outer-most onion layer. We build up layers around the default_action, + # after 1 iteration of the loop, a simplified representation of the + # bytecode is: # - # JUMPI(case[n-1].condition) - # + default_action + JUMP() - # + JUMPDEST + case[n-1].action + JUMP() + # JUMPI(case[n-1].condition) + # + default_action + JUMP() + # + JUMPDEST + case[n-1].action + JUMP() # # and after n=len(cases) iterations: # - # JUMPI(case[0].condition) - # + JUMPI(case[1].condition) - # ... - # + JUMPI(case[n-1].condition) - # + default_action + JUMP() - # + JUMPDEST + case[n-1].action + JUMP() - # + ... - # + JUMPDEST + case[1].action + JUMP() - # + JUMPDEST + case[0].action + JUMP() - # + # JUMPI(case[0].condition) + # + JUMPI(case[1].condition) + # ... + # + JUMPI(case[n-1].condition) + default_action + JUMP() + JUMPDEST + + # case[n-1].action + JUMP() + ... + JUMPDEST + case[1].action + JUMP() + # + JUMPDEST + case[0].action + JUMP() for case in reversed(cases): action = case.action if evm_code_type == EVMCodeType.LEGACY: diff --git a/ethereum_test_tools/utility/generators.py b/ethereum_test_tools/utility/generators.py index 95c9094e91..f155cb3ba4 100644 --- a/ethereum_test_tools/utility/generators.py +++ b/ethereum_test_tools/utility/generators.py @@ -43,7 +43,10 @@ def param(self): class ContractAddressHasBalance(StrEnum): - """Represents whether the target deployment test has a balance before deployment.""" + """ + Represents whether the target deployment test has a balance before + deployment. + """ ZERO_BALANCE = "zero_balance" NONZERO_BALANCE = "nonzero_balance" @@ -51,8 +54,8 @@ class ContractAddressHasBalance(StrEnum): class SystemContractDeployTestFunction(Protocol): """ - Represents a function to be decorated with the `generate_system_contract_deploy_test` - decorator. + Represents a function to be decorated with the + `generate_system_contract_deploy_test` decorator. """ def __call__( @@ -64,19 +67,21 @@ def __call__( test_type: DeploymentTestType, ) -> Generator[Block, None, None]: """ - Args: - fork (Fork): The fork to test. - pre (Alloc): The pre state of the blockchain. - post (Alloc): The post state of the blockchain. - test_type (DeploymentTestType): The type of deployment test currently being filled. + Arguments: + fork (Fork): The fork to test. + pre (Alloc): The pre state of the blockchain. + post (Alloc): The post state of the blockchain. + test_type(DeploymentTestType): The type of deployment test + currently being filled. Yields: - Block: To add after the block where the contract was deployed (e.g. can contain extra - transactions to execute after the system contract has been deployed, and/or a header - object to verify that the headers are correct). + Block: To add after the block where the contract was deployed + (e.g. can contain extra transactions to execute after + the system contract has been deployed, and/or a header + object to verify that the headers are correct). """ - ... + pass def generate_system_contract_deploy_test( @@ -92,27 +97,44 @@ def generate_system_contract_deploy_test( Generates following test cases: - | before/after fork | fail on | invalid block | - | | empty block | | - --------------------------------------|-------------------|-------------|---------------| - `deploy_before_fork-nonzero_balance` | before | False | False | - `deploy_before_fork-zero_balance` | before | True | False | - `deploy_on_fork_block-nonzero_balance`| on fork block | False | False | - `deploy_on_fork_block-zero_balance` | on fork block | True | False | - `deploy_after_fork-nonzero_balance` | after | False | False | - `deploy_after_fork-zero_balance` | after | True | True | - - The `has balance` parametrization does not have an effect on the expectation of the test. - - Args: - fork (Fork): The fork to test. - tx_json_path (Path): Path to the JSON file with the transaction to deploy the system - contract. - Providing a JSON file is useful to copy-paste the transaction from the EIP. - expected_deploy_address (Address): The expected address of the deployed contract. - fail_on_empty_code (bool): If True, the test is expected to fail on empty code. - expected_system_contract_storage (Dict | None): The expected storage of the system - contract. + | before/after fork | fail on | invalid block | + empty block | | + --------------------|-------------------|--------------|----------------| + `deploy_before_fork-| before | False | False | + nonzero_balance` + + `deploy_before_fork-| before | True | False | + zero_balance` + + `deploy_on_fork_ | on fork block | False | False | + block-nonzero_ + balance` + + `deploy_on_fork_ | on fork block | True | False | + block-zero_balance` + + `deploy_after_fork | after | False | False | + -nonzero_balance` + + `deploy_after_fork | after | True | True | + -zero_balance` + + + The `has balance` parametrization does not have an effect on the + expectation of the test. + + Arguments: + fork (Fork): The fork to test. + tx_json_path (Path): Path to the JSON file with the transaction to + deploy the system contract. Providing a JSON + file is useful to copy-paste the transaction + from the EIP. + expected_deploy_address (Address): The expected address of the deployed + contract. + fail_on_empty_code (bool): If True, the test is expected to fail + on empty code. + expected_system_contract_storage (Dict | None): The expected storage of + the system contract. """ with open(tx_json_path, mode="r") as f: @@ -213,7 +235,8 @@ def wrapper( ) balance = 1 if has_balance == ContractAddressHasBalance.NONZERO_BALANCE else 0 pre[expected_deploy_address] = Account( - code=b"", # Remove the code that is automatically allocated on the fork + code=b"", # Remove the code that is automatically allocated on + # the fork nonce=0, balance=balance, ) @@ -227,7 +250,8 @@ def wrapper( fork_pre_allocation = fork.pre_allocation_blockchain() assert expected_deploy_address_int in fork_pre_allocation expected_code = fork_pre_allocation[expected_deploy_address_int]["code"] - # Note: balance check is omitted; it may be modified by the underlying, decorated test + # Note: balance check is omitted; it may be modified by the + # underlying, decorated test account_kwargs = { "code": expected_code, "nonce": 1, @@ -240,8 +264,8 @@ def wrapper( nonce=1, ) - # Extra blocks (if any) returned by the decorated function to add after the - # contract is deployed. + # Extra blocks (if any) returned by the decorated function to add + # after the contract is deployed. if test_type != DeploymentTestType.DEPLOY_AFTER_FORK or not fail_on_empty_code: # Only fill more blocks if the deploy block does not fail. blocks += list(func(fork=fork, pre=pre, post=post, test_type=test_type)) @@ -265,14 +289,15 @@ def generate_system_contract_error_test( max_gas_limit: int, ): """ - Generate a test that verifies the correct behavior when a system contract fails execution. + Generate a test that verifies the correct behavior when a system contract + fails execution. Parametrizations required: - - system_contract (Address): The address of the system contract to deploy. - - valid_from (Fork): The fork from which the test is valid. + - system_contract (Address): The address of the system contract to deploy. + - valid_from (Fork): The fork from which the test is valid. - Args: - max_gas_limit (int): The maximum gas limit for the system transaction. + Arguments: + max_gas_limit (int): The maximum gas limit for the system transaction. """ @@ -288,25 +313,27 @@ def wrapper( ): modified_system_contract_code = Bytecode() - # Depending on the test case, we need to modify the system contract code accordingly. + # Depending on the test case, we need to modify the system contract + # code accordingly. if ( test_type == SystemContractTestType.GAS_LIMIT or test_type == SystemContractTestType.OUT_OF_GAS_ERROR ): # Run code so that it reaches the gas limit. gas_costs = fork.gas_costs() - # The code works by storing N values to storage, and N is calculated based on the - # gas costs for the given fork. - # This code will only work once, so if the system contract is re-executed - # in a subsequent block, it will consume less gas. + # The code works by storing N values to storage, and N is + # calculated based on the gas costs for the given fork. This + # code will only work once, so if the system contract is re- + # executed in a subsequent block, it will consume less gas. gas_used_per_storage = ( gas_costs.G_STORAGE_SET + gas_costs.G_COLD_SLOAD + (gas_costs.G_VERY_LOW * 2) ) modified_system_contract_code += sum( Op.SSTORE(i, 1) for i in range(max_gas_limit // gas_used_per_storage) ) - # If the gas limit is not divisible by the gas used per storage, we need to add - # some NO-OP (JUMPDEST) to the code that each consume 1 gas. + # If the gas limit is not divisible by the gas used per + # storage, we need to add some NO-OP (JUMPDEST) to the code + # that each consume 1 gas. assert gas_costs.G_JUMPDEST == 1, ( f"JUMPDEST gas cost should be 1, but got {gas_costs.G_JUMPDEST}. " "Generator `generate_system_contract_error_test` needs to be updated." @@ -316,8 +343,9 @@ def wrapper( ) if test_type == SystemContractTestType.OUT_OF_GAS_ERROR: - # If the test type is OUT_OF_GAS_ERROR, we need to add a JUMPDEST to the code - # to ensure that we go over the limit by one gas. + # If the test type is OUT_OF_GAS_ERROR, we need to add a + # JUMPDEST to the code to ensure that we go over the limit + # by one gas. modified_system_contract_code += Op.JUMPDEST modified_system_contract_code += Op.STOP elif test_type == SystemContractTestType.REVERT_ERROR: @@ -335,7 +363,8 @@ def wrapper( balance=0, ) - # Simple test transaction to verify the block failed to modify the state. + # Simple test transaction to verify the block failed to modify the + # state. value_receiver = pre.fund_eoa(amount=0) test_tx = Transaction( to=value_receiver, diff --git a/ethereum_test_tools/utility/pytest.py b/ethereum_test_tools/utility/pytest.py index 4e01a6cd4a..ca93f55e09 100644 --- a/ethereum_test_tools/utility/pytest.py +++ b/ethereum_test_tools/utility/pytest.py @@ -8,8 +8,8 @@ class UnknownParameterInCasesError(Exception): """ - Exception raised when a test case contains parameters - that are not present in the defaults. + Exception raised when a test case contains parameters that are not present + in the defaults. """ def __init__(self) -> None: @@ -34,66 +34,76 @@ def extend_with_defaults( The function returns a dictionary that can be directly unpacked and passed to the `@pytest.mark.parametrize` decorator. - Args: - defaults (Dict[str, Any]): A dictionary of default parameter names and - their values. These values will be added to each case unless the case - already defines a value for each parameter. - cases (List[ParameterSet]): A list of `pytest.param` objects representing - different test cases. Its first argument must be a dictionary defining - parameter names and values. - parametrize_kwargs (Any): Additional keyword arguments to be passed to - `@pytest.mark.parametrize`. These arguments are not modified by this - function and are passed through unchanged. + Arguments: + defaults (Dict[str, Any]): A dictionary of default parameter names + and their values. These values will be added + to each case unless the case already defines + a value for each parameter. + cases (List[ParameterSet]): A list of `pytest.param` objects + representing different test cases. + Its first argument must be a dictionary + defining parameter names and values. + parametrize_kwargs (Any): Additional keyword arguments to be passed to + `@pytest.mark.parametrize`. These arguments are + not modified by this function and are passed + through unchanged. Returns: - Dict[str, Any]: A dictionary with the following structure: - `argnames`: A list of parameter names. - `argvalues`: A list of test cases with modified parameter values. - `parametrize_kwargs`: Additional keyword arguments passed through unchanged. + Dict[str, Any]: A dictionary with the following structure: + `argnames`: A list of parameter names. + `argvalues`: A list of test cases with modified parameter values. + `parametrize_kwargs`: Additional keyword arguments passed + through unchanged. Example: - ```python - @pytest.mark.parametrize(**extend_with_defaults( - defaults=dict( - min_value=0, # default minimum value is 0 - max_value=100, # default maximum value is 100 - average=50, # default average value is 50 + ```python + @pytest.mark.parametrize(**extend_with_defaults( + defaults=dict( + min_value=0, # default minimum value is 0 + max_value=100, # default maximum value is 100 + average=50, # default average value is 50 + ), + + cases=[ + pytest.param( + dict(), # use default + values id='default_case', + ), + + pytest.param( + dict(min_value=10), # override with min_value=10 + id='min_value_10', + ), + + pytest.param( + dict(max_value=200), # override with max_value=200 + id='max_value_200', + ), + + pytest.param( + dict(min_value=-10, max_value=50), # override both min_value + # and max_value + id='min_-10_max_50', + ), + + pytest.param( + # all defaults are overridden + dict(min_value=20, max_value=80, average=50), + id="min_20_max_80_avg_50", ), - cases=[ - pytest.param( - dict(), # use default values - id='default_case', - ), - pytest.param( - dict(min_value=10), # override with min_value=10 - id='min_value_10', - ), - pytest.param( - dict(max_value=200), # override with max_value=200 - id='max_value_200', - ), - pytest.param( - dict(min_value=-10, max_value=50), # override both min_value - # and max_value - id='min_-10_max_50', - ), - pytest.param( - dict(min_value=20, max_value=80, average=50), # all defaults - # are overridden - id="min_20_max_80_avg_50", - ), - pytest.param( - dict(min_value=100, max_value=0), # invalid range - id='invalid_range', - marks=pytest.mark.xfail(reason='invalid range'), - ) - ], - )) - def test_range(min_value, max_value, average): - assert min_value <= max_value - assert min_value <= average <= max_value - ``` + + pytest.param( + dict(min_value=100, max_value=0), # invalid range + id='invalid_range', + marks=pytest.mark.xfail(reason='invalid range'), + ) + ], + )) + def test_range(min_value, max_value, average): + assert min_value <= max_value + assert min_value <= average <= max_value + ``` The above test will execute with the following sets of parameters: @@ -103,14 +113,15 @@ def test_range(min_value, max_value, average): "max_value_200": {"min_value": 0, "max_value": 200, "average": 50} "min_-10_max_50": {"min_value": -10, "max_value": 50, "average": 50} "min_20_max_80_avg_50": {"min_value": 20, "max_value": 80, "average": 50} - "invalid_range": {"min_value": 100, "max_value": 0, "average": 50} # expected to fail + # expected to fail + "invalid_range": {"min_value": 100, "max_value": 0, "average": 50} ``` Notes: - - Each case in `cases` must contain exactly one value, which is a dictionary - of parameter values. - - The function performs an in-place update of the `cases` list, so the - original `cases` list is modified. + - Each case in `cases` must contain exactly one value, which is a + dictionary of parameter values. + - The function performs an in-place update of the `cases` list, so + the original `cases` list is modified. """ for i, case in enumerate(cases): @@ -120,7 +131,8 @@ def test_range(min_value, max_value, average): ) if set(case.values[0].keys()) - set(defaults.keys()): raise UnknownParameterInCasesError() - # Overwrite values in defaults if the parameter is present in the test case values + # Overwrite values in defaults if the parameter is present in the test + # case values merged_params = {**defaults, **case.values[0]} # type: ignore cases[i] = pytest.param(*merged_params.values(), id=case.id, marks=case.marks) diff --git a/ethereum_test_tools/utility/tests/test_pytest.py b/ethereum_test_tools/utility/tests/test_pytest.py index f8f242c92f..0db71cd0ea 100644 --- a/ethereum_test_tools/utility/tests/test_pytest.py +++ b/ethereum_test_tools/utility/tests/test_pytest.py @@ -6,7 +6,8 @@ from ethereum_test_tools.utility.pytest import UnknownParameterInCasesError -# TODO: This is from the docstring in extend_with_defaults; should be tested automatically +# TODO: This is from the docstring in extend_with_defaults; should be tested +# automatically @pytest.mark.parametrize( **extend_with_defaults( defaults={ @@ -28,13 +29,13 @@ id="max_value_200", ), pytest.param( - {"min_value": -10, "max_value": 50}, # override both min_value - # and max_value + # override both min_value and max_value + {"min_value": -10, "max_value": 50}, id="min_-10_max_50", ), pytest.param( - {"min_value": 20, "max_value": 80, "average": 50}, # all defaults - # are overridden + # all defaults are overridden + {"min_value": 20, "max_value": 80, "average": 50}, id="min_20_max_80_avg_50", ), pytest.param( diff --git a/ethereum_test_tools/utility/versioning.py b/ethereum_test_tools/utility/versioning.py index 1d0578fd94..58b91bcd1f 100644 --- a/ethereum_test_tools/utility/versioning.py +++ b/ethereum_test_tools/utility/versioning.py @@ -9,10 +9,11 @@ def get_current_commit_hash_or_tag(repo_path=".", shorten_hash=False): """ Get the latest commit tag or commit hash from the repository. - If a tag points to the current commit, return the tag name. - If no tag exists: - - If shorten_hash is True, return the first 8 characters of the commit hash. - - Otherwise, return the full commit hash. + If a tag points to the current commit, return the tag name. If no tag + exists: + - If shorten_hash is True, return the first 8 characters of the + commit hash. + - Otherwise, return the full commit hash. """ try: repo = Repo(repo_path) diff --git a/ethereum_test_types/account_types.py b/ethereum_test_types/account_types.py index 53befb4592..51a17ebe15 100644 --- a/ethereum_test_types/account_types.py +++ b/ethereum_test_types/account_types.py @@ -50,8 +50,8 @@ class State: def set_account(state: State, address: Bytes20, account: Optional[FrontierAccount]) -> None: """ - Set the `Account` object at an address. Setting to `None` deletes - the account (but not its storage, see `destroy_account()`). + Set the `Account` object at an address. Setting to `None` deletes the + account (but not its storage, see `destroy_account()`). """ trie_set(state._main_trie, address, account) @@ -93,9 +93,11 @@ def get_storage_root(address: Bytes20) -> Bytes32: class EOA(Address): """ - An Externally Owned Account (EOA) is an account controlled by a private key. + An Externally Owned Account (EOA) is an account controlled by a private + key. - The EOA is defined by its address and (optionally) by its corresponding private key. + The EOA is defined by its address and (optionally) by its corresponding + private key. """ key: Hash | None @@ -354,7 +356,10 @@ def fund_eoa( delegation: Address | Literal["Self"] | None = None, nonce: NumberConvertible | None = None, ) -> EOA: - """Add a previously unused EOA to the pre-alloc with the balance specified by `amount`.""" + """ + Add a previously unused EOA to the pre-alloc with the balance specified + by `amount`. + """ raise NotImplementedError("fund_eoa is not implemented in the base class") def fund_address(self, address: Address, amount: NumberConvertible): @@ -370,7 +375,7 @@ def empty_account(self) -> Address: """ Return a previously unused account guaranteed to be empty. - This ensures the account has zero balance, zero nonce, no code, and no storage. - The account is not a precompile or a system contract. + This ensures the account has zero balance, zero nonce, no code, and no + storage. The account is not a precompile or a system contract. """ raise NotImplementedError("empty_account is not implemented in the base class") diff --git a/ethereum_test_types/blob_types.py b/ethereum_test_types/blob_types.py index 3adc860c86..fa2cc59610 100644 --- a/ethereum_test_types/blob_types.py +++ b/ethereum_test_types/blob_types.py @@ -50,7 +50,8 @@ class Blob(CamelModel): data: Bytes commitment: Bytes proof: List[Bytes] | Bytes # Bytes < Osaka, List[Bytes] >= Osaka - cells: List[Bytes] | None # None (in json: null) < Osaka, List[Bytes] >= Osaka + # None (in json: null) < Osaka, List[Bytes] >= Osaka + cells: List[Bytes] | None versioned_hash: Hash name: str @@ -72,13 +73,18 @@ def trusted_setup(cls): @staticmethod def get_filename(fork: Fork, seed: int) -> str: - """Return filename this blob would have as string (with .json extension).""" + """ + Return filename this blob would have as string (with .json extension). + """ amount_cell_proofs: int = cast(int, fork.get_blob_constant("AMOUNT_CELL_PROOFS")) return "blob_" + str(seed) + "_cell_proofs_" + str(amount_cell_proofs) + ".json" @staticmethod def get_filepath(fork: Fork, seed: int): - """Return the Path to the blob that would be created with these parameters.""" + """ + Return the Path to the blob that would be created with these + parameters. + """ # determine amount of cell proofs for this fork (0 or 128) would_be_filename: str = Blob.get_filename(fork, seed) @@ -87,7 +93,10 @@ def get_filepath(fork: Fork, seed: int): @staticmethod def from_fork(fork: Fork, seed: int = 0, timestamp: int = 0) -> "Blob": - """Construct Blob instances. Fork logic is encapsulated within nested functions.""" + """ + Construct Blob instances. Fork logic is encapsulated within nested + functions. + """ def generate_blob_data(rng_seed: int = 0) -> Bytes: """Calculate blob data deterministically via provided seed.""" @@ -139,12 +148,16 @@ def get_commitment(data: Bytes) -> Bytes: return commitment def get_proof(fork: Fork, data: Bytes) -> List[Bytes] | Bytes: - # determine whether this fork is = osaka by looking at amount of cell_proofs + # determine whether this fork is = osaka by looking at + # amount of cell_proofs amount_cell_proofs = fork.get_blob_constant("AMOUNT_CELL_PROOFS") # cancun, prague if amount_cell_proofs == 0: - z = 2 # 2 is one of many possible valid field elements z (https://github.com/ethereum/consensus-specs/blob/ad884507f7a1d5962cd3dfb5f7b3e41aab728c55/tests/core/pyspec/eth2spec/test/utils/kzg_tests.py#L58-L66) + z = 2 # 2 is one of many possible valid field elements z + # https://github.com/ethereum/consensus-specs/blob/ad884507f + # 7a1d5962cd3dfb5f7b3e41aab728c55/tests/core/pyspec/eth2spec/ + # test/utils/kzg_tests.py#L58-L66) z_valid_size: bytes = z.to_bytes( cast(int, fork.get_blob_constant("BYTES_PER_FIELD_ELEMENT")), byteorder="big" ) @@ -164,7 +177,8 @@ def get_proof(fork: Fork, data: Bytes) -> List[Bytes] | Bytes: ) def get_cells(fork: Fork, data: Bytes) -> List[Bytes] | None: - # determine whether this fork is = osaka by looking at amount of cell_proofs + # determine whether this fork is = osaka by looking at + # amount of cell_proofs amount_cell_proofs = fork.get_blob_constant("AMOUNT_CELL_PROOFS") # cancun, prague @@ -189,8 +203,8 @@ def get_cells(fork: Fork, data: Bytes) -> List[Bytes] | None: parents=True, exist_ok=True ) # create all necessary dirs on the way - # handle transition forks - # (blob related constants are needed and only available for normal forks) + # handle transition forks (blob related constants are needed and only + # available for normal forks) fork = fork.fork_at(timestamp=timestamp) # if this blob already exists then load from file. use lock @@ -224,7 +238,8 @@ def get_cells(fork: Fork, data: Bytes) -> List[Bytes] | None: seed=seed, timestamp=timestamp, ) - # for most effective caching temporarily persist every blob that is created in cache + # for most effective caching temporarily persist every blob that is + # created in cache blob.write_to_file() return blob @@ -234,7 +249,8 @@ def from_file(file_name: str) -> "Blob": """ Read a .json file and reconstruct object it represents. - You can load a blob only via its filename (with or without .json extension). + You can load a blob only via its filename (with or without .json + extension). """ # ensure filename was passed assert file_name.startswith("blob_"), ( @@ -272,11 +288,15 @@ def write_to_file(self): if output_location.exists(): logger.debug(f"Blob {output_location} already exists. It will be overwritten.") - with open(output_location, "w", encoding="utf-8") as f: # overwrite existing + # overwrite existing + with open(output_location, "w", encoding="utf-8") as f: f.write(json_str) def verify_cell_kzg_proof_batch(self, cell_indices: list) -> bool: - """Check whether all cell proofs are valid and returns True only if that is the case.""" + """ + Check whether all cell proofs are valid and returns True only if that + is the case. + """ amount_cell_proofs: int = cast(int, self.fork.get_blob_constant("AMOUNT_CELL_PROOFS")) assert amount_cell_proofs > 0, ( @@ -303,12 +323,14 @@ def delete_cells_then_recover_them(self, deletion_indices: list[int]): """ Simulate the cell recovery process in user-specified scenario. - Note: Requirement for successful reconstruction is having at least N of the 2N cells. + Note: Requirement for successful reconstruction is having at least N of + the 2N cells. - Theoretical Usage: You pass a cell list with to 128 elements to this function - along with a list of deletion indices. These cells will be deleted and then - the ckzg recovery mechanism is used to repair the missing cells. - If no assertion is triggered the reconstruction was successful. + Theoretical Usage: You pass a cell list with to 128 elements to this + function along with a list of deletion indices. These cells will be + deleted and then the ckzg recovery mechanism is used to repair the + missing cells. If no assertion is triggered the reconstruction was + successful. """ amount_cell_proofs: int = cast(int, self.fork.get_blob_constant("AMOUNT_CELL_PROOFS")) @@ -370,7 +392,8 @@ class ProofCorruptionMode(Enum): """ Define what the proof corruption modes do. - For Osaka and later each Bytes object in the list is manipulated this way. + For Osaka and later each Bytes object in the list is manipulated this + way. """ CORRUPT_FIRST_BYTE = 1 # corrupts a single byte (index 0) @@ -382,7 +405,9 @@ def corrupt_proof(self, mode: ProofCorruptionMode): """Corrupt the proof field, supports different corruption modes.""" def corrupt_byte(b: bytes) -> Bytes: - """Bit-flip all bits of provided byte using XOR to guarantee change.""" + """ + Bit-flip all bits of provided byte using XOR to guarantee change. + """ if len(b) != 1: raise ValueError("Input must be a single byte") return Bytes(bytes([b[0] ^ 0xFF])) diff --git a/ethereum_test_types/block_access_list/__init__.py b/ethereum_test_types/block_access_list/__init__.py index 6544bc7108..03cad90aae 100644 --- a/ethereum_test_types/block_access_list/__init__.py +++ b/ethereum_test_types/block_access_list/__init__.py @@ -1,8 +1,9 @@ """ Block Access List (BAL) models for EIP-7928. -Following the established pattern in the codebase (AccessList, AuthorizationTuple), -these are simple data classes that can be composed together. +Following the established pattern in the codebase (AccessList, +AuthorizationTuple), these are simple data classes that can be composed +together. """ from .account_absent_values import BalAccountAbsentValues diff --git a/ethereum_test_types/block_access_list/account_absent_values.py b/ethereum_test_types/block_access_list/account_absent_values.py index 7bf3fd2213..c0fea606a9 100644 --- a/ethereum_test_types/block_access_list/account_absent_values.py +++ b/ethereum_test_types/block_access_list/account_absent_values.py @@ -1,10 +1,11 @@ """ BalAccountAbsentValues class for BAL testing. -This module provides a unified class for specifying explicit absent values in Block Access Lists. -This class uses the same change classes as BalAccountChanges to specify specific values that -should NOT exist in the BAL. For checking complete absence, use BalAccountExpectation -with empty lists instead. +This module provides a unified class for specifying explicit absent values +in Block Access Lists. This class uses the same change classes as +BalAccountChanges to specify specific values that should NOT exist in the BAL. +For checking complete absence, use BalAccountExpectation with empty lists +instead. """ from typing import List @@ -31,18 +32,19 @@ class BalAccountAbsentValues(CamelModel): """ - Represents explicit absent value expectations for a specific account in a block. + Represents explicit absent value expectations for a specific account + in a block. - This class specifies specific changes that should NOT exist in the BAL for a - given account. + This class specifies specific changes that should NOT exist in the BAL + for a given account. - IMPORTANT: This class is for checking that specific values are absent, NOT for - checking that entire categories are empty. For complete absence checks - (e.g., "no nonce changes at all"), use BalAccountExpectation with empty lists - instead. + IMPORTANT: This class is for checking that specific values are absent, + NOT for checking that entire categories are empty. For complete + absence checks (e.g., "no nonce changes at all"), use + BalAccountExpectation with empty lists instead. - The validation works by checking that none of the specified explicit changes - exist in the actual BAL. + The validation works by checking that none of the specified + explicit changes exist in the actual BAL. Example: # Forbid specific nonce change at tx 1 with post_nonce=5, and specific @@ -156,8 +158,8 @@ def _validate_forbidden_changes( def validate_against(self, account: BalAccountChange) -> None: """ - Validate that the account does not contain the forbidden changes specified in - this object. + Validate that the account does not contain the forbidden changes + specified in this object. Args: account: The BalAccountChange to validate against diff --git a/ethereum_test_types/block_access_list/expectations.py b/ethereum_test_types/block_access_list/expectations.py index ffa213bd51..8bcdeba538 100644 --- a/ethereum_test_types/block_access_list/expectations.py +++ b/ethereum_test_types/block_access_list/expectations.py @@ -1,7 +1,8 @@ """ Block Access List expectation classes for test validation. -This module contains classes for defining and validating expected BAL values in tests. +This module contains classes for defining and validating expected +BAL values in tests. """ from typing import Any, Callable, Dict, List, Optional @@ -27,7 +28,8 @@ class BalAccountExpectation(CamelModel): """ Represents expected changes to a specific account in a block. - Same as BalAccountChange but without the address field, used for expectations. + Same as BalAccountChange but without the address field, + used for expectations. """ nonce_changes: List[BalNonceChange] = Field( @@ -102,13 +104,16 @@ def modify( Create a new expectation with a modifier for invalid test cases. Args: - modifiers: One or more functions that take and return a BlockAccessList + modifiers: One or more functions that take and return + a BlockAccessList Returns: - A new BlockAccessListExpectation instance with the modifiers applied + A new BlockAccessListExpectation instance with + the modifiers applied Example: - from ethereum_test_types.block_access_list.modifiers import remove_nonces + from ethereum_test_types.block_access_list. + modifiers import remove_nonces expectation = BlockAccessListExpectation( account_expectations={...} @@ -247,7 +252,8 @@ def _compare_account_expectations( expected: BalAccountExpectation, actual: BalAccountChange ) -> None: """ - Compare expected and actual account changes using subsequence validation. + Compare expected and actual account changes using + subsequence validation. Args: expected: The expected account changes @@ -305,7 +311,8 @@ def _compare_account_expectations( expected_slot_changes = expected_slot.slot_changes if not expected_slot_changes: - # Empty expected means any slot_changes are acceptable + # Empty expected means any + # slot_changes are acceptable pass else: # Validate slot_changes as subsequence diff --git a/ethereum_test_types/block_access_list/modifiers.py b/ethereum_test_types/block_access_list/modifiers.py index a9df449d15..d873de9e7d 100644 --- a/ethereum_test_types/block_access_list/modifiers.py +++ b/ethereum_test_types/block_access_list/modifiers.py @@ -1,9 +1,9 @@ """ BAL modifier functions for invalid test cases. -This module provides modifier functions that can be used to modify Block Access Lists -in various ways for testing invalid block scenarios. They are composable and can be -combined to create complex modifications. +This module provides modifier functions that can be used to modify Block Access +Lists in various ways for testing invalid block scenarios. They are composable +and can be combined to create complex modifications. """ from typing import Any, Callable, List, Optional @@ -60,7 +60,10 @@ def _modify_field_value( nested: bool = False, slot: Optional[int] = None, ) -> Callable[[BlockAccessList], BlockAccessList]: - """Abstracted helper to modify a field value for a specific account and transaction.""" + """ + Abstracted helper to modify a field value for a specific account and + transaction. + """ found_address = False def transform(bal: BlockAccessList) -> BlockAccessList: @@ -154,7 +157,9 @@ def modify_nonce( def modify_balance( address: Address, tx_index: int, balance: int ) -> Callable[[BlockAccessList], BlockAccessList]: - """Set an incorrect balance value for a specific account and transaction.""" + """ + Set an incorrect balance value for a specific account and transaction. + """ return _modify_field_value( address, tx_index, "balance_changes", BalBalanceChange, balance, "post_balance" ) @@ -163,7 +168,10 @@ def modify_balance( def modify_storage( address: Address, tx_index: int, slot: int, value: int ) -> Callable[[BlockAccessList], BlockAccessList]: - """Set an incorrect storage value for a specific account, transaction, and slot.""" + """ + Set an incorrect storage value for a specific account, transaction, and + slot. + """ return _modify_field_value( address, tx_index, @@ -227,7 +235,8 @@ def transform(bal: BlockAccessList) -> BlockAccessList: balance_indices[tx2] = True storage_change.tx_index = HexNumber(tx1) - # Note: storage_reads is just a list of StorageKey, no tx_index to swap + # Note: storage_reads is just a list of StorageKey, no tx_index to + # swap # Swap in code changes if new_account.code_changes: diff --git a/ethereum_test_types/block_access_list/t8n.py b/ethereum_test_types/block_access_list/t8n.py index 808ace06f5..848b8d796a 100644 --- a/ethereum_test_types/block_access_list/t8n.py +++ b/ethereum_test_types/block_access_list/t8n.py @@ -16,8 +16,10 @@ class BlockAccessList(EthereumTestRootModel[List[BalAccountChange]]): """ Block Access List for t8n tool communication and fixtures. - This model represents the BAL exactly as defined in EIP-7928 - it is itself a list - of account changes (root model), not a container. Used for: + This model represents the BAL exactly as defined in EIP-7928 + - it is itself a list of account changes (root model), not a container. + + Used for: - Communication with t8n tools - Fixture generation - RLP encoding for hash verification diff --git a/ethereum_test_types/block_types.py b/ethereum_test_types/block_types.py index 268296f49a..8e7977a3b1 100644 --- a/ethereum_test_types/block_types.py +++ b/ethereum_test_types/block_types.py @@ -38,7 +38,10 @@ class EnvironmentDefaults: class WithdrawalGeneric(CamelModel, Generic[NumberBoundTypeVar]): - """Withdrawal generic type, used as a parent class for `Withdrawal` and `FixtureWithdrawal`.""" + """ + Withdrawal generic type, used as a parent class for `Withdrawal` and + `FixtureWithdrawal`. + """ index: NumberBoundTypeVar validator_index: NumberBoundTypeVar @@ -47,8 +50,8 @@ class WithdrawalGeneric(CamelModel, Generic[NumberBoundTypeVar]): def to_serializable_list(self) -> List[Any]: """ - Return list of the withdrawal's attributes in the order they should - be serialized. + Return list of the withdrawal's attributes in the order they should be + serialized. """ return [ Uint(self.index), @@ -98,8 +101,8 @@ class EnvironmentGeneric(CamelModel, Generic[NumberBoundTypeVar]): class Environment(EnvironmentGeneric[ZeroPaddedHexNumber]): """ - Structure used to keep track of the context in which a block - must be executed. + Structure used to keep track of the context in which a block must be + executed. """ blob_gas_used: ZeroPaddedHexNumber | None = Field(None, alias="currentBlobGasUsed") diff --git a/ethereum_test_types/chain_config_types.py b/ethereum_test_types/chain_config_types.py index a8c7b2e484..d9ece600f1 100644 --- a/ethereum_test_types/chain_config_types.py +++ b/ethereum_test_types/chain_config_types.py @@ -9,7 +9,8 @@ class ChainConfigDefaults: """ Default values for the chain configuration. - Can be modified by modules that import this module and want to override the default values. + Can be modified by modules that import this module and want to override the + default values. """ chain_id: int = 1 diff --git a/ethereum_test_types/eof/constants.py b/ethereum_test_types/eof/constants.py index fbc6e88a6d..c047002fa2 100644 --- a/ethereum_test_types/eof/constants.py +++ b/ethereum_test_types/eof/constants.py @@ -1,7 +1,4 @@ -""" -EVM Object Format generic constants. -Applicable to all EOF versions. -""" +"""EVM Object Format generic constants. Applicable to all EOF versions.""" EOF_MAGIC = b"\xef\x00" """ @@ -9,21 +6,15 @@ avoid clashes with three contracts which were deployed on Mainnet. """ EOF_HEADER_TERMINATOR = b"\x00" -""" -Byte that terminates the header of the EOF format. -""" +"""Byte that terminates the header of the EOF format.""" LATEST_EOF_VERSION = 1 -""" -Latest existing EOF version. -""" +"""Latest existing EOF version.""" VERSION_BYTE_LENGTH = 1 -""" -Length of the version byte. -""" +"""Length of the version byte.""" MAX_RUNTIME_STACK_HEIGHT = 1024 """ -Maximum height of the EVM runtime operand stack. -Exceeding this value during execution will result in the stack overflow exception. -This value applies to both legacy EVM and EOF. +Maximum height of the EVM runtime operand stack. Exceeding this value during +execution will result in the stack overflow exception. This value applies to +both legacy EVM and EOF. """ diff --git a/ethereum_test_types/eof/v1/__init__.py b/ethereum_test_types/eof/v1/__init__.py index 0a7385cad9..1dddb0f71c 100644 --- a/ethereum_test_types/eof/v1/__init__.py +++ b/ethereum_test_types/eof/v1/__init__.py @@ -1,4 +1,6 @@ -"""EVM Object Format Version 1 Library to generate bytecode for testing purposes.""" +""" +EVM Object Format Version 1 Library to generate bytecode for testing purposes. +""" from dataclasses import dataclass from enum import Enum, IntEnum, auto @@ -56,7 +58,10 @@ class ContainerKind(Enum): def __get_pydantic_core_schema__( source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Call class constructor without info and appends the serialization schema.""" + """ + Call class constructor without info and appends the serialization + schema. + """ return no_info_plain_validator_function( source_type.from_str, serialization=to_string_ser_schema(), @@ -105,19 +110,18 @@ class Section(CopyValidateModel): data: Bytes = Bytes(b"") """ - Data to be contained by this section. - Can be SupportsBytes, another EOF container or any other abstract data. + Data to be contained by this section. Can be SupportsBytes, another EOF + container or any other abstract data. """ custom_size: int = 0 """ - Custom size value to be used in the header. - If unset, the header is built with length of the data. + Custom size value to be used in the header. If unset, the header is built + with length of the data. """ kind: SectionKind | int """ - Kind of section that is represented by this object. - Can be any `int` outside of the values defined by `SectionKind` - for testing purposes. + Kind of section that is represented by this object. Can be any `int` + outside of the values defined by `SectionKind` for testing purposes. """ force_type_listing: bool = False """ @@ -125,22 +129,16 @@ class Section(CopyValidateModel): container. """ code_inputs: int = 0 - """ - Data stack items consumed by this code section (function) - """ + """Data stack items consumed by this code section (function)""" code_outputs: int = NON_RETURNING_SECTION """ Data stack items produced by or expected at the end of this code section (function) """ max_stack_increase: int | None = None - """ - Maximum operand stack height increase above the code section inputs. - """ + """Maximum operand stack height increase above the code section inputs.""" max_stack_height: int | None = None - """ - Maximum height data stack reaches during execution of code section. - """ + """Maximum height data stack reaches during execution of code section.""" auto_max_stack_height: bool = False """ Whether to automatically compute the best suggestion for the @@ -152,20 +150,17 @@ class Section(CopyValidateModel): code_outputs values for this code section. """ skip_header_listing: bool = False - """ - Skip section from listing in the header - """ + """Skip section from listing in the header""" skip_body_listing: bool = False - """ - Skip section from listing in the body - """ + """Skip section from listing in the body""" skip_types_body_listing: bool = False """ Skip section from listing in the types body (input, output, stack) bytes """ skip_types_header_listing: bool = False """ - Skip section from listing in the types header (not calculating input, output, stack size) + Skip section from listing in the types header (not calculating input, + output, stack size) """ @cached_property @@ -219,27 +214,27 @@ def type_definition(self) -> bytes: def with_max_stack_height(self, max_stack_height) -> "Section": """ - Create copy of the section with `max_stack_height` set to the - specified value. + Create copy of the section with `max_stack_height` set to the specified + value. """ return self.copy(max_stack_height=max_stack_height) def with_auto_max_stack_height(self) -> "Section": - """Create copy of the section with `auto_max_stack_height` set to True.""" + """ + Create copy of the section with `auto_max_stack_height` set to True. + """ return self.copy(auto_max_stack_height=True) def with_auto_code_inputs_outputs(self) -> "Section": """ - Create copy of the section with `auto_code_inputs_outputs` set to - True. + Create copy of the section with `auto_code_inputs_outputs` set to True. """ return self.copy(auto_code_inputs_outputs=True) @staticmethod def list_header(sections: List["Section"]) -> bytes: """ - Create single code header for all code sections contained in - the list. + Create single code header for all code sections contained in the list. """ # Allow 'types section' to use skip_header_listing flag if sections[0].skip_header_listing: @@ -250,7 +245,8 @@ def list_header(sections: List["Section"]) -> bytes: h = sections[0].kind.to_bytes(HEADER_SECTION_KIND_BYTE_LENGTH, "big") - # Count only those sections that are not marked to be skipped for header calculation + # Count only those sections that are not marked to be skipped for + # header calculation header_registered_sections = 0 for cs in sections: if not cs.skip_header_listing: @@ -258,7 +254,8 @@ def list_header(sections: List["Section"]) -> bytes: h += header_registered_sections.to_bytes(HEADER_SECTION_COUNT_BYTE_LENGTH, "big") for cs in sections: - # If section is marked to skip the header calculation, don't make header for it + # If section is marked to skip the header calculation, don't make + # header for it if cs.skip_header_listing: continue size = cs.custom_size if "custom_size" in cs.model_fields_set else len(cs.data) @@ -307,13 +304,9 @@ class Container(CopyValidateModel): """Class that represents an EOF V1 container.""" name: Optional[str] = None - """ - Name of the container - """ + """Name of the container""" sections: List[Section] = Field(default_factory=list) - """ - List of sections in the container - """ + """List of sections in the container""" magic: Bytes = Bytes(EOF_MAGIC) """ Custom magic value used to override the mandatory EOF value for testing @@ -321,59 +314,46 @@ class Container(CopyValidateModel): """ version: Bytes = Bytes(VERSION_NUMBER_BYTES) """ - Custom version value used to override the mandatory EOF V1 value - for testing purposes. + Custom version value used to override the mandatory EOF V1 value for + testing purposes. """ header_terminator: Bytes = Bytes(EOF_HEADER_TERMINATOR) - """ - Bytes used to terminate the header. - """ + """Bytes used to terminate the header.""" extra: Bytes = Bytes(b"") """ - Extra data to be appended at the end of the container, which will - not be considered part of any of the sections, for testing purposes. + Extra data to be appended at the end of the container, which will not be + considered part of any of the sections, for testing purposes. """ auto_type_section: AutoSection = AutoSection.AUTO """ - Automatically generate a `TYPE` section based on the - included `CODE` kind sections. + Automatically generate a `TYPE` section based on the included `CODE` kind + sections. """ auto_data_section: bool = True - """ - Automatically generate a `DATA` section. - """ + """Automatically generate a `DATA` section.""" auto_sort_sections: AutoSection = AutoSection.AUTO """ - Automatically sort sections for the header and body: - Headers: type section first, all code sections, container sections, last - data section(s) - Body: type section first, all code sections, data section(s), last - container sections + Automatically sort sections for the header and body: Headers: type section + first, all code sections, container sections, last data section(s) Body: + type section first, all code sections, data section(s), last container + sections """ skip_join_concurrent_sections_in_header: bool = False - """ - Skip joining concurrent sections in the header (code and container) - """ + """Skip joining concurrent sections in the header (code and container)""" validity_error: EOFExceptionInstanceOrList | str | None = None - """ - Optional error expected for the container. - - TODO: Remove str - """ + """Optional error expected for the container. TODO: Remove str""" kind: ContainerKind = ContainerKind.RUNTIME - """ - Kind type of the container. - """ + """Kind type of the container.""" raw_bytes: Optional[Bytes] = None """ - Optional raw bytes that represent the container. - Used to have a cohesive type among all test cases, even those that do not - resemble a valid EOF V1 container. + Optional raw bytes that represent the container. Used to have a cohesive + type among all test cases, even those that do not resemble a valid EOF V1 + container. """ expected_bytecode: Optional[Bytes] = None """ - Optional raw bytes of the expected constructed bytecode. - This allows confirming that raw EOF and Container() representations are identical. + Optional raw bytes of the expected constructed bytecode. This allows + confirming that raw EOF and Container() representations are identical. """ @cached_property @@ -419,7 +399,8 @@ def bytecode(self) -> bytes: # Add headers if header_sections: - # Join headers of the same kind in a list of lists, only if they are next to each other + # Join headers of the same kind in a list of lists, only if they + # are next to each other concurrent_sections: List[List[Section]] = [[header_sections[0]]] for s in header_sections[1:]: if ( @@ -469,7 +450,9 @@ def Init( # noqa: N802 deploy_container: "Container", initcode_prefix: Optional[Bytecode] = None, ) -> "Container": - """Create simple init container that deploys the specified container.""" + """ + Create simple init container that deploys the specified container. + """ if initcode_prefix is None: initcode_prefix = Bytecode() return cls( @@ -498,8 +481,8 @@ def __len__(self) -> int: def __str__(self) -> str: """ - Return name of the container if available, otherwise the bytecode of the container - as a string. + Return name of the container if available, otherwise the bytecode of + the container as a string. """ if self.name: return self.name @@ -514,13 +497,9 @@ class Initcode(Bytecode): """ name: str = "EOF V1 Initcode" - """ - Name used to identify the initcode. - """ + """Name used to identify the initcode.""" deploy_container: Container - """ - Container to be deployed. - """ + """Container to be deployed.""" @cached_property def init_container(self) -> Container: @@ -539,7 +518,9 @@ def init_container(self) -> Container: @cached_property def bytecode(self) -> bytes: - """Generate an EOF container performs `EOFCREATE` with the specified code.""" + """ + Generate an EOF container performs `EOFCREATE` with the specified code. + """ initcode = Container( sections=[ Section.Code( diff --git a/ethereum_test_types/helpers.py b/ethereum_test_types/helpers.py index 802adfced2..4378dc292b 100644 --- a/ethereum_test_types/helpers.py +++ b/ethereum_test_types/helpers.py @@ -19,8 +19,8 @@ def ceiling_division(a: int, b: int) -> int: """ - Calculate ceil without using floating point. - Used by many of the EVM's formulas. + Calculate ceil without using floating point. Used by many of the EVM's + formulas. """ return -(a // -b) @@ -34,8 +34,8 @@ def compute_create_address( opcode: Op = Op.CREATE, ) -> Address: """ - Compute address of the resulting contract created using a transaction - or the `CREATE` opcode. + Compute address of the resulting contract created using a transaction or + the `CREATE` opcode. """ if opcode == Op.CREATE: if isinstance(address, EOA): @@ -68,7 +68,10 @@ def compute_create2_address( def compute_eofcreate_address( address: FixedSizeBytesConvertible, salt: FixedSizeBytesConvertible ) -> Address: - """Compute address of the resulting contract created using the `EOFCREATE` opcode.""" + """ + Compute address of the resulting contract created using the `EOFCREATE` + opcode. + """ hash_bytes = Bytes(b"\xff" + b"\x00" * 12 + Address(address) + Hash(salt)).keccak256() return Address(hash_bytes[-20:]) @@ -106,13 +109,14 @@ class TestParameterGroup(BaseModel): def __repr__(self): """ - Generate repr string, intended to be used as a test id, based on the class - name and the values of the non-default optional fields. + Generate repr string, intended to be used as a test id, based on the + class name and the values of the non-default optional fields. """ class_name = self.__class__.__name__ field_strings = [ f"{field}_{value}" - # Include the field only if it is not optional or not set to its default value + # Include the field only if it is not optional or not set to its + # default value for field, value in self.model_dump(exclude_defaults=True, exclude_unset=True).items() ] diff --git a/ethereum_test_types/request_types.py b/ethereum_test_types/request_types.py index e56ed23148..d38fd62b5e 100644 --- a/ethereum_test_types/request_types.py +++ b/ethereum_test_types/request_types.py @@ -30,26 +30,18 @@ class DepositRequest(RequestBase, CamelModel): """Deposit Request type.""" pubkey: BLSPublicKey - """ - The public key of the beacon chain validator. - """ + """The public key of the beacon chain validator.""" withdrawal_credentials: Hash - """ - The withdrawal credentials of the beacon chain validator. - """ + """The withdrawal credentials of the beacon chain validator.""" amount: HexNumber - """ - The amount in gwei of the deposit. - """ + """The amount in gwei of the deposit.""" signature: BLSSignature """ - The signature of the deposit using the validator's private key that matches the - `pubkey`. + The signature of the deposit using the validator's private key that matches + the `pubkey`. """ index: HexNumber - """ - The index of the deposit. - """ + """The index of the deposit.""" type: ClassVar[int] = 0 @@ -69,16 +61,16 @@ class WithdrawalRequest(RequestBase, CamelModel): source_address: Address = Address(0) """ - The address of the execution layer account that made the withdrawal request. + The address of the execution layer account that made the withdrawal + request. """ validator_pubkey: BLSPublicKey """ - The current public key of the validator as it currently is in the beacon state. + The current public key of the validator as it currently is in the beacon + state. """ amount: HexNumber - """ - The amount in gwei to be withdrawn on the beacon chain. - """ + """The amount in gwei to be withdrawn on the beacon chain.""" type: ClassVar[int] = 1 @@ -96,15 +88,18 @@ class ConsolidationRequest(RequestBase, CamelModel): source_address: Address = Address(0) """ - The address of the execution layer account that made the consolidation request. + The address of the execution layer account that made the consolidation + request. """ source_pubkey: BLSPublicKey """ - The public key of the source validator as it currently is in the beacon state. + The public key of the source validator as it currently is in the beacon + state. """ target_pubkey: BLSPublicKey """ - The public key of the target validator as it currently is in the beacon state. + The public key of the target validator as it currently is in the beacon + state. """ type: ClassVar[int] = 2 diff --git a/ethereum_test_types/tests/test_blob_types.py b/ethereum_test_types/tests/test_blob_types.py index 4aefc61a91..88cf1501f5 100644 --- a/ethereum_test_types/tests/test_blob_types.py +++ b/ethereum_test_types/tests/test_blob_types.py @@ -24,14 +24,14 @@ def increment_counter(timeout: float = 10): """ Increment counter in file, creating if doesn't exist. - This is needed because we require the unit test 'test_transition_fork_blobs' to run - at the end without having to include another dependency for ordering tests. - That test has to run at the end because it assumes that no json blobs not created - by itself are created while it is running. - - The hardcoded counter value in the test above has to be updated if any new blob_related - unit tests that create json blobs are added in the future. - + This is needed because we require the unit test + 'test_transition_fork_blobs' to run at the end without having to include + another dependency for ordering tests. That test has to run at the end + because it assumes that no json blobs not created by itself are created + while it is running. + + The hardcoded counter value in the test above has to be updated if any new + blob_related unit tests that create json blobs are added in the future. """ file_path = CACHED_BLOBS_DIRECTORY / "blob_unit_test_counter.txt" lock_file = file_path.with_suffix(".lock") @@ -62,7 +62,6 @@ def wait_until_counter_reached(target: int, poll_interval: float = 0.1): try: current_value = int(file_path.read_text().strip()) if current_value == target: - # file_path.unlink() # get rid to effectively reset counter to 0 return current_value elif current_value > target: pytest.fail( @@ -86,8 +85,8 @@ def test_blob_creation_and_writing_and_reading( fork, ): # noqa: F811 """ - Generates blobs for different forks and ensures writing to file - and reading from file works as expected. + Generates blobs for different forks and ensures writing to file and reading + from file works as expected. """ timestamp = 100 b = Blob.from_fork(fork=fork, seed=seed, timestamp=timestamp) @@ -145,15 +144,20 @@ def test_transition_fork_blobs( fork, timestamp, ): - """Generates blobs for transition forks (time 14999 is old fork, time 15000 is new fork).""" - # line below guarantees that this test runs only after the other blob unit tests are done + """ + Generates blobs for transition forks (time 14999 is old fork, time 15000 is + new fork). + """ + # line below guarantees that this test runs only after the other blob unit + # tests are done wait_until_counter_reached(21) clear_blob_cache(CACHED_BLOBS_DIRECTORY) print(f"Original fork: {fork}, Timestamp: {timestamp}") pre_transition_fork = fork.transitions_from() - post_transition_fork_at_15k = fork.transitions_to() # only reached if timestamp >= 15000 + # only reached if timestamp >= 15000 + post_transition_fork_at_15k = fork.transitions_to() if not pre_transition_fork.supports_blobs() and timestamp < 15000: print( @@ -178,6 +182,7 @@ def test_transition_fork_blobs( f"transitioned to {post_transition_fork_at_15k.name()} but is still at {b.fork.name()}" ) - # delete counter at last iteration (otherwise re-running all unit tests will fail) + # delete counter at last iteration (otherwise re-running all unit tests + # will fail) if timestamp == 15_000 and pre_transition_fork == Prague: (CACHED_BLOBS_DIRECTORY / "blob_unit_test_counter.txt").unlink() diff --git a/ethereum_test_types/tests/test_block_access_lists.py b/ethereum_test_types/tests/test_block_access_lists.py index e8a36d7321..0665081072 100644 --- a/ethereum_test_types/tests/test_block_access_lists.py +++ b/ethereum_test_types/tests/test_block_access_lists.py @@ -143,7 +143,8 @@ def test_partial_validation(): account_expectations={ alice: BalAccountExpectation( nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], - # balance_changes and storage_reads not set and won't be validated + # balance_changes and storage_reads not set and won't be + # validated ), } ) @@ -338,8 +339,8 @@ def test_expected_addresses_auto_sorted(): """ Test that expected addresses are automatically sorted before comparison. - The BAL *Expectation address order should not matter for the dict. - We DO, however, validate that the actual BAL (from t8n) is sorted correctly. + The BAL *Expectation address order should not matter for the dict. We DO, + however, validate that the actual BAL (from t8n) is sorted correctly. """ alice = Address(0xA) bob = Address(0xB) @@ -815,7 +816,8 @@ def test_absent_values_with_multiple_tx_indices(): alice: BalAccountExpectation( absent_values=BalAccountAbsentValues( nonce_changes=[ - # wrongly forbid change at txs 1 and 2 (1 exists, so should fail) + # wrongly forbid change at txs 1 and 2 + # (1 exists, so should fail) BalNonceChange(tx_index=1, post_nonce=1), BalNonceChange(tx_index=2, post_nonce=0), ] @@ -961,13 +963,19 @@ def test_bal_account_absent_values_comprehensive(): ], ) def test_bal_account_absent_values_empty_list_validation_raises(field_name, field_value): - """Test that empty lists in BalAccountAbsentValues fields raise appropriate errors.""" + """ + Test that empty lists in BalAccountAbsentValues fields + raise appropriate errors. + """ with pytest.raises(ValueError, match="Empty lists are not allowed"): BalAccountAbsentValues(**{field_name: field_value}) def test_bal_account_absent_values_empty_slot_changes_raises(): - """Test that empty slot_changes in storage_changes raises appropriate error.""" + """ + Test that empty slot_changes in storage_changes + raises appropriate error. + """ with pytest.raises(ValueError, match="Empty lists are not allowed"): BalAccountAbsentValues( storage_changes=[ diff --git a/ethereum_test_types/tests/test_eof_v1.py b/ethereum_test_types/tests/test_eof_v1.py index 21c1b8b196..1c454ab870 100644 --- a/ethereum_test_types/tests/test_eof_v1.py +++ b/ethereum_test_types/tests/test_eof_v1.py @@ -867,7 +867,8 @@ def remove_comments_from_string(input_string): # Find the index of the first '#' character comment_start = line.find("#") - # If a '#' is found, slice up to that point; otherwise, take the whole line + # If a '#' is found, slice up to that point; otherwise, take the whole + # line if comment_start != -1: cleaned_line = line[:comment_start].rstrip() else: diff --git a/ethereum_test_types/tests/test_post_alloc.py b/ethereum_test_types/tests/test_post_alloc.py index c9639b7e54..45111760fc 100644 --- a/ethereum_test_types/tests/test_post_alloc.py +++ b/ethereum_test_types/tests/test_post_alloc.py @@ -10,13 +10,17 @@ @pytest.fixture() def post(request: pytest.FixtureRequest) -> Alloc: - """Post state: Set from the test's indirectly parametrized `post` parameter.""" + """ + Post state: Set from the test's indirectly parametrized `post` parameter. + """ return Alloc.model_validate(request.param) @pytest.fixture() def alloc(request: pytest.FixtureRequest) -> Alloc: - """Alloc state: Set from the test's indirectly parametrized `alloc` parameter.""" + """ + Alloc state: Set from the test's indirectly parametrized `alloc` parameter. + """ return Alloc.model_validate(request.param) diff --git a/ethereum_test_types/transaction_types.py b/ethereum_test_types/transaction_types.py index 4ffe706bb0..ce1117635e 100644 --- a/ethereum_test_types/transaction_types.py +++ b/ethereum_test_types/transaction_types.py @@ -81,7 +81,8 @@ class AuthorizationTupleGeneric(CamelModel, Generic[NumberBoundTypeVar], Signabl def get_rlp_signing_prefix(self) -> bytes: """ - Return a prefix that has to be appended to the serialized signing object. + Return a prefix that has to be appended to the serialized signing + object. By default, an empty string is returned. """ @@ -107,7 +108,10 @@ class AuthorizationTuple(AuthorizationTupleGeneric[HexNumber]): secret_key: Hash | None = None def model_post_init(self, __context: Any) -> None: - """Automatically signs the authorization tuple if a secret key or sender are provided.""" + """ + Automatically signs the authorization tuple if a secret key or sender + are provided. + """ super().model_post_init(__context) self.sign() @@ -198,7 +202,9 @@ class TransactionValidateToAsEmptyString(CamelModel): @model_validator(mode="before") @classmethod def validate_to_as_empty_string(cls, data: Any) -> Any: - """If the `to` field is an empty string, set the model value to None.""" + """ + If the `to` field is an empty string, set the model value to None. + """ if ( isinstance(data, dict) and "to" in data @@ -210,11 +216,16 @@ def validate_to_as_empty_string(cls, data: Any) -> Any: class TransactionFixtureConverter(TransactionValidateToAsEmptyString): - """Handler for serializing and validating the `to` field as an empty string.""" + """ + Handler for serializing and validating the `to` field as an empty string. + """ @model_serializer(mode="wrap", when_used="json-unless-none") def serialize_to_as_empty_string(self, serializer): - """Serialize the `to` field as the empty string if the model value is None.""" + """ + Serialize the `to` field as the empty string if the model value is + None. + """ default = serializer(self) if default is not None and "to" not in default: default["to"] = "" @@ -222,16 +233,18 @@ def serialize_to_as_empty_string(self, serializer): class TransactionTransitionToolConverter(TransactionValidateToAsEmptyString): - """Handler for serializing and validating the `to` field as an empty string.""" + """ + Handler for serializing and validating the `to` field as an empty string. + """ @model_serializer(mode="wrap", when_used="json-unless-none") def serialize_to_as_none(self, serializer): """ Serialize the `to` field as `None` if the model value is None. - This is required as we use `exclude_none=True` when serializing, but the - t8n tool explicitly requires a value of `None` (respectively null), for - if the `to` field should be unset (contract creation). + This is required as we use `exclude_none=True` when serializing, but + the t8n tool explicitly requires a value of `None` (respectively null), + for if the `to` field should be unset (contract creation). """ default = serializer(self) if default is not None and "to" not in default: @@ -250,8 +263,8 @@ class TransactionTestMetadata(CamelModel): def to_json(self) -> str: """ - Convert the transaction metadata into json string for it to be embedded in the - request id. + Convert the transaction metadata into json string for it to be embedded + in the request id. """ return self.model_dump_json(exclude_none=True, by_alias=True) @@ -291,8 +304,8 @@ def __str__(self): class InvalidSignaturePrivateKeyError(Exception): """ - Transaction describes both the signature and private key of - source account. + Transaction describes both the signature and private key of source + account. """ def __str__(self): @@ -522,8 +535,8 @@ def with_signature_and_sender(self, *, keep_secret_key: bool = False) -> "Transa def get_rlp_signing_fields(self) -> List[str]: """ - Return the list of values included in the envelope used for signing depending on - the transaction type. + Return the list of values included in the envelope used for signing + depending on the transaction type. """ field_list: List[str] if self.ty == 6: @@ -611,8 +624,8 @@ def get_rlp_signing_fields(self) -> List[str]: def get_rlp_fields(self) -> List[str]: """ - Return the list of values included in the list used for rlp encoding depending on - the transaction type. + Return the list of values included in the list used for rlp encoding + depending on the transaction type. """ fields = self.get_rlp_signing_fields() if self.ty == 0 and self.protected: @@ -621,8 +634,8 @@ def get_rlp_fields(self) -> List[str]: def get_rlp_prefix(self) -> bytes: """ - Return the transaction type as bytes to be appended at the beginning of the - serialized transaction if type is not 0. + Return the transaction type as bytes to be appended at the beginning of + the serialized transaction if type is not 0. """ if self.ty > 0: return bytes([self.ty]) @@ -630,8 +643,8 @@ def get_rlp_prefix(self) -> bytes: def get_rlp_signing_prefix(self) -> bytes: """ - Return the transaction type as bytes to be appended at the beginning of the - serialized transaction signing envelope if type is not 0. + Return the transaction type as bytes to be appended at the beginning of + the serialized transaction signing envelope if type is not 0. """ if self.ty > 0: return bytes([self.ty]) @@ -650,7 +663,10 @@ def hash(self) -> Hash: @cached_property def serializable_list(self) -> Any: - """Return list of values included in the transaction as a serializable object.""" + """ + Return list of values included in the transaction as a serializable + object. + """ return self.rlp() if self.ty > 0 else self.to_list(signing=False) @staticmethod @@ -663,7 +679,9 @@ def list_root(input_txs: List["Transaction"]) -> Hash: @staticmethod def list_blob_versioned_hashes(input_txs: List["Transaction"]) -> List[Hash]: - """Get list of ordered blob versioned hashes from a list of transactions.""" + """ + Get list of ordered blob versioned hashes from a list of transactions. + """ return [ blob_versioned_hash for tx in input_txs @@ -687,11 +705,10 @@ class NetworkWrappedTransaction(CamelModel, RLPSerializable): Network wrapped transaction as defined in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844#networking). - < Osaka: - rlp([tx_payload_body, blobs, commitments, proofs]) + < Osaka: rlp([tx_payload_body, blobs, commitments, proofs]) - >= Osaka: - rlp([tx_payload_body, wrapper_version, blobs, commitments, cell_proofs]) + >= Osaka: rlp([tx_payload_body, wrapper_version, blobs, commitments, + cell_proofs]) """ tx: Transaction @@ -740,15 +757,18 @@ def cell_proofs(self) -> Sequence[Bytes] | None: def get_rlp_fields(self) -> List[str]: """ - Return an ordered list of field names to be included in RLP serialization. + Return an ordered list of field names to be included in RLP + serialization. Function can be overridden to customize the logic to return the fields. By default, rlp_fields class variable is used. - The list can be nested list up to one extra level to represent nested fields. + The list can be nested list up to one extra level to represent nested + fields. """ - # only put a wrapper_version field for >=osaka (value 1), otherwise omit field + # only put a wrapper_version field for >=osaka (value 1), otherwise + # omit field wrapper = [] if self.wrapper_version is not None: wrapper = ["wrapper_version"] @@ -761,11 +781,11 @@ def get_rlp_fields(self) -> List[str]: if self.cell_proofs is not None: rlp_cell_proofs = ["cell_proofs"] - rlp_fields: List[ - str - ] = [ # structure explained in https://eips.ethereum.org/EIPS/eip-7594#Networking + rlp_fields: List[str] = [ # structure explained in + # https://eips.ethereum.org/EIPS/eip-7594#Networking "tx", # tx_payload_body - *wrapper, # wrapper_version, which is always 1 for osaka (was non-existing before) + *wrapper, # wrapper_version, which is always 1 for osaka (was non- + # existing before) "blobs", # Blob.data "commitments", *rlp_proofs, @@ -782,8 +802,8 @@ def get_rlp_fields(self) -> List[str]: def get_rlp_prefix(self) -> bytes: """ - Return the transaction type as bytes to be appended at the beginning of the - serialized transaction if type is not 0. + Return the transaction type as bytes to be appended at the beginning of + the serialized transaction if type is not 0. """ if self.tx.ty > 0: return bytes([self.tx.ty]) diff --git a/ethereum_test_types/trie.py b/ethereum_test_types/trie.py index 8c97e51956..4d0c7ba312 100644 --- a/ethereum_test_types/trie.py +++ b/ethereum_test_types/trie.py @@ -1,4 +1,6 @@ -"""The state trie is the structure responsible for storing.""" +""" +The state trie is the structure responsible for storing. +""" import copy from dataclasses import dataclass, field @@ -58,17 +60,11 @@ def encode_account(raw_account_data: FrontierAccount, storage_root: Bytes) -> By # note: an empty trie (regardless of whether it is secured) has root: -# -# keccak256(RLP(b'')) -# == -# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # noqa: E501,SC10 -# +# keccak256(RLP(b'')) == +# 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 # also: -# -# keccak256(RLP(())) -# == -# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # noqa: E501,SC10 -# +# keccak256(RLP(())) == +# 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 # which is the sha3Uncles hash in block header with no uncles EMPTY_TRIE_ROOT = Bytes32( bytes.fromhex("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") @@ -137,9 +133,10 @@ class BranchNode: def encode_internal_node(node: Optional[InternalNode]) -> Extended: """ - Encode a Merkle Trie node into its RLP form. The RLP will then be - serialized into a `Bytes` and hashed unless it is less that 32 bytes - when serialized. + Encode a Merkle Trie node into its RLP form. + + The RLP will then be serialized into a `Bytes` and hashed unless it is less + that 32 bytes when serialized. This function also accepts `None`, representing the absence of a node, which is encoded to `b""`. @@ -211,7 +208,6 @@ def trie_set(trie: Trie[K, V], key: K, value: V) -> None: This method deletes the key if `value == trie.default`, because the Merkle Trie represents the default value by omitting it from the trie. - """ if value == trie.default: if key in trie._data: @@ -225,7 +221,6 @@ def trie_get(trie: Trie[K, V], key: K) -> V: Get an item from the Merkle Trie. This method returns `trie.default` if the key is missing. - """ return trie._data.get(key, trie.default) @@ -248,11 +243,10 @@ def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: Highest nibble:: - +---+---+----------+--------+ - | _ | _ | is_leaf | parity | - +---+---+----------+--------+ - 3 2 1 0 - + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 The lowest bit of the nibble encodes the parity of the length of the remaining nibbles -- `0` when even and `1` when odd. The second lowest bit @@ -274,7 +268,9 @@ def nibble_list_to_compact(x: Bytes, is_leaf: bool) -> Bytes: def bytes_to_nibble_list(bytes_: Bytes) -> Bytes: - """Convert a `Bytes` into to a sequence of nibbles (bytes with value < 16).""" + """ + Convert a `Bytes` into to a sequence of nibbles (bytes with value < 16). + """ nibble_list = bytearray(2 * len(bytes_)) for byte_index, byte in enumerate(bytes_): nibble_list[byte_index * 2] = (byte & 0xF0) >> 4 diff --git a/ethereum_test_vm/bytecode.py b/ethereum_test_vm/bytecode.py index 5eea5b0cce..298f80c6e2 100644 --- a/ethereum_test_vm/bytecode.py +++ b/ethereum_test_vm/bytecode.py @@ -16,9 +16,9 @@ class Bytecode: """ Base class to represent EVM bytecode. - Stack calculations are automatically done after an addition operation between two bytecode - objects. The stack height is not guaranteed to be correct, so the user must take this into - consideration. + Stack calculations are automatically done after an addition operation + between two bytecode objects. The stack height is not guaranteed to be + correct, so the user must take this into consideration. Parameters ---------- @@ -63,8 +63,8 @@ def __new__( return instance if isinstance(bytes_or_byte_code_base, Bytecode): - # Required because Enum class calls the base class with the instantiated object as - # parameter. + # Required because Enum class calls the base class with the + # instantiated object as parameter. obj = super().__new__(cls) obj._bytes_ = bytes_or_byte_code_base._bytes_ obj.popped_stack_items = bytes_or_byte_code_base.popped_stack_items @@ -113,8 +113,8 @@ def __eq__(self, other): Allow comparison between Bytecode instances and bytes objects. Raises: - - NotImplementedError: if the comparison is not between an Bytecode - or a bytes object. + - NotImplementedError: if the comparison is not between an + Bytecode or a bytes object. """ if isinstance(other, Bytecode): @@ -142,7 +142,9 @@ def __hash__(self): ) def __add__(self, other: "Bytecode | bytes | int | None") -> "Bytecode": - """Concatenate the bytecode representation with another bytecode object.""" + """ + Concatenate the bytecode representation with another bytecode object. + """ if other is None or (isinstance(other, int) and other == 0): # Edge case for sum() function return self @@ -160,33 +162,40 @@ def __add__(self, other: "Bytecode | bytes | int | None") -> "Bytecode": b_pop, b_push = other.popped_stack_items, other.pushed_stack_items b_min, b_max = other.min_stack_height, other.max_stack_height - # NOTE: "_pop" is understood as the number of elements required by an instruction or - # bytecode to be popped off the stack before it starts returning (pushing). + # NOTE: "_pop" is understood as the number of elements required by an + # instruction or bytecode to be popped off the stack before it starts + # returning (pushing). - # Auxiliary variables representing "stages" of the execution of `c = a + b` bytecode: - # Assume starting point 0 as reference: + # Auxiliary variables representing "stages" of the execution of + # `c = a + b` bytecode: Assume starting point 0 as reference: a_start = 0 - # A (potentially) pops some elements and reaches its "bottom", might be negative: + # A (potentially) pops some elements and reaches its "bottom", might be + # negative: a_bottom = a_start - a_pop - # After this A pushes some elements, then B pops and reaches its "bottom": + # After this A pushes some elements, then B pops and reaches its + # "bottom": b_bottom = a_bottom + a_push - b_pop # C's bottom is either at the bottom of A or B: c_bottom = min(a_bottom, b_bottom) if c_bottom == a_bottom: - # C pops the same as A to reach its bottom, then the rest of A and B are C's "push" + # C pops the same as A to reach its bottom, then the rest of A and + # B are C's "push" c_pop = a_pop c_push = a_push - b_pop + b_push else: - # A and B are C's "pop" to reach its bottom, then pushes the same as B + # A and B are C's "pop" to reach its bottom, then pushes the same + # as B c_pop = a_pop - a_push + b_pop c_push = b_push - # C's minimum required stack is either A's or B's shifted by the net stack balance of A + # C's minimum required stack is either A's or B's shifted by the net + # stack balance of A c_min = max(a_min, b_min + a_pop - a_push) - # C starts from c_min, then reaches max either in the spot where A reached a_max or in the - # spot where B reached b_max, after A had completed. + # C starts from c_min, then reaches max either in the spot where A + # reached a_max or in the spot where B reached b_max, after A had + # completed. c_max = max(c_min + a_max - a_min, c_min - a_pop + a_push + b_max - b_min) return Bytecode( @@ -199,7 +208,9 @@ def __add__(self, other: "Bytecode | bytes | int | None") -> "Bytecode": ) def __radd__(self, other: "Bytecode | int | None") -> "Bytecode": - """Concatenate the opcode byte representation with another bytes object.""" + """ + Concatenate the opcode byte representation with another bytes object. + """ if other is None or (isinstance(other, int) and other == 0): # Edge case for sum() function return self @@ -207,7 +218,9 @@ def __radd__(self, other: "Bytecode | int | None") -> "Bytecode": return other.__add__(self) def __mul__(self, other: int) -> "Bytecode": - """Concatenate another bytes object with the opcode byte representation.""" + """ + Concatenate another bytes object with the opcode byte representation. + """ if other < 0: raise ValueError("Cannot multiply by a negative number") if other == 0: @@ -218,7 +231,10 @@ def __mul__(self, other: int) -> "Bytecode": return output def hex(self) -> str: - """Return the hexadecimal representation of the opcode byte representation.""" + """ + Return the hexadecimal representation of the opcode byte + representation. + """ return bytes(self).hex() def keccak256(self) -> Hash: @@ -229,7 +245,10 @@ def keccak256(self) -> Hash: def __get_pydantic_core_schema__( cls, source_type: Any, handler: GetCoreSchemaHandler ) -> PlainValidatorFunctionSchema: - """Provide Pydantic core schema for Bytecode serialization and validation.""" + """ + Provide Pydantic core schema for Bytecode + serialization and validation. + """ return no_info_plain_validator_function( cls, serialization=plain_serializer_function_ser_schema( diff --git a/ethereum_test_vm/evm_types.py b/ethereum_test_vm/evm_types.py index bb7fe296dc..992f580e89 100644 --- a/ethereum_test_vm/evm_types.py +++ b/ethereum_test_vm/evm_types.py @@ -4,7 +4,9 @@ class EVMCodeType(str, Enum): - """Enum representing the type of EVM code that is supported in a given fork.""" + """ + Enum representing the type of EVM code that is supported in a given fork. + """ LEGACY = "legacy" EOF_V1 = "eof_v1" diff --git a/ethereum_test_vm/opcodes.py b/ethereum_test_vm/opcodes.py index 5f2aef894b..85b79c65e5 100644 --- a/ethereum_test_vm/opcodes.py +++ b/ethereum_test_vm/opcodes.py @@ -1,9 +1,10 @@ """ Ethereum Virtual Machine opcode definitions. -Acknowledgments: The individual opcode documentation below is due to the work by -[smlXL](https://github.com/smlxl) on [evm.codes](https://www.evm.codes/), available as open -source [github.com/smlxl/evm.codes](https://github.com/smlxl/evm.codes) - thank you! And thanks +Acknowledgments: The individual opcode documentation below is due to the work +by [smlXL](https://github.com/smlxl) on [evm.codes](https://www.evm.codes/), +available as open source [github.com/smlxl/ +evm.codes](https://github.com/smlxl/evm.codes) - thank you! And thanks to @ThreeHrSleep for integrating it in the docstrings. """ @@ -18,7 +19,8 @@ def _get_int_size(n: int) -> int: """Return size of an integer in bytes.""" if n < 0: - # Negative numbers in the EVM are represented as two's complement of 32 bytes + # Negative numbers in the EVM are represented as two's complement + # of 32 bytes return 32 byte_count = 0 while n: @@ -45,7 +47,8 @@ def _stack_argument_to_bytecode( if data_size > 32: raise ValueError("Opcode stack data must be less than 32 bytes") elif data_size == 0: - # Pushing 0 is done with the PUSH1 opcode for compatibility reasons. + # Pushing 0 is done with the PUSH1 opcode + # for compatibility reasons. data_size = 1 arg = arg.to_bytes( length=data_size, @@ -55,7 +58,8 @@ def _stack_argument_to_bytecode( else: arg = to_bytes(arg).lstrip(b"\0") # type: ignore if arg == b"": - # Pushing 0 is done with the PUSH1 opcode for compatibility reasons. + # Pushing 0 is done with the PUSH1 opcode for + # compatibility reasons. arg = b"\x00" data_size = len(arg) @@ -67,20 +71,23 @@ def _stack_argument_to_bytecode( class Opcode(Bytecode): """ - Represents a single Opcode instruction in the EVM, with extra metadata useful to parametrize - tests. + Represents a single Opcode instruction in the EVM, with extra + metadata useful to parametrize tests. Parameters ---------- - data_portion_length: number of bytes after the opcode in the bytecode that represent data - - data_portion_formatter: function to format the data portion of the opcode, if any - - stack_properties_modifier: function to modify the stack properties of the opcode after the - data portion has been processed - - kwargs: list of keyword arguments that can be passed to the opcode, in the order they are - meant to be placed in the stack - - kwargs_defaults: default values for the keyword arguments if any, otherwise 0 - - unchecked_stack: whether the bytecode should ignore stack checks when being called + - data_portion_formatter: function to format the data portion of the + opcode, if any + - stack_properties_modifier: function to modify the stack properties of + the opcode after the data portion has been processed + - kwargs: list of keyword arguments that can be passed to the opcode, + in the order they are meant to be placed in the stack + - kwargs_defaults: default values for the keyword arguments if any, + otherwise 0 + - unchecked_stack: whether the bytecode should ignore stack checks + when being called """ @@ -111,8 +118,8 @@ def __new__( if kwargs_defaults is None: kwargs_defaults = {} if type(opcode_or_byte) is Opcode: - # Required because Enum class calls the base class with the instantiated object as - # parameter. + # Required because Enum class calls the base class + # with the instantiated object as parameter. return opcode_or_byte elif isinstance(opcode_or_byte, int) or isinstance(opcode_or_byte, bytes): obj_bytes = ( @@ -147,8 +154,8 @@ def __new__( def __getitem__(self, *args: "int | bytes | str | Iterable[int]") -> "Opcode": """ - Initialize a new instance of the opcode with the data portion set, and also clear - the data portion variables to avoid reusing them. + Initialize a new instance of the opcode with the data portion set, + and also clear the data portion variables to avoid reusing them. """ if self.data_portion_formatter is None and self.data_portion_length == 0: raise ValueError("Opcode does not have a data portion or has already been set") @@ -160,8 +167,8 @@ def __getitem__(self, *args: "int | bytes | str | Iterable[int]") -> "Opcode": else: data_portion = self.data_portion_formatter(*args) elif self.data_portion_length > 0: - # For opcodes with a data portion, the first argument is the data and the rest of the - # arguments form the stack. + # For opcodes with a data portion, the first argument is the + # data and the rest of the arguments form the stack. assert len(args) == 1, "Opcode with data portion requires exactly one argument" data = args[0] if isinstance(data, bytes) or isinstance(data, SupportsBytes) or isinstance(data, str): @@ -222,26 +229,31 @@ def __call__( **kwargs: "int | bytes | str | Opcode | Bytecode", ) -> Bytecode: """ - Make all opcode instances callable to return formatted bytecode, which constitutes a data - portion, that is located after the opcode byte, and pre-opcode bytecode, which is normally - used to set up the stack. + Make all opcode instances callable to return formatted bytecode, which + constitutes a data portion, that is located after the opcode byte, + and pre-opcode bytecode, which is normally used to set up the stack. - This useful to automatically format, e.g., call opcodes and their stack arguments as + This useful to automatically format, e.g., call opcodes and their + stack arguments as `Opcodes.CALL(Opcodes.GAS, 0x1234, 0x0, 0x0, 0x0, 0x0, 0x0)`. - Data sign is automatically detected but for this reason the range of the input must be: - `[-2^(data_portion_bits-1), 2^(data_portion_bits)]` where: `data_portion_bits == - data_portion_length * 8` + Data sign is automatically detected but for this reason the range + of the input must be: + `[-2^(data_portion_bits-1), 2^(data_portion_bits)]` + where: + `data_portion_bits == data_portion_length * 8` - For the stack, the arguments are set up in the opposite order they are given, so the first - argument is the last item pushed to the stack. + For the stack, the arguments are set up in the opposite order they + are given, so the first argument is the last item pushed to the stack. - The resulting stack arrangement does not take into account opcode stack element - consumption, so the stack height is not guaranteed to be correct and the user must take - this into consideration. + The resulting stack arrangement does not take into account + opcode stack element consumption, so the stack height is not + guaranteed to be correct and the user must take this into + consideration. - Integers can also be used as stack elements, in which case they are automatically converted - to PUSH operations, and negative numbers always use a PUSH32 operation. + Integers can also be used as stack elements, in which case they + are automatically converted to PUSH operations, and negative numbers + always use a PUSH32 operation. Hex-strings will be automatically converted to bytes. """ @@ -317,8 +329,8 @@ def __new__( if macro_or_bytes is None: macro_or_bytes = Bytecode() if isinstance(macro_or_bytes, Macro): - # Required because Enum class calls the base class with the instantiated object as - # parameter. + # Required because Enum class calls the base class + # with the instantiated object as parameter. return macro_or_bytes else: instance = super().__new__(cls, macro_or_bytes) @@ -342,8 +354,9 @@ def __call__(self, *args_t: OpcodeCallArg, **kwargs) -> Bytecode: RJUMPV_BRANCH_OFFSET_BYTE_LENGTH = 2 -# TODO: Allowing Iterable here is a hacky way to support `range`, because Python 3.11+ will allow -# `Op.RJUMPV[*range(5)]`. This is a temporary solution until Python 3.11+ is the minimum required +# TODO: Allowing Iterable here is a hacky way to support `range`, +# because Python 3.11+ will allow `Op.RJUMPV[*range(5)]`. +# This is a temporary solution until Python 3.11+ is the minimum required # version. @@ -419,8 +432,9 @@ class Opcodes(Opcode, Enum): Contains deprecated and not yet implemented opcodes. - This enum is !! NOT !! meant to be iterated over by the tests. Instead, create a list with - cherry-picked opcodes from this Enum within the test if iteration is needed. + This enum is !! NOT !! meant to be iterated over by the tests. + Instead, create a list with cherry-picked opcodes from this Enum + within the test if iteration is needed. Do !! NOT !! remove or modify existing opcodes from this list. """ @@ -585,7 +599,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - c: signed integer result of the division. If the denominator is 0, the result will be 0 + - c: signed integer result of the division. If the denominator is 0, + the result will be 0 ---- Fork @@ -615,7 +630,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - a % b: integer result of the integer modulo. If the denominator is 0, the result will be 0 + - a % b: integer result of the integer modulo. If the denominator is 0, + the result will be 0 Fork ---- @@ -644,8 +660,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - a % b: integer result of the signed integer modulo. If the denominator is 0, the result will - be 0 + - a % b: integer result of the signed integer modulo. If the denominator + is 0, the result will be 0 Fork ---- @@ -675,8 +691,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - (a + b) % N: integer result of the addition followed by a modulo. If the denominator is 0, - the result will be 0 + - (a + b) % N: integer result of the addition followed by a modulo. + If the denominator is 0, the result will be 0 Fork ---- @@ -706,8 +722,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - (a * b) % N: integer result of the multiplication followed by a modulo. If the denominator - is 0, the result will be 0 + - (a * b) % N: integer result of the multiplication followed by a modulo. + If the denominator is 0, the result will be 0 Fork ---- @@ -1083,8 +1099,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - y: the indicated byte at the least significant position. If the byte offset is out of range, - the result is 0 + - y: the indicated byte at the least significant position. + If the byte offset is out of range, the result is 0 Fork ---- @@ -1286,7 +1302,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - balance: balance of the given account in wei. Returns 0 if the account doesn't exist + - balance: balance of the given account in wei. Returns 0 if the + account doesn't exist Fork ---- @@ -1315,8 +1332,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - address: the 20-byte address of the sender of the transaction. It can only be an account - without code + - address: the 20-byte address of the sender of the transaction. + It can only be an account without code Fork ---- @@ -1344,8 +1361,9 @@ class Opcodes(Opcode, Enum): Outputs ---- - - address: the 20-byte address of the caller account. This is the account that did the last - call (except delegate call) + - address: the 20-byte address of the caller account. + This is the account that did the last + call (except delegate call) Fork ---- @@ -1365,7 +1383,8 @@ class Opcodes(Opcode, Enum): Description ---- - Get deposited value by the instruction/transaction responsible for this execution + Get deposited value by the instruction/transaction responsible + for this execution Inputs ---- @@ -1401,8 +1420,9 @@ class Opcodes(Opcode, Enum): Outputs ---- - - data[offset]: 32-byte value starting from the given offset of the calldata. All bytes after - the end of the calldata are set to 0 + - data[offset]: 32-byte value starting from the given offset of + the calldata. All bytes after the end of the calldata + are set to 0 Fork ---- @@ -1614,7 +1634,8 @@ class Opcodes(Opcode, Enum): ---- - minimum_word_size = (size + 31) / 32 - static_gas = 0 - - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost + - dynamic_gas = 3 * minimum_word_size + + memory_expansion_cost + address_access_cost Source: [evm.codes/#3C](https://www.evm.codes/#3C) """ @@ -1655,7 +1676,8 @@ class Opcodes(Opcode, Enum): Inputs ---- - dest_offset: byte offset in the memory where the result will be copied - - offset: byte offset in the return data from the last executed sub context to copy + - offset: byte offset in the return data from the last + executed sub context to copy - size: byte size to copy Fork @@ -1686,8 +1708,9 @@ class Opcodes(Opcode, Enum): Outputs ---- - - hash: hash of the chosen account's code, the empty hash (0xc5d24601...) if the account has no - code, or 0 if the account does not exist or has been destroyed + - hash: hash of the chosen account's code, the empty hash (0xc5d24601...) + if the account has no code, or 0 if the account does not exist or + has been destroyed Fork ---- @@ -1712,12 +1735,14 @@ class Opcodes(Opcode, Enum): Inputs ---- - - blockNumber: block number to get the hash from. Valid range is the last 256 blocks (not - including the current one). Current block number can be queried with NUMBER + - blockNumber: block number to get the hash from. Valid range is the + last 256 blocks (not including the current one). Current + block number can be queried with NUMBER Outputs ---- - - hash: hash of the chosen block, or 0 if the block number is not in the valid range + - hash: hash of the chosen block, or 0 if the block number is not + in the valid range Fork ---- @@ -1957,7 +1982,8 @@ class Opcodes(Opcode, Enum): Description ---- - Returns the versioned hash of a single blob contained in the type-3 transaction + Returns the versioned hash of a single blob contained in + the type-3 transaction Inputs ---- @@ -1975,7 +2001,8 @@ class Opcodes(Opcode, Enum): ---- 3 - Source: [eips.ethereum.org/EIPS/eip-4844](https://eips.ethereum.org/EIPS/eip-4844) + Source: [eips.ethereum.org/EIPS/ + eip-4844](https://eips.ethereum.org/EIPS/eip-4844) """ BLOBBASEFEE = Opcode(0x4A, popped_stack_items=0, pushed_stack_items=1) @@ -2003,7 +2030,8 @@ class Opcodes(Opcode, Enum): ---- 2 - Source: [eips.ethereum.org/EIPS/eip-7516](https://eips.ethereum.org/EIPS/eip-7516) + Source: [eips.ethereum.org/EIPS/eip-7516](https://eips.ethereum.org/ + EIPS/eip-7516) """ POP = Opcode(0x50, popped_stack_items=1) @@ -2049,8 +2077,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: the 32 bytes in memory starting at that offset. If it goes beyond its current size - (see MSIZE), writes 0s + - value: the 32 bytes in memory starting at that offset. + If it goes beyond its current size (see MSIZE), writes 0s Fork ---- @@ -2106,8 +2134,8 @@ class Opcodes(Opcode, Enum): Inputs ---- - offset: offset in the memory in bytes - - value: 1-byte value to write in the memory (the least significant byte of the 32-byte stack - value) + - value: 1-byte value to write in the memory (the least significant + byte of the 32-byte stack value) Fork ---- @@ -2136,7 +2164,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: 32-byte value corresponding to that key. 0 if that key was never written before + - value: 32-byte value corresponding to that key. 0 if that + key was never written before Fork ---- @@ -2208,8 +2237,8 @@ class Opcodes(Opcode, Enum): Inputs ---- - - pc: byte offset in the deployed code where execution will continue from. Must be a - JUMPDEST instruction + - pc: byte offset in the deployed code where execution will continue from. + Must be a JUMPDEST instruction Outputs ---- @@ -2237,11 +2266,12 @@ class Opcodes(Opcode, Enum): Inputs ---- - - pc: byte offset in the deployed code where execution will continue from. Must be a - JUMPDEST instruction - - condition: the program counter will be altered with the new value only if this value is - different from 0. Otherwise, the program counter is simply incremented and the next - instruction will be executed + - pc: byte offset in the deployed code where execution will continue from. + Must be a JUMPDEST instruction + - condition: the program counter will be altered with the new value only + if this value is different from 0. Otherwise, the program + counter is simply incremented and the next instruction + will be executed Fork ---- @@ -2261,7 +2291,8 @@ class Opcodes(Opcode, Enum): Description ---- - Get the value of the program counter prior to the increment corresponding to this instruction + Get the value of the program counter prior to the increment corresponding + to this instruction Inputs ---- @@ -2313,8 +2344,8 @@ class Opcodes(Opcode, Enum): Description ---- - Get the amount of available gas, including the corresponding reduction for the cost of this - instruction + Get the amount of available gas, including the corresponding reduction + for the cost of this instruction Inputs ---- @@ -2406,7 +2437,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: 32-byte value corresponding to that key. 0 if that key was never written + - value: 32-byte value corresponding to that key. 0 if that key + was never written Fork ---- @@ -2441,7 +2473,8 @@ class Opcodes(Opcode, Enum): ---- 100 - Source: [eips.ethereum.org/EIPS/eip-1153](https://eips.ethereum.org/EIPS/eip-1153) + Source: [eips.ethereum.org/EIPS/eip-1153](https://eips.ethereum.org/EIPS/ + eip-1153) """ MCOPY = Opcode(0x5E, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) @@ -2473,7 +2506,8 @@ class Opcodes(Opcode, Enum): - static_gas = 3 - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost - Source: [eips.ethereum.org/EIPS/eip-5656](https://eips.ethereum.org/EIPS/eip-5656) + Source: [eips.ethereum.org/EIPS/eip-5656](https://eips.ethereum.org/EIPS/ + eip-5656) """ PUSH0 = Opcode(0x5F, pushed_stack_items=1) @@ -2519,7 +2553,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in the + lowest significant bytes) Fork ---- @@ -2547,7 +2582,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in the lowest + significant bytes) Fork ---- @@ -2575,7 +2611,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in the + lowest significant bytes) Fork ---- @@ -2603,7 +2640,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in the lowest + significant bytes) Fork ---- @@ -2631,7 +2669,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in the lowest + significant bytes) Fork ---- @@ -2659,7 +2698,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in the + lowest significant bytes) Fork ---- @@ -2687,7 +2727,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in the + lowest significant bytes) Fork ---- @@ -2715,7 +2756,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in the + lowest significant bytes) Fork ---- @@ -2743,7 +2785,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in the + lowest significant bytes) Fork ---- @@ -2771,7 +2814,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -2799,7 +2843,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -2827,7 +2872,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in the + lowest significant bytes) Fork ---- @@ -2855,7 +2901,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -2883,7 +2930,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -2912,7 +2960,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -2940,7 +2989,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -2968,7 +3018,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -2996,7 +3047,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3024,7 +3076,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3052,7 +3105,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3080,7 +3134,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3108,7 +3163,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3136,7 +3192,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3164,7 +3221,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3192,7 +3250,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3220,7 +3279,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3248,7 +3308,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3276,7 +3337,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3304,7 +3366,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3332,7 +3395,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3360,7 +3424,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -3388,7 +3453,8 @@ class Opcodes(Opcode, Enum): Outputs ---- - - value: pushed value, aligned to the right (put in the lowest significant bytes) + - value: pushed value, aligned to the right (put in + the lowest significant bytes) Fork ---- @@ -4725,7 +4791,8 @@ class Opcodes(Opcode, Enum): Gas ---- - Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200) + Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/ + eip-4200) """ DATALOAD = Opcode(0xD0, popped_stack_items=1, pushed_stack_items=1, kwargs=["offset"]) @@ -4755,7 +4822,8 @@ class Opcodes(Opcode, Enum): ---- 4 - Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) + Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/ + eip-7480) """ DATALOADN = Opcode(0xD1, pushed_stack_items=1, data_portion_length=2) @@ -4789,7 +4857,8 @@ class Opcodes(Opcode, Enum): ---- 3 - Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) + Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/ + eip-7480) """ DATASIZE = Opcode(0xD2, pushed_stack_items=1) @@ -4818,7 +4887,8 @@ class Opcodes(Opcode, Enum): ---- 2 - Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) + Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/ + eip-7480) """ DATACOPY = Opcode(0xD3, popped_stack_items=3, kwargs=["dest_offset", "offset", "size"]) @@ -4852,7 +4922,8 @@ class Opcodes(Opcode, Enum): - static_gas = 3 - dynamic_gas = 3 * minimum_word_size + memory_expansion_cost - Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/eip-7480) + Source: [eips.ethereum.org/EIPS/eip-7480](https://eips.ethereum.org/EIPS/ + eip-7480) """ RJUMPI = Opcode(0xE1, popped_stack_items=1, data_portion_length=2) @@ -4878,7 +4949,8 @@ class Opcodes(Opcode, Enum): Gas ---- - Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200) + Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/ + eip-4200) """ RJUMPV = Opcode( @@ -4896,11 +4968,13 @@ class Opcodes(Opcode, Enum): ---- Relative jump with variable offset. - When calling this opcode to generate bytecode, the first argument is used to format the data - portion of the opcode, and it can be either of two types: - - A bytes type, and in this instance the bytes are used verbatim as the data portion. - - An integer iterable, list or tuple or any other iterable, where each element is a - jump offset. + When calling this opcode to generate bytecode, the first argument is + used to format the data portion of the opcode, and it can be either + of two types: + - A bytes type, and in this instance the bytes are used verbatim + as the data portion. + - An integer iterable, list or tuple or any other iterable, where + each element is a jump offset. Inputs ---- @@ -4915,7 +4989,8 @@ class Opcodes(Opcode, Enum): Gas ---- - Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/eip-4200) + Source: [eips.ethereum.org/EIPS/eip-4200](https://eips.ethereum.org/EIPS/ + eip-4200) """ CALLF = Opcode(0xE3, data_portion_length=2, unchecked_stack=True) @@ -4930,21 +5005,21 @@ class Opcodes(Opcode, Enum): - deduct 5 gas - read uint16 operand idx - - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs, execution results in - an exceptional halt + - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs, + execution results in an exceptional halt - if 1024 <= len(return_stack), execution results in an exceptional halt - push new element to return_stack (current_code_idx, pc+3) - update current_code_idx to idx and set pc to 0 Inputs ---- - Any: The inputs are not checked because we cannot know how many inputs the callee - function/section requires + Any: The inputs are not checked because we cannot know how many inputs + the callee function/section requires Outputs ---- - Any: The outputs are variable because we cannot know how many outputs the callee - function/section produces + Any: The outputs are variable because we cannot know how many outputs the + callee function/section produces Fork ---- @@ -4955,7 +5030,8 @@ class Opcodes(Opcode, Enum): 5 Source: - [ipsilon/eof/blob/main/spec/eof.md](https://github.com/ipsilon/eof/blob/main/spec/eof.md) + [ipsilon/eof/blob/main/spec/eof.md](https://github.com/ipsilon/eof/blob/ + main/spec/eof.md) """ RETF = Opcode(0xE4, terminating=True) @@ -4995,8 +5071,8 @@ class Opcodes(Opcode, Enum): - deduct 5 gas - read uint16 operand idx - - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs, execution results in - an exceptional halt + - if 1024 < len(stack) + types[idx].max_stack_height - types[idx].inputs, + execution results in an exceptional halt - set current_code_idx to idx - set pc = 0 @@ -5102,7 +5178,8 @@ class Opcodes(Opcode, Enum): Description ---- - Exchanges two stack positions. Two nybbles, n is high 4 bits + 1, then m is 4 low bits + 1. + Exchanges two stack positions. Two nybbles, n is high 4 bits + 1, + then m is 4 low bits + 1. Exchanges the n+1'th item with the n + m + 1 item. Inputs x and y when the opcode is used as `EXCHANGE[x, y]`, are equal to: @@ -5231,7 +5308,8 @@ class Opcodes(Opcode, Enum): Inputs ---- - value: value in wei to send to the new account - - offset: byte offset in the memory in bytes, the initialization code for the new account + - offset: byte offset in the memory in bytes, the initialization code + for the new account - size: byte size to copy (size of the initialization code) Outputs @@ -5250,8 +5328,9 @@ class Opcodes(Opcode, Enum): code_deposit_cost = 200 * deployed_code_size static_gas = 32000 - dynamic_gas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost - + code_deposit_cost + dynamic_gas = init_code_cost + memory_expansion_cost + + deployment_code_execution_cost + + code_deposit_cost ``` Source: [evm.codes/#F0](https://www.evm.codes/#F0) @@ -5265,7 +5344,8 @@ class Opcodes(Opcode, Enum): kwargs_defaults={"gas": GAS}, ) """ - CALL(gas, address, value, args_offset, args_size, ret_offset, ret_size) = success + CALL(gas, address, value, args_offset, args_size, ret_offset, ret_size) + = success ---- Description @@ -5274,14 +5354,15 @@ class Opcodes(Opcode, Enum): Inputs ---- - - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub - context is returned to this one + - gas: amount of gas to send to the sub context to execute. The gas that + is not used by the sub context is returned to this one - address: the account which context to execute - value: value in wei to send to the account - - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_offset: byte offset in the memory in bytes, the calldata of + the sub context - args_size: byte size to copy (size of the calldata) - - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub - context + - ret_offset: byte offset in the memory in bytes, where to store the + return data of the sub context - ret_size: byte size to copy (size of the return data) Outputs @@ -5296,8 +5377,9 @@ class Opcodes(Opcode, Enum): ---- ``` static_gas = 0 - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost - + positive_value_cost + value_to_empty_account_cost + dynamic_gas = memory_expansion_cost + code_execution_cost + + address_access_cost + positive_value_cost + + value_to_empty_account_cost ``` Source: [evm.codes/#F1](https://www.evm.codes/#F1) @@ -5311,24 +5393,26 @@ class Opcodes(Opcode, Enum): kwargs_defaults={"gas": GAS}, ) """ - CALLCODE(gas, address, value, args_offset, args_size, ret_offset, ret_size) = success + CALLCODE(gas, address, value, args_offset, args_size, ret_offset, ret_size) + = success ---- Description ---- - Message-call into this account with an alternative account's code. Executes code starting at - the address to which the call is made. + Message-call into this account with an alternative account's code. + Executes code starting at the address to which the call is made. Inputs ---- - - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub - context is returned to this one + - gas: amount of gas to send to the sub context to execute. The gas that + is not used by the sub context is returned to this one - address: the account which code to execute - value: value in wei to send to the account - - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_offset: byte offset in the memory in bytes, the calldata of + the sub context - args_size: byte size to copy (size of the calldata) - - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub - context + - ret_offset: byte offset in the memory in bytes, where to store the + return data of the sub context - ret_size: byte size to copy (size of the return data) Outputs @@ -5343,8 +5427,8 @@ class Opcodes(Opcode, Enum): ---- ``` static_gas = 0 - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost - + positive_value_cost + dynamic_gas = memory_expansion_cost + code_execution_cost + + address_access_cost + positive_value_cost ``` Source: [evm.codes/#F2](https://www.evm.codes/#F2) @@ -5361,8 +5445,8 @@ class Opcodes(Opcode, Enum): Inputs ---- - - offset: byte offset in the memory in bytes, to copy what will be the return data of this - context + - offset: byte offset in the memory in bytes, to copy what will be + the return data of this context - size: byte size to copy (size of the return data) Outputs @@ -5389,23 +5473,25 @@ class Opcodes(Opcode, Enum): kwargs_defaults={"gas": GAS}, ) """ - DELEGATECALL(gas, address, args_offset, args_size, ret_offset, ret_size) = success + DELEGATECALL(gas, address, args_offset, args_size, ret_offset, ret_size) + = success ---- Description ---- - Message-call into this account with an alternative account's code, but persisting the current - values for sender and value + Message-call into this account with an alternative account's code, but + persisting the current values for sender and value Inputs ---- - - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub - context is returned to this one + - gas: amount of gas to send to the sub context to execute. The gas that + is not used by the sub context is returned to this one - address: the account which code to execute - - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_offset: byte offset in the memory in bytes, the calldata of + the sub context - args_size: byte size to copy (size of the calldata) - - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub - context + - ret_offset: byte offset in the memory in bytes, where to store + the return data of the sub context - ret_size: byte size to copy (size of the return data) Outputs @@ -5419,7 +5505,8 @@ class Opcodes(Opcode, Enum): Gas ---- - static_gas = 0 - - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + - dynamic_gas = memory_expansion_cost + code_execution_cost + + address_access_cost Source: [evm.codes/#F4](https://www.evm.codes/#F4) """ @@ -5441,9 +5528,11 @@ class Opcodes(Opcode, Enum): Inputs ---- - value: value in wei to send to the new account - - offset: byte offset in the memory in bytes, the initialization code of the new account + - offset: byte offset in the memory in bytes, the initialization code + of the new account - size: byte size to copy (size of the initialization code) - - salt: 32-byte value used to create the new account at a deterministic address + - salt: 32-byte value used to create the new account at a + deterministic address Outputs ---- @@ -5486,7 +5575,8 @@ class Opcodes(Opcode, Enum): Inputs ---- - address: the account which context to execute - - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_offset: byte offset in the memory in bytes, the calldata of + the sub context - args_size: byte size to copy (size of the calldata) - value: value in wei to send to the account @@ -5494,7 +5584,8 @@ class Opcodes(Opcode, Enum): ---- - success: - `0` if the call was successful. - - `1` if the call has reverted (also can be pushed earlier in a light failure scenario). + - `1` if the call has reverted (also can be pushed earlier in a + light failure scenario). - `2` if the call has failed. Fork @@ -5505,8 +5596,9 @@ class Opcodes(Opcode, Enum): ---- ``` static_gas = 0 - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost - + positive_value_cost + value_to_empty_account_cost + dynamic_gas = memory_expansion_cost + code_execution_cost + + address_access_cost + positive_value_cost + + value_to_empty_account_cost ``` Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) @@ -5524,20 +5616,22 @@ class Opcodes(Opcode, Enum): Description ---- - Message-call into this account with an alternative account's code, but persisting the current - values for sender and value + Message-call into this account with an alternative account's code, + but persisting the current values for sender and value Inputs ---- - address: the account which context to execute - - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_offset: byte offset in the memory in bytes, the calldata of + the sub context - args_size: byte size to copy (size of the calldata) Outputs ---- - success: - `0` if the call was successful. - - `1` if the call has reverted (also can be pushed earlier in a light failure scenario). + - `1` if the call has reverted (also can be pushed earlier in a + light failure scenario). - `2` if the call has failed. Fork @@ -5547,7 +5641,8 @@ class Opcodes(Opcode, Enum): Gas ---- - static_gas = 0 - - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + - dynamic_gas = memory_expansion_cost + code_execution_cost + + address_access_cost Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) """ @@ -5560,7 +5655,8 @@ class Opcodes(Opcode, Enum): kwargs_defaults={"gas": GAS}, ) """ - STATICCALL(gas, address, args_offset, args_size, ret_offset, ret_size) = success + STATICCALL(gas, address, args_offset, args_size, ret_offset, ret_size) + = success ---- Description @@ -5569,13 +5665,14 @@ class Opcodes(Opcode, Enum): Inputs ---- - - gas: amount of gas to send to the sub context to execute. The gas that is not used by the sub - context is returned to this one + - gas: amount of gas to send to the sub context to execute. The gas + that is not used by the sub context is returned to this one - address: the account which context to execute - - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_offset: byte offset in the memory in bytes, the calldata of the + sub context - args_size: byte size to copy (size of the calldata) - - ret_offset: byte offset in the memory in bytes, where to store the return data of the sub - context + - ret_offset: byte offset in the memory in bytes, where to store the + return data of the sub context - ret_size: byte size to copy (size of the return data) Outputs @@ -5589,7 +5686,8 @@ class Opcodes(Opcode, Enum): Gas ---- - static_gas = 0 - - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + - dynamic_gas = memory_expansion_cost + code_execution_cost + + address_access_cost Source: [evm.codes/#FA](https://www.evm.codes/#FA) """ @@ -5611,14 +5709,16 @@ class Opcodes(Opcode, Enum): Inputs ---- - address: the account which context to execute - - args_offset: byte offset in the memory in bytes, the calldata of the sub context + - args_offset: byte offset in the memory in bytes, the calldata + of the sub context - args_size: byte size to copy (size of the calldata) Outputs ---- - success: - `0` if the call was successful. - - `1` if the call has reverted (also can be pushed earlier in a light failure scenario). + - `1` if the call has reverted (also can be pushed earlier in a + light failure scenario). - `2` if the call has failed. Fork @@ -5628,7 +5728,8 @@ class Opcodes(Opcode, Enum): Gas ---- - static_gas = 0 - - dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + - dynamic_gas = memory_expansion_cost + code_execution_cost + + address_access_cost Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) """ @@ -5644,7 +5745,8 @@ class Opcodes(Opcode, Enum): Inputs ---- - - offset: byte offset in the return data from the last executed sub context to copy + - offset: byte offset in the return data from the last executed + sub context to copy Fork ---- @@ -5666,7 +5768,8 @@ class Opcodes(Opcode, Enum): Inputs ---- - - offset: byte offset in the memory in bytes. The return data of the calling context + - offset: byte offset in the memory in bytes. The return data of + the calling context - size: byte size to copy (size of the return data) Fork @@ -5771,7 +5874,10 @@ class Opcodes(Opcode, Enum): def _mstore_operation(data: OpcodeCallArg = b"", offset: OpcodeCallArg = 0) -> Bytecode: - """Generate the bytecode that stores an arbitrary amount of data in memory.""" + """ + Generate the bytecode that stores an arbitrary + amount of data in memory. + """ assert isinstance(offset, int) if isinstance(data, int): data = data.to_bytes(32, "big") @@ -5782,10 +5888,11 @@ def _mstore_operation(data: OpcodeCallArg = b"", offset: OpcodeCallArg = 0) -> B if len(chunk) == 32: bytecode += Opcodes.MSTORE(offset, chunk) else: - # We need to MLOAD the existing data at the offset and then do a bitwise OR with the - # new data to store it in memory. + # We need to MLOAD the existing data at the offset and then + # do a bitwise OR with the new data to store it in memory. bytecode += Opcodes.MLOAD(offset) - # Create a mask to zero out the leftmost bytes of the existing data. + # Create a mask to zero out the leftmost bytes of + # the existing data. mask_size = 32 - len(chunk) bytecode += _push_opcodes_byte_list[mask_size - 1][-1] bytecode += Opcodes.AND diff --git a/pytest_plugins/concurrency.py b/pytest_plugins/concurrency.py index 10dadcca9c..0601824c33 100644 --- a/pytest_plugins/concurrency.py +++ b/pytest_plugins/concurrency.py @@ -1,6 +1,6 @@ """ -Pytest plugin to create a temporary folder for the session where -multi-process tests can store data that is shared between processes. +Pytest plugin to create a temporary folder for the session where multi-process +tests can store data that is shared between processes. The provided `session_temp_folder` fixture is used, for example, by `consume` when running hive simulators to ensure that only one `test_suite` is created @@ -24,8 +24,8 @@ def session_temp_folder_name(testrun_uid: str) -> str: Define the name of the temporary folder that will be shared among all the xdist workers to coordinate the tests. - "testrun_uid" is a fixture provided by the xdist plugin, and is unique for each test run, - so it is used to create the unique folder name. + "testrun_uid" is a fixture provided by the xdist plugin, and is unique for + each test run, so it is used to create the unique folder name. """ return f"pytest-{testrun_uid}" @@ -35,11 +35,11 @@ def session_temp_folder( session_temp_folder_name: str, ) -> Generator[Path, None, None]: """ - Create a global temporary folder that will be shared among all the - xdist workers to coordinate the tests. + Create a global temporary folder that will be shared among all the xdist + workers to coordinate the tests. - We also create a file to keep track of how many workers are still using the folder, so we can - delete it when the last worker is done. + We also create a file to keep track of how many workers are still using the + folder, so we can delete it when the last worker is done. """ session_temp_folder = Path(get_temp_dir()) / session_temp_folder_name session_temp_folder.mkdir(exist_ok=True) diff --git a/pytest_plugins/consume/consume.py b/pytest_plugins/consume/consume.py index 676c754808..4313615b19 100644 --- a/pytest_plugins/consume/consume.py +++ b/pytest_plugins/consume/consume.py @@ -1,4 +1,6 @@ -"""A pytest plugin providing common functionality for consuming test fixtures.""" +""" +A pytest plugin providing common functionality for consuming test fixtures. +""" import re import sys @@ -53,7 +55,10 @@ def __init__(self, url: str, destination_folder: Path): # noqa: D107 self.archive_name = self.strip_archive_extension(Path(self.parsed_url.path).name) def download_and_extract(self) -> Tuple[bool, Path]: - """Download the URL and extract it locally if it hasn't already been downloaded.""" + """ + Download the URL and extract it locally if it hasn't already been + downloaded. + """ if self.destination_folder.exists(): return True, self.detect_extracted_directory() @@ -94,8 +99,8 @@ def fetch_and_extract(self) -> Path: def detect_extracted_directory(self) -> Path: """ - Detect a single top-level dir within the extracted archive, otherwise return - destination_folder. + Detect a single top-level dir within the extracted archive, otherwise + return destination_folder. """ # noqa: D200 extracted_dirs = [ d for d in self.destination_folder.iterdir() if d.is_dir() and d.name != ".meta" @@ -196,7 +201,9 @@ def from_url( def from_release_spec( cls, spec: str, cache_folder: Optional[Path] = None, extract_to: Optional[Path] = None ) -> "FixturesSource": - """Create a fixture source from a release spec (e.g., develop@latest).""" + """ + Create a fixture source from a release spec (e.g., develop@latest). + """ if cache_folder is None: cache_folder = CACHED_DOWNLOADS_DIRECTORY url = get_release_url(spec) @@ -224,7 +231,9 @@ def from_release_spec( @staticmethod def validate_local_path(path: Path) -> "FixturesSource": - """Validate that a local fixture path exists and contains JSON files.""" + """ + Validate that a local fixture path exists and contains JSON files. + """ if not path.exists(): pytest.exit(f"Specified fixture directory '{path}' does not exist.") if not any(path.glob("**/*.json")): @@ -242,24 +251,29 @@ def __init__(self, pattern: str, collectonly: bool = False): # noqa: D107 @staticmethod def _escape_id(pattern: str) -> str: """ - Escape regex char in the pattern; prepend and append '.*' (for `fill` IDs). + Escape regex char in the pattern; prepend and append '.*' (for `fill` + IDs). - The `pattern` is prefixed and suffixed with a wildcard match to allow `fill` - test case IDs to be specified, otherwise the full `consume` test ID must be - specified. + The `pattern` is prefixed and suffixed with a wildcard match to allow + `fill` test case IDs to be specified, otherwise the full `consume` test + ID must be specified. """ return f".*{re.escape(pattern)}.*" @classmethod def from_string(cls, pattern: str) -> "SimLimitBehavior": """ - Parse the `--sim.limit` argument and return a `SimLimitBehavior` instance. + Parse the `--sim.limit` argument and return a `SimLimitBehavior` + instance. If `pattern`: - - Is "collectonly", enable collection mode without filtering. - - Starts with "collectonly:", enable collection mode and use the rest as a regex pattern. - - Starts with "id:", treat the rest as a literal test ID and escape special regex chars. - - Starts with "collectonly:id:", enable collection mode with a literal test ID. + - Is "collectonly", enable collection mode without filtering. + - Starts with "collectonly:", enable collection mode and use the + rest as a regex pattern. + - Starts with "id:", treat the rest as a literal test ID and escape + special regex chars. + - Starts with "collectonly:id:", enable collection mode with a + literal test ID. """ if pattern == "collectonly": return cls(pattern=".*", collectonly=True) @@ -357,22 +371,23 @@ def pytest_configure(config): # noqa: D103 test collection begins. `@pytest.hookimpl(tryfirst=True)` is applied to ensure that this hook is - called before the pytest-html plugin's pytest_configure to ensure that - it uses the modified `htmlpath` option. + called before the pytest-html plugin's pytest_configure to ensure that it + uses the modified `htmlpath` option. """ # Validate --extract-to usage if config.option.extract_to_folder is not None and "cache" not in sys.argv: pytest.exit("The --extract-to flag is only valid with the 'cache' command.") if config.option.fixtures_source is None: - # NOTE: Setting the default value here is necessary for correct stdin/piping behavior. + # NOTE: Setting the default value here is necessary for correct + # stdin/piping behavior. config.fixtures_source = FixturesSource( input_option=default_input(), path=Path(default_input()) ) else: - # NOTE: Setting `type=FixturesSource.from_input` in pytest_addoption() causes the option to - # be evaluated twice which breaks the result of `was_cached`; the work-around is to call it - # manually here. + # NOTE: Setting `type=FixturesSource.from_input` in pytest_addoption() + # causes the option to be evaluated twice which breaks the result of + # `was_cached`; the work-around is to call it manually here. config.fixtures_source = FixturesSource.from_input( config.option.fixtures_source, Path(config.option.fixture_cache_folder), @@ -428,7 +443,8 @@ def pytest_configure(config): # noqa: D103 all_forks = { # type: ignore fork for fork in set(get_forks()) | get_transition_forks() if not fork.ignore() } - # Append all forks within the index file (compatibility with `ethereum/tests`) + # Append all forks within the index file (compatibility with + # `ethereum/tests`) all_forks.update(getattr(index, "forks", [])) for fork in all_forks: config.addinivalue_line("markers", f"{fork}: Tests for the {fork} fork") @@ -483,7 +499,8 @@ def fixtures_source(request) -> FixturesSource: # noqa: D103 def pytest_generate_tests(metafunc): """ Generate test cases for every test fixture in all the JSON fixture files - within the specified fixtures directory, or read from stdin if the directory is 'stdin'. + within the specified fixtures directory, or read from stdin if the + directory is 'stdin'. """ if "cache" in sys.argv: return diff --git a/pytest_plugins/consume/direct/conftest.py b/pytest_plugins/consume/direct/conftest.py index e584e01347..db9208a910 100644 --- a/pytest_plugins/consume/direct/conftest.py +++ b/pytest_plugins/consume/direct/conftest.py @@ -1,6 +1,6 @@ """ -A pytest plugin that configures the consume command to act as a test runner -for "direct" client fixture consumer interfaces. +A pytest plugin that configures the consume command to act as a test runner for +"direct" client fixture consumer interfaces. For example, via go-ethereum's `evm blocktest` or `evm statetest` commands. """ @@ -120,7 +120,8 @@ def fixture_path(test_case: TestCaseIndexFile | TestCaseStream, fixtures_source: """ Path to the current JSON fixture file. - If the fixture source is stdin, the fixture is written to a temporary json file. + If the fixture source is stdin, the fixture is written to a temporary json + file. """ if fixtures_source.is_stdin: assert isinstance(test_case, TestCaseStream) diff --git a/pytest_plugins/consume/direct/test_via_direct.py b/pytest_plugins/consume/direct/test_via_direct.py index f1f9508144..e1f014d019 100644 --- a/pytest_plugins/consume/direct/test_via_direct.py +++ b/pytest_plugins/consume/direct/test_via_direct.py @@ -1,6 +1,6 @@ """ -Executes a JSON test fixture directly against a client using a dedicated -client interface similar to geth's EVM 'blocktest' command. +Executes a JSON test fixture directly against a client using a dedicated client +interface similar to geth's EVM 'blocktest' command. """ from pathlib import Path @@ -16,8 +16,8 @@ def test_fixture( test_dump_dir: Path | None, ): """ - Generic test function used to call the fixture consumer with a given fixture file path and - a fixture name (for a single test run). + Generic test function used to call the fixture consumer with a given + fixture file path and a fixture name (for a single test run). """ fixture_consumer.consume_fixture( test_case.format, diff --git a/pytest_plugins/consume/releases.py b/pytest_plugins/consume/releases.py index 2e694a7eec..26ecc67b17 100644 --- a/pytest_plugins/consume/releases.py +++ b/pytest_plugins/consume/releases.py @@ -48,7 +48,8 @@ def from_string(cls, release_string: str) -> "ReleaseTag": """ Create a release descriptor from a string. - The release source can be in the format `tag_name@version` or just `tag_name`. + The release source can be in the format `tag_name@version` or just + `tag_name`. """ version: str | None if "@" in release_string: @@ -69,7 +70,8 @@ def __eq__(self, value) -> bool: """ Check if the release descriptor matches the string value. - Returns True if the value is the same as the tag name or the tag name and version. + Returns True if the value is the same as the tag name or the tag name + and version. """ assert isinstance(value, str), f"Expected a string, but got: {value}" if self.version is not None: @@ -141,7 +143,9 @@ class Releases(RootModel[List[ReleaseInformation]]): def is_docker_or_ci() -> bool: - """Check if the code is running inside a Docker container or a CI environment.""" + """ + Check if the code is running inside a Docker container or a CI environment. + """ return "GITHUB_ACTIONS" in os.environ or Path("/.dockerenv").exists() @@ -221,14 +225,16 @@ def get_release_page_url(release_string: str) -> str: Return the GitHub Release page URL for a specific release descriptor. This function can handle: - - A standard release string (e.g., "eip7692@latest") - from execution-spec-tests only. + - A standard release string (e.g., "eip7692@latest") from + execution-spec-tests only. - A direct asset download link (e.g., - "https://github.com/ethereum/execution-spec-tests/releases/download/v4.0.0/fixtures_eip7692.tar.gz"). + "https://github.com/ethereum/execution-spec-tests/releases/ + download/v4.0.0/fixtures_eip7692.tar.gz"). """ release_information = get_release_information() - # Case 1: If it's a direct GitHub Releases download link, - # find which release in `release_information` has an asset with this exact URL. + # Case 1: If it's a direct GitHub Releases download link, find which + # release in `release_information` has an asset with this exact URL. repo_pattern = "|".join(re.escape(repo) for repo in SUPPORTED_REPOS) regex_pattern = rf"https://github\.com/({repo_pattern})/releases/download/" if re.match(regex_pattern, release_string): @@ -238,7 +244,8 @@ def get_release_page_url(release_string: str) -> str: return release.url # The HTML page for this release raise NoSuchReleaseError(f"No release found for asset URL: {release_string}") - # Case 2: Otherwise, treat it as a release descriptor (e.g., "eip7692@latest") + # Case 2: Otherwise, treat it as a release descriptor (e.g., + # "eip7692@latest") release_descriptor = ReleaseTag.from_string(release_string) for release in release_information: if release_descriptor in release: @@ -252,9 +259,10 @@ def get_release_information() -> List[ReleaseInformation]: """ Get the release information. - First check if the cached release information file exists. If it does, but it is older than 4 - hours, delete the file, unless running inside a CI environment or a Docker container. - Then download the release information from the Github API and save it to the cache file. + First check if the cached release information file exists. If it does, but + it is older than 4 hours, delete the file, unless running inside a CI + environment or a Docker container. Then download the release information + from the Github API and save it to the cache file. """ if CACHED_RELEASE_INFORMATION_FILE.exists(): last_modified = CACHED_RELEASE_INFORMATION_FILE.stat().st_mtime diff --git a/pytest_plugins/consume/simulators/base.py b/pytest_plugins/consume/simulators/base.py index 0b62ebb587..22736c97eb 100644 --- a/pytest_plugins/consume/simulators/base.py +++ b/pytest_plugins/consume/simulators/base.py @@ -45,7 +45,9 @@ def __init__(self) -> None: self._fixtures: Dict[Path, Fixtures] = {} def __getitem__(self, key: Path) -> Fixtures: - """Return the fixtures from the index file, if not found, load from disk.""" + """ + Return the fixtures from the index file, if not found, load from disk. + """ assert key.is_file(), f"Expected a file path, got '{key}'" if key not in self._fixtures: self._fixtures[key] = Fixtures.model_validate_json(key.read_text()) @@ -54,7 +56,10 @@ def __getitem__(self, key: Path) -> Fixtures: @pytest.fixture(scope="session") def fixture_file_loader() -> Dict[Path, Fixtures]: - """Return a singleton dictionary that caches loaded fixture files used in all tests.""" + """ + Return a singleton dictionary that caches loaded fixture files used in all + tests. + """ return FixturesDict() @@ -65,12 +70,12 @@ def fixture( test_case: TestCaseIndexFile | TestCaseStream, ) -> BaseFixture: """ - Load the fixture from a file or from stream in any of the supported - fixture formats. + Load the fixture from a file or from stream in any of the supported fixture + formats. - The fixture is either already available within the test case (if consume - is taking input on stdin) or loaded from the fixture json file if taking - input from disk (fixture directory with index file). + The fixture is either already available within the test case (if consume is + taking input on stdin) or loaded from the fixture json file if taking input + from disk (fixture directory with index file). """ fixture: BaseFixture if fixtures_source.is_stdin: diff --git a/pytest_plugins/consume/simulators/exceptions.py b/pytest_plugins/consume/simulators/exceptions.py index 0e8d4d63a7..8db60438e0 100644 --- a/pytest_plugins/consume/simulators/exceptions.py +++ b/pytest_plugins/consume/simulators/exceptions.py @@ -54,7 +54,10 @@ def client_exception_mapper( @pytest.fixture(scope="session") def disable_strict_exception_matching(request: pytest.FixtureRequest) -> List[str]: - """Return the list of clients or forks that should NOT use strict exception matching.""" + """ + Return the list of clients or forks that should NOT use strict exception + matching. + """ config_string = request.config.getoption("disable_strict_exception_matching") return config_string.split(",") if config_string else [] @@ -76,7 +79,8 @@ def fork_strict_exception_matching( disable_strict_exception_matching: List[str], ) -> bool: """Return True if the fork should use strict exception matching.""" - # NOTE: `in` makes it easier for transition forks ("Prague" in "CancunToPragueAtTime15k") + # NOTE: `in` makes it easier for transition forks ("Prague" in + # "CancunToPragueAtTime15k") return not any( s.lower() in str(fixture.fork).lower() for s in disable_strict_exception_matching ) diff --git a/pytest_plugins/consume/simulators/helpers/exceptions.py b/pytest_plugins/consume/simulators/helpers/exceptions.py index 6307fb095b..f6a7e7e2bc 100644 --- a/pytest_plugins/consume/simulators/helpers/exceptions.py +++ b/pytest_plugins/consume/simulators/helpers/exceptions.py @@ -16,10 +16,16 @@ class GenesisBlockMismatchExceptionError(Exception): - """Definers a mismatch exception between the client and fixture genesis blockhash.""" + """ + Definers a mismatch exception between the client and fixture genesis + blockhash. + """ def __init__(self, *, expected_header: FixtureHeader, got_genesis_block: Dict[str, str]): - """Initialize the exception with the expected and received genesis block headers.""" + """ + Initialize the exception with the expected and received genesis block + headers. + """ message = ( "Genesis block hash mismatch.\n\n" f"Expected: {expected_header.block_hash}\n" @@ -47,7 +53,9 @@ def __init__(self, *, expected_header: FixtureHeader, got_genesis_block: Dict[st @staticmethod def compare_models(expected: FixtureHeader, got: FixtureHeader) -> Tuple[Dict, List]: - """Compare two FixtureHeader model instances and return their differences.""" + """ + Compare two FixtureHeader model instances and return their differences. + """ differences = {} unexpected_fields = [] for (exp_name, exp_value), (got_name, got_value) in zip(expected, got, strict=False): diff --git a/pytest_plugins/consume/simulators/helpers/ruleset.py b/pytest_plugins/consume/simulators/helpers/ruleset.py index c1b7195b29..2098dc6c93 100644 --- a/pytest_plugins/consume/simulators/helpers/ruleset.py +++ b/pytest_plugins/consume/simulators/helpers/ruleset.py @@ -43,10 +43,12 @@ def get_blob_schedule_entries(fork: Fork) -> Dict[str, int]: """ Generate blob schedule entries for each fork (and respective parent forks). - Adds the following entries to the ruleset for the given fork (and parent forks): - HIVE_{FORK}_BLOB_TARGET: target_blobs_per_block() - HIVE_{FORK}_BLOB_MAX: max_blobs_per_block() - HIVE_{FORK}_BLOB_BASE_FEE_UPDATE_FRACTION: blob_base_fee_update_fraction() + Adds the following entries to the ruleset for the given fork (and parent + forks): + HIVE_{FORK}_BLOB_TARGET: target_blobs_per_block() + HIVE_{FORK}_BLOB_MAX: max_blobs_per_block() + HIVE_{FORK}_BLOB_BASE_FEE_UPDATE_FRACTION: blob_base_fee_update_ + fraction() """ entries: Dict = {} forks_with_blobs: List[Fork] = [] diff --git a/pytest_plugins/consume/simulators/helpers/timing.py b/pytest_plugins/consume/simulators/helpers/timing.py index eddfe3f780..e5cadee957 100644 --- a/pytest_plugins/consume/simulators/helpers/timing.py +++ b/pytest_plugins/consume/simulators/helpers/timing.py @@ -5,7 +5,9 @@ class TimingData: - """The times taken to perform the various steps of a test case (seconds).""" + """ + The times taken to perform the various steps of a test case (seconds). + """ name: str start_time: float | None diff --git a/pytest_plugins/consume/simulators/rlp/conftest.py b/pytest_plugins/consume/simulators/rlp/conftest.py index f2d8f93a34..66ad7dd62a 100644 --- a/pytest_plugins/consume/simulators/rlp/conftest.py +++ b/pytest_plugins/consume/simulators/rlp/conftest.py @@ -46,7 +46,10 @@ def blocks_rlp(fixture: BlockchainFixture) -> List[Bytes]: @pytest.fixture(scope="function") def buffered_blocks_rlp(blocks_rlp: List[bytes]) -> List[io.BufferedReader]: - """Convert the RLP-encoded blocks of the current test fixture to buffered readers.""" + """ + Convert the RLP-encoded blocks of the current test fixture to buffered + readers. + """ block_rlp_files = [] for _, block_rlp in enumerate(blocks_rlp): block_rlp_stream = io.BytesIO(block_rlp) diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py index 1d54d0586c..1ef5a774de 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py @@ -1,8 +1,10 @@ """ -A hive based simulator that executes blocks against clients using the `engine_newPayloadVX` method -from the Engine API. The simulator uses the `BlockchainEngineFixtures` to test against clients. +A hive based simulator that executes blocks against clients using the +`engine_newPayloadVX` method from the Engine API. The simulator uses the +`BlockchainEngineFixtures` to test against clients. -Each `engine_newPayloadVX` is verified against the appropriate VALID/INVALID responses. +Each `engine_newPayloadVX` is verified against the appropriate VALID/INVALID +responses. """ import time @@ -39,10 +41,12 @@ def test_blockchain_via_engine( strict_exception_matching: bool, ): """ - 1. Check the client genesis block hash matches `fixture.genesis.block_hash`. - 2. Execute the test case fixture blocks against the client under test using the - `engine_newPayloadVX` method from the Engine API. - 3. For valid payloads a forkchoice update is performed to finalize the chain. + 1. Check the client genesis block hash matches + `fixture.genesis.block_hash`. + 2. Execute the test case fixture blocks against the client under test using + the `engine_newPayloadVX` method from the Engine API. + 3. For valid payloads a forkchoice update is performed to finalize the + chain. """ # Send a initial forkchoice update with timing_data.time("Initial forkchoice update"): diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py index 4c63eba5b7..e894947a30 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py @@ -1,8 +1,9 @@ """ -A hive based simulator that executes RLP-encoded blocks against clients. The simulator uses the -`BlockchainFixtures` to test this against clients. +A hive based simulator that executes RLP-encoded blocks against clients. The +simulator uses the `BlockchainFixtures` to test this against clients. -Clients consume the genesis and RLP-encoded blocks from input files upon start-up. +Clients consume the genesis and RLP-encoded blocks from input files upon +start-up. """ import logging @@ -23,7 +24,8 @@ def test_via_rlp( fixture: BlockchainFixture, ): """ - 1. Check the client genesis block hash matches `fixture.genesis.block_hash`. + 1. Check the client genesis block hash matches + `fixture.genesis.block_hash`. 2. Check the client last block hash matches `fixture.last_block_hash`. """ with timing_data.time("Get genesis block"): diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py index 5ef252776a..2781b7540f 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py @@ -1,10 +1,12 @@ """ -A hive based simulator that executes blocks against clients using the `engine_newPayloadV*` method -from the Engine API with sync testing. The simulator uses the `BlockchainEngineSyncFixtures` to -test against clients with client synchronization. +A hive based simulator that executes blocks against clients using the +`engine_newPayloadV*` method from the Engine API with sync testing. The +simulator uses the `BlockchainEngineSyncFixtures` to test against clients with +client synchronization. This simulator: -1. Spins up two clients: one as the client under test and another as the sync client +1. Spins up two clients: one as the client under test and another as the sync + client 2. Executes payloads on the client under test 3. Has the sync client synchronize from the client under test 4. Verifies that the sync was successful @@ -328,8 +330,8 @@ def test_blockchain_via_sync( f"{forkchoice_response}" ) - # Add peer using admin_addPeer - # This seems to be required... TODO: we can maybe improve flow here if not required + # Add peer using admin_addPeer This seems to be required... TODO: we can + # maybe improve flow here if not required logger.info(f"Adding peer: {client_enode_url}") assert sync_admin_rpc is not None, "sync_admin_rpc is required" try: @@ -338,7 +340,8 @@ def test_blockchain_via_sync( except Exception as e: raise LoggedError(f"admin_addPeer failed: {e}") from e - time.sleep(1) # quick sleep to allow for connection - TODO: is this necessary? + # quick sleep to allow for connection - TODO: is this necessary? + time.sleep(1) try: sync_peer_count = sync_net_rpc.peer_count() @@ -352,7 +355,8 @@ def test_blockchain_via_sync( except Exception as e: logger.warning(f"Could not verify peer connection: {e}") - # Trigger sync by sending the target block via newPayload followed by forkchoice update + # Trigger sync by sending the target block via newPayload followed by + # forkchoice update logger.info(f"Triggering sync to block {last_valid_block_hash}") # Find the last valid payload to send to sync client @@ -374,7 +378,8 @@ def test_blockchain_via_sync( ) try: - version = last_valid_payload.new_payload_version # log version used for debugging + # log version used for debugging + version = last_valid_payload.new_payload_version logger.info(f"Sending target payload via engine_newPayloadV{version}") # send the payload to sync client @@ -403,9 +408,9 @@ def test_blockchain_via_sync( # Give a moment for P2P connections to establish after sync starts time.sleep(1) - # Check peer count after triggering sync - # Note: Reth does not actually raise the peer count but doesn't seem - # to need this to sync. + # Check peer count after triggering sync Note: Reth does not + # actually raise the peer count but doesn't seem to need this to + # sync. try: assert sync_net_rpc is not None, "sync_net_rpc is required" client_peer_count = net_rpc.peer_count() @@ -444,7 +449,8 @@ def test_blockchain_via_sync( # Send periodic forkchoice updates to keep sync alive if time.time() - last_forkchoice_time >= forkchoice_interval: try: - # Send forkchoice update to sync client to trigger/maintain sync + # Send forkchoice update to sync client to trigger/maintain + # sync assert sync_engine_rpc is not None, "sync_engine_rpc is required" sync_fc_response = sync_engine_rpc.forkchoice_updated( forkchoice_state=last_valid_block_forkchoice_state, diff --git a/pytest_plugins/consume/simulators/single_test_client.py b/pytest_plugins/consume/simulators/single_test_client.py index b6db7674c9..0ea5da90ac 100644 --- a/pytest_plugins/consume/simulators/single_test_client.py +++ b/pytest_plugins/consume/simulators/single_test_client.py @@ -1,4 +1,6 @@ -"""Common pytest fixtures for simulators with single-test client architecture.""" +""" +Common pytest fixtures for simulators with single-test client architecture. +""" import io import json @@ -23,7 +25,10 @@ @pytest.fixture(scope="function") def client_genesis(fixture: BlockchainFixtureCommon) -> dict: - """Convert the fixture genesis block header and pre-state to a client genesis state.""" + """ + Convert the fixture genesis block header and pre-state to a client genesis + state. + """ genesis = to_json(fixture.genesis) alloc = to_json(fixture.pre) # NOTE: nethermind requires account keys without '0x' prefix @@ -51,7 +56,10 @@ def environment( @pytest.fixture(scope="function") def buffered_genesis(client_genesis: dict) -> io.BufferedReader: - """Create a buffered reader for the genesis block header of the current test fixture.""" + """ + Create a buffered reader for the genesis block header of the current test + fixture. + """ genesis_json = json.dumps(client_genesis) genesis_bytes = genesis_json.encode("utf-8") return io.BufferedReader(cast(io.RawIOBase, io.BytesIO(genesis_bytes))) @@ -71,7 +79,9 @@ def client( client_type: ClientType, total_timing_data: TimingData, ) -> Generator[Client, None, None]: - """Initialize the client with the appropriate files and environment variables.""" + """ + Initialize the client with the appropriate files and environment variables. + """ logger.info(f"Starting client ({client_type.name})...") logger.debug(f"Main client Network ID: {environment.get('HIVE_NETWORK_ID', 'NOT SET!')}") logger.debug(f"Main client Chain ID: {environment.get('HIVE_CHAIN_ID', 'NOT SET!')}") diff --git a/pytest_plugins/consume/simulators/sync/conftest.py b/pytest_plugins/consume/simulators/sync/conftest.py index bf9a132379..9447ea4728 100644 --- a/pytest_plugins/consume/simulators/sync/conftest.py +++ b/pytest_plugins/consume/simulators/sync/conftest.py @@ -60,7 +60,8 @@ def pytest_collection_modifyitems(session, config, items): # Format: ``-{client}_sync_{sync_client}`` new_suffix = f"-{client_name}::sync_{sync_client_name}" - # client_param-tests/path/to/test.py::test_name[test_params]-sync_client_param + # client_param- + # tests/path/to/test.py::test_name[test_params]-sync_client_param # 1. Remove the client prefix from the beginning # 2. Replace the -client_param part at the end with our new format nodeid = item.nodeid @@ -119,7 +120,10 @@ def admin_rpc(client: Client) -> AdminRPC: @pytest.fixture(scope="function") def sync_genesis(fixture: BlockchainEngineSyncFixture) -> dict: - """Convert the fixture genesis block header and pre-state to a sync client genesis state.""" + """ + Convert the fixture genesis block header and pre-state to a sync client + genesis state. + """ genesis = to_json(fixture.genesis) alloc = to_json(fixture.pre) # NOTE: nethermind requires account keys without '0x' prefix @@ -129,7 +133,9 @@ def sync_genesis(fixture: BlockchainEngineSyncFixture) -> dict: @pytest.fixture(scope="function") def sync_buffered_genesis(sync_genesis: dict) -> io.BufferedReader: - """Create a buffered reader for the genesis block header of the sync client.""" + """ + Create a buffered reader for the genesis block header of the sync client. + """ genesis_json = json.dumps(sync_genesis) genesis_bytes = genesis_json.encode("utf-8") return io.BufferedReader(cast(io.RawIOBase, io.BytesIO(genesis_bytes))) diff --git a/pytest_plugins/consume/simulators/test_case_description.py b/pytest_plugins/consume/simulators/test_case_description.py index 3a97c63f19..8989bd05c2 100644 --- a/pytest_plugins/consume/simulators/test_case_description.py +++ b/pytest_plugins/consume/simulators/test_case_description.py @@ -1,4 +1,7 @@ -"""Pytest fixtures that help create the test case "Description" displayed in the Hive UI.""" +""" +Pytest fixtures that help create the test case "Description" displayed in the +Hive UI. +""" import logging import textwrap @@ -30,7 +33,10 @@ def hive_clients_yaml_generator_command( hive_clients_yaml_target_filename: str, hive_info: HiveInfo, ) -> str: - """Generate a shell command that creates a clients YAML file for the current client.""" + """ + Generate a shell command that creates a clients YAML file for the current + client. + """ try: if not client_file: raise ValueError("No client information available - try updating hive") @@ -65,10 +71,13 @@ def filtered_hive_options(hive_info: HiveInfo) -> List[str]: logger.info("Hive info: %s", hive_info.command) unwanted_options = [ - "--client", # gets overwritten: we specify a single client; the one from the test case + "--client", # gets overwritten: we specify a single client; the one + # from the test case "--client-file", # gets overwritten: we'll write our own client file - "--results-root", # use default value instead (or you have to pass it to ./hiveview) - "--sim.limit", # gets overwritten: we only run the current test case id + "--results-root", # use default value instead (or you have to pass it + # to ./hiveview) + "--sim.limit", # gets overwritten: we only run the current test case + # id "--sim.parallelism", # skip; we'll only be running a single test ] @@ -118,7 +127,10 @@ def hive_dev_command( client_type: ClientType, hive_client_config_file_parameter: str, ) -> str: - """Return the command used to instantiate hive alongside the `consume` command.""" + """ + Return the command used to instantiate hive alongside the `consume` + command. + """ return f"./hive --dev {hive_client_config_file_parameter} --client {client_type.name}" @@ -151,7 +163,8 @@ def test_case_description( if "description" not in fixture.info or fixture.info["description"] is None: test_docstring = "No documentation available." else: - # this prefix was included in the fixture description field for fixtures <= v4.3.0 + # this prefix was included in the fixture description field for + # fixtures <= v4.3.0 test_docstring = fixture.info["description"].replace("Test function documentation:\n", "") # type: ignore description = textwrap.dedent(f""" @@ -162,15 +175,18 @@ def test_case_description( {test_docstring} Run This Test Locally: - To run this test in hive: + To run this test in + hive + : {hive_clients_yaml_generator_command} {hive_consume_command} - Advanced: Run the test against a hive developer backend using EEST's consume command + Advanced: Run the test against a hive developer backend using + EEST's consume command Create the client YAML file, as above, then: 1. Start hive in dev mode: {hive_dev_command} 2. In the EEST repository root: {eest_consume_command} - """) # noqa: E501 + """) description = description.strip() description = description.replace("\n", "
") diff --git a/pytest_plugins/consume/tests/test_consume_args.py b/pytest_plugins/consume/tests/test_consume_args.py index 110566fd80..5864687926 100644 --- a/pytest_plugins/consume/tests/test_consume_args.py +++ b/pytest_plugins/consume/tests/test_consume_args.py @@ -22,7 +22,10 @@ def test_function(state_test, pre): @pytest.fixture def minimal_test_path(pytester: pytest.Pytester) -> Path: - """Minimal test file that's written to a file using pytester and ready to fill.""" + """ + Minimal test file that's written to a file using pytester and ready to + fill. + """ tests_dir = pytester.mkdir("tests") test_file = tests_dir / MINIMAL_TEST_FILE_NAME test_file.write_text(MINIMAL_TEST_CONTENTS) @@ -72,11 +75,12 @@ def fill_tests( """ Run fill to generate test fixtures for use with testing consume. - We only need to do this once so ideally the scope of this fixture should be "module", - however the `pytester` fixture's scope is function and cannot be accessed from a higher - scope fixture. + We only need to do this once so ideally the scope of this fixture should be + "module", however the `pytester` fixture's scope is function and cannot be + accessed from a higher scope fixture. - Instead we use a file lock and only write the fixtures once to the directory. + Instead we use a file lock and only write the fixtures once to the + directory. """ with FileLock(fixtures_dir.with_suffix(".lock")): meta_folder = fixtures_dir / ".meta" @@ -100,9 +104,11 @@ def fill_tests( @pytest.fixture(autouse=True, scope="function") def test_fixtures(pytester: Pytester, fixtures_dir: Path, fill_tests: None) -> List[Path]: """ - Copy test fixtures from the regular temp path to the pytester temporary dir. + Copy test fixtures from the regular temp path to the pytester temporary + dir. - We intentionally copy the `.meta/index.json` file to test its compatibility with consume. + We intentionally copy the `.meta/index.json` file to test its compatibility + with consume. """ del fill_tests @@ -131,7 +137,11 @@ def copy_consume_test_paths(pytester: Pytester): shutil.move("conftest.py", target_dir / "conftest.py") -single_test_id = f"src/pytest_plugins/consume/direct/test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/{MINIMAL_TEST_FILE_NAME}::test_function[fork_Shanghai-state_test]]" # noqa: E501 +single_test_id = ( + "src/pytest_plugins/consume/direct/" + "test_via_direct.py::test_fixture[CollectOnlyFixtureConsumer-tests/" + f"{MINIMAL_TEST_FILE_NAME}::test_function[fork_Shanghai-state_test]]" +) @pytest.mark.parametrize( diff --git a/pytest_plugins/consume/tests/test_fixtures_source_input_types.py b/pytest_plugins/consume/tests/test_fixtures_source_input_types.py index 9eb205c73f..e18cc2b731 100644 --- a/pytest_plugins/consume/tests/test_fixtures_source_input_types.py +++ b/pytest_plugins/consume/tests/test_fixtures_source_input_types.py @@ -10,7 +10,9 @@ class TestSimplifiedConsumeBehavior: """Test suite for the simplified consume behavior.""" def test_fixtures_source_from_release_url_no_api_calls(self): - """Test that direct release URLs do not make API calls for release page.""" + """ + Test that direct release URLs do not make API calls for release page. + """ test_url = "https://github.com/ethereum/execution-spec-tests/releases/download/v3.0.0/fixtures_develop.tar.gz" with patch("pytest_plugins.consume.consume.FixtureDownloader") as mock_downloader: @@ -26,7 +28,9 @@ def test_fixtures_source_from_release_url_no_api_calls(self): assert source.input_option == test_url def test_fixtures_source_from_release_spec_makes_api_calls(self): - """Test that release specs still make API calls and get release page.""" + """ + Test that release specs still make API calls and get release page. + """ test_spec = "stable@latest" with patch("pytest_plugins.consume.consume.get_release_url") as mock_get_url: @@ -68,7 +72,9 @@ def test_fixtures_source_from_regular_url_no_release_page(self): assert source.url == test_url def test_output_formatting_without_release_page_for_direct_urls(self): - """Test output formatting when release page is empty for direct URLs.""" + """ + Test output formatting when release page is empty for direct URLs. + """ from unittest.mock import MagicMock from pytest import Config @@ -97,7 +103,9 @@ def test_output_formatting_without_release_page_for_direct_urls(self): assert "Input:" in reason def test_output_formatting_with_release_page_for_specs(self): - """Test output formatting when release page is present for release specs.""" + """ + Test output formatting when release page is present for release specs. + """ from unittest.mock import MagicMock from pytest import Config diff --git a/pytest_plugins/custom_logging/__init__.py b/pytest_plugins/custom_logging/__init__.py index a03e1b28ad..9e71d615ba 100644 --- a/pytest_plugins/custom_logging/__init__.py +++ b/pytest_plugins/custom_logging/__init__.py @@ -1,4 +1,7 @@ -"""Import the logging module content to make it available from pytest_plugins.logging.""" +""" +Import the logging module content to make it available from +pytest_plugins.logging. +""" from .plugin_logging import ( FAIL_LEVEL, diff --git a/pytest_plugins/custom_logging/plugin_logging.py b/pytest_plugins/custom_logging/plugin_logging.py index dfe2cf7d1a..3387992c8a 100644 --- a/pytest_plugins/custom_logging/plugin_logging.py +++ b/pytest_plugins/custom_logging/plugin_logging.py @@ -1,15 +1,17 @@ """ A Pytest plugin to configure logging for pytest sessions. -Note: While pytest's builtin logging is generally amazing, it does not write timestamps -when log output is written to pytest's caplog (the captured output for a test). And having -timestamps in this output is the main use case for adding logging to our plugins. -This output gets shown in the `FAILURES` summary section, which is shown as the -"simulator log" in hive simulations. For this use case, timestamps are essential to verify -timing issues against the clients log. +Note: While pytest's builtin logging is generally amazing, it does not write +timestamps when log output is written to pytest's caplog (the captured output +for a test). And having timestamps in this output is the main use case for +adding logging to our plugins. This output gets shown in the `FAILURES` summary +section, which is shown as the "simulator log" in hive simulations. For this +use case, timestamps are essential to verify timing issues against the clients +log. This module provides both: -1. A standalone logging configuration system that can be used in any Python project +1. A standalone logging configuration system that can be used in any + Python project 2. A pytest plugin that automatically configures logging for pytest sessions """ @@ -71,8 +73,8 @@ def fail( """ Log a message with FAIL level severity (35). - This level is between WARNING (30) and ERROR (40), intended for test failures - and similar issues. + This level is between WARNING (30) and ERROR (40), intended for test + failures and similar issues. """ if stacklevel is None: stacklevel = 1 @@ -94,15 +96,22 @@ def get_logger(name: str) -> EESTLogger: class UTCFormatter(logging.Formatter): - """Log formatter that formats UTC timestamps with milliseconds and +00:00 suffix.""" + """ + Log formatter that formats UTC timestamps with milliseconds and +00:00 + suffix. + """ - def formatTime(self, record, datefmt=None): # noqa: D102,N802 # camelcase required + def formatTime(self, record, datefmt=None): # noqa: D102,N802 + # camelcase required dt = datetime.fromtimestamp(record.created, tz=timezone.utc) return dt.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] + "+00:00" class ColorFormatter(UTCFormatter): - """Formatter that adds ANSI color codes to log level names for terminal output.""" + """ + Formatter that adds ANSI color codes to log level names for terminal + output. + """ running_in_docker: ClassVar[bool] = Path("/.dockerenv").exists() @@ -150,9 +159,9 @@ def from_cli(cls, value: str) -> int: raise ValueError(f"Invalid log level '{value}'. Expected one of: {valid} or a number.") -# ============================================================================== +# ========================================================================= # Standalone logging configuration (usable without pytest) -# ============================================================================== +# ========================================================================= def configure_logging( @@ -169,14 +178,13 @@ def configure_logging( same settings as the pytest plugin. Args: - log_level: The logging level to use (name or numeric value) - log_file: Path to the log file (if None, no file logging is set up) - log_to_stdout: Whether to log to stdout - log_format: The log format string - use_color: Whether to use colors in stdout output (auto-detected if None) + log_level: The logging level to use (name or numeric value) + log_file: Path to the log file (if None, no file logging is set up) + log_to_stdout: Whether to log to stdout + log_format: The log format string + use_color: Whether to use colors in stdout output (auto-detected if None) - Returns: - The file handler if log_file is provided, otherwise None + Returns: The file handler if log_file is provided, otherwise None """ # Initialize root logger @@ -222,9 +230,9 @@ def configure_logging( return file_handler_instance -# ============================================================================== +# ========================================================================== # Pytest plugin integration -# ============================================================================== +# ========================================================================== def pytest_addoption(parser): # noqa: D103 @@ -232,7 +240,8 @@ def pytest_addoption(parser): # noqa: D103 "logging", "Arguments related to logging from test fixtures and tests." ) logging_group.addoption( - "--eest-log-level", # --log-level is defined by pytest's built-in logging + "--eest-log-level", # --log-level is defined by pytest's built-in + # logging "--eestloglevel", action="store", default="INFO", @@ -274,9 +283,9 @@ def pytest_configure(config: pytest.Config) -> None: """ Initialize logging for pytest sessions. - This goes to a lot of effort to ensure that a log file is created per worker - if xdist is used and that the timestamp used in the filename is the same across - main and all workers. + This goes to a lot of effort to ensure that a log file is created per + worker if xdist is used and that the timestamp used in the filename is the + same across main and all workers. """ global file_handler @@ -312,10 +321,11 @@ def pytest_report_header(config: pytest.Config) -> list[str]: return [] -def pytest_terminal_summary(terminalreporter: TerminalReporter, exitstatus: int) -> None: - """Display the log file path in the terminal summary like the HTML report does.""" - del exitstatus - +def pytest_terminal_summary(terminalreporter: TerminalReporter) -> None: + """ + Display the log file path in the terminal summary like the HTML report + does. + """ if terminalreporter.config.option.collectonly: return if eest_log_file_path := terminalreporter.config.option.eest_log_file_path: diff --git a/pytest_plugins/execute/__init__.py b/pytest_plugins/execute/__init__.py index 08e96f5178..71d37fb87e 100644 --- a/pytest_plugins/execute/__init__.py +++ b/pytest_plugins/execute/__init__.py @@ -1 +1,4 @@ -"""A pytest plugin that provides fixtures that execute tests in live devnets/testnets.""" +""" +A pytest plugin that provides fixtures that execute tests in live +devnets/testnets. +""" diff --git a/pytest_plugins/execute/eth_config/eth_config.py b/pytest_plugins/execute/eth_config/eth_config.py index cb8d30a029..c373083eb9 100644 --- a/pytest_plugins/execute/eth_config/eth_config.py +++ b/pytest_plugins/execute/eth_config/eth_config.py @@ -95,8 +95,8 @@ def pytest_addoption(parser): def pytest_configure(config: pytest.Config) -> None: """ - Load the network configuration file and load the specific network to be used for - the test. + Load the network configuration file and load the specific network to be + used for the test. """ genesis_config_file = config.getoption("genesis_config_file") genesis_config_url = config.getoption("genesis_config_url") @@ -183,14 +183,20 @@ def pytest_configure(config: pytest.Config) -> None: @pytest.fixture(autouse=True, scope="session") def rpc_endpoint(request) -> str: - """Return remote RPC endpoint to be used to make requests to the execution client.""" + """ + Return remote RPC endpoint to be used to make requests to the execution + client. + """ return request.config.getoption("rpc_endpoint") def all_rpc_endpoints(config) -> Dict[str, List[EthRPC]]: - """Derive a mapping of exec clients to the RPC URLs they are reachable at.""" + """ + Derive a mapping of exec clients to the RPC URLs they are reachable at. + """ rpc_endpoint = config.getoption("rpc_endpoint") - el_clients: List[str] = config.getoption("majority_clients") # besu, erigon, .. + # besu, erigon, .. + el_clients: List[str] = config.getoption("majority_clients") if len(el_clients) == 0: endpoint_name = rpc_endpoint try: @@ -215,23 +221,23 @@ def all_rpc_endpoints(config) -> Dict[str, List[EthRPC]]: for exec_client in el_clients } # url_dict looks like this: - # { - # 'besu': [, , ..], # noqa: E501 - # 'erigon': ... - # ... - # } + # { 'besu': [, + # , ..], + # 'erigon': ... ... } return url_dict def pytest_generate_tests(metafunc: pytest.Metafunc): """Generate tests for all clients under test.""" # all_rpc_endpoints is a dictionary with the name of the exec client as key - # and the possible URLs to contact it (different cl combinations) as value list + # and the possible URLs to contact it (different cl combinations) as value + # list all_rpc_endpoints_dict = all_rpc_endpoints(metafunc.config) if metafunc.definition.name == "test_eth_config_majority": if len(all_rpc_endpoints_dict) < 2: - # The test function is not run because we only have a single client, so no majority comparison # noqa: E501 + # The test function is not run because we only have a single + # client, so no majority comparison logger.info( "Skipping eth_config majority because less than 2 exec clients were passed" ) diff --git a/pytest_plugins/execute/eth_config/execute_eth_config.py b/pytest_plugins/execute/eth_config/execute_eth_config.py index af43ec0b1e..efdc3122f9 100644 --- a/pytest_plugins/execute/eth_config/execute_eth_config.py +++ b/pytest_plugins/execute/eth_config/execute_eth_config.py @@ -1,4 +1,6 @@ -"""Pytest test to verify a client's configuration using `eth_config` RPC endpoint.""" +""" +Pytest test to verify a client's configuration using `eth_config` RPC endpoint. +""" import json import time @@ -17,7 +19,9 @@ @pytest.fixture(scope="function") def eth_config_response(eth_rpc: List[EthRPC]) -> EthConfigResponse | None: - """Get the `eth_config` response from the client to be verified by all tests.""" + """ + Get the `eth_config` response from the client to be verified by all tests. + """ for rpc in eth_rpc: try: response = rpc.config() @@ -37,13 +41,17 @@ def network(request) -> NetworkConfig: @pytest.fixture(scope="function") def current_time() -> int: - """Get the `eth_config` response from the client to be verified by all tests.""" + """ + Get the `eth_config` response from the client to be verified by all tests. + """ return int(time.time()) @pytest.fixture(scope="function") def expected_eth_config(network: NetworkConfig, current_time: int) -> EthConfigResponse: - """Calculate the current fork value to verify against the client's response.""" + """ + Calculate the current fork value to verify against the client's response. + """ return network.get_eth_config(current_time) @@ -190,12 +198,15 @@ def test_eth_config_last_fork_id( def test_eth_config_majority( all_rpc_endpoints: Dict[str, List[EthRPC]], ) -> None: - """Queries devnet exec clients for their eth_config and fails if not all have the same response.""" # noqa: E501 + """ + Queries devnet exec clients for their eth_config and fails if not all have + the same response. + """ responses = dict() # Dict[exec_client_name : response] # noqa: C408 client_to_url_used_dict = dict() # noqa: C408 for exec_client in all_rpc_endpoints.keys(): - # try only as many consensus+exec client combinations until you receive a response - # if all combinations for a given exec client fail we panic + # try only as many consensus+exec client combinations until you receive + # a response if all combinations for a given exec client fail we panic for eth_rpc_target in all_rpc_endpoints[exec_client]: try: response = eth_rpc_target.config(timeout=5) @@ -212,7 +223,7 @@ def test_eth_config_majority( responses[exec_client] = response_str client_to_url_used_dict[exec_client] = ( eth_rpc_target.url - ) # remember which cl+el combination was used # noqa: E501 + ) # remember which cl+el combination was used logger.info(f"Response of {exec_client}: {response_str}\n\n") break # no need to gather more responses for this client @@ -226,14 +237,15 @@ def test_eth_config_majority( "this execution client" ) # determine hashes of client responses - client_to_hash_dict = dict() # Dict[exec_client : response hash] # noqa: C408 + client_to_hash_dict = {} # Dict[exec_client : response hash] # noqa: C408 for client in responses.keys(): response_bytes = responses[client].encode("utf-8") response_hash = sha256(response_bytes).digest().hex() logger.info(f"Response hash of client {client}: {response_hash}") client_to_hash_dict[client] = response_hash - # if not all responses have the same hash there is a critical consensus issue + # if not all responses have the same hash there is a critical consensus + # issue expected_hash = "" for h in client_to_hash_dict.keys(): if expected_hash == "": @@ -241,15 +253,17 @@ def test_eth_config_majority( continue assert client_to_hash_dict[h] == expected_hash, ( - "Critical consensus issue: Not all eth_config responses are the same!\n" + "Critical consensus issue: Not all eth_config responses are the " + " same!\n" "Here is an overview of client response hashes:\n" + "\n\t".join(f"{k}: {v}" for k, v in client_to_hash_dict.items()) - + "\n\n" # noqa: E501 + + "\n\n" "Here is an overview of which URLs were contacted:\n\t" + "\n\t".join(f"{k}: @{v.split('@')[1]}" for k, v in client_to_url_used_dict.items()) - + "\n\n" # log which cl+el combinations were used without leaking full url # noqa: E501 + + "\n\n" + # log which cl+el combinations were used without leaking full url "Here is a dump of all client responses:\n" - + "\n\n".join(f"{k}: {v}" for k, v in responses.items()) # noqa: E501 + + "\n\n".join(f"{k}: {v}" for k, v in responses.items()) ) assert expected_hash != "" diff --git a/pytest_plugins/execute/eth_config/execute_types.py b/pytest_plugins/execute/eth_config/execute_types.py index efe32bb430..393d5c251c 100644 --- a/pytest_plugins/execute/eth_config/execute_types.py +++ b/pytest_plugins/execute/eth_config/execute_types.py @@ -33,8 +33,8 @@ class AddressOverrideDict(EthereumTestRootModel): """ Dictionary with overrides to the default addresses specified for each fork. - Required for testnets or devnets which have a different location of precompiles or system - contracts. + Required for testnets or devnets which have a different location of + precompiles or system contracts. """ root: Dict[Address, Address] @@ -73,8 +73,8 @@ def system_contracts(self) -> Dict[str, Address]: def get_config(self, fork_id: ForkHash) -> ForkConfig: """ - Get the current and next fork configurations given the current time and the network - configuration. + Get the current and next fork configurations given the current time and + the network configuration. """ return ForkConfig( activation_time=self.activation_time, @@ -87,7 +87,10 @@ def get_config(self, fork_id: ForkHash) -> ForkConfig: def calculate_fork_id(genesis_hash: Hash, activation_times: Set[int]) -> ForkHash: - """Calculate the fork Id given the genesis hash and each fork activation times.""" + """ + Calculate the fork Id given the genesis hash and each fork activation + times. + """ buffer = bytes(genesis_hash) for activation_time in sorted(activation_times): if activation_time == 0: @@ -275,9 +278,11 @@ def fork(self) -> Fork: @classmethod def preprocess_fork_times_blocks(cls, data: Any): """ - Pre-process the dictionary to put fork block numbers and times in the correct format. + Pre-process the dictionary to put fork block numbers and times in the + correct format. - Fork times and block numbers have the following format in the root of the object: + Fork times and block numbers have the following format in the root of + the object: ``` "berlinBlock": 0, @@ -287,8 +292,8 @@ def preprocess_fork_times_blocks(cls, data: Any): "osakaTime": 1753379304, ``` - This function strips the "*Block" and "*Time" part and moves the values. - + This function strips the "*Block" and "*Time" part and moves the + values. """ if isinstance(data, dict): fork_activation_times: Dict[str, int] = {} diff --git a/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py b/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py index bb147b8241..7a7bd7df0c 100644 --- a/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py +++ b/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py @@ -414,7 +414,7 @@ target: 15 max: 20 baseFeeUpdateFraction: 5007716 -""" +""" # W505 @pytest.fixture(scope="session") @@ -435,7 +435,9 @@ def network(request: pytest.FixtureRequest, network_configs: NetworkConfigFile) @pytest.fixture def eth_config(network: NetworkConfig, current_time: int) -> EthConfigResponse: - """Get the `eth_config` response from the client to be verified by all tests.""" + """ + Get the `eth_config` response from the client to be verified by all tests. + """ return network.get_eth_config(current_time) diff --git a/pytest_plugins/execute/execute.py b/pytest_plugins/execute/execute.py index e6ed68af65..42676a6211 100644 --- a/pytest_plugins/execute/execute.py +++ b/pytest_plugins/execute/execute.py @@ -1,4 +1,6 @@ -"""Test execution plugin for pytest, to run Ethereum tests using in live networks.""" +""" +Test execution plugin for pytest, to run Ethereum tests using in live networks. +""" import os from dataclasses import dataclass, field @@ -122,12 +124,12 @@ def pytest_configure(config): Couple of notes: 1. Register the plugin's custom markers and process command-line options. - Custom marker registration: - https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers + Custom marker registration: + https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers 2. `@pytest.hookimpl(tryfirst=True)` is applied to ensure that this hook is - called before the pytest-html plugin's pytest_configure to ensure that - it uses the modified `htmlpath` option. + called before the pytest-html plugin's pytest_configure to ensure that + it uses the modified `htmlpath` option. """ # Modify the block gas limit if specified. if config.getoption("transaction_gas_limit"): @@ -256,7 +258,9 @@ def default_max_priority_fee_per_gas(request) -> int: def modify_transaction_defaults( default_gas_price: int, default_max_fee_per_gas: int, default_max_priority_fee_per_gas: int ): - """Modify transaction defaults to values better suited for live networks.""" + """ + Modify transaction defaults to values better suited for live networks. + """ TransactionDefaults.gas_price = default_gas_price TransactionDefaults.max_fee_per_gas = default_max_fee_per_gas TransactionDefaults.max_priority_fee_per_gas = default_max_priority_fee_per_gas @@ -264,7 +268,10 @@ def modify_transaction_defaults( @dataclass(kw_only=True) class Collector: - """A class that collects transactions and post-allocations for every test case.""" + """ + A class that collects transactions and post-allocations for every test + case. + """ eth_rpc: EthRPC collected_tests: Dict[str, BaseExecute] = field(default_factory=dict) @@ -280,8 +287,8 @@ def collector( eth_rpc: EthRPC, ) -> Generator[Collector, None, None]: """ - Return configured fixture collector instance used for all tests - in one test module. + Return configured fixture collector instance used for all tests in one test + module. """ del request @@ -293,8 +300,8 @@ def base_test_parametrizer(cls: Type[BaseTest]): """ Generate pytest.fixture for a given BaseTest subclass. - Implementation detail: All spec fixtures must be scoped on test function level to avoid - leakage between tests. + Implementation detail: All spec fixtures must be scoped on test function + level to avoid leakage between tests. """ cls_fixture_parameters = [p for p in ALL_FIXTURE_PARAMETERS if p in cls.model_fields] @@ -311,14 +318,15 @@ def base_test_parametrizer_func( collector: Collector, ): """ - Fixture used to instantiate an auto-fillable BaseTest object from within - a test function. + Fixture used to instantiate an auto-fillable BaseTest object from + within a test function. - Every test that defines a test filler must explicitly specify its parameter name - (see `pytest_parameter_name` in each implementation of BaseTest) in its function - arguments. + Every test that defines a test filler must explicitly specify its + parameter name (see `pytest_parameter_name` in each implementation of + BaseTest) in its function arguments. - When parametrize, indirect must be used along with the fixture format as value. + When parametrize, indirect must be used along with the fixture format + as value. """ execute_format = request.param assert execute_format in BaseExecute.formats.values() @@ -377,8 +385,8 @@ def __init__(self, *args, **kwargs): def pytest_generate_tests(metafunc: pytest.Metafunc): """ - Pytest hook used to dynamically generate test cases for each fixture format a given - test spec supports. + Pytest hook used to dynamically generate test cases for each fixture format + a given test spec supports. """ engine_rpc_supported = metafunc.config.engine_rpc_supported # type: ignore for test_type in BaseTest.spec_types.values(): @@ -397,10 +405,11 @@ def pytest_generate_tests(metafunc: pytest.Metafunc): ) -def pytest_collection_modifyitems(config: pytest.Config, items: List[pytest.Item]): - """Remove transition tests and add the appropriate execute markers to the test.""" - del config - +def pytest_collection_modifyitems(items: List[pytest.Item]): + """ + Remove transition tests and add the appropriate execute markers to the + test. + """ items_for_removal = [] for i, item in enumerate(items): if isinstance(item, EIPSpecTestItem): diff --git a/pytest_plugins/execute/pre_alloc.py b/pytest_plugins/execute/pre_alloc.py index 273a6ab3a4..239de55f93 100644 --- a/pytest_plugins/execute/pre_alloc.py +++ b/pytest_plugins/execute/pre_alloc.py @@ -48,8 +48,9 @@ class AddressStubs(EthereumTestRootModel[Dict[str, Address]]): """ Address stubs class. - The key represents the label that is used in the test to tag the contract, and the value - is the address where the contract is already located at in the current network. + The key represents the label that is used in the test to tag the contract, + and the value is the address where the contract is already located at in + the current network. """ root: Dict[str, Address] @@ -65,8 +66,8 @@ def __getitem__(self, item: str) -> Address: @classmethod def model_validate_json_or_file(cls, json_data_or_path: str) -> Self: """ - Try to load from file if the value resembles a path that ends with .json/.yml and the - file exists. + Try to load from file if the value resembles a path that ends with + .json/.yml and the file exists. """ lower_json_data_or_path = json_data_or_path.lower() if ( @@ -342,7 +343,10 @@ def fund_eoa( delegation: Address | Literal["Self"] | None = None, nonce: NumberConvertible | None = None, ) -> EOA: - """Add a previously unused EOA to the pre-alloc with the balance specified by `amount`.""" + """ + Add a previously unused EOA to the pre-alloc with the balance specified + by `amount`. + """ assert nonce is None, "nonce parameter is not supported for execute" eoa = next(self._eoa_iterator) eoa.label = label @@ -385,7 +389,8 @@ def fund_eoa( if delegation is not None: if not isinstance(delegation, Address) and delegation == "Self": delegation = eoa - # TODO: This tx has side-effects on the EOA state because of the delegation + # TODO: This tx has side-effects on the EOA state because of + # the delegation fund_tx = Transaction( sender=self._sender, to=eoa, @@ -409,7 +414,8 @@ def fund_eoa( authorization_list=[ AuthorizationTuple( chain_id=self._chain_id, - address=0, # Reset delegation to an address without code + # Reset delegation to an address without code + address=0, nonce=eoa.nonce, signer=eoa, ), @@ -478,7 +484,8 @@ def fund_address(self, address: Address, amount: NumberConvertible): def empty_account(self) -> Address: """ - Add a previously unused account guaranteed to be empty to the pre-alloc. + Add a previously unused account guaranteed to be empty to the + pre-alloc. This ensures the account has: - Zero balance @@ -486,8 +493,9 @@ def empty_account(self) -> Address: - No code - No storage - This is different from precompiles or system contracts. The function does not - send any transactions, ensuring that the account remains "empty." + This is different from precompiles or system contracts. The function + does not send any transactions, ensuring that the account remains + "empty." Returns: Address: The address of the created empty account. diff --git a/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py b/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py index 017eb40fbc..d41fd68843 100644 --- a/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py +++ b/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py @@ -1,4 +1,7 @@ -"""Chain builder Ethereum RPC that can drive the chain when new transactions are submitted.""" +""" +Chain builder Ethereum RPC that can drive the chain when new transactions are +submitted. +""" import time from pathlib import Path @@ -87,10 +90,11 @@ def __iter__(self): class PendingTxHashes: """ - A class to manage the pending transaction hashes in a multi-process environment. + A class to manage the pending transaction hashes in a multi-process + environment. - It uses a lock file to ensure that only one process can access the pending hashes file at a - time. + It uses a lock file to ensure that only one process can access the pending + hashes file at a time. """ pending_hashes_file: Path @@ -166,9 +170,9 @@ def __iter__(self): class ChainBuilderEthRPC(BaseEthRPC, namespace="eth"): """ - Special type of Ethereum RPC client that also has access to the Engine API and automatically - coordinates block generation based on the number of pending transactions or a block generation - interval. + Special type of Ethereum RPC client that also has access to the Engine API + and automatically coordinates block generation based on the number of + pending transactions or a block generation interval. """ fork: Fork @@ -336,11 +340,12 @@ def wait_for_transactions( self, transactions: List[Transaction] ) -> List[TransactionByHashResponse]: """ - Wait for all transactions in the provided list to be included in a block. + Wait for all transactions in the provided list to be included in a + block. - Waits for all transactions in the provided list to be included in a block - by polling `eth_getTransactionByHash` until they are confirmed or a - timeout occurs. + Waits for all transactions in the provided list to be included in a + block by polling `eth_getTransactionByHash` until they are confirmed or + a timeout occurs. Args: transactions: A list of transactions to track. @@ -398,8 +403,8 @@ def wait_for_transactions( class PendingTransactionHandler: """ - Manages block generation based on the number of pending transactions or a block generation - interval. + Manages block generation based on the number of pending transactions or a + block generation interval. Attributes: block_generation_interval: The number of iterations after which a block @@ -423,11 +428,12 @@ def handle(self): """ Handle pending transactions and generate blocks if necessary. - If the number of pending transactions reaches the limit, a block is generated. + If the number of pending transactions reaches the limit, a block is + generated. - If no new transactions have been added to the pending list and the block - generation interval has been reached, a block is generated to avoid potential - deadlock. + If no new transactions have been added to the pending list and the + block generation interval has been reached, a block is generated to + avoid potential deadlock. """ with self.chain_builder_eth_rpc.pending_tx_hashes: if ( @@ -442,8 +448,8 @@ def handle(self): == self.last_pending_tx_hashes_count and self.i % self.block_generation_interval == 0 ): - # If no new transactions have been added to the pending list, - # generate a block to avoid potential deadlock. + # If no new transactions have been added to the pending + # list, generate a block to avoid potential deadlock. self.chain_builder_eth_rpc.generate_block() self.last_pending_tx_hashes_count = len(self.chain_builder_eth_rpc.pending_tx_hashes) self.i += 1 diff --git a/pytest_plugins/execute/rpc/hive.py b/pytest_plugins/execute/rpc/hive.py index 0ae0f02e09..c36349c5fa 100644 --- a/pytest_plugins/execute/rpc/hive.py +++ b/pytest_plugins/execute/rpc/hive.py @@ -147,7 +147,10 @@ def base_pre_genesis( @pytest.fixture(scope="session") def client_genesis(base_pre_genesis: Tuple[Alloc, FixtureHeader]) -> dict: - """Convert the fixture's genesis block header and pre-state to a client genesis state.""" + """ + Convert the fixture's genesis block header and pre-state to a client + genesis state. + """ genesis = to_json(base_pre_genesis[1]) # NOTE: to_json() excludes None values alloc = to_json(base_pre_genesis[0]) # NOTE: nethermind requires account keys without '0x' prefix @@ -211,7 +214,9 @@ def test_suite_description() -> str: def base_hive_test( request: pytest.FixtureRequest, test_suite: HiveTestSuite, session_temp_folder: Path ) -> Generator[HiveTest, None, None]: - """Test (base) used to deploy the main client to be used throughout all tests.""" + """ + Test (base) used to deploy the main client to be used throughout all tests. + """ base_name = "base_hive_test" base_file = session_temp_folder / base_name base_lock_file = session_temp_folder / f"{base_name}.lock" @@ -276,7 +281,9 @@ def client( client_type: ClientType, session_temp_folder: Path, ) -> Generator[Client, None, None]: - """Initialize the client with the appropriate files and environment variables.""" + """ + Initialize the client with the appropriate files and environment variables. + """ base_name = "hive_client" base_file = session_temp_folder / base_name base_error_file = session_temp_folder / f"{base_name}.err" diff --git a/pytest_plugins/execute/rpc/remote.py b/pytest_plugins/execute/rpc/remote.py index d5168af951..4f87766235 100644 --- a/pytest_plugins/execute/rpc/remote.py +++ b/pytest_plugins/execute/rpc/remote.py @@ -87,7 +87,8 @@ def pytest_configure(config: pytest.Config): """Check if a chain ID configuration is provided.""" if config.getoption("rpc_chain_id") is None and config.getoption("chain_id") is None: pytest.exit("No chain ID configuration found. Please use --chain-id.") - # Verify the chain ID configuration is consistent with the remote RPC endpoint + # Verify the chain ID configuration is consistent with the remote RPC + # endpoint rpc_endpoint = config.getoption("rpc_endpoint") eth_rpc = EthRPC(rpc_endpoint) remote_chain_id = eth_rpc.chain_id() @@ -127,8 +128,9 @@ def pytest_configure(config: pytest.Config): f"JWT secret must be a bytes object, got {type(jwt_secret)}" ) engine_rpc = EngineRPC(engine_endpoint, jwt_secret=jwt_secret) - # TODO: Perform a request to the engine endpoint to verify that the JWT secret is valid. - # Potentially could be `engine_getClientVersionV1` but need to implement this in rpc.py. + # TODO: Perform a request to the engine endpoint to verify that the JWT + # secret is valid. Potentially could be `engine_getClientVersionV1` but + # need to implement this in rpc.py. config.engine_rpc = engine_rpc # type: ignore @@ -140,7 +142,10 @@ def engine_rpc(request) -> EngineRPC | None: @pytest.fixture(autouse=True, scope="session") def rpc_endpoint(request) -> str: - """Return remote RPC endpoint to be used to make requests to the execution client.""" + """ + Return remote RPC endpoint to be used to make requests to the execution + client. + """ return request.config.getoption("rpc_endpoint") diff --git a/pytest_plugins/execute/sender.py b/pytest_plugins/execute/sender.py index 016fd4862f..a93a4081d2 100644 --- a/pytest_plugins/execute/sender.py +++ b/pytest_plugins/execute/sender.py @@ -85,15 +85,17 @@ def sender_key_initial_balance( """ Calculate the initial balance of each sender key. - The way to do this is to fetch the seed sender balance and divide it by the number of - workers. This way we can ensure that each sender key has the same initial balance. + The way to do this is to fetch the seed sender balance and divide it by the + number of workers. This way we can ensure that each sender key has the same + initial balance. - We also only do this once per session, because if we try to fetch the balance again, it - could be that another worker has already sent a transaction and the balance is different. + We also only do this once per session, because if we try to fetch the + balance again, it could be that another worker has already sent a + transaction and the balance is different. - It's not really possible to calculate the transaction costs of each test that each worker - is going to run, so we can't really calculate the initial balance of each sender key - based on that. + It's not really possible to calculate the transaction costs of each test + that each worker is going to run, so we can't really calculate the initial + balance of each sender key based on that. """ base_name = "sender_key_initial_balance" base_file = session_temp_folder / base_name @@ -108,7 +110,8 @@ def sender_key_initial_balance( seed_account_sweep_amount = eth_rpc.get_balance(seed_sender) seed_sender_balance_per_worker = seed_account_sweep_amount // worker_count assert seed_sender_balance_per_worker > 100, "Seed sender balance too low" - # Subtract the cost of the transaction that is going to be sent to the seed sender + # Subtract the cost of the transaction that is going to be sent to + # the seed sender sender_key_initial_balance = seed_sender_balance_per_worker - ( sender_fund_refund_gas_limit * sender_funding_transactions_gas_price ) @@ -132,11 +135,12 @@ def sender_key( """ Get the sender keys for all tests. - The seed sender is going to be shared among different processes, so we need to lock it - before we produce each funding transaction. + The seed sender is going to be shared among different processes, so we need + to lock it before we produce each funding transaction. """ - # For the seed sender we do need to keep track of the nonce because it is shared among - # different processes, and there might not be a new block produced between the transactions. + # For the seed sender we do need to keep track of the nonce because it is + # shared among different processes, and there might not be a new block + # produced between the transactions. seed_sender_nonce_file_name = "seed_sender_nonce" seed_sender_lock_file_name = f"{seed_sender_nonce_file_name}.lock" seed_sender_nonce_file = session_temp_folder / seed_sender_nonce_file_name @@ -172,15 +176,16 @@ def sender_key( ) refund_gas_limit = sender_fund_refund_gas_limit - # double the gas price to ensure the transaction is included and overwrites any other - # transaction that might have been sent by the sender. + # double the gas price to ensure the transaction is included and overwrites + # any other transaction that might have been sent by the sender. refund_gas_price = sender_funding_transactions_gas_price * 2 tx_cost = refund_gas_limit * refund_gas_price if (remaining_balance - 1) < tx_cost: return - # Update the nonce of the sender in case one of the pre-alloc transactions failed + # Update the nonce of the sender in case one of the pre-alloc transactions + # failed sender.nonce = Number(eth_rpc.get_transaction_count(sender)) refund_tx = Transaction( diff --git a/pytest_plugins/filler/eip_checklist.py b/pytest_plugins/filler/eip_checklist.py index 2387aa178c..855c903bb5 100644 --- a/pytest_plugins/filler/eip_checklist.py +++ b/pytest_plugins/filler/eip_checklist.py @@ -1,8 +1,8 @@ """ Pytest plugin for generating EIP test completion checklists. -This plugin collects checklist markers from tests and generates a filled checklist -for each EIP based on the template at +This plugin collects checklist markers from tests and generates a filled +checklist for each EIP based on the template at docs/writing_tests/checklist_templates/eip_testing_checklist_template.md """ @@ -195,7 +195,9 @@ class ConflictingChecklistItemsWarning(ChecklistWarning): @classmethod def from_items(cls, all_items: Dict[str, EIPItem]) -> ChecklistWarning | None: - """Generate a conflicting checklist items warning from a list of items.""" + """ + Generate a conflicting checklist items warning from a list of items. + """ conflicting_items = [ item for item in all_items.values() if item.not_applicable and item.covered ] @@ -335,8 +337,8 @@ def generate_filled_checklist_lines(self) -> List[str]: # Replace the title line with the EIP number lines[lines.index(TITLE_LINE)] = f"# EIP-{self.number} Test Checklist" - # Last, add the warnings if there are any, this must be the last thing we do - # to avoid shifting the lines below the percentage line + # Last, add the warnings if there are any, this must be the last thing + # we do to avoid shifting the lines below the percentage line if self.warnings: warnings_line_idx = lines.index(WARNINGS_LINE) warnings_lines = ["", "## ⚠️ Checklist Warnings ⚠️", ""] diff --git a/pytest_plugins/filler/filler.py b/pytest_plugins/filler/filler.py index 30b605d753..edb3293c87 100644 --- a/pytest_plugins/filler/filler.py +++ b/pytest_plugins/filler/filler.py @@ -2,8 +2,8 @@ Top-level pytest configuration file providing: - Command-line options, - Test-fixtures that can be used by all test cases, -and that modifies pytest hooks in order to fill test specs for all tests and -writes the generated fixtures to file. +and that modifies pytest hooks in order to fill test specs for all tests +and writes the generated fixtures to file. """ import configparser @@ -60,12 +60,16 @@ class PhaseManager: """ Manages the execution phase for fixture generation. - The filler plugin supports two-phase execution for pre-allocation group generation: - - Phase 1: Generate pre-allocation groups (pytest run with --generate-pre-alloc-groups). - - Phase 2: Fill fixtures using pre-allocation groups (pytest run with --use-pre-alloc-groups). + The filler plugin supports two-phase execution for pre-allocation group + generation: + - Phase 1: Generate pre-allocation groups (pytest run with + --generate-pre-alloc-groups). - Note: These are separate pytest runs orchestrated by the CLI wrapper. - Each run gets a fresh PhaseManager instance (no persistence between phases). + - Phase 2: Fill fixtures using pre-allocation + groups (pytest run with --use-pre-alloc-groups). + + Note: These are separate pytest runs orchestrated by the CLI wrapper. Each + run gets a fresh PhaseManager instance (no persistence between phases). """ current_phase: FixtureFillingPhase @@ -77,13 +81,15 @@ def from_config(cls, config: pytest.Config) -> "Self": Create a PhaseManager from pytest configuration. Flag logic: - - use_pre_alloc_groups: We're in phase 2 (FILL) after phase 1 (PRE_ALLOC_GENERATION). - - generate_pre_alloc_groups or generate_all_formats: We're in phase 1 - (PRE_ALLOC_GENERATION). - - Otherwise: Normal single-phase filling (FILL). - - Note: generate_all_formats triggers PRE_ALLOC_GENERATION because the CLI - passes it to phase 1 to ensure all formats are considered for grouping. + - use_pre_alloc_groups: We're in phase 2 (FILL) after phase + 1 (PRE_ALLOC_GENERATION). + - generate_pre_alloc_groups or generate_all_formats: + We're in phase 1 (PRE_ALLOC_GENERATION). - + Otherwise: Normal single-phase filling (FILL). + + Note: generate_all_formats triggers PRE_ALLOC_GENERATION because the + CLI passes it to phase 1 to ensure all formats are considered for + grouping. """ generate_pre_alloc = config.getoption("generate_pre_alloc_groups", False) use_pre_alloc = config.getoption("use_pre_alloc_groups", False) @@ -127,10 +133,11 @@ def is_single_phase_fill(self) -> bool: @dataclass(kw_only=True) class FormatSelector: """ - Handles fixture format selection based on the current phase and format capabilities. + Handles fixture format selection based on the current phase and format + capabilities. - This class encapsulates the complex logic for determining which fixture formats - should be generated in each phase of the two-phase execution model. + This class encapsulates the complex logic for determining which fixture + formats should be generated in each phase of the two-phase execution model. """ phase_manager: PhaseManager @@ -141,10 +148,11 @@ def should_generate(self, fixture_format: Type[BaseFixture] | LabeledFixtureForm Determine if a fixture format should be generated in the current phase. Args: - fixture_format: The fixture format to check (may be wrapped in LabeledFixtureFormat) + fixture_format: The fixture format to check (may be wrapped in + LabeledFixtureFormat). Returns: - True if the format should be generated in the current phase + True if the format should be generated in the current phase. """ format_phases = fixture_format.format_phases @@ -155,7 +163,10 @@ def should_generate(self, fixture_format: Type[BaseFixture] | LabeledFixtureForm return self._should_generate_fill(format_phases) def _should_generate_pre_alloc(self, format_phases: Set[FixtureFillingPhase]) -> bool: - """Determine if format should be generated during pre-alloc generation phase.""" + """ + Determine if format should be generated during pre-alloc generation + phase. + """ # Only generate formats that need pre-allocation groups return FixtureFillingPhase.PRE_ALLOC_GENERATION in format_phases @@ -164,7 +175,8 @@ def _should_generate_fill(self, format_phases: Set[FixtureFillingPhase]) -> bool if FixtureFillingPhase.PRE_ALLOC_GENERATION in self.phase_manager.previous_phases: # Phase 2: After pre-alloc generation if self.generate_all_formats: - # Generate all formats, including those that don't need pre-alloc + # Generate all formats, including those that don't need pre- + # alloc return True else: # Only generate formats that needed pre-alloc groups @@ -179,12 +191,13 @@ class FillingSession: """ Manages all state for a single pytest fill session. - This class serves as the single source of truth for all filler state management, - including phase management, format selection, and pre-allocation groups. + This class serves as the single source of truth for all filler state + management, including phase management, format selection, and + pre-allocation groups. - Important: Each pytest run gets a fresh FillingSession instance. There is no - persistence between phase 1 (generate pre-alloc) and phase 2 (use pre-alloc) - except through file I/O. + Important: Each pytest run gets a fresh FillingSession instance. There is + no persistence between phase 1 (generate pre-alloc) and phase 2 (use + pre-alloc) except through file I/O. """ fixture_output: FixtureOutput @@ -240,7 +253,8 @@ def should_generate_format( self, fixture_format: Type[BaseFixture] | LabeledFixtureFormat ) -> bool: """ - Determine if a fixture format should be generated in the current session. + Determine if a fixture format should be generated in the current + session. Args: fixture_format: The fixture format to check. @@ -335,9 +349,9 @@ def calculate_post_state_diff(post_state: Alloc, genesis_state: Alloc) -> Alloc: """ Calculate the state difference between post_state and genesis_state. - This function enables significant space savings in Engine X fixtures by storing - only the accounts that changed during test execution, rather than the full - post-state which may contain thousands of unchanged accounts. + This function enables significant space savings in Engine X fixtures by + storing only the accounts that changed during test execution, rather than + the full post-state which may contain thousands of unchanged accounts. Returns an Alloc containing only the accounts that: - Changed between genesis and post state (balance, nonce, storage, code) @@ -624,12 +638,12 @@ def pytest_configure(config): Couple of notes: 1. Register the plugin's custom markers and process command-line options. - Custom marker registration: - https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers + Custom marker registration: + https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers 2. `@pytest.hookimpl(tryfirst=True)` is applied to ensure that this hook is - called before the pytest-html plugin's pytest_configure to ensure that - it uses the modified `htmlpath` option. + called before the pytest-html plugin's pytest_configure to ensure that + it uses the modified `htmlpath` option. """ # Register custom markers # Modify the block gas limit if specified. @@ -646,7 +660,8 @@ def pytest_configure(config): return try: - # Check whether the directory exists and is not empty; if --clean is set, it will delete it + # Check whether the directory exists and is not empty; if --clean is + # set, it will delete it config.fixture_output.create_directories(is_master=not hasattr(config, "workerinput")) except ValueError as e: pytest.exit(str(e), returncode=pytest.ExitCode.USAGE_ERROR) @@ -670,8 +685,9 @@ def pytest_configure(config): "optimize_gas", False ) - # Instantiate the transition tool here to check that the binary path/trace option is valid. - # This ensures we only raise an error once, if appropriate, instead of for every test. + # Instantiate the transition tool here to check that the binary path/trace + # option is valid. This ensures we only raise an error once, if + # appropriate, instead of for every test. evm_bin = config.getoption("evm_bin") trace = config.getoption("evm_collect_traces") t8n_server_url = config.getoption("t8n_server_url") @@ -730,8 +746,8 @@ def pytest_report_teststatus(report, config: pytest.Config): We use this: 1. To disable test session progress report if we're writing the JSON - fixtures to stdout to be read by a consume command on stdin. I.e., - don't write this type of output to the console: + fixtures to stdout to be read by a consume command on stdin. I.e., don't + write this type of output to the console: ```text ...x... ``` @@ -872,7 +888,8 @@ def pytest_runtest_makereport(item, call): ]: report.user_properties.append(("evm_dump_dir", item.config.evm_dump_dir)) else: - report.user_properties.append(("evm_dump_dir", "N/A")) # not yet for EOF + # not yet for EOF + report.user_properties.append(("evm_dump_dir", "N/A")) def pytest_html_report_title(report): @@ -889,8 +906,7 @@ def evm_bin(request: pytest.FixtureRequest) -> Path | None: @pytest.fixture(autouse=True, scope="session") def verify_fixtures_bin(request: pytest.FixtureRequest) -> Path | None: """ - Return configured evm tool binary path used to run statetest or - blocktest. + Return configured evm tool binary path used to run statetest or blocktest. """ return request.config.getoption("verify_fixtures_bin") @@ -935,8 +951,8 @@ def evm_fixture_verification( verify_fixtures_bin: Path | None, ) -> Generator[FixtureConsumer | None, None, None]: """ - Return configured evm binary for executing statetest and blocktest - commands used to verify generated JSON fixtures. + Return configured evm binary for executing statetest and blocktest commands + used to verify generated JSON fixtures. """ if not do_fixture_verification: yield None @@ -1049,8 +1065,9 @@ def dump_dir_parameter_level( Directory to dump evm transition tool debug output on a test parameter level. - Example with --evm-dump-dir=/tmp/evm: - -> /tmp/evm/shanghai__eip3855_push0__test_push0__test_push0_key_sstore/fork_shanghai/ + Example with --evm-dump-dir=/tmp/evm: -> + /tmp/evm/shanghai__eip3855_push0__test_push0__test_push0_key_sstore/fork_shangh + ai/ """ evm_dump_dir = node_to_test_info(request.node).get_dump_dir_path( base_dump_dir, @@ -1102,8 +1119,8 @@ def fixture_collector( fixture_output: FixtureOutput, ) -> Generator[FixtureCollector, None, None]: """ - Return configured fixture collector instance used for all tests - in one test module. + Return configured fixture collector instance used for all tests in one test + module. """ # Dynamically load the 'static_filler' and 'solc' plugins if needed if request.config.getoption("fill_static_tests_enabled"): @@ -1163,8 +1180,9 @@ def fixture_source_url( ) test_module_relative_path = os.path.relpath(request.module.__file__) if module_relative_path != test_module_relative_path: - # This can be the case when the test function's body only contains pass and the entire - # test logic is implemented as a test generator from the framework. + # This can be the case when the test function's body only contains pass + # and the entire test logic is implemented as a test generator from the + # framework. test_module_github_url = generate_github_url( test_module_relative_path, branch_or_commit_or_tag=commit_hash_or_tag, @@ -1177,8 +1195,8 @@ def base_test_parametrizer(cls: Type[BaseTest]): """ Generate pytest.fixture for a given BaseTest subclass. - Implementation detail: All spec fixtures must be scoped on test function level to avoid - leakage between tests. + Implementation detail: All spec fixtures must be scoped on test function + level to avoid leakage between tests. """ cls_fixture_parameters = [p for p in ALL_FIXTURE_PARAMETERS if p in cls.model_fields] @@ -1201,14 +1219,15 @@ def base_test_parametrizer_func( witness_generator, ): """ - Fixture used to instantiate an auto-fillable BaseTest object from within - a test function. + Fixture used to instantiate an auto-fillable BaseTest object from + within a test function. - Every test that defines a test filler must explicitly specify its parameter name - (see `pytest_parameter_name` in each implementation of BaseTest) in its function - arguments. + Every test that defines a test filler must explicitly specify its + parameter name (see `pytest_parameter_name` in each implementation of + BaseTest) in its function arguments. - When parametrize, indirect must be used along with the fixture format as value. + When parametrize, indirect must be used along with the fixture format + as value. """ if hasattr(request.node, "fixture_format"): fixture_format = request.node.fixture_format @@ -1248,13 +1267,15 @@ def __init__(self, *args, **kwargs): # Phase 1: Generate pre-allocation groups if session.phase_manager.is_pre_alloc_generation: - # Use the original update_pre_alloc_groups method which returns the groups + # Use the original update_pre_alloc_groups method which + # returns the groups self.update_pre_alloc_groups( session.pre_alloc_groups, fork, request.node.nodeid ) return # Skip fixture generation in phase 1 - # Phase 2: Use pre-allocation groups (only for BlockchainEngineXFixture) + # Phase 2: Use pre-allocation groups (only for + # BlockchainEngineXFixture) pre_alloc_hash = None if FixtureFillingPhase.PRE_ALLOC_GENERATION in fixture_format.format_phases: pre_alloc_hash = self.compute_pre_alloc_group_hash(fork=fork) @@ -1273,11 +1294,13 @@ def __init__(self, *args, **kwargs): ): gas_optimized_tests = request.config.gas_optimized_tests assert gas_optimized_tests is not None - # Force adding something to the list, even if it's None, - # to keep track of failed tests in the output file. + # Force adding something to the list, even if it's + # None, to keep track of failed tests in the output + # file. gas_optimized_tests[request.node.nodeid] = self._gas_optimization - # Post-process for Engine X format (add pre_hash and state diff) + # Post-process for Engine X format (add pre_hash and state + # diff) if ( FixtureFillingPhase.PRE_ALLOC_GENERATION in fixture_format.format_phases and pre_alloc_hash is not None @@ -1299,7 +1322,8 @@ def __init__(self, *args, **kwargs): _info_metadata=t8n._info_metadata, ) - # Generate witness data if witness functionality is enabled via the witness plugin + # Generate witness data if witness functionality is enabled via + # the witness plugin if witness_generator is not None: witness_generator(fixture) @@ -1328,11 +1352,11 @@ def __init__(self, *args, **kwargs): def pytest_generate_tests(metafunc: pytest.Metafunc): """ - Pytest hook used to dynamically generate test cases for each fixture format a given - test spec supports. + Pytest hook used to dynamically generate test cases for each fixture format + a given test spec supports. - NOTE: The static test filler does NOT use this hook. See FillerFile.collect() in - ./static_filler.py for more details. + NOTE: The static test filler does NOT use this hook. See + FillerFile.collect() in ./static_filler.py for more details. """ session: FillingSession = metafunc.config.filling_session # type: ignore[attr-defined] for test_type in BaseTest.spec_types.values(): @@ -1360,7 +1384,8 @@ def pytest_collection_modifyitems( Remove pre-Paris tests parametrized to generate hive type fixtures; these can't be used in the Hive Pyspec Simulator. - Replaces the test ID for state tests that use a transition fork with the base fork. + Replaces the test ID for state tests that use a transition fork with the + base fork. These can't be handled in this plugins pytest_generate_tests() as the fork parametrization occurs in the forks plugin. @@ -1390,7 +1415,8 @@ def pytest_collection_modifyitems( markers = list(item.iter_markers()) - # Automatically apply pre_alloc_group marker to slow tests that are not benchmark tests + # Automatically apply pre_alloc_group marker to slow tests that are not + # benchmark tests has_slow_marker = any(marker.name == "slow" for marker in markers) has_benchmark_marker = any(marker.name == "benchmark" for marker in markers) has_pre_alloc_group_marker = any(marker.name == "pre_alloc_group" for marker in markers) @@ -1408,8 +1434,8 @@ def pytest_collection_modifyitems( # Re-collect markers after adding the new one markers = list(item.iter_markers()) - # Both the fixture format itself and the spec filling it have a chance to veto the - # filling of a specific format. + # Both the fixture format itself and the spec filling it have a chance + # to veto the filling of a specific format. if fixture_format.discard_fixture_format_by_marks(fork, markers): items_for_removal.append(i) continue diff --git a/pytest_plugins/filler/fixture_output.py b/pytest_plugins/filler/fixture_output.py index 3238c7d6ec..c9f421f6ed 100644 --- a/pytest_plugins/filler/fixture_output.py +++ b/pytest_plugins/filler/fixture_output.py @@ -69,7 +69,9 @@ def pre_alloc_groups_folder_path(self) -> Path: @property def should_auto_enable_all_formats(self) -> bool: - """Check if all formats should be auto-enabled due to tarball output.""" + """ + Check if all formats should be auto-enabled due to tarball output. + """ return self.is_tarball @staticmethod @@ -95,7 +97,8 @@ def is_directory_usable_for_phase(self) -> bool: # Phase 1: Directory must be completely empty return self.is_directory_empty() elif self.use_pre_alloc_groups: - # Phase 2: Only pre-allocation groups must exist, no other files allowed + # Phase 2: Only pre-allocation groups must exist, no other files + # allowed if not self.pre_alloc_groups_folder_path.exists(): return False # Check that only the pre-allocation group files exist @@ -149,13 +152,14 @@ def create_directories(self, is_master: bool) -> None: """ Create output and metadata directories if needed. - If clean flag is set, remove and recreate the directory. - Otherwise, verify the directory is empty before proceeding. + If clean flag is set, remove and recreate the directory. Otherwise, + verify the directory is empty before proceeding. """ if self.is_stdout: return - # Only the master process should delete/create directories if using pytest-xdist + # Only the master process should delete/create directories if using + # pytest-xdist if not is_master: return diff --git a/pytest_plugins/filler/gen_test_doc/gen_test_doc.py b/pytest_plugins/filler/gen_test_doc/gen_test_doc.py index 044b2a2e9a..aae46ab5fe 100644 --- a/pytest_plugins/filler/gen_test_doc/gen_test_doc.py +++ b/pytest_plugins/filler/gen_test_doc/gen_test_doc.py @@ -1,34 +1,34 @@ """ A pytest plugin that generates test case documentation for use in mkdocs. -It generates the top-level "Test Case Reference" section in EEST's mkdocs -site. +It generates the top-level "Test Case Reference" section in EEST's mkdocs site. Note: ---- -- No output directory is specified for the generated output; file IO occurs - via the `mkdocs-gen-files` plugin. `mkdocs serve` writes intermediate files - to our local `docs/` directory and then copies it to the site directory. - We modify `docs/navigation.md` and write all other output underneath - `docs/tests`. If mkdocs is interrupted, these intermediate artifacts are - left in `docs/`. +- No output directory is specified for the generated output; file IO +occurs via the `mkdocs-gen-files` plugin. `mkdocs serve` writes intermediate +files to our local `docs/` directory and then copies it to the site directory. +We modify `docs/navigation.md` and write all other output underneath +`docs/tests`. If mkdocs is interrupted, these intermediate artifacts are left +in `docs/`. Usage: ------ !!! note "Ensuring a clean build" - In case mkdocs has polluted the `docs/` directory with intermediate files, run: +In case mkdocs has polluted the `docs/` directory with intermediate files, run: - ```console - git restore docs/navigation.md # Careful if you have local modifications! - rm -rf docs/tests docs/docs site - ``` +```console +git restore docs/navigation.md # Careful if you have local modifications! +rm -rf docs/tests docs/docs site +``` To test doc generation, run the plugin without mkdocs: ```console -uv run fill -p pytest_plugins.filler.gen_test_doc.gen_test_doc --gen-docs --fork= tests +uv run fill -p pytest_plugins.filler.gen_test_doc.gen_test_doc --gen-docs \ + --fork= tests ``` Or to build and view the site: @@ -128,8 +128,8 @@ def get_test_function_import_path(item: pytest.Item) -> str: """ Retrieve the fully qualified import path for an item's test function. - This is used in jinja2 templates to get the test function, respectively - the test function's class, documentation with mkdocstrings. + This is used in jinja2 templates to get the test function, respectively the + test function's class, documentation with mkdocstrings. """ item = cast(pytest.Function, item) # help mypy infer type module_name = item.module.__name__ @@ -150,7 +150,8 @@ def get_import_path(path: Path) -> str: Get the import path for a given path. - For modules, strip the file extension. - - For directories (i.e., packages such as `tests.berlin`), `with_suffix()` is ignored. + - For directories (i.e., packages such as `tests.berlin`), + `with_suffix()` is ignored. To do: ------ @@ -273,7 +274,8 @@ def pytest_collection_modifyitems(self, config: pytest.Config, items: List[pytes self.create_module_page_props() # add the pages to the page_props dict self.page_props = {**self.page_props, **self.function_page_props, **self.module_page_props} - # this adds pages for the intermediate directory structure (tests, tests/berlin) + # this adds pages for the intermediate directory structure (tests, + # tests/berlin) self.add_directory_page_props() # add other interesting pages self.add_spec_page_props() @@ -297,7 +299,8 @@ def _setup_logger(self): Configure the mkdocs logger and adds a StreamHandler if outside mkdocs. We use the mkdocs logger to report warnings if conditions are invalid - - this will inform the user and fail the build with `mkdocs build --strict`. + this will inform the user and fail the build with `mkdocs build + --strict`. """ if not logger.hasHandlers() or logger.level == logging.NOTSET: stream_handler = logging.StreamHandler(sys.stdout) @@ -309,12 +312,12 @@ def get_doc_site_base_url(self) -> str: """ Return site's base in its URL for inclusion of local files. - This is required in order to include docs/javascripts/site.js, for + This is required in order to include docs/javascripts/site.js, for example, in the standalone html pages. - Github pages deploys to a sub-directory "execution-spec-tests" and - mike deploys a version of the site underneath a sub-directory named - after the version, e.g.: + Github pages deploys to a sub-directory "execution-spec-tests" and mike + deploys a version of the site underneath a sub-directory named after + the version, e.g.: - https://eest.ethereum.org/main/ - https://eest.ethereum.org/v4.1.0/ @@ -352,7 +355,8 @@ def add_global_page_props_to_env(self): def create_function_page_props(self, test_functions: Dict["str", List[Item]]) -> None: """ - Traverse all test items and create a lookup of doc pages & required props. + Traverse all test items and create a lookup of doc pages & required + props. To do: Needs refactor. """ @@ -361,17 +365,20 @@ def create_function_page_props(self, test_functions: Dict["str", List[Item]]) -> ] for function_id, function_items in test_functions.items(): assert all(isinstance(item, pytest.Function) for item in function_items) - items = cast(List[pytest.Function], function_items) # help mypy infer type + # help mypy infer type + items = cast(List[pytest.Function], function_items) # extract parametrized test cases for each test function test_cases = [] if getattr(items[0], "callspec", None): for item in items: param_set = item.callspec.params - # Don't show skipped parameters as columns in the test case table + # Don't show skipped parameters as columns in the test case + # table keys = [key for key in param_set.keys() if key not in skip_params] values = [param_set[key] for key in keys] - # TODO: This formatting of bytes objects should be moved elsewhere + # TODO: This formatting of bytes objects should be moved + # elsewhere values = [ ( " ".join( @@ -406,8 +413,8 @@ def create_function_page_props(self, test_functions: Dict["str", List[Item]]) -> if not valid_from_marker: valid_from_fork = "Frontier" else: - # NOTE: The EOF tests cases contain two fork names in their valid_from marker, - # separated by a comma. Take the last. + # NOTE: The EOF tests cases contain two fork names in their + # valid_from marker, separated by a comma. Take the last. valid_from_fork = valid_from_marker.args[0].split(",")[-1] target_or_valid_fork = ( @@ -481,7 +488,8 @@ def add_directory_page_props(self) -> None: """ Discover the intermediate directory pages and extract their properties. - These directories may not have any test modules within them, e.g., tests/berlin/. + These directories may not have any test modules within them, e.g., + tests/berlin/. """ sub_paths: Set[Path] = set() for module_page in self.module_page_props.values(): @@ -511,10 +519,12 @@ def add_directory_page_props(self) -> None: path=directory, pytest_node_id=str(directory), source_code_url=generate_github_url(directory, branch_or_commit_or_tag=self.ref), - # TODO: This won't work in all cases; should be from the development fork - # Currently breaks for `tests/unscheduled/eip7692_eof_v1/index.md` # noqa: SC100 + # TODO: This won't work in all cases; should be from the + # development fork Currently breaks for + # `tests/unscheduled/eip7692_eof_v1/index.md` target_or_valid_fork=fork.capitalize() if fork else "Unknown", - package_name=get_import_path(directory), # init.py will be used for docstrings + # init.py will be used for docstrings + package_name=get_import_path(directory), is_benchmark=is_benchmark, ) @@ -538,7 +548,10 @@ def find_files_within_collection_scope(self, file_pattern: str) -> List[Path]: return [Path(file) for file in set(files)] def add_spec_page_props(self) -> None: - """Add page path properties for spec files discovered in the collection scope.""" + """ + Add page path properties for spec files discovered in the collection + scope. + """ for spec_path in self.find_files_within_collection_scope("spec.py"): self.page_props[str(spec_path)] = ModulePageProps( title="Spec", @@ -551,44 +564,58 @@ def add_spec_page_props(self) -> None: ) def add_markdown_page_props(self) -> None: - """Add page path properties for markdown files discovered in the collection scope.""" + """ + Add page path properties for markdown files discovered in the + collection scope. + """ for md_path in self.find_files_within_collection_scope("*.md"): self.page_props[str(md_path)] = MarkdownPageProps( title=md_path.stem, path=md_path, source_code_url=generate_github_url(md_path, branch_or_commit_or_tag=self.ref), - pytest_node_id=str(md_path), # abuse: not a test, but used in source code link + # abuse: not a test, but used in source code link + pytest_node_id=str(md_path), target_or_valid_fork="", package_name="", ) def update_mkdocs_nav(self) -> None: - """Add the generated 'Test Case Reference' entries to the mkdocs navigation menu.""" + """ + Add the generated 'Test Case Reference' entries to the mkdocs + navigation menu. + """ fork_order = {fork.name().lower(): i for i, fork in enumerate(reversed(get_forks()))} def sort_by_fork_deployment_and_path(x: PageProps) -> Tuple[Any, ...]: """ - Key function used to sort navigation menu entries for test case ref docs. + Key function used to sort navigation menu entries for test case ref + docs. Nav entries / output files contain special cases such as: - ("Test Case Reference",) -> tests/index.md - ("Test Case Reference", "Berlin") -> tests/berlin/index.md - ("Test Case Reference", "EIP-7692 EOF V1", tracker.md") - tests/unscheduled/eip7692_eof_v1/tracker.md + tests/unscheduled/eip7692_eof_v1/tracker.md - ("Test Case Reference", "Shanghai", "EIP-3855 PUSH0", "Spec") -> - tests/shanghai/eip3855_push0/spec.py + tests/shanghai/eip3855_push0/spec.py - This function provides and ordering to sort nav men entries as follows: + This function provides and ordering to sort nav men entries as + follows: - 1. Forks are listed in the chronological order that they were deployed. - 2. Special files listed first (before test pages): "*.md" and `Spec.py`, - 3. The page's corresponding file path under `./tests/`. + 1. Forks are listed in the chronological order that they were + deployed. + 2. Special files listed first (before test pages): "*.md" + and `Spec.py`, + 3. The page's corresponding file path under + `./tests/`. """ length = len(x.path.parts) if length > 1: - fork = str(x.path.parts[1]).lower() # the fork folder from the relative path - if fork not in fork_order: # unscheduled features added to the end + # the fork folder from the relative path + fork = str(x.path.parts[1]).lower() + # unscheduled features added to the end + if fork not in fork_order: return (999, str(x.path)) if length == 1: return (0,) diff --git a/pytest_plugins/filler/gen_test_doc/page_props.py b/pytest_plugins/filler/gen_test_doc/page_props.py index 2c3194ee8c..471cd1f2d5 100644 --- a/pytest_plugins/filler/gen_test_doc/page_props.py +++ b/pytest_plugins/filler/gen_test_doc/page_props.py @@ -1,10 +1,10 @@ """ Classes and helpers used for templates, navigation menus and file output. -The dataclass fields are used to define the page properties fields which -are used in the jinja2 templates when generating site content (located in -docs/templates). The classes also define each page's navigation menu entry -and target output file. +The dataclass fields are used to define the page properties fields which are +used in the jinja2 templates when generating site content (located in +docs/templates). The classes also define each page's navigation menu entry and +target output file. A few helpers are defined with EEST logic in order to sanitize strings from file paths for use in navigation menu. @@ -23,7 +23,8 @@ def apply_name_filters(input_string: str): """ - Apply a list of capitalizations/regexes to names used in titles & nav menus. + Apply a list of capitalizations/regexes to names used in titles & nav + menus. Note: As of 2024-10-08, with 634 doc pages, this function constitutes ~2.0s of the total runtime (~5.5s). This seems to be insignificant with the time @@ -62,7 +63,9 @@ def apply_name_filters(input_string: str): def snake_to_capitalize(string: str) -> str: # noqa: D103 - """Convert valid identifiers to a capitalized string, otherwise leave as-is.""" + """ + Convert valid identifiers to a capitalized string, otherwise leave as-is. + """ if string.isidentifier(): return " ".join(word.capitalize() for word in string.split("_")) return string @@ -74,14 +77,17 @@ def sanitize_string_title(string: str) -> str: def nav_path_to_sanitized_str_tuple(nav_path: Path) -> tuple: - """Convert a nav path to a tuple of sanitized strings for use in mkdocs navigation.""" + """ + Convert a nav path to a tuple of sanitized strings for use in mkdocs + navigation. + """ return tuple(sanitize_string_title(part) for part in nav_path.parts) class FileOpener(Protocol): """ - Protocol to replace `mkdocs_gen_files` so it doesn't have to be imported/installed for - unit tests. + Protocol to replace `mkdocs_gen_files` so it doesn't have to be + imported/installed for unit tests. """ def open(self, path: Path, mode: str) -> ContextManager[IO[Any]]: @@ -94,8 +100,8 @@ class PagePropsBase: """ Common test reference doc page properties and definitions. - The dataclass attributes are made directly available in the jinja2 - found in `docs/templates/*.j2`. + The dataclass attributes are made directly available in the jinja2 found in + `docs/templates/*.j2`. """ title: str @@ -159,7 +165,10 @@ def write_page(self, file_opener: FileOpener, jinja2_env: Environment): @dataclass class TestCase: - """Properties used to define a single test case in test function parameter tables.""" + """ + Properties used to define a single test case in test function parameter + tables. + """ full_id: str abbreviated_id: str @@ -200,10 +209,11 @@ def nav_entry(self, top_level_nav_entry) -> tuple: def write_page(self, file_opener: FileOpener, jinja2_env: Environment): """ - Test functions also get a static HTML page with parametrized test cases. + Test functions also get a static HTML page with parametrized test + cases. - This is intended for easier viewing (without mkdocs styling) of the data-table - that documents the parametrized test cases. + This is intended for easier viewing (without mkdocs styling) of the + data-table that documents the parametrized test cases. """ super().write_page(file_opener, jinja2_env) if not self.cases: @@ -218,7 +228,10 @@ def write_page(self, file_opener: FileOpener, jinja2_env: Environment): @dataclass class TestFunction: - """Properties used to build the test function overview table in test module pages.""" + """ + Properties used to build the test function overview table in test module + pages. + """ name: str test_type: str @@ -228,7 +241,10 @@ class TestFunction: @dataclass class ModulePageProps(PagePropsBase): - """Definitions used for test modules, e.g., `tests/berlin/eip2930_access_list/test_acl.py`.""" + """ + Definitions used for test modules, e.g., + `tests/berlin/eip2930_access_list/test_acl.py`. + """ test_functions: List[TestFunction] = field(default_factory=list) @@ -247,7 +263,10 @@ def target_output_file(self) -> Path: @dataclass class DirectoryPageProps(PagePropsBase): - """Definitions used for parent directories in test paths, e.g., `tests/berlin`.""" + """ + Definitions used for parent directories in test paths, e.g., + `tests/berlin`. + """ @property def template(self) -> str: @@ -262,7 +281,9 @@ def target_output_file(self) -> Path: @dataclass class MarkdownPageProps(PagePropsBase): - """Definitions used to verbatim include markdown files included in test paths.""" + """ + Definitions used to verbatim include markdown files included in test paths. + """ @property def template(self) -> str: diff --git a/pytest_plugins/filler/ported_tests.py b/pytest_plugins/filler/ported_tests.py index 228647baf5..0d7f5475bb 100644 --- a/pytest_plugins/filler/ported_tests.py +++ b/pytest_plugins/filler/ported_tests.py @@ -1,20 +1,21 @@ """ A pytest plugin that shows `ported_from` marker information. -This plugin extracts and displays information from @pytest.mark.ported_from markers, -showing either the static filler file paths or associated PR URLs. +This plugin extracts and displays information from @pytest.mark.ported_from +markers, showing either the static filler file paths or associated PR URLs. Usage: ------ -# Show static filler file paths -uv run fill --show-ported-from tests/ +# Show static filler file paths: +# uv run fill --show-ported-from tests/ -# Show PR URLs instead -uv run fill --show-ported-from=prs tests/ +# Show PR URLs instead: +# uv run fill --show-ported-from=prs tests/ The plugin will: 1. Collect all test items with @pytest.mark.ported_from markers -2. Extract either the file paths (first positional argument) or PR URLs (pr keyword argument) +2. Extract either the file paths (first positional argument) or PR URLs (pr + keyword argument) 3. Output a deduplicated, sorted list, one per line 4. Skip test execution (collection only) 5. Exclude tests with coverage_missed_reason from output @@ -22,7 +23,8 @@ Marker Format: -------------- @pytest.mark.ported_from( - ["path/to/static_filler1.json", "path/to/static_filler2.json"], + ["path/to/static_filler1.json", + "path/to/static_filler2.json"], pr=[ "https://github.com/ethereum/execution-spec-tests/pull/1234", "https://github.com/ethereum/execution-spec-tests/pull/5678", diff --git a/pytest_plugins/filler/pre_alloc.py b/pytest_plugins/filler/pre_alloc.py index 49a9a4594b..3bb74b3e0f 100644 --- a/pytest_plugins/filler/pre_alloc.py +++ b/pytest_plugins/filler/pre_alloc.py @@ -147,8 +147,9 @@ def deploy_contract( """ Deploy a contract to the allocation. - Warning: `address` parameter is a temporary solution to allow tests to hard-code the - contract address. Do NOT use in new tests as it will be removed in the future! + Warning: `address` parameter is a temporary solution to allow tests to + hard-code the contract address. Do NOT use in new tests as it will be + removed in the future! """ if storage is None: storage = {} @@ -195,10 +196,11 @@ def fund_eoa( nonce: NumberConvertible | None = None, ) -> EOA: """ - Add a previously unused EOA to the pre-alloc with the balance specified by `amount`. + Add a previously unused EOA to the pre-alloc with the balance specified + by `amount`. - If amount is 0, nothing will be added to the pre-alloc but a new and unique EOA will be - returned. + If amount is 0, nothing will be added to the pre-alloc but a new and + unique EOA will be returned. """ eoa = next(self._eoa_iterator) if amount is None: @@ -218,13 +220,14 @@ def fund_eoa( if nonce > 0: eoa.nonce = nonce else: - # Type-4 transaction is sent to the EOA to set the storage, so the nonce must be 1 + # Type-4 transaction is sent to the EOA to set the storage, so + # the nonce must be 1 if not isinstance(delegation, Address) and delegation == "Self": delegation = eoa - # If delegation is None but storage is not, realistically the nonce should be 2 - # because the account must have delegated to set the storage and then again to - # reset the delegation (but can be overridden by the test for a non-realistic - # scenario) + # If delegation is None but storage is not, realistically the + # nonce should be 2 because the account must have delegated to + # set the storage and then again to reset the delegation (but + # can be overridden by the test for a non-realistic scenario) real_nonce = 2 if delegation is None else 1 nonce = Number(real_nonce if nonce is None else nonce) account = Account( @@ -257,7 +260,8 @@ def fund_address(self, address: Address, amount: NumberConvertible): def empty_account(self) -> Address: """ - Add a previously unused account guaranteed to be empty to the pre-alloc. + Add a previously unused account guaranteed to be empty to the + pre-alloc. This ensures the account has: - Zero balance @@ -265,8 +269,9 @@ def empty_account(self) -> Address: - No code - No storage - This is different from precompiles or system contracts. The function does not - send any transactions, ensuring that the account remains "empty." + This is different from precompiles or system contracts. The function + does not send any transactions, ensuring that the account remains + "empty." Returns: Address: The address of the created empty account. @@ -314,8 +319,8 @@ def sha256_from_string(s: str) -> int: if name not in ALL_FIXTURE_FORMAT_NAMES: ALL_FIXTURE_FORMAT_NAMES.append(name) -# Sort by length, from longest to shortest, since some fixture format names contain others -# so we are always sure to catch the longest one first. +# Sort by length, from longest to shortest, since some fixture format names +# contain others so we are always sure to catch the longest one first. ALL_FIXTURE_FORMAT_NAMES.sort(key=len, reverse=True) @@ -324,17 +329,18 @@ def node_id_for_entropy(request: pytest.FixtureRequest, fork: Fork | None) -> st """ Return the node id with the fixture format name and fork name stripped. - Used in cases where we are filling for pre-alloc groups, and we take the name of the - test as source of entropy to get a deterministic address when generating the pre-alloc - grouping. + Used in cases where we are filling for pre-alloc groups, and we take the + name of the test as source of entropy to get a deterministic address when + generating the pre-alloc grouping. - Removing the fixture format and the fork name from the node id before hashing results in the - contracts and senders addresses being the same across fixture types and forks for the same - test. + Removing the fixture format and the fork name from the node id before + hashing results in the contracts and senders addresses being the same + across fixture types and forks for the same test. """ node_id: str = request.node.nodeid if fork is None: - # FIXME: Static tests don't have a fork, so we need to get it from the node. + # FIXME: Static tests don't have a fork, so we need to get it from the + # node. assert hasattr(request.node, "fork") fork = request.node.fork for fixture_format_name in ALL_FIXTURE_FORMAT_NAMES: @@ -358,7 +364,8 @@ def contract_address_iterator( ) -> Iterator[Address]: """Return iterator over contract addresses with dynamic scoping.""" if request.config.getoption( - # TODO: Ideally, we should check the fixture format instead of checking parameters. + # TODO: Ideally, we should check the fixture format instead of checking + # parameters. "generate_pre_alloc_groups", default=False, ) or request.config.getoption("use_pre_alloc_groups", default=False): @@ -383,7 +390,8 @@ def eoa_iterator( ) -> Iterator[EOA]: """Return iterator over EOAs copies with dynamic scoping.""" if request.config.getoption( - # TODO: Ideally, we should check the fixture format instead of checking parameters. + # TODO: Ideally, we should check the fixture format instead of checking + # parameters. "generate_pre_alloc_groups", default=False, ) or request.config.getoption("use_pre_alloc_groups", default=False): diff --git a/pytest_plugins/filler/static_filler.py b/pytest_plugins/filler/static_filler.py index 4fbe412f09..70feff2023 100644 --- a/pytest_plugins/filler/static_filler.py +++ b/pytest_plugins/filler/static_filler.py @@ -1,6 +1,6 @@ """ -Static filler pytest plugin that reads test cases from static files and fills them into test -fixtures. +Static filler pytest plugin that reads test cases from static files and fills +them into test fixtures. """ import inspect @@ -111,7 +111,10 @@ def get_all_combinations_from_parametrize_marks( def pytest_collect_file(file_path: Path, parent) -> pytest.Collector | None: - """Pytest hook that collects test cases from static files and fills them into test fixtures.""" + """ + Pytest hook that collects test cases from static files and fills them into + test fixtures. + """ fill_static_tests_enabled = parent.config.getoption("fill_static_tests_enabled") if not fill_static_tests_enabled: return None @@ -147,8 +150,8 @@ class NoIntResolver(yaml.SafeLoader): class FillerFile(pytest.File): """ - Filler file that reads test cases from static files and fills them into test - fixtures. + Filler file that reads test cases from static files and fills them into + test fixtures. """ def collect(self: "FillerFile") -> Generator["FillerTestItem", None, None]: @@ -241,7 +244,8 @@ def collect(self: "FillerFile") -> Generator["FillerTestItem", None, None]: get_all_combinations_from_parametrize_marks(parametrize_marks) ) for parameter_set in parameter_set_list: - # Copy and extend the params with the parameter set + # Copy and extend the params with the + # parameter set case_marks = ( marks[:] + [ @@ -349,10 +353,10 @@ def yul(fork: Fork, request: pytest.FixtureRequest): """ Fixture that allows contract code to be defined with Yul code. - This fixture defines a class that wraps the ::ethereum_test_tools.Yul - class so that upon instantiation within the test case, it provides the - test case's current fork parameter. The forks is then available for use - in solc's arguments for the Yul code compilation. + This fixture defines a class that wraps the ::ethereum_test_tools.Yul class + so that upon instantiation within the test case, it provides the test + case's current fork parameter. The forks is then available for use in + solc's arguments for the Yul code compilation. Test cases can override the default value by specifying a fixed version with the @pytest.mark.compile_yul_with(FORK) marker. diff --git a/pytest_plugins/filler/tests/conftest.py b/pytest_plugins/filler/tests/conftest.py index 903d6e8019..570f9e3d0d 100644 --- a/pytest_plugins/filler/tests/conftest.py +++ b/pytest_plugins/filler/tests/conftest.py @@ -9,10 +9,11 @@ @pytest.fixture(autouse=True) def monkeypatch_path_for_entry_points(monkeypatch): """ - Monkeypatch the PATH to add the "bin" directory where entrypoints are installed. + Monkeypatch the PATH to add the "bin" directory where entrypoints are + installed. - This would typically be in the venv in which pytest is running these tests and fill, - which, with uv, is `./.venv/bin`. + This would typically be in the venv in which pytest is running these tests + and fill, which, with uv, is `./.venv/bin`. This is required in order for fill to locate the ethereum-spec-evm-resolver "binary" (entrypoint) when being executed using pytester. diff --git a/pytest_plugins/filler/tests/test_benchmarking.py b/pytest_plugins/filler/tests/test_benchmarking.py index acceecda6b..42c8f80874 100644 --- a/pytest_plugins/filler/tests/test_benchmarking.py +++ b/pytest_plugins/filler/tests/test_benchmarking.py @@ -37,12 +37,11 @@ def setup_test_directory_structure( Set up the common test directory structure used across multiple tests. Args: - pytester: The pytest Pytester fixture - test_content: The content to write to the test file - test_filename: The name of the test file to create + pytester: The pytest Pytester fixture + test_content: The content to write to the test file + test_filename: The name of the test file to create - Returns: - The path to the created test module file + Returns: The path to the created test module file """ tests_dir = pytester.mkdir("tests") @@ -71,7 +70,10 @@ def test_gas_benchmark_option_added(pytester: pytest.Pytester): def test_benchmarking_mode_configured_with_option(pytester: pytest.Pytester): - """Test that fill_mode is set to BENCHMARKING when --gas-benchmark-values is used.""" + """ + Test that fill_mode is set to BENCHMARKING when --gas-benchmark-values is + used. + """ setup_test_directory_structure(pytester, test_module_dummy, "test_dummy_benchmark.py") # Test with gas benchmark values @@ -96,7 +98,10 @@ def test_benchmarking_mode_configured_with_option(pytester: pytest.Pytester): def test_benchmarking_mode_not_configured_without_option(pytester: pytest.Pytester): - """Test that fill_mode is not set to BENCHMARKING when --gas-benchmark-values is not used.""" + """ + Test that fill_mode is not set to BENCHMARKING when --gas-benchmark-values + is not used. + """ setup_test_directory_structure(pytester, test_module_dummy, "test_dummy_benchmark.py") # Test without gas benchmark values diff --git a/pytest_plugins/filler/tests/test_collect_only.py b/pytest_plugins/filler/tests/test_collect_only.py index 8fee4e198f..b9b09974cb 100644 --- a/pytest_plugins/filler/tests/test_collect_only.py +++ b/pytest_plugins/filler/tests/test_collect_only.py @@ -51,6 +51,6 @@ def test_collect_only_output(pytester: pytest.Pytester): in line for line in result.outlines ), f"Expected test output: {result.outlines}" - # fill generates 3 test variants: state_test, blockchain_test_from_state_test, - # blockchain_test_engine_from_state_test + # fill generates 3 test variants: state_test, + # blockchain_test_from_state_test, blockchain_test_engine_from_state_test assert any("3 tests collected" in line for line in result.outlines) diff --git a/pytest_plugins/filler/tests/test_format_selector.py b/pytest_plugins/filler/tests/test_format_selector.py index 16c34c5939..0346bc1ce5 100644 --- a/pytest_plugins/filler/tests/test_format_selector.py +++ b/pytest_plugins/filler/tests/test_format_selector.py @@ -77,11 +77,14 @@ def test_should_generate_single_phase_pre_alloc_format(self): }, ) - # Should not generate because it needs pre-alloc but we're in single phase + # Should not generate because it needs pre-alloc but we're in single + # phase assert not format_selector.should_generate(format_with_pre_alloc) def test_should_generate_phase2_with_pre_alloc_format(self): - """Test phase 2 (after pre-alloc) with format that supports pre-alloc.""" + """ + Test phase 2 (after pre-alloc) with format that supports pre-alloc. + """ phase_manager = PhaseManager( current_phase=FixtureFillingPhase.FILL, previous_phases={FixtureFillingPhase.PRE_ALLOC_GENERATION}, @@ -166,8 +169,12 @@ def test_should_generate_labeled_format(self): assert format_selector.should_generate(labeled_format) def test_comprehensive_scenarios(self): - """Test comprehensive scenarios covering all phase and format combinations.""" - # Test matrix: (current_phase, previous_phases, format_phases, generate_all) -> expected + """ + Test comprehensive scenarios covering all phase and format + combinations. + """ + # Test matrix: (current_phase, previous_phases, format_phases, + # generate_all) -> expected test_cases: List[ # type: ignore[annotation-unchecked] Tuple[ FixtureFillingPhase, Set[FixtureFillingPhase], Set[FixtureFillingPhase], bool, bool diff --git a/pytest_plugins/filler/tests/test_generate_all_formats.py b/pytest_plugins/filler/tests/test_generate_all_formats.py index 8c39d01708..3f7a354333 100644 --- a/pytest_plugins/filler/tests/test_generate_all_formats.py +++ b/pytest_plugins/filler/tests/test_generate_all_formats.py @@ -4,7 +4,10 @@ def test_fixture_output_with_generate_all_formats(): - """Test that FixtureOutput properly handles the should_generate_all_formats parameter.""" + """ + Test that FixtureOutput properly handles the should_generate_all_formats + parameter. + """ # Test with should_generate_all_formats=True fixture_output = FixtureOutput( output_path="/tmp/test", @@ -20,7 +23,10 @@ def test_fixture_output_with_generate_all_formats(): def test_fixture_output_from_config_includes_generate_all_formats(): - """Test that FixtureOutput.from_config includes the should_generate_all_formats option.""" + """ + Test that FixtureOutput.from_config includes the + should_generate_all_formats option. + """ # Mock pytest config object class MockConfig: @@ -43,7 +49,10 @@ def getoption(self, option): def test_tarball_output_auto_enables_generate_all_formats(): - """Test that tarball output (.tar.gz) automatically enables should_generate_all_formats.""" + """ + Test that tarball output (.tar.gz) automatically enables + should_generate_all_formats. + """ # Mock pytest config object with tarball output class MockConfig: @@ -67,7 +76,10 @@ def getoption(self, option): def test_regular_output_does_not_auto_enable_generate_all_formats(): - """Test that regular directory output doesn't auto-enable should_generate_all_formats.""" + """ + Test that regular directory output doesn't auto-enable + should_generate_all_formats. + """ # Mock pytest config object with regular output class MockConfig: @@ -91,7 +103,10 @@ def getoption(self, option): def test_explicit_generate_all_formats_overrides_tarball_auto_enable(): - """Test that explicitly setting should_generate_all_formats=True works with tarball output.""" + """ + Test that explicitly setting should_generate_all_formats=True works with + tarball output. + """ # Mock pytest config object with tarball output and explicit flag class MockConfig: diff --git a/pytest_plugins/filler/tests/test_output_directory.py b/pytest_plugins/filler/tests/test_output_directory.py index 4eba64d88f..eca2cb1015 100644 --- a/pytest_plugins/filler/tests/test_output_directory.py +++ b/pytest_plugins/filler/tests/test_output_directory.py @@ -21,7 +21,10 @@ def test_function(state_test, pre): @pytest.fixture def minimal_test_path(pytester: pytest.Pytester) -> Path: - """Minimal test file that's written to a file using pytester and ready to fill.""" + """ + Minimal test file that's written to a file using pytester and ready to + fill. + """ tests_dir = pytester.mkdir("tests") test_file = tests_dir / MINIMAL_TEST_FILE_NAME test_file.write_text(MINIMAL_TEST_CONTENTS) @@ -48,7 +51,10 @@ def run_fill( fill_fork_until: str, default_t8n: TransitionTool, ): - """Create a function to run the fill command with various output directory scenarios.""" + """ + Create a function to run the fill command with various output directory + scenarios. + """ def _run_fill( output_dir: Path, @@ -56,7 +62,10 @@ def _run_fill( expect_failure: bool = False, disable_capture_output: bool = False, ) -> pytest.RunResult: - """Run the fill command with the specified output directory and clean flag.""" + """ + Run the fill command with the specified output directory and clean + flag. + """ pytester.copy_example(name="src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini") args = [ "-c", @@ -141,7 +150,9 @@ def test_fill_to_nonempty_directory_with_clean(tmp_path_factory: TempPathFactory def test_fill_to_directory_with_meta_fails(tmp_path_factory: TempPathFactory, run_fill): - """Test filling to a directory with .meta subdirectory fails without --clean.""" + """ + Test filling to a directory with .meta subdirectory fails without --clean. + """ # Create a directory with .meta output_dir = tmp_path_factory.mktemp("directory_with_meta") meta_dir = output_dir / ".meta" @@ -204,7 +215,9 @@ def test_fill_to_tarball_directory(tmp_path_factory: TempPathFactory, run_fill): # New tests for the is_master functionality def test_create_directories_skips_when_not_master(): - """Test that create_directories skips operations when not the master process.""" + """ + Test that create_directories skips operations when not the master process. + """ fixture_output = FixtureOutput( output_path=Path("/fake/path"), clean=True, @@ -227,7 +240,10 @@ def test_create_directories_skips_when_not_master(): def test_create_directories_operates_when_master(): - """Test that create_directories performs operations when is the master process.""" + """ + Test that create_directories performs operations when is the master + process. + """ fixture_output = FixtureOutput( output_path=Path("/fake/path"), clean=True, @@ -264,7 +280,8 @@ def test_create_directories_checks_empty_when_master(): patch.object(Path, "exists", return_value=True), patch.object(Path, "mkdir"), ): - # Call with is_master=True and expect an error about non-empty directory + # Call with is_master=True and expect an error about non-empty + # directory with pytest.raises(ValueError, match="not empty"): fixture_output.create_directories(is_master=True) @@ -274,7 +291,10 @@ def test_create_directories_checks_empty_when_master(): def test_stdout_skips_directory_operations_regardless_of_master(): - """Test that stdout output skips directory operations regardless of is_master value.""" + """ + Test that stdout output skips directory operations regardless of is_master + value. + """ fixture_output = FixtureOutput( output_path=Path("stdout"), clean=True, diff --git a/pytest_plugins/filler/tests/test_phase_manager.py b/pytest_plugins/filler/tests/test_phase_manager.py index e727b64154..6aa6e5fa7b 100644 --- a/pytest_plugins/filler/tests/test_phase_manager.py +++ b/pytest_plugins/filler/tests/test_phase_manager.py @@ -74,7 +74,7 @@ def test_from_config_use_pre_alloc(self): assert not phase_manager.is_single_phase_fill def test_from_config_generate_all_formats(self): - """Test that generate_all_formats triggers PRE_ALLOC_GENERATION phase.""" + """Generate_all_formats should trigger PRE_ALLOC_GENERATION phase.""" config = MockConfig(generate_all_formats=True) phase_manager = PhaseManager.from_config(config) @@ -94,7 +94,7 @@ def test_from_config_generate_all_and_pre_alloc(self): assert phase_manager.is_pre_alloc_generation def test_from_config_use_pre_alloc_with_generate_all(self): - """Test phase 2 with generate_all_formats (passed by CLI to phase 2).""" + """Test phase 2 with generate_all_formats (passed by CLI).""" config = MockConfig(use_pre_alloc_groups=True, generate_all_formats=True) phase_manager = PhaseManager.from_config(config) @@ -104,19 +104,27 @@ def test_from_config_use_pre_alloc_with_generate_all(self): assert phase_manager.is_fill_after_pre_alloc def test_all_flag_combinations(self): - """Test all 8 possible flag combinations to ensure correct phase determination.""" + """ + Test all 8 possible flag combinations to ensure correct phase + determination. + """ test_cases = [ - # (generate_pre_alloc, use_pre_alloc, generate_all) -> (current_phase, has_previous) - (False, False, False, FixtureFillingPhase.FILL, False), # Normal fill + # (generate_pre_alloc, use_pre_alloc, generate_all) -> + # (current_phase, has_previous) + # Normal fill + (False, False, False, FixtureFillingPhase.FILL, False), # Generate all triggers phase 1 (False, False, True, FixtureFillingPhase.PRE_ALLOC_GENERATION, False), (False, True, False, FixtureFillingPhase.FILL, True), # Phase 2 - (False, True, True, FixtureFillingPhase.FILL, True), # Phase 2 with generate all + # Phase 2 with generate all + (False, True, True, FixtureFillingPhase.FILL, True), (True, False, False, FixtureFillingPhase.PRE_ALLOC_GENERATION, False), # Phase 1 # Phase 1 with generate all (True, False, True, FixtureFillingPhase.PRE_ALLOC_GENERATION, False), - (True, True, False, FixtureFillingPhase.FILL, True), # Invalid but use_pre_alloc wins - (True, True, True, FixtureFillingPhase.FILL, True), # Invalid but use_pre_alloc wins + # Invalid but use_pre_alloc wins + (True, True, False, FixtureFillingPhase.FILL, True), + # Invalid but use_pre_alloc wins + (True, True, True, FixtureFillingPhase.FILL, True), ] for gen_pre, use_pre, gen_all, expected_phase, has_previous in test_cases: diff --git a/pytest_plugins/filler/tests/test_prealloc_group.py b/pytest_plugins/filler/tests/test_prealloc_group.py index 86ccc9c3b6..29e9da7c62 100644 --- a/pytest_plugins/filler/tests/test_prealloc_group.py +++ b/pytest_plugins/filler/tests/test_prealloc_group.py @@ -412,7 +412,10 @@ def test_pre_alloc_grouping_by_test_type( test_definitions: List[FormattedTest], expected_different_pre_alloc_groups: int, ): - """Test pre-alloc grouping when filling state tests, and the effect of the `state_test.env`.""" + """ + Test pre-alloc grouping when filling state tests, and the effect of the + `state_test.env`. + """ tests_dir = Path(pytester.mkdir("tests")) for i, test in enumerate(test_definitions): test_module = tests_dir / f"test_{i}.py" diff --git a/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py b/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py index 508db25a68..6ffd67994a 100644 --- a/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py +++ b/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py @@ -1,8 +1,8 @@ """ Example usage of the pre_alloc_group marker. -This file demonstrates how tests would use the marker in practice. -Note: This is just documentation, not executable tests. +This file demonstrates how tests would use the marker in practice. Note: This +is just documentation, not executable tests. """ import pytest @@ -13,9 +13,12 @@ "separate", reason="Deploys beacon root contract using actual hardcoded deployer address" ) def test_beacon_root_contract_deployment(): - """Test beacon root contract deployment with the official deployer address.""" - # This test uses the actual beacon root deployer address (e.g., 0x4242...4242) - # which could conflict with dynamically allocated addresses in other tests + """ + Test beacon root contract deployment with the official deployer address. + """ + # This test uses the actual beacon root deployer address (e.g., + # 0x4242...4242) which could conflict with dynamically allocated addresses + # in other tests pass @@ -25,8 +28,9 @@ def test_beacon_root_contract_deployment(): ) def test_custom_consolidation_contract(): """Test that deploys a modified consolidation contract.""" - # This test deploys a consolidation contract with custom bytecode that differs - # from the standard implementation, requiring isolation from other consolidation tests + # This test deploys a consolidation contract with custom bytecode that + # differs from the standard implementation, requiring isolation from other + # consolidation tests pass @@ -36,8 +40,9 @@ def test_custom_consolidation_contract(): ) def test_custom_consolidation_edge_cases(): """Test edge cases with the custom consolidation contract.""" - # This test can share the pre-allocation with test_custom_consolidation_contract - # since they both use the same custom contract setup + # This test can share the pre-allocation with + # test_custom_consolidation_contract since they both use the same custom + # contract setup pass diff --git a/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py b/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py index c5f3d012c1..67b0d43c5f 100644 --- a/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py +++ b/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py @@ -6,7 +6,10 @@ def test_slow_marker_gets_pre_alloc_group(pytester, default_t8n: TransitionTool): - """Test that slow tests without benchmark marker get pre_alloc_group automatically.""" + """ + Test that slow tests without benchmark marker get pre_alloc_group + automatically. + """ test_module = textwrap.dedent( """\ import pytest @@ -49,7 +52,9 @@ def test_slow_without_benchmark(state_test: StateTestFiller, pre: Alloc): def test_slow_with_benchmark_no_pre_alloc(pytester, default_t8n: TransitionTool): - """Test that slow tests WITH benchmark marker do NOT get pre_alloc_group.""" + """ + Test that slow tests WITH benchmark marker do NOT get pre_alloc_group. + """ test_module = textwrap.dedent( """\ import pytest @@ -92,7 +97,9 @@ def test_slow_with_benchmark(state_test: StateTestFiller, pre: Alloc): def test_slow_with_existing_pre_alloc_unchanged(pytester, default_t8n: TransitionTool): - """Test that slow tests with existing pre_alloc_group marker are unchanged.""" + """ + Test that slow tests with existing pre_alloc_group marker are unchanged. + """ test_module = textwrap.dedent( """\ import pytest @@ -176,7 +183,9 @@ def test_normal_speed(state_test: StateTestFiller, pre: Alloc): def test_integration_with_fill(pytester, default_t8n: TransitionTool): - """Integration test using actual fill command to verify marker application.""" + """ + Integration test using actual fill command to verify marker application. + """ test_module = textwrap.dedent( """\ import pytest @@ -221,10 +230,15 @@ def test_slow_for_integration(state_test: StateTestFiller, pre: Alloc): "tests/cancun/slow_test_module/", ] - # The test generates 3 formats (state_test, blockchain_test, blockchain_test_engine) - # But it also runs on multiple forks (Cancun and Prague), so expect more tests - # This is fine - the important thing is that they all pass + # The test generates 3 formats (state_test, blockchain_test, + # blockchain_test_engine). + + # But it also runs on multiple forks (Cancun and + # Prague), so expect more tests. + + # This is fine - the important thing is that they all pass. result = pytester.runpytest(*args) - # Verify that tests passed (don't care about exact count due to fork variations) + # Verify that tests passed (don't care about exact count due to fork + # variations) assert result.ret == 0, "Fill command should succeed" diff --git a/pytest_plugins/filler/tests/test_verify_sync_marker.py b/pytest_plugins/filler/tests/test_verify_sync_marker.py index 2ecc167d62..83e7450dfb 100644 --- a/pytest_plugins/filler/tests/test_verify_sync_marker.py +++ b/pytest_plugins/filler/tests/test_verify_sync_marker.py @@ -72,9 +72,12 @@ def test_verify_sync_marker( Test blockchain sync fixture generation with verify_sync marker. The test module has 3 test functions (4 test cases with parametrization): - - test_verify_sync_default: generates all formats except sync (no verify_sync marker) - - test_verify_sync_with_marker: generates all formats including sync (has verify_sync marker) - - test_verify_sync_with_param_marks: tests parametrized marks with verify_sync (2 cases) + - test_verify_sync_default: generates all formats except sync + (no verify_sync marker) + - test_verify_sync_with_marker: generates all formats including sync + (has verify_sync marker) + - test_verify_sync_with_param_marks: tests parametrized marks with + verify_sync (2 cases) Each test generates fixture formats: - BlockchainFixture (always) @@ -83,13 +86,15 @@ def test_verify_sync_marker( Expected outcomes: - 4 test cases total - - Each generates BlockchainFixture (4) and BlockchainEngineFixture (4) = 8 fixtures + - Each generates BlockchainFixture (4) and BlockchainEngineFixture (4) = + 8 fixtures + - Sync fixtures: - - test_verify_sync_with_marker: 1 sync fixture ✓ - - test_verify_sync_with_param_marks[no_exception]: 1 sync fixture ✓ - - Total sync fixtures: 2 - - Not generated (due to exception_test marker): - - test_verify_sync_with_param_marks[with_exception]: sync fixture not generated + - test_verify_sync_with_marker: 1 sync fixture ✓ + - test_verify_sync_with_param_marks[no_exception]: 1 sync fixture ✓ + - Total sync fixtures: 2 - Not generated (due to exception_test marker): + - test_verify_sync_with_param_marks[with_exception]: sync fixture + not generated Final counts: - Passed: 8 (base fixtures) + 2 (sync fixtures) = 10 passed diff --git a/pytest_plugins/filler/witness.py b/pytest_plugins/filler/witness.py index fc21e3dcee..fe88ab282c 100644 --- a/pytest_plugins/filler/witness.py +++ b/pytest_plugins/filler/witness.py @@ -1,8 +1,9 @@ """ Pytest plugin for witness functionality. -Provides --witness command-line option that checks for the witness-filler tool in PATH -and generates execution witness data for blockchain test fixtures when enabled. +Provides --witness command-line option that checks for the witness-filler tool +in PATH and generates execution witness data for blockchain test fixtures when +enabled. """ import shutil @@ -17,7 +18,9 @@ class WitnessFillerResult(EthereumTestRootModel[List[WitnessChunk]]): - """Model that defines the expected result from the `witness-filler` command.""" + """ + Model that defines the expected result from the `witness-filler` command. + """ root: List[WitnessChunk] @@ -26,9 +29,9 @@ class Merge(Paris): """ Paris fork that serializes as 'Merge' for witness-filler compatibility. - IMPORTANT: This class MUST be named 'Merge' (not 'MergeForWitness' or similar) - because the class name is used directly in Pydantic serialization, and - witness-filler expects exactly 'Merge' for this fork. + IMPORTANT: This class MUST be named 'Merge' (not 'MergeForWitness' or + similar) because the class name is used directly in Pydantic serialization, + and witness-filler expects exactly 'Merge' for this fork. """ pass @@ -54,7 +57,8 @@ def pytest_configure(config): """ Pytest hook called after command line options have been parsed. - If --witness is enabled, checks that the witness-filler tool is available in PATH. + If --witness is enabled, checks that the witness-filler tool is available + in PATH. """ if config.getoption("witness"): # Check if witness-filler binary is available in PATH @@ -75,20 +79,22 @@ def witness_generator( """ Provide a witness generator function if --witness is enabled. - Returns: - None if witness functionality is disabled. - Callable that generates witness data for a BlockchainFixture if enabled. - + Returns: None if witness functionality is disabled. Callable that generates + witness data for a BlockchainFixture if enabled. """ if not request.config.getoption("witness"): return None def generate_witness(fixture: BlockchainFixture) -> None: - """Generate witness data for a blockchain fixture using the witness-filler tool.""" + """ + Generate witness data for a blockchain fixture using the witness-filler + tool. + """ if not isinstance(fixture, BlockchainFixture): return None - # Hotfix: witness-filler expects "Merge" but execution-spec-tests uses "Paris" + # Hotfix: witness-filler expects "Merge" but execution-spec-tests uses + # "Paris" original_fork = None if fixture.fork is Paris: original_fork = fixture.fork diff --git a/pytest_plugins/fix_package_test_path.py b/pytest_plugins/fix_package_test_path.py index a8503deeaa..c54580ee2f 100644 --- a/pytest_plugins/fix_package_test_path.py +++ b/pytest_plugins/fix_package_test_path.py @@ -1,6 +1,6 @@ """ -Pytest plugin to fix the test IDs for all pytest command that use a command-logic test -file. +Pytest plugin to fix the test IDs for all pytest command that use a +command-logic test file. """ from typing import List @@ -9,7 +9,10 @@ def pytest_collection_modifyitems(items: List[pytest.Item]): - """Modify collected item names to remove the test runner function from the name.""" + """ + Modify collected item names to remove the test runner function from the + name. + """ for item in items: original_name = item.originalname # type: ignore remove = f"{original_name}[" diff --git a/pytest_plugins/forks/forks.py b/pytest_plugins/forks/forks.py index 6147b981de..52346f366f 100644 --- a/pytest_plugins/forks/forks.py +++ b/pytest_plugins/forks/forks.py @@ -87,10 +87,12 @@ def __init__( Initialize a new fork parametrizer object for a given fork. Args: - fork: The fork for which the test cases will be parametrized. - marks: A list of pytest marks to apply to all the test cases parametrized by the fork. - fork_covariant_parameters: A list of fork covariant parameters for the test case, for - unit testing purposes only. + fork: The fork for which the test cases will be parametrized. + marks: A list of pytest marks to apply to all the test cases + parametrized by the fork. + fork_covariant_parameters: A list of fork covariant parameters + for the test case, for unit testing + purposes only. """ if marks is None: @@ -122,7 +124,8 @@ def argnames(self) -> List[str]: def argvalues(self) -> List[ParameterSet]: """Return the parameter values for the test case.""" parameter_set_combinations = itertools.product( - # Add the values for each parameter, all of them are lists of at least one element. + # Add the values for each parameter, all of them are lists of at + # least one element. *[p.values for p in self.fork_covariant_parameters], ) @@ -148,8 +151,8 @@ def argvalues(self) -> List[ParameterSet]: class CovariantDescriptor: """ - A descriptor for a parameter that is covariant with the fork: - the parametrized values change depending on the fork. + A descriptor for a parameter that is covariant with the fork: the + parametrized values change depending on the fork. """ argnames: List[str] = [] @@ -175,11 +178,13 @@ def __init__( Initialize a new covariant descriptor. Args: - argnames: The names of the parameters that are covariant with the fork. - fn: A function that takes the fork as the single parameter and returns the values for - the parameter for each fork. - selector: A function that filters the values for the parameter. - marks: A list of pytest marks to apply to the test cases parametrized by the parameter. + argnames: The names of the parameters that are covariant with the + fork. + fn: A function that takes the fork as the single parameter and + returns the values for the parameter for each fork. + selector: A function that filters the values for the parameter. + marks: A list of pytest marks to apply to the test cases + parametrized by the parameter. """ self.argnames = ( @@ -226,8 +231,8 @@ def process_values(self, values: Iterable[Any]) -> List[ParameterSet]: """ Filter the values for the covariant parameter. - I.e. if the marker has an argument, the argument is interpreted as a lambda function - that filters the values. + I.e. if the marker has an argument, the argument is interpreted as a + lambda function that filters the values. """ processed_values: List[ParameterSet] = [] for value in values: @@ -251,18 +256,21 @@ def add_values(self, fork_parametrizer: ForkParametrizer) -> None: class CovariantDecorator(CovariantDescriptor): """ - A marker used to parametrize a function by a covariant parameter with the values - returned by a fork method. + A marker used to parametrize a function by a covariant parameter with the + values returned by a fork method. - The decorator must be subclassed with the appropriate class variables before initialization. + The decorator must be subclassed with the appropriate class variables + before initialization. Attributes: - marker_name: Name of the marker. - description: Description of the marker. - fork_attribute_name: Name of the method to call on the fork to get the values. - marker_parameter_names: Names of the parameters to be parametrized in the test function. - indirect: Whether the parameters should be passed through fixtures (indirect - parametrization). + marker_name: Name of the marker. + description: Description of the marker. + fork_attribute_name: Name of the method to call on the fork to + get the values. + marker_parameter_names: Names of the parameters to be parametrized + in the test function. + indirect: Whether the parameters should be passed through fixtures + (indirect parametrization). """ @@ -276,11 +284,12 @@ def __init__(self, metafunc: Metafunc): """ Initialize the covariant decorator. - The decorator must already be subclassed with the appropriate class variables before - initialization. + The decorator must already be subclassed with the appropriate class + variables before initialization. Args: - metafunc: The metafunc object that pytest uses when generating tests. + metafunc: The metafunc object that pytest uses when generating + tests. """ self.metafunc = metafunc @@ -408,7 +417,8 @@ def pytest_configure(config: pytest.Config): Register the plugin's custom markers and process command-line options. Custom marker registration: - https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers + https://docs.pytest.org/en/7.1.x/how-to/ + writing_plugins.html# registering-custom-markers """ config.addinivalue_line( "markers", @@ -565,7 +575,10 @@ def fork(request): @pytest.fixture(scope="session") def session_fork(request: pytest.FixtureRequest) -> Fork | None: - """Session-wide fork object used if the plugin is configured in single-fork mode.""" + """ + Session-wide fork object used if the plugin is configured in single-fork + mode. + """ if hasattr(request.config, "single_fork_mode") and request.config.single_fork_mode: return list(request.config.selected_fork_set)[0] # type: ignore raise AssertionError( @@ -584,12 +597,14 @@ class ValidityMarker(ABC): Subclassing this class allows for the creation of new validity markers. - Instantiation must be done per test function, and the `process` method must be called to - process the fork arguments. + Instantiation must be done per test function, and the `process` method must + be called to process the fork arguments. When subclassing, the following optional parameters can be set: - - marker_name: Name of the marker, if not set, the class name is converted to underscore. - - mutually_exclusive: List of other marker types incompatible with this one. + - marker_name: Name of the marker, if not set, the class name is + converted to underscore. + - mutually_exclusive: List of other marker types incompatible + with this one. - flag: Whether the marker is a flag and should always be included. """ @@ -609,7 +624,8 @@ def __init_subclass__( """Register the validity marker subclass.""" super().__init_subclass__(**kwargs) if marker_name is None: - # Use the class name converted to underscore: https://stackoverflow.com/a/1176023 + # Use the class name converted to underscore: + # https://stackoverflow.com/a/1176023 marker_name = MARKER_NAME_REGEX.sub("_", cls.__name__).lower() cls.marker_name = marker_name cls.mutually_exclusive = mutually_exclusive if mutually_exclusive else [] @@ -661,14 +677,18 @@ def get_all_validity_markers(markers: Iterator[pytest.Mark]) -> List["ValidityMa @staticmethod def get_test_fork_set(validity_markers: List["ValidityMarker"]) -> Set[Fork]: - """Get the set of forks where a test is valid from the validity markers and filters.""" + """ + Get the set of forks where a test is valid from the validity markers + and filters. + """ if not len( [validity_marker for validity_marker in validity_markers if not validity_marker.flag] ): # Limit to non-transition forks if no validity markers were applied test_fork_set = set(ALL_FORKS) else: - # Start with all forks and transitions if any validity markers were applied + # Start with all forks and transitions if any validity markers were + # applied test_fork_set = set(ALL_FORKS_WITH_TRANSITIONS) for v in validity_markers: @@ -679,14 +699,20 @@ def get_test_fork_set(validity_markers: List["ValidityMarker"]) -> Set[Fork]: @staticmethod def get_test_fork_set_from_markers(markers: Iterator[pytest.Mark]) -> Set[Fork]: - """Get the set of forks where a test is valid using the markers applied to the test.""" + """ + Get the set of forks where a test is valid using the markers applied to + the test. + """ return ValidityMarker.get_test_fork_set(ValidityMarker.get_all_validity_markers(markers)) @staticmethod def get_test_fork_set_from_metafunc( metafunc: Metafunc, ) -> Set[Fork]: - """Get the set of forks where a test is valid using its pytest meta-function.""" + """ + Get the set of forks where a test is valid using its pytest + meta-function. + """ return ValidityMarker.get_test_fork_set_from_markers(metafunc.definition.iter_markers()) @staticmethod @@ -711,16 +737,17 @@ def _process_with_marker_args(self, *args, **kwargs) -> Set[Fork]: Method must be implemented by the subclass. - If the validity marker is of flag type, the returned forks will be subtracted from the - fork set, otherwise the returned forks will be intersected with the current set. + If the validity marker is of flag type, the returned forks will be + subtracted from the fork set, otherwise the returned forks will be + intersected with the current set. """ pass class ValidFrom(ValidityMarker): """ - Marker used to specify the fork from which the test is valid. The test will not be filled for - forks before the specified fork. + Marker used to specify the fork from which the test is valid. The test will + not be filled for forks before the specified fork. ```python import pytest @@ -735,8 +762,8 @@ def test_something_only_valid_after_london( pass ``` - In this example, the test will only be filled for the London fork and after, e.g. London, - Paris, Shanghai, Cancun, etc. + In this example, the test will only be filled for the London fork and + after, e.g. London, Paris, Shanghai, Cancun, etc. """ def _process_with_marker_args(self, *fork_args) -> Set[Fork]: @@ -750,8 +777,8 @@ def _process_with_marker_args(self, *fork_args) -> Set[Fork]: class ValidUntil(ValidityMarker): """ - Marker to specify the fork until which the test is valid. The test will not be filled for - forks after the specified fork. + Marker to specify the fork until which the test is valid. The test will not + be filled for forks after the specified fork. ```python import pytest @@ -766,8 +793,8 @@ def test_something_only_valid_until_london( pass ``` - In this example, the test will only be filled for the London fork and before, e.g. London, - Berlin, Istanbul, etc. + In this example, the test will only be filled for the London fork and + before, e.g. London, Berlin, Istanbul, etc. """ def _process_with_marker_args(self, *fork_args) -> Set[Fork]: @@ -796,7 +823,8 @@ def test_something_only_valid_at_london_and_cancun( pass ``` - In this example, the test will only be filled for the London and Cancun forks. + In this example, the test will only be filled for the London and Cancun + forks. """ def _process_with_marker_args(self, *fork_args) -> Set[Fork]: @@ -806,11 +834,12 @@ def _process_with_marker_args(self, *fork_args) -> Set[Fork]: class ValidAtTransitionTo(ValidityMarker, mutually_exclusive=[ValidAt, ValidFrom, ValidUntil]): """ - Marker to specify that a test is only meant to be filled at the transition to the specified - fork. + Marker to specify that a test is only meant to be filled at the transition + to the specified fork. - The test usually starts at the fork prior to the specified fork at genesis and at block 5 (for - pre-merge forks) or at timestamp 15,000 (for post-merge forks) the fork transition occurs. + The test usually starts at the fork prior to the specified fork at genesis + and at block 5 (for pre-merge forks) or at timestamp 15,000 (for post-merge + forks) the fork transition occurs. ```python import pytest @@ -825,36 +854,40 @@ def test_something_that_happens_during_the_fork_transition_to_london( pass ``` - In this example, the test will only be filled for the fork that transitions to London at block - number 5, `BerlinToLondonAt5`, and no other forks. + In this example, the test will only be filled for the fork that transitions + to London at block number 5, `BerlinToLondonAt5`, and no other forks. - To see or add a new transition fork, see the `ethereum_test_forks.forks.transition` module. + To see or add a new transition fork, see the + `ethereum_test_forks.forks.transition` module. - Note that the test uses a `BlockchainTestFiller` fixture instead of a `StateTestFiller`, - as the transition forks are used to test changes throughout the blockchain progression, and - not just the state change of a single transaction. + Note that the test uses a `BlockchainTestFiller` fixture instead of a + `StateTestFiller`, as the transition forks are used to test changes + throughout the blockchain progression, and not just the state change of a + single transaction. This marker also accepts the following keyword arguments: - - `subsequent_transitions`: Force the test to also fill for subsequent fork transitions. - - `until`: Implies `subsequent_transitions` and puts a limit on which transition fork will the - test filling will be limited to. + - `subsequent_transitions`: Force the test to also fill for subsequent fork + transitions. + - `until`: Implies `subsequent_transitions` and puts a limit + on which transition fork will the test filling will be limited to. For example: ```python @pytest.mark.valid_at_transition_to("Cancun", subsequent_transitions=True) ``` - produces tests on `ShanghaiToCancunAtTime15k` and `CancunToPragueAtTime15k`, and any transition - fork after that. + produces tests on `ShanghaiToCancunAtTime15k` and + `CancunToPragueAtTime15k`, and any transition fork after that. And: ```python - @pytest.mark.valid_at_transition_to("Cancun", subsequent_transitions=True, until="Prague") + @pytest.mark.valid_at_transition_to("Cancun", + subsequent_transitions=True, until="Prague") ``` - produces tests on `ShanghaiToCancunAtTime15k` and `CancunToPragueAtTime15k`, but no forks after - Prague. + produces tests on `ShanghaiToCancunAtTime15k` and + `CancunToPragueAtTime15k`, but no forks after Prague. """ def _process_with_marker_args( @@ -984,7 +1017,10 @@ def pytest_generate_tests(metafunc: pytest.Metafunc): def add_fork_covariant_parameters( metafunc: Metafunc, fork_parametrizers: List[ForkParametrizer] ) -> None: - """Iterate over the fork covariant descriptors and add their values to the test function.""" + """ + Iterate over the fork covariant descriptors and add their values to the + test function. + """ # Process all covariant decorators uniformly for covariant_descriptor in fork_covariant_decorators: if list(metafunc.definition.iter_markers(covariant_descriptor.marker_name)): diff --git a/pytest_plugins/forks/tests/test_bad_command_line_options.py b/pytest_plugins/forks/tests/test_bad_command_line_options.py index 3799dbb570..5d45dd2427 100644 --- a/pytest_plugins/forks/tests/test_bad_command_line_options.py +++ b/pytest_plugins/forks/tests/test_bad_command_line_options.py @@ -1,6 +1,5 @@ """ -Test that the correct error is produced if bad/invalid command-line -arguments are used. +Test the correct error is produced with bad/invalid command-line arguments. """ import pytest @@ -59,11 +58,11 @@ def test_bad_options(pytester, options, error_string): """ Test that a test with an invalid command-line options: - - Creates an outcome with exactly one error. - - Triggers the expected error string in pytest's console output. + - Creates an outcome with exactly one error. + - Triggers the expected error string in pytest's console output. - Each invalid marker/marker combination is tested with one test in its own test - session. + Each invalid marker/marker combination is tested with one test in its own + test session. """ pytester.makepyfile( """ diff --git a/pytest_plugins/forks/tests/test_bad_validity_markers.py b/pytest_plugins/forks/tests/test_bad_validity_markers.py index 7aea95220c..1e33c30aed 100644 --- a/pytest_plugins/forks/tests/test_bad_validity_markers.py +++ b/pytest_plugins/forks/tests/test_bad_validity_markers.py @@ -1,4 +1,6 @@ -"""Test that the correct error is produced if bad/invalid validity markers are specified.""" +""" +Test the correct error is produced with bad/invalid validity markers. +""" import pytest @@ -214,11 +216,11 @@ def test_case(state_test): def test_invalid_validity_markers(pytester, error_string, test_function): """ Test that a test with an invalid marker cases: - - Creates an outcome with exactly one error. - - Triggers the expected error string in pytest's console output. + - Creates an outcome with exactly one error. + - Triggers the expected error string in pytest's console output. - Each invalid marker/marker combination is tested with one test in its own test - session. + Each invalid marker/marker combination is tested with one test in its own + test session. """ pytester.makepyfile(test_function) pytester.copy_example(name="src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini") diff --git a/pytest_plugins/forks/tests/test_fork_parametrizer_types.py b/pytest_plugins/forks/tests/test_fork_parametrizer_types.py index e655b46605..94d6eb5eb1 100644 --- a/pytest_plugins/forks/tests/test_fork_parametrizer_types.py +++ b/pytest_plugins/forks/tests/test_fork_parametrizer_types.py @@ -188,7 +188,9 @@ def test_fork_parametrizer( expected_names: List[str], expected_parameter_sets: List[ParameterSet], ): - """Test that the fork parametrizer correctly parametrizes tests based on the fork name.""" + """ + Test the fork parametrizer correctly parametrizes using the fork name. + """ argnames, values = parameters_from_fork_parametrizer_list(fork_parametrizers) assert argnames == expected_names assert len(values) == len(expected_parameter_sets) diff --git a/pytest_plugins/help/__init__.py b/pytest_plugins/help/__init__.py index c1a6507e99..2e861b4d85 100644 --- a/pytest_plugins/help/__init__.py +++ b/pytest_plugins/help/__init__.py @@ -1 +1,3 @@ -"""Pytest plugin that prints help defined in other execution-spec-tests plugins.""" +""" +Pytest plugin that prints help defined in other execution-spec-tests plugins. +""" diff --git a/pytest_plugins/help/help.py b/pytest_plugins/help/help.py index b70c0357a5..808584e314 100644 --- a/pytest_plugins/help/help.py +++ b/pytest_plugins/help/help.py @@ -65,7 +65,9 @@ def pytest_addoption(parser): @pytest.hookimpl(tryfirst=True) def pytest_configure(config): - """Handle specific help flags by displaying the corresponding help message.""" + """ + Handle specific help flags by displaying the corresponding help message. + """ if config.getoption("show_check_eip_versions_help"): show_specific_help( config, @@ -143,7 +145,10 @@ def pytest_configure(config): def show_specific_help(config, expected_ini, substrings): - """Print help options filtered by specific substrings from the given configuration.""" + """ + Print help options filtered by specific substrings from the given + configuration. + """ pytest_ini = Path(config.inifile) if pytest_ini.name != expected_ini: raise ValueError( diff --git a/pytest_plugins/help/tests/test_help.py b/pytest_plugins/help/tests/test_help.py index 9b7b45ae6c..3ed648720b 100644 --- a/pytest_plugins/help/tests/test_help.py +++ b/pytest_plugins/help/tests/test_help.py @@ -18,8 +18,8 @@ @pytest.mark.parametrize("help_flag", ["--fill-help"]) def test_local_arguments_present_in_fill_help(pytester, help_flag): """ - Test that locally defined command-line flags appear in the help if - our custom help flag is used. + Test that locally defined command-line flags appear in the help if our + custom help flag is used. """ pytester.copy_example(name="src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini") result = pytester.runpytest("-c", "pytest-fill.ini", help_flag) @@ -43,7 +43,10 @@ def test_local_arguments_present_in_fill_help(pytester, help_flag): ], ) def test_local_arguments_present_in_base_consume_help(pytester, help_flag, command): - """Test that locally defined command-line flags appear in the help for consume subcommands.""" + """ + Test that locally defined command-line flags appear in the help for consume + subcommands. + """ pytester.copy_example(name="src/cli/pytest_commands/pytest_ini_files/pytest-consume.ini") result = pytester.runpytest("-c", "pytest-consume.ini", command, help_flag) for test_arg in CONSUME_TEST_ARGS: diff --git a/pytest_plugins/pytest_hive/pytest_hive.py b/pytest_plugins/pytest_hive/pytest_hive.py index 34dfd78809..b1624391ef 100644 --- a/pytest_plugins/pytest_hive/pytest_hive.py +++ b/pytest_plugins/pytest_hive/pytest_hive.py @@ -10,23 +10,28 @@ Log Capture Architecture: ------------------------- -This module implements a log capture approach that ensures all logs, including those -generated during fixture teardown, are properly captured and included in the test results. - -The key insight is that we need to ensure that test finalization happens *before* the -test suite is finalized, but *after* all fixtures have been torn down so we can capture -their logs. This is accomplished through the fixture teardown mechanism in pytest: - -1. Since the `hive_test` fixture depends on the `test_suite` fixture, pytest guarantees - that the teardown of `hive_test` runs before the teardown of `test_suite` -2. All logs are processed and the test is finalized in the teardown phase of the - `hive_test` fixture using the pytest test report data -3. This sequencing ensures that all logs are captured and the test is properly finalized - before its parent test suite is finalized - -This approach relies on the pytest fixture dependency graph and teardown ordering to -ensure proper sequencing, which is more reliable than using hooks which might run in -an unpredictable order relative to fixture teardown. +This module implements a log capture approach that ensures all logs, +including those generated during fixture teardown, are properly +captured and included in the test results. + +The key insight is that we need to ensure that test finalization happens +*before* the test suite is finalized, but *after* all fixtures have been torn +down so we can capture their logs. This is accomplished through the fixture +teardown mechanism in pytest: + +1. Since the `hive_test` fixture depends on the `test_suite` fixture, pytest +guarantees that the teardown of `hive_test` runs before the teardown of +`test_suite` + +2. All logs are processed and the test is finalized in the +teardown phase of the `hive_test` fixture using the pytest test report data + +3. This sequencing ensures that all logs are captured and the test is properly +finalized before its parent test suite is finalized + +This approach relies on the pytest fixture dependency graph and teardown +ordering to ensure proper sequencing, which is more reliable than using hooks +which might run in an unpredictable order relative to fixture teardown. """ import json @@ -59,8 +64,8 @@ def pytest_configure(config): # noqa: D103 "or in fish:\n" "set -x HIVE_SIMULATOR http://127.0.0.1:3000" ) - # TODO: Try and get these into fixtures; this is only here due to the "dynamic" parametrization - # of client_type with hive_execution_clients. + # TODO: Try and get these into fixtures; this is only here due to the + # "dynamic" parametrization of client_type with hive_execution_clients. config.hive_simulator_url = hive_simulator_url config.hive_simulator = Simulation(url=hive_simulator_url) try: @@ -133,8 +138,8 @@ def pytest_report_header(config, start_path): @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): """ - Make the setup, call, and teardown results available in the teardown phase of - a test fixture (i.e., after yield has been called). + Make the setup, call, and teardown results available in the teardown phase + of a test fixture (i.e., after yield has been called). This is used to get the test result and pass it to the hive test suite. @@ -238,10 +243,11 @@ def hive_test(request, test_suite: HiveTestSuite): """ Propagate the pytest test case and its result to the hive server. - This fixture handles both starting the test and ending it with all logs, including - those generated during teardown of other fixtures. The approach of processing teardown - logs directly in the teardown phase of this fixture ensures that the test gets properly - finalized before the test suite is torn down. + This fixture handles both starting the test and ending it with all logs, + including those generated during teardown of other fixtures. The approach + of processing teardown logs directly in the teardown phase of this fixture + ensures that the test gets properly finalized before the test suite is torn + down. """ try: test_case_description = request.getfixturevalue("test_case_description") diff --git a/pytest_plugins/shared/benchmarking.py b/pytest_plugins/shared/benchmarking.py index 6f19877665..c5688476b3 100644 --- a/pytest_plugins/shared/benchmarking.py +++ b/pytest_plugins/shared/benchmarking.py @@ -55,7 +55,10 @@ def gas_benchmark_value(request: pytest.FixtureRequest) -> int: @pytest.fixture def genesis_environment(request: pytest.FixtureRequest) -> Environment: # noqa: D103 - """Return an Environment instance with appropriate gas limit based on test type.""" + """ + Return an Environment instance with appropriate gas limit based on test + type. + """ if request.node.get_closest_marker("benchmark") is not None: return Environment(gas_limit=BENCHMARKING_MAX_GAS) return Environment() @@ -63,7 +66,10 @@ def genesis_environment(request: pytest.FixtureRequest) -> Environment: # noqa: @pytest.fixture def env(request: pytest.FixtureRequest) -> Environment: # noqa: D103 - """Return an Environment instance with appropriate gas limit based on test type.""" + """ + Return an Environment instance with appropriate gas limit based on test + type. + """ if request.node.get_closest_marker("benchmark") is not None: return Environment(gas_limit=BENCHMARKING_MAX_GAS) return Environment() diff --git a/pytest_plugins/shared/execute_fill.py b/pytest_plugins/shared/execute_fill.py index 21b9b7ea5b..0df88c2ef3 100644 --- a/pytest_plugins/shared/execute_fill.py +++ b/pytest_plugins/shared/execute_fill.py @@ -1,4 +1,6 @@ -"""Shared pytest fixtures and hooks for EEST generation modes (fill and execute).""" +""" +Shared pytest fixtures and hooks for EEST generation modes (fill and execute). +""" from typing import List @@ -18,11 +20,12 @@ "env", } """ -List of test parameters that have a default fixture value which can be retrieved and used -for the test instance if it was not explicitly specified when calling from the test -function. +List of test parameters that have a default fixture value which can be +retrieved and used for the test instance if it was not explicitly specified +when calling from the test function. -All parameter names included in this list must define a fixture in one of the plugins. +All parameter names included in this list must define a fixture in one of the +plugins. """ @@ -35,12 +38,12 @@ def pytest_configure(config: pytest.Config): Couple of notes: 1. Register the plugin's custom markers and process command-line options. - Custom marker registration: - https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers + Custom marker registration: + https://docs.pytest.org/en/7.1.x/how-to/writing_plugins.html#registering-custom-markers 2. `@pytest.hookimpl(tryfirst=True)` is applied to ensure that this hook is - called before the pytest-html plugin's pytest_configure to ensure that - it uses the modified `htmlpath` option. + called before the pytest-html plugin's pytest_configure to ensure that + it uses the modified `htmlpath` option. """ if config.pluginmanager.has_plugin("pytest_plugins.filler.filler"): for fixture_format in BaseFixture.formats.values(): @@ -154,7 +157,10 @@ def pytest_configure(config: pytest.Config): @pytest.fixture(scope="function") def test_case_description(request: pytest.FixtureRequest) -> str: - """Fixture to extract and combine docstrings from the test class and the test function.""" + """ + Fixture to extract and combine docstrings from the test class and the test + function. + """ description_unavailable = ( "No description available - add a docstring to the python test class or function." ) @@ -172,8 +178,8 @@ def test_case_description(request: pytest.FixtureRequest) -> str: def pytest_make_parametrize_id(config: pytest.Config, val: str, argname: str): """ - Pytest hook called when generating test ids. We use this to generate - more readable test ids for the generated tests. + Pytest hook called when generating test ids. We use this to generate more + readable test ids for the generated tests. """ del config return f"{argname}_{val}" diff --git a/pytest_plugins/shared/helpers.py b/pytest_plugins/shared/helpers.py index bbe720b652..3c55d59376 100644 --- a/pytest_plugins/shared/helpers.py +++ b/pytest_plugins/shared/helpers.py @@ -30,11 +30,11 @@ def labeled_format_parameter_set( | FixtureFormat, ) -> ParameterSet: """ - Return a parameter set from a fixture/execute format and parses a label if there's - any. + Return a parameter set from a fixture/execute format and parses a label if + there's any. - The label will be used in the test id and also will be added as a marker to the - generated test case when filling/executing the test. + The label will be used in the test id and also will be added as a marker to + the generated test case when filling/executing the test. """ if isinstance(format_with_or_without_label, LabeledExecuteFormat) or isinstance( format_with_or_without_label, LabeledFixtureFormat diff --git a/pytest_plugins/shared/transaction_fixtures.py b/pytest_plugins/shared/transaction_fixtures.py index be3b16a6d6..cfe0cd6ef5 100644 --- a/pytest_plugins/shared/transaction_fixtures.py +++ b/pytest_plugins/shared/transaction_fixtures.py @@ -125,10 +125,12 @@ def type_4_default_transaction(sender, pre): @pytest.fixture def typed_transaction(request, fork): """ - Fixture that provides a Transaction object based on the parametrized tx type. + Fixture that provides a Transaction object based on the parametrized tx + type. - This fixture works with the @pytest.mark.with_all_typed_transactions marker, - which parametrizes the test with all transaction types supported by the fork. + This fixture works with the @pytest.mark.with_all_typed_transactions + marker, which parametrizes the test with all transaction types supported by + the fork. The actual transaction type value comes from the marker's parametrization. """ diff --git a/pytest_plugins/solc/solc.py b/pytest_plugins/solc/solc.py index e46d195478..692c5237c9 100644 --- a/pytest_plugins/solc/solc.py +++ b/pytest_plugins/solc/solc.py @@ -85,7 +85,8 @@ def pytest_configure(config: pytest.Config): # Extract version number try: - # --version format is typically something like "0.8.24+commit.e11b9ed9.Linux.g++" + # --version format is typically something like + # "0.8.24+commit.e11b9ed9.Linux.g++" version_str = version_line.split()[1].split("+")[0] solc_version_semver = Version.parse(version_str) except (IndexError, ValueError) as e: diff --git a/pytest_plugins/spec_version_checker/spec_version_checker.py b/pytest_plugins/spec_version_checker/spec_version_checker.py index 4091e88229..b5fb41c93d 100644 --- a/pytest_plugins/spec_version_checker/spec_version_checker.py +++ b/pytest_plugins/spec_version_checker/spec_version_checker.py @@ -70,18 +70,17 @@ def get_ref_spec_from_module( Return the reference spec object defined in a module. Args: - module: The module to extract reference spec from - github_token: Optional GitHub token for API authentication + module: The module to extract reference spec from + github_token: Optional GitHub token for API authentication Raises: - Exception: If the module path contains "eip" and the module - does not define a reference spec. + Exception: If the module path contains "eip" and the module does + not define a reference spec. Returns: - spec_obj: Return None if the module path does not contain "eip", - i.e., the module is not required to define a reference spec, - otherwise, return the ReferenceSpec object as defined by the - module. + spec_obj: Return None if the module path does not contain "eip", + i.e., the module is not required to define a reference spec, otherwise, + return the ReferenceSpec object as defined by the module. """ if not is_test_for_an_eip(str(module.__file__)): @@ -115,13 +114,12 @@ def is_test_for_an_eip(input_string: str) -> bool: def test_eip_spec_version(module: ModuleType, github_token: Optional[str] = None): """ - Test that the ReferenceSpec object as defined in the test module - is not outdated when compared to the remote hash from - ethereum/EIPs. + Test that the ReferenceSpec object as defined in the test module is not + outdated when compared to the remote hash from ethereum/EIPs. Args: - module: Module to test - github_token: Optional GitHub token for API authentication + module: Module to test + github_token: Optional GitHub token for API authentication """ ref_spec = get_ref_spec_from_module(module, github_token=github_token) @@ -157,9 +155,9 @@ def __init__(self, name: str, parent: Node, **kwargs: Any): Initialize the test item. Args: - name: Name of the test - parent: Parent node - **kwargs: Additional keyword arguments + name: Name of the test + parent: Parent node + **kwargs: Additional keyword arguments """ super().__init__(name, parent) @@ -202,12 +200,11 @@ def reportinfo(self) -> tuple[str, int, str]: return "spec_version_checker", 0, f"{self.name}" -def pytest_collection_modifyitems( - session: pytest.Session, config: pytest.Config, items: List[Item] -): - """Insert a new test EIPSpecTestItem for every test module with 'eip' in its path.""" - del session - +def pytest_collection_modifyitems(config: pytest.Config, items: List[Item]): + """ + Insert a new test EIPSpecTestItem for every test module with 'eip' in its + path. + """ github_token = config.github_token if hasattr(config, "github_token") else None modules: Set[Module] = {item.parent for item in items if isinstance(item.parent, Module)} From e86958f9eadb4cfca38b81059e5e9056b2bc044c Mon Sep 17 00:00:00 2001 From: felix Date: Thu, 25 Sep 2025 16:39:21 +0000 Subject: [PATCH 033/102] chore: shorten docstrings and single-line comments to 79 (ruff w505: doc-line-too-long) (#2180) * split comments across multiple lines when necessary * chore(tooling): check w505 in tox lint env * fixes * chore: remove abstract and other admonitions from test module docstrings * fixes * chore: fix more malformatted tables * chore: fix broken unordered-lists/args * chore: fix broken unordered-lists/args * chore: improve docstrings, also for D205 * chore: improve docstrings, also for D205 * chore: fix long or poorly formatted comments * chore: manually revert and fix docstrings/comments * fix: bad string formatting fix in unit test * last batch of manual fixes * fix * fix --------- Co-authored-by: danceratopz --- amsterdam/__init__.py | 5 +- .../test_block_access_lists_invalid.py | 43 +- benchmark/__init__.py | 13 +- benchmark/conftest.py | 5 +- benchmark/helpers.py | 3 +- benchmark/test_worst_blocks.py | 30 +- benchmark/test_worst_bytecode.py | 140 +++--- benchmark/test_worst_compute.py | 453 +++++++++++------- benchmark/test_worst_memory.py | 45 +- benchmark/test_worst_opcode.py | 5 +- benchmark/test_worst_stateful_opcodes.py | 87 ++-- berlin/eip2929_gas_cost_increases/__init__.py | 5 +- .../test_precompile_warming.py | 30 +- berlin/eip2930_access_list/__init__.py | 3 +- .../test_tx_intrinsic_gas.py | 9 +- byzantium/eip198_modexp_precompile/helpers.py | 21 +- .../eip198_modexp_precompile/test_modexp.py | 32 +- cancun/eip1153_tstore/__init__.py | 48 +- cancun/eip1153_tstore/test_tload_calls.py | 17 +- .../eip1153_tstore/test_tload_reentrancy.py | 10 +- cancun/eip1153_tstore/test_tstorage.py | 49 +- .../test_tstorage_clear_after_tx.py | 19 +- .../test_tstorage_create_contexts.py | 57 ++- .../test_tstorage_execution_contexts.py | 22 +- .../test_tstorage_reentrancy_contexts.py | 107 +++-- .../test_tstorage_selfdestruct.py | 23 +- .../eip1153_tstore/test_tstore_reentrancy.py | 17 +- cancun/eip4788_beacon_root/conftest.py | 22 +- .../test_beacon_root_contract.py | 142 +++--- cancun/eip4844_blobs/conftest.py | 58 ++- cancun/eip4844_blobs/spec.py | 33 +- cancun/eip4844_blobs/test_blob_txs.py | 189 +++++--- cancun/eip4844_blobs/test_blob_txs_full.py | 22 +- cancun/eip4844_blobs/test_blobhash_opcode.py | 52 +- .../test_blobhash_opcode_contexts.py | 35 +- cancun/eip4844_blobs/test_excess_blob_gas.py | 105 ++-- .../test_excess_blob_gas_fork_transition.py | 42 +- .../test_point_evaluation_precompile.py | 87 ++-- .../test_point_evaluation_precompile_gas.py | 26 +- cancun/eip5656_mcopy/common.py | 9 +- cancun/eip5656_mcopy/test_mcopy.py | 22 +- cancun/eip5656_mcopy/test_mcopy_contexts.py | 29 +- .../test_mcopy_memory_expansion.py | 26 +- ..._dynamic_create2_selfdestruct_collision.py | 163 ++++--- .../test_reentrancy_selfdestruct_revert.py | 17 +- .../eip6780_selfdestruct/test_selfdestruct.py | 228 +++++---- .../test_selfdestruct_revert.py | 46 +- .../test_blobgasfee_opcode.py | 30 +- constantinople/eip1014_create2/__init__.py | 4 +- .../eip1014_create2/test_create_returndata.py | 17 +- .../eip1014_create2/test_recreate.py | 4 +- .../eip145_bitwise_shift/__init__.py | 4 +- constantinople/eip145_bitwise_shift/spec.py | 4 +- frontier/create/test_create_one_byte.py | 4 +- frontier/identity_precompile/common.py | 20 +- frontier/identity_precompile/test_identity.py | 7 +- .../test_identity_returndatasize.py | 7 +- frontier/opcodes/test_all_opcodes.py | 14 +- frontier/opcodes/test_call.py | 65 ++- .../test_call_and_callcode_gas_calculation.py | 104 ++-- frontier/opcodes/test_calldataload.py | 11 +- frontier/opcodes/test_calldatasize.py | 11 +- frontier/opcodes/test_dup.py | 16 +- frontier/opcodes/test_push.py | 36 +- frontier/opcodes/test_selfdestruct.py | 6 +- .../precompiles/test_precompile_absence.py | 7 +- frontier/precompiles/test_precompiles.py | 36 +- frontier/scenarios/common.py | 49 +- .../programs/all_frontier_opcodes.py | 9 +- frontier/scenarios/programs/context_calls.py | 4 +- .../scenarios/scenarios/call_combinations.py | 39 +- .../scenarios/create_combinations.py | 8 +- frontier/scenarios/test_scenarios.py | 34 +- homestead/coverage/test_coverage.py | 13 +- istanbul/eip1344_chainid/__init__.py | 3 +- istanbul/eip1344_chainid/test_chainid.py | 3 +- istanbul/eip152_blake2/__init__.py | 3 +- istanbul/eip152_blake2/common.py | 30 +- istanbul/eip152_blake2/conftest.py | 4 +- istanbul/eip152_blake2/spec.py | 20 +- istanbul/eip152_blake2/test_blake2.py | 3 +- .../eip152_blake2/test_blake2_delegatecall.py | 12 +- osaka/__init__.py | 5 +- osaka/eip7594_peerdas/__init__.py | 3 +- osaka/eip7594_peerdas/test_get_blobs.py | 28 +- osaka/eip7594_peerdas/test_max_blob_per_tx.py | 22 +- osaka/eip7823_modexp_upper_bounds/__init__.py | 5 +- osaka/eip7823_modexp_upper_bounds/conftest.py | 36 +- .../test_modexp_upper_bounds.py | 11 +- .../__init__.py | 3 +- .../eip7825_transaction_gas_limit_cap/spec.py | 4 +- .../test_tx_gas_limit.py | 51 +- .../test_tx_gas_limit_transition_fork.py | 16 +- osaka/eip7883_modexp_gas_increase/__init__.py | 3 +- osaka/eip7883_modexp_gas_increase/conftest.py | 36 +- osaka/eip7883_modexp_gas_increase/helpers.py | 5 +- osaka/eip7883_modexp_gas_increase/spec.py | 24 +- .../test_modexp_thresholds.py | 183 +++---- .../test_modexp_thresholds_transition.py | 9 +- osaka/eip7918_blob_reserve_price/conftest.py | 22 +- osaka/eip7918_blob_reserve_price/spec.py | 8 +- .../test_blob_base_fee.py | 50 +- .../test_blob_reserve_price_with_bpo.py | 7 +- ...blob_reserve_price_with_bpo_transitions.py | 58 ++- osaka/eip7934_block_rlp_limit/__init__.py | 3 +- .../test_max_block_rlp_size.py | 34 +- osaka/eip7939_count_leading_zeros/__init__.py | 3 +- .../test_count_leading_zeros.py | 27 +- .../__init__.py | 3 +- .../conftest.py | 26 +- .../eip7951_p256verify_precompiles/helpers.py | 15 +- osaka/eip7951_p256verify_precompiles/spec.py | 3 +- .../test_p256verify.py | 124 +++-- .../test_p256verify_before_fork.py | 10 +- .../security/test_selfdestruct_balance_bug.py | 26 +- prague/__init__.py | 5 +- .../__init__.py | 5 +- .../conftest.py | 61 +-- .../eip2537_bls_12_381_precompiles/helpers.py | 340 ++++++++----- prague/eip2537_bls_12_381_precompiles/spec.py | 8 +- .../test_bls12_g1add.py | 23 +- .../test_bls12_g1msm.py | 17 +- .../test_bls12_g1mul.py | 19 +- .../test_bls12_g2add.py | 20 +- .../test_bls12_g2msm.py | 17 +- .../test_bls12_g2mul.py | 19 +- .../test_bls12_map_fp2_to_g2.py | 50 +- .../test_bls12_map_fp_to_g1.py | 28 +- .../test_bls12_pairing.py | 16 +- .../test_bls12_precompiles_before_fork.py | 10 +- ...t_bls12_variable_length_input_contracts.py | 140 +++--- .../test_block_hashes.py | 78 +-- .../test_contract_deployment.py | 24 +- prague/eip6110_deposits/conftest.py | 13 +- prague/eip6110_deposits/helpers.py | 102 ++-- prague/eip6110_deposits/test_deposits.py | 22 +- .../test_modified_contract.py | 62 ++- .../conftest.py | 13 +- .../helpers.py | 84 ++-- .../spec.py | 5 +- .../test_contract_deployment.py | 5 +- .../test_modified_withdrawal_contract.py | 18 +- .../test_withdrawal_requests.py | 10 +- .../test_withdrawal_requests_during_fork.py | 19 +- prague/eip7251_consolidations/conftest.py | 15 +- prague/eip7251_consolidations/helpers.py | 86 ++-- .../test_consolidations.py | 10 +- .../test_consolidations_during_fork.py | 19 +- .../test_contract_deployment.py | 5 +- .../test_modified_consolidation_contract.py | 17 +- .../__init__.py | 3 +- .../conftest.py | 92 ++-- .../eip7623_increase_calldata_cost/helpers.py | 15 +- .../test_execution_gas.py | 28 +- .../test_refunds.py | 83 ++-- .../test_transaction_validity.py | 34 +- .../conftest.py | 11 +- .../spec.py | 5 +- .../test_multi_type_requests.py | 97 ++-- prague/eip7702_set_code_tx/helpers.py | 9 +- prague/eip7702_set_code_tx/test_gas.py | 140 +++--- prague/eip7702_set_code_tx/test_invalid_tx.py | 62 ++- .../eip7702_set_code_tx/test_set_code_txs.py | 256 ++++++---- .../test_set_code_txs_2.py | 146 ++++-- shanghai/eip3651_warm_coinbase/__init__.py | 3 +- .../test_warm_coinbase.py | 7 +- shanghai/eip3855_push0/__init__.py | 3 +- shanghai/eip3855_push0/test_push0.py | 27 +- shanghai/eip3860_initcode/__init__.py | 3 +- shanghai/eip3860_initcode/spec.py | 4 +- shanghai/eip3860_initcode/test_initcode.py | 96 ++-- shanghai/eip3860_initcode/test_with_eof.py | 13 +- shanghai/eip4895_withdrawals/__init__.py | 4 +- .../eip4895_withdrawals/test_withdrawals.py | 46 +- unscheduled/__init__.py | 5 +- unscheduled/eip7692_eof_v1/__init__.py | 8 +- .../eip7692_eof_v1/eip3540_eof_v1/__init__.py | 13 +- .../test_all_opcodes_in_container.py | 60 ++- .../eip3540_eof_v1/test_container_size.py | 13 +- .../test_container_validation.py | 38 +- .../eip3540_eof_v1/test_eof_example.py | 52 +- .../eip3540_eof_v1/test_opcodes_in_legacy.py | 9 +- .../test_section_header_body_mismatch.py | 27 +- .../eip3540_eof_v1/test_section_order.py | 24 +- .../eip3540_eof_v1/test_section_size.py | 16 +- .../eip4200_relative_jumps/__init__.py | 10 +- .../eip4200_relative_jumps/test_rjump.py | 114 +++-- .../eip4200_relative_jumps/test_rjumpi.py | 109 +++-- .../eip4200_relative_jumps/test_rjumpv.py | 100 ++-- .../eip4750_functions/__init__.py | 10 +- .../eip4750_functions/test_callf_execution.py | 30 +- .../eip4750_functions/test_code_validation.py | 55 ++- .../eip7692_eof_v1/eip5450_stack/__init__.py | 11 +- .../eip5450_stack/test_code_validation.py | 73 +-- .../eip5450_stack/test_execution.py | 13 +- .../eip7692_eof_v1/eip6206_jumpf/__init__.py | 10 +- .../eip6206_jumpf/test_jumpf_execution.py | 38 +- .../eip6206_jumpf/test_jumpf_stack.py | 18 +- .../eip6206_jumpf/test_jumpf_target.py | 20 +- .../eip6206_jumpf/test_jumpf_validation.py | 38 +- .../test_nonreturning_validation.py | 28 +- .../eip663_dupn_swapn_exchange/__init__.py | 10 +- .../eip663_dupn_swapn_exchange/test_dupn.py | 7 +- .../test_exchange.py | 5 +- .../eip663_dupn_swapn_exchange/test_swapn.py | 5 +- .../eip7069_extcall/__init__.py | 11 +- .../test_address_space_extension.py | 12 +- .../eip7069_extcall/test_calldata.py | 44 +- .../eip7069_extcall/test_calls.py | 70 ++- .../eip7069_extcall/test_gas.py | 35 +- .../test_returndatacopy_memory_expansion.py | 19 +- .../eip7069_extcall/test_returndataload.py | 37 +- .../eip7480_data_section/__init__.py | 12 +- .../eip7480_data_section/test_data_opcodes.py | 5 +- .../test_datacopy_memory_expansion.py | 19 +- .../eip7620_eof_create/__init__.py | 33 +- .../eip7620_eof_create/test_eofcreate.py | 46 +- .../test_eofcreate_failures.py | 117 +++-- .../eip7620_eof_create/test_gas.py | 5 +- .../test_legacy_eof_creates.py | 15 +- .../eip7620_eof_create/test_memory.py | 20 +- .../eip7620_eof_create/test_returncode.py | 21 +- .../test_subcontainer_validation.py | 57 ++- .../eip7873_tx_create/__init__.py | 5 +- .../eip7873_tx_create/test_creation_tx.py | 6 +- .../eip7873_tx_create/test_txcreate.py | 46 +- .../test_txcreate_failures.py | 115 +++-- .../test_txcreate_validates.py | 19 +- unscheduled/eip7692_eof_v1/gas_test.py | 25 +- 229 files changed, 5110 insertions(+), 3380 deletions(-) diff --git a/amsterdam/__init__.py b/amsterdam/__init__.py index b4d638e152..89848292b5 100644 --- a/amsterdam/__init__.py +++ b/amsterdam/__init__.py @@ -1 +1,4 @@ -"""Test cases for EVM functionality introduced in Amsterdam, [EIP-7773: Hardfork Meta - Glamsterdam](https://eip.directory/eips/eip-7773).""" # noqa: E501 +""" +Test cases for EVM functionality introduced in Amsterdam, [EIP-7773: Hardfork +Meta - Glamsterdam](https://eip.directory/eips/eip-7773). +""" diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py index 7041a3bbcf..34ae52f903 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_invalid.py @@ -1,7 +1,7 @@ """ Test cases for invalid Block Access Lists. -These tests verify that clients properly reject blocks with corrupted BALs +These tests verify that clients properly reject blocks with corrupted BALs. """ import pytest @@ -52,7 +52,10 @@ def test_bal_invalid_missing_nonce( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test that clients reject blocks where BAL is missing required nonce changes.""" + """ + Test that clients reject blocks where BAL is missing required nonce + changes. + """ sender = pre.fund_eoa(amount=10**18) receiver = pre.fund_eoa(amount=0) @@ -91,7 +94,9 @@ def test_bal_invalid_nonce_value( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test that clients reject blocks where BAL contains incorrect nonce value.""" + """ + Test that clients reject blocks where BAL contains incorrect nonce value. + """ sender = pre.fund_eoa(amount=10**18) receiver = pre.fund_eoa(amount=0) @@ -130,7 +135,10 @@ def test_bal_invalid_storage_value( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test that clients reject blocks where BAL contains incorrect storage values.""" + """ + Test that clients reject blocks where BAL contains incorrect storage + values. + """ sender = pre.fund_eoa(amount=10**18) # Simple storage contract with canary values @@ -190,7 +198,10 @@ def test_bal_invalid_tx_order( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test that clients reject blocks where BAL has incorrect transaction ordering.""" + """ + Test that clients reject blocks where BAL has incorrect transaction + ordering. + """ sender1 = pre.fund_eoa(amount=10**18) sender2 = pre.fund_eoa(amount=10**18) receiver = pre.fund_eoa(amount=0) @@ -247,7 +258,10 @@ def test_bal_invalid_account( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test that clients reject blocks where BAL contains accounts that don't exist.""" + """ + Test that clients reject blocks where BAL contains accounts that don't + exist. + """ sender = pre.fund_eoa(amount=10**18) receiver = pre.fund_eoa(amount=0) phantom = pre.fund_eoa(amount=0) @@ -295,7 +309,10 @@ def test_bal_invalid_duplicate_account( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test that clients reject blocks where BAL contains duplicate account entries.""" + """ + Test that clients reject blocks where BAL contains duplicate account + entries. + """ sender = pre.fund_eoa(amount=10**18) receiver = pre.fund_eoa(amount=0) @@ -337,7 +354,9 @@ def test_bal_invalid_account_order( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test that clients reject blocks where BAL has incorrect account ordering.""" + """ + Test that clients reject blocks where BAL has incorrect account ordering. + """ sender = pre.fund_eoa(amount=10**18) receiver = pre.fund_eoa(amount=0) @@ -454,7 +473,9 @@ def test_bal_invalid_missing_account( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test that clients reject blocks where BAL is missing an entire account.""" + """ + Test that clients reject blocks where BAL is missing an entire account. + """ sender = pre.fund_eoa(amount=10**18) receiver = pre.fund_eoa(amount=0) @@ -496,7 +517,9 @@ def test_bal_invalid_balance_value( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test that clients reject blocks where BAL contains incorrect balance value.""" + """ + Test that clients reject blocks where BAL contains incorrect balance value. + """ sender = pre.fund_eoa(amount=10**18) receiver = pre.fund_eoa(amount=0) diff --git a/benchmark/__init__.py b/benchmark/__init__.py index 8c37b7d6e0..ce3a8eda04 100644 --- a/benchmark/__init__.py +++ b/benchmark/__init__.py @@ -1,8 +1,9 @@ """ -abstract: Benchmark tests for EVMs. - Benchmark tests aim to maximize the usage of a specific opcode, - precompile, or operation within a transaction or block. These can - be executed against EVM implementations to ensure they handle - pathological cases efficiently and correctly, allowing Ethereum to - safely [Scale the L1](https://protocol.ethereum.foundation/). +Benchmark tests for EVMs. + +Benchmark tests aim to maximize the usage of a specific opcode, precompile, +or operation within a transaction or block. These can be executed against +EVM implementations to ensure they handle pathological cases efficiently +and correctly, allowing Ethereum to safely +[Scale the L1](https://protocol.ethereum.foundation/). """ diff --git a/benchmark/conftest.py b/benchmark/conftest.py index 1e2e781381..d51b47dda8 100644 --- a/benchmark/conftest.py +++ b/benchmark/conftest.py @@ -10,7 +10,10 @@ def pytest_generate_tests(metafunc): - """Modify test generation to enforce default benchmark fork for benchmark tests.""" + """ + Modify test generation to enforce default benchmark fork for benchmark + tests. + """ benchmark_dir = Path(__file__).parent test_file_path = Path(metafunc.definition.fspath) diff --git a/benchmark/helpers.py b/benchmark/helpers.py index ca3e070572..c0e7f80ac6 100644 --- a/benchmark/helpers.py +++ b/benchmark/helpers.py @@ -9,7 +9,8 @@ def code_loop_precompile_call(calldata: Bytecode, attack_block: Bytecode, fork: """Create a code loop that calls a precompile with the given calldata.""" max_code_size = fork.max_code_size() - # The attack contract is: CALLDATA_PREP + #JUMPDEST + [attack_block]* + JUMP(#) + # The attack contract is: CALLDATA_PREP + #JUMPDEST + [attack_block]* + + # JUMP(#) jumpdest = Op.JUMPDEST jump_back = Op.JUMP(len(calldata)) max_iters_loop = (max_code_size - len(calldata) - len(jumpdest) - len(jump_back)) // len( diff --git a/benchmark/test_worst_blocks.py b/benchmark/test_worst_blocks.py index b71f303506..6d95ef657b 100644 --- a/benchmark/test_worst_blocks.py +++ b/benchmark/test_worst_blocks.py @@ -1,8 +1,5 @@ """ -abstract: Tests that benchmark EVMs in worst-case block scenarios. - Tests that benchmark EVMs in worst-case block scenarios. - -Tests running worst-case block scenarios for EVMs. +Tests that benchmark EVMs in worst-case block scenarios. """ import random @@ -26,7 +23,10 @@ @pytest.fixture def iteration_count(intrinsic_cost: int, gas_benchmark_value: int): - """Calculate the number of iterations based on the gas limit and intrinsic cost.""" + """ + Calculate the number of iterations based on the gas limit and intrinsic + cost. + """ return gas_benchmark_value // intrinsic_cost @@ -186,12 +186,14 @@ def test_block_full_data( gas_benchmark_value: int, ): """Test a block with empty payload.""" - # Gas cost calculation based on EIP-7683: (https://eips.ethereum.org/EIPS/eip-7683) + # Gas cost calculation based on EIP-7683: + # (https://eips.ethereum.org/EIPS/eip-7683) # # tx.gasUsed = 21000 + max( # STANDARD_TOKEN_COST * tokens_in_calldata # + execution_gas_used - # + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata)), + # + isContractCreation * (32000 + + # INITCODE_WORD_COST * words(calldata)), # TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata) # # Simplified in this test case: @@ -208,7 +210,8 @@ def test_block_full_data( # Token accounting: # tokens_in_calldata = zero_bytes + 4 * non_zero_bytes # - # So we calculate how many bytes we can fit into calldata based on available gas. + # So we calculate how many bytes we can fit into calldata based on + # available gas. gas_available = gas_benchmark_value - intrinsic_cost @@ -240,7 +243,10 @@ def test_block_full_access_list_and_data( fork: Fork, gas_benchmark_value: int, ): - """Test a block with access lists (60% gas) and calldata (40% gas) using random mixed bytes.""" + """ + Test a block with access lists (60% gas) and calldata (40% gas) using + random mixed bytes. + """ attack_gas_limit = gas_benchmark_value gas_available = attack_gas_limit - intrinsic_cost @@ -271,7 +277,8 @@ def test_block_full_access_list_and_data( ) ] - # Calculate calldata with 29% of gas for zero bytes and 71% for non-zero bytes + # Calculate calldata with 29% of gas for zero bytes and 71% for non-zero + # bytes # Token accounting: tokens_in_calldata = zero_bytes + 4 * non_zero_bytes # We want to split the gas budget: # - 29% of gas_for_calldata for zero bytes @@ -287,7 +294,8 @@ def test_block_full_access_list_and_data( # Zero bytes: 1 token per byte # Non-zero bytes: 4 tokens per byte num_zero_bytes = tokens_for_zero_bytes # 1 token = 1 zero byte - num_non_zero_bytes = tokens_for_non_zero_bytes // 4 # 4 tokens = 1 non-zero byte + # 4 tokens = 1 non-zero byte + num_non_zero_bytes = tokens_for_non_zero_bytes // 4 # Create calldata with mixed bytes calldata = bytearray() diff --git a/benchmark/test_worst_bytecode.py b/benchmark/test_worst_bytecode.py index 9c38e010bb..1422739404 100644 --- a/benchmark/test_worst_bytecode.py +++ b/benchmark/test_worst_bytecode.py @@ -1,7 +1,4 @@ """ -abstract: Tests that benchmark EVMs in worst-case opcode scenarios. - Tests that benchmark EVMs in worst-case opcode scenarios. - Tests that benchmark EVMs in worst-case opcode scenarios. """ @@ -56,30 +53,30 @@ def test_worst_bytecode_single_opcode( gas_benchmark_value: int, ): """ - Test a block execution where a single opcode execution maxes out the gas limit, - and the opcodes access a huge amount of contract code. + Test a block execution where a single opcode execution maxes out the gas + limit, and the opcodes access a huge amount of contract code. - We first use a single block to deploy a factory contract that will be used to deploy - a large number of contracts. + We first use a single block to deploy a factory contract that will be used + to deploy a large number of contracts. This is done to avoid having a big pre-allocation size for the test. - The test is performed in the last block of the test, and the entire block gas limit is - consumed by repeated opcode executions. + The test is performed in the last block of the test, and the entire block + gas limit is consumed by repeated opcode executions. """ - # The attack gas limit is the gas limit which the target tx will use - # The test will scale the block gas limit to setup the contracts accordingly to be - # able to pay for the contract deposit. This has to take into account the 200 gas per byte, - # but also the quadratic memory expansion costs which have to be paid each time the - # memory is being setup + # The attack gas limit is the gas limit which the target tx will use The + # test will scale the block gas limit to setup the contracts accordingly to + # be able to pay for the contract deposit. This has to take into account + # the 200 gas per byte, but also the quadratic memory expansion costs which + # have to be paid each time the memory is being setup attack_gas_limit = gas_benchmark_value max_contract_size = fork.max_code_size() gas_costs = fork.gas_costs() - # Calculate the absolute minimum gas costs to deploy the contract - # This does not take into account setting up the actual memory (using KECCAK256 and XOR) - # so the actual costs of deploying the contract is higher + # Calculate the absolute minimum gas costs to deploy the contract This does + # not take into account setting up the actual memory (using KECCAK256 and + # XOR) so the actual costs of deploying the contract is higher memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() memory_gas_minimum = memory_expansion_gas_calculator(new_bytes=len(bytes(max_contract_size))) code_deposit_gas_minimum = ( @@ -90,7 +87,8 @@ def test_worst_bytecode_single_opcode( # Calculate the loop cost of the attacker to query one address loop_cost = ( gas_costs.G_KECCAK_256 # KECCAK static cost - + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic cost for CREATE2 + + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic + # cost for CREATE2 + gas_costs.G_VERY_LOW * 3 # ~MSTOREs+ADDs + gas_costs.G_COLD_ACCOUNT_ACCESS # Opcode cost + 30 # ~Gluing opcodes @@ -101,8 +99,9 @@ def test_worst_bytecode_single_opcode( attack_gas_limit - intrinsic_gas_cost_calc() - gas_costs.G_VERY_LOW * 4 ) // loop_cost - # Set the block gas limit to a relative high value to ensure the code deposit tx - # fits in the block (there is enough gas available in the block to execute this) + # Set the block gas limit to a relative high value to ensure the code + # deposit tx fits in the block (there is enough gas available in the block + # to execute this) minimum_gas_limit = code_deposit_gas_minimum * 2 * num_contracts if env.gas_limit < minimum_gas_limit: raise Exception( @@ -111,16 +110,17 @@ def test_worst_bytecode_single_opcode( "optimizing gas usage during the setup phase of this test." ) - # The initcode will take its address as a starting point to the input to the keccak - # hash function. - # It will reuse the output of the hash function in a loop to create a large amount of - # seemingly random code, until it reaches the maximum contract size. + # The initcode will take its address as a starting point to the input to + # the keccak hash function. It will reuse the output of the hash function + # in a loop to create a large amount of seemingly random code, until it + # reaches the maximum contract size. initcode = ( Op.MSTORE(0, Op.ADDRESS) + While( body=( Op.SHA3(Op.SUB(Op.MSIZE, 32), 32) - # Use a xor table to avoid having to call the "expensive" sha3 opcode as much + # Use a xor table to avoid having to call the "expensive" sha3 + # opcode as much + sum( (Op.PUSH32[xor_value] + Op.XOR + Op.DUP1 + Op.MSIZE + Op.MSTORE) for xor_value in XOR_TABLE @@ -129,16 +129,16 @@ def test_worst_bytecode_single_opcode( ), condition=Op.LT(Op.MSIZE, max_contract_size), ) - # Despite the whole contract has random bytecode, we make the first opcode be a STOP - # so CALL-like attacks return as soon as possible, while EXTCODE(HASH|SIZE) work as - # intended. + # Despite the whole contract has random bytecode, we make the first + # opcode be a STOP so CALL-like attacks return as soon as possible, + # while EXTCODE(HASH|SIZE) work as intended. + Op.MSTORE8(0, 0x00) + Op.RETURN(0, max_contract_size) ) initcode_address = pre.deploy_contract(code=initcode) - # The factory contract will simply use the initcode that is already deployed, - # and create a new contract and return its address if successful. + # The factory contract will simply use the initcode that is already + # deployed, and create a new contract and return its address if successful. factory_code = ( Op.EXTCODECOPY( address=initcode_address, @@ -160,8 +160,8 @@ def test_worst_bytecode_single_opcode( ) factory_address = pre.deploy_contract(code=factory_code) - # The factory caller will call the factory contract N times, creating N new contracts. - # Calldata should contain the N value. + # The factory caller will call the factory contract N times, creating N new + # contracts. Calldata should contain the N value. factory_caller_code = Op.CALLDATALOAD(0) + While( body=Op.POP(Op.CALL(address=factory_address)), condition=Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO, @@ -208,8 +208,8 @@ def test_worst_bytecode_single_opcode( ) if len(attack_code) > max_contract_size: - # TODO: A workaround could be to split the opcode code into multiple contracts - # and call them in sequence. + # TODO: A workaround could be to split the opcode code into multiple + # contracts and call them in sequence. raise ValueError( f"Code size {len(attack_code)} exceeds maximum code size {max_contract_size}" ) @@ -254,17 +254,18 @@ def test_worst_initcode_jumpdest_analysis( """ Test the jumpdest analysis performance of the initcode. - This benchmark places a very long initcode in the memory and then invoke CREATE instructions - with this initcode up to the block gas limit. The initcode itself has minimal execution time - but forces the EVM to perform the full jumpdest analysis on the parametrized byte pattern. - The initicode is modified by mixing-in the returned create address between CREATE invocations - to prevent caching. + This benchmark places a very long initcode in the memory and then invoke + CREATE instructions with this initcode up to the block gas limit. The + initcode itself has minimal execution time but forces the EVM to perform + the full jumpdest analysis on the parametrized byte pattern. The initicode + is modified by mixing-in the returned create address between CREATE + invocations to prevent caching. """ max_code_size = fork.max_code_size() initcode_size = fork.max_initcode_size() - # Expand the initcode pattern to the transaction data so it can be used in CALLDATACOPY - # in the main contract. TODO: tune the tx_data_len param. + # Expand the initcode pattern to the transaction data so it can be used in + # CALLDATACOPY in the main contract. TODO: tune the tx_data_len param. tx_data_len = 1024 tx_data = pattern * (tx_data_len // len(pattern)) tx_data += (tx_data_len - len(tx_data)) * bytes(Op.JUMPDEST) @@ -332,8 +333,9 @@ def test_worst_initcode_jumpdest_analysis( @pytest.mark.parametrize( "max_code_size_ratio, non_zero_data, value", [ - # To avoid a blowup of combinations, the value dimension is only explored for - # the non-zero data case, so isn't affected by code size influence. + # To avoid a blowup of combinations, the value dimension is only + # explored for the non-zero data case, so isn't affected by code size + # influence. pytest.param(0, False, 0, id="0 bytes without value"), pytest.param(0, False, 1, id="0 bytes with value"), pytest.param(0.25, True, 0, id="0.25x max code size with non-zero data"), @@ -356,7 +358,9 @@ def test_worst_create( value: int, gas_benchmark_value: int, ): - """Test the CREATE and CREATE2 performance with different configurations.""" + """ + Test the CREATE and CREATE2 performance with different configurations. + """ max_code_size = fork.max_code_size() code_size = int(max_code_size * max_code_size_ratio) @@ -381,7 +385,9 @@ def test_worst_create( # Create the benchmark contract which has the following design: # ``` # PUSH(value) - # [EXTCODECOPY(full initcode_template_contract) -- Conditional that non_zero_data is True]` + # [EXTCODECOPY(full initcode_template_contract) + # -> Conditional that non_zero_data is True] + # # JUMPDEST (#) # (CREATE|CREATE2) # (CREATE|CREATE2) @@ -407,10 +413,11 @@ def test_worst_create( # - DUP3 refers to PUSH1(value) above. Op.POP(Op.CREATE(value=Op.DUP3, offset=0, size=Op.DUP2)) if opcode == Op.CREATE - # For CREATE2: we manually push the arguments because we leverage the return value of - # previous CREATE2 calls as salt for the next CREATE2 call. - # - DUP4 is targeting the PUSH1(value) from the code_prefix. - # - DUP3 is targeting the EXTCODESIZE value pushed in code_prefix. + # For CREATE2: we manually push the arguments because we leverage the + # return value of previous CREATE2 calls as salt for the next CREATE2 + # call. + # - DUP4 is targeting the PUSH1(value) from the code_prefix. + # - DUP3 is targeting the EXTCODESIZE value pushed in code_prefix. else Op.DUP3 + Op.PUSH0 + Op.DUP4 + Op.CREATE2 ) code = code_loop_precompile_call(code_prefix, attack_block, fork) @@ -444,20 +451,20 @@ def test_worst_creates_collisions( gas_benchmark_value: int, ): """Test the CREATE and CREATE2 collisions performance.""" - # We deploy a "proxy contract" which is the contract that will be called in a loop - # using all the gas in the block. This "proxy contract" is the one executing CREATE2 - # failing with a collision. - # The reason why we need a "proxy contract" is that CREATE(2) failing with a collision will - # consume all the available gas. If we try to execute the CREATE(2) directly without being - # wrapped **and capped in gas** in a previous CALL, we would run out of gas very fast! - # - # The proxy contract calls CREATE(2) with empty initcode. The current call frame gas will - # be exhausted because of the collision. For this reason the caller will carefully give us - # the minimal gas necessary to execute the CREATE(2) and not waste any extra gas in the - # CREATE(2)-failure. - # - # Note that these CREATE(2) calls will fail because in (**) below we pre-alloc contracts - # with the same address as the ones that CREATE(2) will try to create. + # We deploy a "proxy contract" which is the contract that will be called in + # a loop using all the gas in the block. This "proxy contract" is the one + # executing CREATE2 failing with a collision. The reason why we need a + # "proxy contract" is that CREATE(2) failing with a collision will consume + # all the available gas. If we try to execute the CREATE(2) directly + # without being wrapped **and capped in gas** in a previous CALL, we would + # run out of gas very fast! + # The proxy contract calls CREATE(2) with empty initcode. The current call + # frame gas will be exhausted because of the collision. For this reason the + # caller will carefully give us the minimal gas necessary to execute the + # CREATE(2) and not waste any extra gas in the CREATE(2)-failure. + # Note that these CREATE(2) calls will fail because in (**) below we pre- + # alloc contracts with the same address as the ones that CREATE(2) will try + # to create. proxy_contract = pre.deploy_contract( code=Op.CREATE2(value=Op.PUSH0, salt=Op.PUSH0, offset=Op.PUSH0, size=Op.PUSH0) if opcode == Op.CREATE2 @@ -465,8 +472,8 @@ def test_worst_creates_collisions( ) gas_costs = fork.gas_costs() - # The CALL to the proxy contract needs at a minimum gas corresponding to the CREATE(2) - # plus extra required PUSH0s for arguments. + # The CALL to the proxy contract needs at a minimum gas corresponding to + # the CREATE(2) plus extra required PUSH0s for arguments. min_gas_required = gas_costs.G_CREATE + gas_costs.G_BASE * (3 if opcode == Op.CREATE else 4) code_prefix = Op.PUSH20(proxy_contract) + Op.PUSH3(min_gas_required) attack_block = Op.POP( @@ -477,7 +484,8 @@ def test_worst_creates_collisions( code = code_loop_precompile_call(code_prefix, attack_block, fork) tx_target = pre.deploy_contract(code=code) - # (**) We deploy the contract that CREATE(2) will attempt to create so any attempt will fail. + # (**) We deploy the contract that CREATE(2) will attempt to create so any + # attempt will fail. if opcode == Op.CREATE2: addr = compute_create2_address(address=proxy_contract, salt=0, initcode=[]) pre.deploy_contract(address=addr, code=Op.INVALID) diff --git a/benchmark/test_worst_compute.py b/benchmark/test_worst_compute.py index d7437a77e4..504b231051 100644 --- a/benchmark/test_worst_compute.py +++ b/benchmark/test_worst_compute.py @@ -1,8 +1,5 @@ """ -abstract: Tests that benchmark EVMs in worst-case compute scenarios. - Tests that benchmark EVMs in worst-case compute scenarios. - -Tests that benchmark EVMs when running worst-case compute opcodes and precompile scenarios. +Tests that benchmark EVMs in worst-case compute scenarios. """ import math @@ -57,8 +54,8 @@ def neg(x: int) -> int: def make_dup(index: int) -> Opcode: """ - Create a DUP instruction which duplicates the index-th (counting from 0) element - from the top of the stack. E.g. make_dup(0) → DUP1. + Create a DUP instruction which duplicates the index-th (counting from 0) + element from the top of the stack. E.g. make_dup(0) → DUP1. """ assert 0 <= index < 16 return Opcode(0x80 + index, pushed_stack_items=1, min_stack_height=index + 1) @@ -158,9 +155,9 @@ def test_worst_callvalue( """ Test running a block with as many CALLVALUE opcodes as possible. - The `non_zero_value` parameter controls whether opcode must return non-zero value. - The `from_origin` parameter controls whether the call frame is the immediate from the - transaction or a previous CALL. + The `non_zero_value` parameter controls whether opcode must return non-zero + value. The `from_origin` parameter controls whether the call frame is the + immediate from the transaction or a previous CALL. """ max_code_size = fork.max_code_size() @@ -222,11 +219,12 @@ def test_worst_returndatasize_nonzero( gas_benchmark_value: int, ): """ - Test running a block which execute as many RETURNDATASIZE opcodes which return a non-zero - buffer as possible. + Test running a block which execute as many RETURNDATASIZE opcodes which + return a non-zero buffer as possible. - The `returned_size` parameter indicates the size of the returned data buffer. - The `return_data_style` indicates how returned data is produced for the opcode caller. + The `returned_size` parameter indicates the size of the returned data + buffer. The `return_data_style` indicates how returned data is produced for + the opcode caller. """ max_code_size = fork.max_code_size() @@ -271,7 +269,10 @@ def test_worst_returndatasize_zero( fork: Fork, gas_benchmark_value: int, ): - """Test running a block with as many RETURNDATASIZE opcodes as possible with a zero buffer.""" + """ + Test running a block with as many RETURNDATASIZE opcodes as possible with a + zero buffer. + """ max_code_size = fork.max_code_size() dummy_contract_call = Bytecode() @@ -351,40 +352,44 @@ def test_worst_keccak( max_code_size = fork.max_code_size() - # Discover the optimal input size to maximize keccak-permutations, not keccak calls. - # The complication of the discovery arises from the non-linear gas cost of memory expansion. + # Discover the optimal input size to maximize keccak-permutations, not + # keccak calls. The complication of the discovery arises from the non- + # linear gas cost of memory expansion. max_keccak_perm_per_block = 0 optimal_input_length = 0 for i in range(1, 1_000_000, 32): iteration_gas_cost = ( 2 * gsc.G_VERY_LOW # PUSHN + PUSH1 + gsc.G_KECCAK_256 # KECCAK256 static cost - + math.ceil(i / 32) * gsc.G_KECCAK_256_WORD # KECCAK256 dynamic cost + + math.ceil(i / 32) * gsc.G_KECCAK_256_WORD # KECCAK256 dynamic + # cost + gsc.G_BASE # POP ) - # From the available gas, we subtract the mem expansion costs considering we know the - # current input size length i. + # From the available gas, we subtract the mem expansion costs + # considering we know the current input size length i. available_gas_after_expansion = max(0, available_gas - mem_exp_gas_calculator(new_bytes=i)) # Calculate how many calls we can do. num_keccak_calls = available_gas_after_expansion // iteration_gas_cost # KECCAK does 1 permutation every 136 bytes. num_keccak_permutations = num_keccak_calls * math.ceil(i / KECCAK_RATE) - # If we found an input size that is better (reg permutations/gas), then save it. + # If we found an input size that is better (reg permutations/gas), then + # save it. if num_keccak_permutations > max_keccak_perm_per_block: max_keccak_perm_per_block = num_keccak_permutations optimal_input_length = i - # max_iters_loop contains how many keccak calls can be done per loop. - # The loop is as big as possible bounded by the maximum code size. + # max_iters_loop contains how many keccak calls can be done per loop. The + # loop is as big as possible bounded by the maximum code size. # # The loop structure is: JUMPDEST + [attack iteration] + PUSH0 + JUMP # # Now calculate available gas for [attack iteration]: - # Numerator = max_code_size-3. The -3 is for the JUMPDEST, PUSH0 and JUMP. - # Denominator = (PUSHN + PUSH1 + KECCAK256 + POP) + PUSH1_DATA + PUSHN_DATA - # TODO: the testing framework uses PUSH1(0) instead of PUSH0 which is suboptimal for the - # attack, whenever this is fixed adjust accordingly. + # Numerator = max_code_size-3. The -3 is for the JUMPDEST, PUSH0 and JUMP + # Denominator = (PUSHN + PUSH1 + KECCAK256 + POP) + PUSH1_DATA + PUSHN_DATA + # + # TODO: the testing framework uses PUSH1(0) instead of PUSH0 which is + # suboptimal for the attack, whenever this is fixed adjust accordingly. start_code = Op.JUMPDEST + Op.PUSH20[optimal_input_length] loop_code = Op.POP(Op.SHA3(Op.PUSH0, Op.DUP1)) end_code = Op.POP + Op.JUMP(Op.PUSH0) @@ -427,7 +432,10 @@ def test_worst_precompile_only_data_input( bytes_per_unit_of_work: int, gas_benchmark_value: int, ): - """Test running a block with as many precompile calls which have a single `data` input.""" + """ + Test running a block with as many precompile calls which have a single + `data` input. + """ # Intrinsic gas cost is paid once. intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() available_gas = gas_benchmark_value - intrinsic_gas_calculator() @@ -435,7 +443,8 @@ def test_worst_precompile_only_data_input( gsc = fork.gas_costs() mem_exp_gas_calculator = fork.memory_expansion_gas_calculator() - # Discover the optimal input size to maximize precompile work, not precompile calls. + # Discover the optimal input size to maximize precompile work, not + # precompile calls. max_work = 0 optimal_input_length = 0 for input_length in range(1, 1_000_000, 32): @@ -450,11 +459,12 @@ def test_worst_precompile_only_data_input( iteration_gas_cost = ( parameters_gas + +static_cost # Precompile static cost - + math.ceil(input_length / 32) * per_word_dynamic_cost # Precompile dynamic cost + + math.ceil(input_length / 32) * per_word_dynamic_cost + # Precompile dynamic cost + gsc.G_BASE # POP ) - # From the available gas, we subtract the mem expansion costs considering we know the - # current input size length. + # From the available gas, we subtract the mem expansion costs + # considering we know the current input size length. available_gas_after_expansion = max( 0, available_gas - mem_exp_gas_calculator(new_bytes=input_length) ) @@ -462,7 +472,8 @@ def test_worst_precompile_only_data_input( num_calls = available_gas_after_expansion // iteration_gas_cost total_work = num_calls * math.ceil(input_length / bytes_per_unit_of_work) - # If we found an input size that is better (reg permutations/gas), then save it. + # If we found an input size that is better (reg permutations/gas), then + # save it. if total_work > max_work: max_work = total_work optimal_input_length = input_length @@ -641,7 +652,8 @@ def test_worst_precompile_only_data_input( ), id="mod_odd_32b_exp_cover_windows", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L38 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L38 pytest.param( ModExpInput( base=192 * "FF", @@ -650,7 +662,8 @@ def test_worst_precompile_only_data_input( ), id="mod_min_gas_base_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L40 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L40 pytest.param( ModExpInput( base=8 * "FF", @@ -659,7 +672,8 @@ def test_worst_precompile_only_data_input( ), id="mod_min_gas_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L42 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L42 pytest.param( ModExpInput( base=40 * "FF", @@ -668,7 +682,8 @@ def test_worst_precompile_only_data_input( ), id="mod_min_gas_balanced", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L44 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L44 pytest.param( ModExpInput( base=32 * "FF", @@ -677,7 +692,8 @@ def test_worst_precompile_only_data_input( ), id="mod_exp_208_gas_balanced", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L46 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L46 pytest.param( ModExpInput( base=8 * "FF", @@ -686,7 +702,8 @@ def test_worst_precompile_only_data_input( ), id="mod_exp_215_gas_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L48 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L48 pytest.param( ModExpInput( base=8 * "FF", @@ -695,7 +712,8 @@ def test_worst_precompile_only_data_input( ), id="mod_exp_298_gas_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L50 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L50 pytest.param( ModExpInput( base=16 * "FF", @@ -704,7 +722,8 @@ def test_worst_precompile_only_data_input( ), id="mod_pawel_2", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L52 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L52 pytest.param( ModExpInput( base=24 * "FF", @@ -713,7 +732,8 @@ def test_worst_precompile_only_data_input( ), id="mod_pawel_3", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L54 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L54 pytest.param( ModExpInput( base=32 * "FF", @@ -722,7 +742,8 @@ def test_worst_precompile_only_data_input( ), id="mod_pawel_4", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L56 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L56 pytest.param( ModExpInput( base=280 * "FF", @@ -731,7 +752,8 @@ def test_worst_precompile_only_data_input( ), id="mod_408_gas_base_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L58 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L58 pytest.param( ModExpInput( base=16 * "FF", @@ -740,7 +762,8 @@ def test_worst_precompile_only_data_input( ), id="mod_400_gas_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L60 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L60 pytest.param( ModExpInput( base=48 * "FF", @@ -749,7 +772,8 @@ def test_worst_precompile_only_data_input( ), id="mod_408_gas_balanced", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L62 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L62 pytest.param( ModExpInput( base=344 * "FF", @@ -758,7 +782,8 @@ def test_worst_precompile_only_data_input( ), id="mod_616_gas_base_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L64 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L64 pytest.param( ModExpInput( base=16 * "FF", @@ -767,7 +792,8 @@ def test_worst_precompile_only_data_input( ), id="mod_600_gas_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L66 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L66 pytest.param( ModExpInput( base=48 * "FF", @@ -776,7 +802,8 @@ def test_worst_precompile_only_data_input( ), id="mod_600_gas_balanced", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L68 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L68 pytest.param( ModExpInput( base=392 * "FF", @@ -785,7 +812,8 @@ def test_worst_precompile_only_data_input( ), id="mod_800_gas_base_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L70 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L70 pytest.param( ModExpInput( base=16 * "FF", @@ -794,7 +822,8 @@ def test_worst_precompile_only_data_input( ), id="mod_800_gas_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L72 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L72 pytest.param( ModExpInput( base=56 * "FF", @@ -803,7 +832,8 @@ def test_worst_precompile_only_data_input( ), id="mod_767_gas_balanced", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L74 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L74 pytest.param( ModExpInput( base=16 * "FF", @@ -812,7 +842,8 @@ def test_worst_precompile_only_data_input( ), id="mod_852_gas_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L76 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L76 pytest.param( ModExpInput( base=408 * "FF", @@ -821,7 +852,8 @@ def test_worst_precompile_only_data_input( ), id="mod_867_gas_base_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L78 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L78 pytest.param( ModExpInput( base=56 * "FF", @@ -830,7 +862,8 @@ def test_worst_precompile_only_data_input( ), id="mod_996_gas_balanced", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L80 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L80 pytest.param( ModExpInput( base=448 * "FF", @@ -839,7 +872,8 @@ def test_worst_precompile_only_data_input( ), id="mod_1045_gas_base_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L82 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L82 pytest.param( ModExpInput( base=32 * "FF", @@ -848,7 +882,8 @@ def test_worst_precompile_only_data_input( ), id="mod_677_gas_base_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L84 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L84 pytest.param( ModExpInput( base=24 * "FF", @@ -857,7 +892,8 @@ def test_worst_precompile_only_data_input( ), id="mod_765_gas_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L86 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/Modexp.cs#L86 pytest.param( ModExpInput( base=32 * "FF", @@ -954,7 +990,8 @@ def test_worst_precompile_only_data_input( ), id="mod_1024_exp_2", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L122 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L122 pytest.param( ModExpInput( base="03", @@ -963,7 +1000,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_example_1", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L124 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L124 pytest.param( ModExpInput( base="", @@ -972,7 +1010,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_example_2", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L126 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L126 pytest.param( ModExpInput( base="e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5", @@ -981,7 +1020,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_1_square", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L128 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L128 pytest.param( ModExpInput( base="e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5", @@ -990,7 +1030,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_1_qube", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L130 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L130 pytest.param( ModExpInput( base="e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5", @@ -999,7 +1040,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_1_pow_0x10001", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L132 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L132 pytest.param( ModExpInput( base="cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51", @@ -1008,7 +1050,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_2_square", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L134 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L134 pytest.param( ModExpInput( base="cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51", @@ -1017,7 +1060,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_2_qube", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L136 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L136 pytest.param( ModExpInput( base="cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51", @@ -1026,7 +1070,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_2_pow_0x10001", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L138 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L138 pytest.param( ModExpInput( base="c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb", @@ -1035,7 +1080,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_3_square", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L140 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L140 pytest.param( ModExpInput( base="c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb", @@ -1044,7 +1090,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_3_qube", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L142 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L142 pytest.param( ModExpInput( base="c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb", @@ -1053,7 +1100,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_3_pow_0x10001", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L144 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L144 pytest.param( ModExpInput( base="db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81", @@ -1062,7 +1110,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_4_square", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L146 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L146 pytest.param( ModExpInput( base="db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81", @@ -1071,7 +1120,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_4_qube", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L148 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L148 pytest.param( ModExpInput( base="db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81", @@ -1080,7 +1130,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_4_pow_0x10001", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L150 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L150 pytest.param( ModExpInput( base="c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf", @@ -1089,7 +1140,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_5_square", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L152 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L152 pytest.param( ModExpInput( base="c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf", @@ -1098,7 +1150,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_5_qube", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L154 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L154 pytest.param( ModExpInput( base="c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf", @@ -1107,7 +1160,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_nagydani_5_pow_0x10001", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L156 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L156 pytest.param( ModExpInput( base="ffffff", @@ -1116,7 +1170,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_marius_1_even", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L158 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L158 pytest.param( ModExpInput( base="ffffffffffffffff76ffffffffffffff", @@ -1125,7 +1180,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_guido_1_even", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L160 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L160 pytest.param( ModExpInput( base="e0060000a921212121212121ff000021", @@ -1134,7 +1190,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_guido_2_even", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L162 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L162 pytest.param( ModExpInput( base="0193585a48e18aad777e9c1b54221a0f58140392e4f091cd5f42b2e8644a9384fbd58ae1edec2477ebf7edbf7c0a3f8bd21d1890ee87646feab3c47be716f842cc3da9b940af312dc54450a960e3fc0b86e56abddd154068e10571a96fff6259431632bc15695c6c8679057e66c2c25c127e97e64ee5de6ea1fc0a4a0e431343fed1daafa072c238a45841da86a9806680bc9f298411173210790359209cd454b5af7b4d5688b4403924e5f863d97e2c5349e1a04b54fcf385b1e9d7714bab8fbf5835f6ff9ed575e77dff7af5cbb641db5d537933bae1fa6555d6c12d6fb31ca27b57771f4aebfbe0bf95e8990c0108ffe7cbdaf370be52cf3ade594543af75ad9329d2d11a402270b5b9a6bf4b83307506e118fca4862749d04e916fc7a039f0d13f2a02e0eedb800199ec95df15b4ccd8669b52586879624d51219e72102fad810b5909b1e372ddf33888fb9beb09b416e4164966edbabd89e4a286be36277fc576ed519a15643dac602e92b63d0b9121f0491da5b16ef793a967f096d80b6c81ecaaffad7e3f06a4a5ac2796f1ed9f68e6a0fd5cf191f0c5c2eec338952ff8d31abc68bf760febeb57e088995ba1d7726a2fdd6d8ca28a181378b8b4ab699bfd4b696739bbf17a9eb2df6251143046137fdbbfacac312ebf67a67da9741b59600000000000", @@ -1143,7 +1200,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_guido_3_even", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L166 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L166 pytest.param( ModExpInput( base="ffffffffffffffff", @@ -1152,7 +1210,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_pawel_1_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L168 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L168 pytest.param( ModExpInput( base="ffffffffffffffffffffffffffffffff", @@ -1161,7 +1220,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_pawel_2_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L170 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L170 pytest.param( ModExpInput( base="ffffffffffffffffffffffffffffffffffffffffffffffff", @@ -1176,7 +1236,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_pawel_3_exp_8", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L172 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L172 pytest.param( ModExpInput( base="ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", @@ -1185,7 +1246,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_pawel_4_exp_heavy", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L174 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L174 pytest.param( ModExpInput( base="29356abadad68ad986c416de6f620bda0e1818b589e84f853a97391694d35496", @@ -1194,7 +1256,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_common_1360n1", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L176 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L176 pytest.param( ModExpInput( base="d41afaeaea32f7409827761b68c41b6e535da4ede1f0800bfb4a6aed18394f6b", @@ -1203,7 +1266,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_common_1360n2", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L178 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L178 pytest.param( ModExpInput( base="1a5be8fae3b3fda9ea329494ae8689c04fae4978ecccfa6a6bfb9f04b25846c0", @@ -1212,7 +1276,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_common_1349n1", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L182 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L182 pytest.param( ModExpInput( base="0000000000000000000000000000000000000000000000000000000000000003", @@ -1221,7 +1286,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_common_1152n1", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L184 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L184 pytest.param( ModExpInput( base="1fb473dd1171cf88116aa77ab3612c2c7d2cf466cc2386cc456130e2727c70b4", @@ -1230,7 +1296,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_common_200n1", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L186 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L186 pytest.param( ModExpInput( base="1951441010b2b95a6e47a6075066a50a036f5ba978c050f2821df86636c0facb", @@ -1239,7 +1306,8 @@ def test_worst_precompile_only_data_input( ), id="mod_vul_common_200n2", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L188 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCases/ModexpVulnerability.cs#L188 pytest.param( ModExpInput( base="288254ba43e713afbe36c9f03b54c00fae4c0a82df1cf165eb46a21c20a48ca2", @@ -1266,14 +1334,15 @@ def test_worst_modexp( gas_benchmark_value: int, ): """ - Test running a block with as many calls to the MODEXP (5) precompile as possible. - All the calls have the same parametrized input. + Test running a block with as many calls to the MODEXP (5) precompile as + possible. All the calls have the same parametrized input. """ # Skip the trailing zeros from the input to make EVM work even harder. calldata = bytes(mod_exp_input).rstrip(b"\x00") code = code_loop_precompile_call( - Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE), # Copy the input to the memory. + Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE), # Copy the input to the + # memory. Op.POP(Op.STATICCALL(Op.GAS, 0x5, Op.PUSH0, Op.CALLDATASIZE, Op.PUSH0, Op.PUSH0)), fork, ) @@ -1298,8 +1367,8 @@ def test_worst_modexp( pytest.param( 0x01, [ - # The inputs below are a valid signature, thus ECRECOVER call won't - # be short-circuited by validations and do actual work. + # The inputs below are a valid signature, thus ECRECOVER call + # won't be short-circuited by validations and do actual work. "38D18ACB67D25C8BB9942764B62F18E17054F66A817BD4295423ADF9ED98873E", "000000000000000000000000000000000000000000000000000000000000001B", "38D18ACB67D25C8BB9942764B62F18E17054F66A817BD4295423ADF9ED98873E", @@ -1317,7 +1386,8 @@ def test_worst_modexp( ], id="bn128_add", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L326 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L326 pytest.param( 0x06, [ @@ -1328,7 +1398,8 @@ def test_worst_modexp( ], id="bn128_add_infinities", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L329 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L329 pytest.param( 0x06, [ @@ -1348,7 +1419,8 @@ def test_worst_modexp( ], id="bn128_mul", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L335 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L335 pytest.param( 0x07, [ @@ -1358,7 +1430,8 @@ def test_worst_modexp( ], id="bn128_mul_infinities_2_scalar", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L338 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L338 pytest.param( 0x07, [ @@ -1368,7 +1441,8 @@ def test_worst_modexp( ], id="bn128_mul_infinities_32_byte_scalar", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L341 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L341 pytest.param( 0x07, [ @@ -1378,7 +1452,8 @@ def test_worst_modexp( ], id="bn128_mul_1_2_2_scalar", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L344 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L344 pytest.param( 0x07, [ @@ -1388,7 +1463,8 @@ def test_worst_modexp( ], id="bn128_mul_1_2_32_byte_scalar", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L347 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L347 pytest.param( 0x07, [ @@ -1398,7 +1474,8 @@ def test_worst_modexp( ], id="bn128_mul_32_byte_coord_and_2_scalar", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L350 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L350 pytest.param( 0x07, [ @@ -1441,7 +1518,8 @@ def test_worst_modexp( ], id="bn128_one_pairing", ), - # Ported from https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L353 + # Ported from + # https://github.com/NethermindEth/nethermind/blob/ceb8d57b8530ce8181d7427c115ca593386909d6/tools/EngineRequestsGenerator/TestCase.cs#L353 pytest.param(0x08, [], id="ec_pairing_zero_input"), pytest.param( 0x08, @@ -1640,9 +1718,10 @@ def test_worst_modexp( pytest.param( bls12381_spec.Spec.G2MSM, [ - # TODO: the //2 is required due to a limitation of the max contract size limit. - # In a further iteration we can insert the inputs as calldata or storage and avoid - # having to do PUSHes which has this limitation. This also applies to G1MSM. + # TODO: the //2 is required due to a limitation of the max + # contract size limit. In a further iteration we can insert the + # inputs as calldata or storage and avoid having to do PUSHes + # which has this limitation. This also applies to G1MSM. (bls12381_spec.Spec.P2 + bls12381_spec.Scalar(bls12381_spec.Spec.Q)) * (len(bls12381_spec.Spec.G2MSM_DISCOUNT_TABLE) // 2), ], @@ -1873,7 +1952,8 @@ def test_worst_jumpdests( DEFAULT_BINOP_ARGS, ), ( - # This has the cycle of 2, after two SUBs values are back to initials. + # This has the cycle of 2, after two SUBs values are back to + # initials. Op.SUB, DEFAULT_BINOP_ARGS, ), @@ -1886,8 +1966,8 @@ def test_worst_jumpdests( ( 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F, # We want the first divisor to be slightly bigger than 2**128: - # this is the worst case for the division algorithm with optimized paths - # for division by 1 and 2 words. + # this is the worst case for the division algorithm with + # optimized paths for division by 1 and 2 words. 0x100000000000000000000000000000033, ), ), @@ -1897,13 +1977,14 @@ def test_worst_jumpdests( ( 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F, # We want the first divisor to be slightly bigger than 2**64: - # this is the worst case for the division algorithm with an optimized path - # for division by 1 word. + # this is the worst case for the division algorithm with an + # optimized path for division by 1 word. 0x10000000000000033, ), ), ( - # Same as DIV-0, but the numerator made positive, and the divisor made negative. + # Same as DIV-0, but the numerator made positive, and the divisor + # made negative. Op.SDIV, ( 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F, @@ -1911,7 +1992,8 @@ def test_worst_jumpdests( ), ), ( - # Same as DIV-1, but the numerator made positive, and the divisor made negative. + # Same as DIV-1, but the numerator made positive, and the divisor + # made negative. Op.SDIV, ( 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F, @@ -1919,17 +2001,20 @@ def test_worst_jumpdests( ), ), ( - # This scenario is not suitable for MOD because the values quickly become 0. + # This scenario is not suitable for MOD because the values quickly + # become 0. Op.MOD, DEFAULT_BINOP_ARGS, ), ( - # This scenario is not suitable for SMOD because the values quickly become 0. + # This scenario is not suitable for SMOD because the values quickly + # become 0. Op.SMOD, DEFAULT_BINOP_ARGS, ), ( - # This keeps the values unchanged, pow(2**256-1, 2**256-1, 2**256) == 2**256-1. + # This keeps the values unchanged, pow(2**256-1, 2**256-1, 2**256) + # == 2**256-1. Op.EXP, ( 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, @@ -2006,9 +2091,9 @@ def test_worst_binop_simple( gas_benchmark_value: int, ): """ - Test running a block with as many binary instructions (takes two args, produces one value) - as possible. The execution starts with two initial values on the stack, and the stack is - balanced by the DUP2 instruction. + Test running a block with as many binary instructions (takes two args, + produces one value) as possible. The execution starts with two initial + values on the stack, and the stack is balanced by the DUP2 instruction. """ max_code_size = fork.max_code_size() @@ -2044,8 +2129,8 @@ def test_worst_unop( gas_benchmark_value: int, ): """ - Test running a block with as many unary instructions (takes one arg, produces one value) - as possible. + Test running a block with as many unary instructions (takes one arg, + produces one value) as possible. """ max_code_size = fork.max_code_size() @@ -2071,7 +2156,8 @@ def test_worst_unop( # `key_mut` indicates the key isn't fixed. @pytest.mark.parametrize("key_mut", [True, False]) -# `val_mut` indicates that at the end of each big-loop, the value of the target key changes. +# `val_mut` indicates that at the end of each big-loop, the value of the target +# key changes. @pytest.mark.parametrize("val_mut", [True, False]) def test_worst_tload( state_test: StateTestFiller, @@ -2098,7 +2184,8 @@ def test_worst_tload( if not key_mut and val_mut: code_prefix = Op.JUMPDEST loop_iter = Op.POP(Op.TLOAD(Op.CALLVALUE)) - code_val_mut = Op.TSTORE(Op.CALLVALUE, Op.GAS) # CALLVALUE configured in the tx + code_val_mut = Op.TSTORE(Op.CALLVALUE, Op.GAS) # CALLVALUE configured + # in the tx if not key_mut and not val_mut: code_prefix = Op.JUMPDEST loop_iter = Op.POP(Op.TLOAD(Op.CALLVALUE)) @@ -2140,12 +2227,13 @@ def test_worst_tstore( init_key = 42 code_prefix = Op.PUSH1(init_key) + Op.JUMPDEST - # If `key_mut` is True, we mutate the key on every iteration of the big loop. + # If `key_mut` is True, we mutate the key on every iteration of the big + # loop. code_key_mut = Op.POP + Op.GAS if key_mut else Bytecode() code_suffix = code_key_mut + Op.JUMP(len(code_prefix) - 1) - # If `dense_val_mut` is set, we use GAS as a cheap way of always storing a different value than - # the previous one. + # If `dense_val_mut` is set, we use GAS as a cheap way of always storing a + # different value than the previous one. loop_iter = Op.TSTORE(Op.DUP2, Op.GAS if dense_val_mut else Op.DUP1) code_body_len = (max_code_size - len(code_prefix) - len(code_suffix)) // len(loop_iter) @@ -2175,9 +2263,10 @@ def test_worst_shifts( gas_benchmark_value: int, ): """ - Test running a block with as many shift instructions with non-trivial arguments. - This test generates left-right pairs of shifts to avoid zeroing the argument. - The shift amounts are randomly pre-selected from the constant pool of 15 values on the stack. + Test running a block with as many shift instructions with non-trivial + arguments. This test generates left-right pairs of shifts to avoid zeroing + the argument. The shift amounts are randomly pre-selected from the constant + pool of 15 values on the stack. """ max_code_size = fork.max_code_size() @@ -2205,10 +2294,12 @@ def sar(x, s): raise ValueError(f"Unexpected shift op: {shift_right}") rng = random.Random(1) # Use random with a fixed seed. - initial_value = 2**256 - 1 # The initial value to be shifted; should be negative for SAR. + initial_value = 2**256 - 1 # The initial value to be shifted; should be + # negative for SAR. - # Create the list of shift amounts with 15 elements (max reachable by DUPs instructions). - # For the worst case keep the values small and omit values divisible by 8. + # Create the list of shift amounts with 15 elements (max reachable by DUPs + # instructions). For the worst case keep the values small and omit values + # divisible by 8. shift_amounts = [x + (x >= 8) + (x >= 15) for x in range(1, 16)] code_prefix = sum(Op.PUSH1[sh] for sh in shift_amounts) + Op.JUMPDEST + Op.CALLDATALOAD(0) @@ -2323,20 +2414,25 @@ def test_worst_mod( gas_benchmark_value: int, ): """ - Test running a block with as many MOD instructions with arguments of the parametrized range. + Test running a block with as many MOD instructions with arguments of the + parametrized range. + The test program consists of code segments evaluating the "MOD chain": mod[0] = calldataload(0) mod[1] = numerators[indexes[0]] % mod[0] mod[2] = numerators[indexes[1]] % mod[1] ... - The "numerators" is a pool of 15 constants pushed to the EVM stack at the program start. - The order of accessing the numerators is selected in a way the mod value remains in the range - as long as possible. + + The "numerators" is a pool of 15 constants pushed to the EVM stack at the + program start. + + The order of accessing the numerators is selected in a way the mod value + remains in the range as long as possible. """ max_code_size = fork.max_code_size() - # For SMOD we negate both numerator and modulus. The underlying computation is the same, - # just the SMOD implementation will have to additionally handle the sign bits. - # The result stays negative. + # For SMOD we negate both numerator and modulus. The underlying computation + # is the same, just the SMOD implementation will have to additionally + # handle the sign bits. The result stays negative. should_negate = op == Op.SMOD num_numerators = 15 @@ -2344,12 +2440,13 @@ def test_worst_mod( numerator_max = 2**numerator_bits - 1 numerator_min = 2 ** (numerator_bits - 1) - # Pick the modulus min value so that it is _unlikely_ to drop to the lower word count. + # Pick the modulus min value so that it is _unlikely_ to drop to the lower + # word count. assert mod_bits >= 63 mod_min = 2 ** (mod_bits - 63) - # Select the random seed giving the longest found MOD chain. - # You can look for a longer one by increasing the numerators_min_len. This will activate + # Select the random seed giving the longest found MOD chain. You can look + # for a longer one by increasing the numerators_min_len. This will activate # the while loop below. match op, mod_bits: case Op.MOD, 255: @@ -2392,18 +2489,22 @@ def test_worst_mod( mod = initial_mod indexes = [] while mod >= mod_min: - results = [n % mod for n in numerators] # Compute results for each numerator. - i = max(range(len(results)), key=results.__getitem__) # And pick the best one. + # Compute results for each numerator. + results = [n % mod for n in numerators] + # And pick the best one. + i = max(range(len(results)), key=results.__getitem__) mod = results[i] indexes.append(i) - assert len(indexes) > numerators_min_len # Disable if you want to find longer MOD chains. + # Disable if you want to find longer MOD chains. + assert len(indexes) > numerators_min_len if len(indexes) > numerators_min_len: break seed += 1 print(f"{seed=}") - # TODO: Don't use fixed PUSH32. Let Bytecode helpers to select optimal push opcode. + # TODO: Don't use fixed PUSH32. Let Bytecode helpers to select optimal push + # opcode. code_constant_pool = sum((Op.PUSH32[n] for n in numerators), Bytecode()) code_prefix = code_constant_pool + Op.JUMPDEST code_suffix = Op.JUMP(len(code_constant_pool)) @@ -2448,7 +2549,9 @@ def test_worst_memory_access( big_memory_expansion: bool, gas_benchmark_value: int, ): - """Test running a block with as many memory access instructions as possible.""" + """ + Test running a block with as many memory access instructions as possible. + """ max_code_size = fork.max_code_size() mem_exp_code = Op.MSTORE8(10 * 1024, 1) if big_memory_expansion else Bytecode() @@ -2488,29 +2591,32 @@ def test_worst_modarith( gas_benchmark_value: int, ): """ - Test running a block with as many "op" instructions with arguments of the parametrized range. + Test running a block with as many "op" instructions with arguments of the + parametrized range. The test program consists of code segments evaluating the "op chain": mod[0] = calldataload(0) mod[1] = (fixed_arg op args[indexes[0]]) % mod[0] mod[2] = (fixed_arg op args[indexes[1]]) % mod[1] - The "args" is a pool of 15 constants pushed to the EVM stack at the program start. + The "args" is a pool of 15 constants pushed to the EVM stack at the program + start. The "fixed_arg" is the 0xFF...FF constant added to the EVM stack by PUSH32 just before executing the "op". - The order of accessing the numerators is selected in a way the mod value remains in the range - as long as possible. + The order of accessing the numerators is selected in a way the mod value + remains in the range as long as possible. """ fixed_arg = 2**256 - 1 num_args = 15 max_code_size = fork.max_code_size() - # Pick the modulus min value so that it is _unlikely_ to drop to the lower word count. + # Pick the modulus min value so that it is _unlikely_ to drop to the lower + # word count. assert mod_bits >= 63 mod_min = 2 ** (mod_bits - 63) - # Select the random seed giving the longest found op chain. - # You can look for a longer one by increasing the op_chain_len. This will activate - # the while loop below. + # Select the random seed giving the longest found op chain. You can look + # for a longer one by increasing the op_chain_len. This will activate the + # while loop below. op_chain_len = 666 match op, mod_bits: case Op.ADDMOD, 255: @@ -2528,7 +2634,8 @@ def test_worst_modarith( case Op.MULMOD, 127: seed = 5 case Op.MULMOD, 63: - # For this setup we were not able to find an op-chain longer than 600. + # For this setup we were not able to find an op-chain longer than + # 600. seed = 4193 op_chain_len = 600 case _: @@ -2545,11 +2652,13 @@ def test_worst_modarith( indexes: list[int] = [] while mod >= mod_min and len(indexes) < op_chain_len: results = [op_fn(a, fixed_arg) % mod for a in args] - i = max(range(len(results)), key=results.__getitem__) # And pick the best one. + # And pick the best one. + i = max(range(len(results)), key=results.__getitem__) mod = results[i] indexes.append(i) - assert len(indexes) == op_chain_len # Disable if you want to find longer op chains. + # Disable if you want to find longer op chains. + assert len(indexes) == op_chain_len if len(indexes) == op_chain_len: break seed += 1 @@ -2561,8 +2670,8 @@ def test_worst_modarith( + sum(make_dup(len(args) - i) + Op.PUSH32[fixed_arg] + op for i in indexes) + Op.POP ) - # Construct the final code. Because of the usage of PUSH32 the code segment is very long, - # so don't try to include multiple of these. + # Construct the final code. Because of the usage of PUSH32 the code segment + # is very long, so don't try to include multiple of these. code = code_constant_pool + Op.JUMPDEST + code_segment + Op.JUMP(len(code_constant_pool)) assert (max_code_size - len(code_segment)) < len(code) <= max_code_size @@ -2608,8 +2717,9 @@ def test_amortized_bn128_pairings( intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() mem_exp_gas_calculator = fork.memory_expansion_gas_calculator() - # This is a theoretical maximum number of pairings that can be done in a block. - # It is only used for an upper bound for calculating the optimal number of pairings below. + # This is a theoretical maximum number of pairings that can be done in a + # block. It is only used for an upper bound for calculating the optimal + # number of pairings below. maximum_number_of_pairings = (gas_benchmark_value - base_cost) // pairing_cost # Discover the optimal number of pairings balancing two dimensions: @@ -2620,19 +2730,21 @@ def test_amortized_bn128_pairings( for i in range(1, maximum_number_of_pairings + 1): # We'll pass all pairing arguments via calldata. available_gas_after_intrinsic = gas_benchmark_value - intrinsic_gas_calculator( - calldata=[0xFF] * size_per_pairing * i # 0xFF is to indicate non-zero bytes. + calldata=[0xFF] * size_per_pairing * i # 0xFF is to indicate non- + # zero bytes. ) available_gas_after_expansion = max( 0, available_gas_after_intrinsic - mem_exp_gas_calculator(new_bytes=i * size_per_pairing), ) - # This is ignoring "glue" opcodes, but helps to have a rough idea of the right - # cutting point. + # This is ignoring "glue" opcodes, but helps to have a rough idea of + # the right cutting point. approx_gas_cost_per_call = gsc.G_WARM_ACCOUNT_ACCESS + base_cost + i * pairing_cost num_precompile_calls = available_gas_after_expansion // approx_gas_cost_per_call - num_pairings_done = num_precompile_calls * i # Each precompile call does i pairings. + num_pairings_done = num_precompile_calls * i # Each precompile call + # does i pairings. if num_pairings_done > max_pairings: max_pairings = num_pairings_done @@ -2921,8 +3033,9 @@ def test_worst_return_revert( # opcode(returned_size) # # ``` - # Filling the contract up to the max size is a cheap way of leveraging CODECOPY to return - # non-zero bytes if requested. Note that since this is a pre-deploy this cost isn't + # Filling the contract up to the max size is a cheap way of leveraging + # CODECOPY to return non-zero bytes if requested. Note that since this + # is a pre-deploy this cost isn't # relevant for the benchmark. mem_preparation = Op.CODECOPY(size=return_size) if return_non_zero_data else Bytecode() executable_code = mem_preparation + opcode(size=return_size) @@ -2999,7 +3112,9 @@ def test_worst_clz_diff_input( gas_benchmark_value: int, env: Environment, ): - """Test running a block with as many CLZ with different input as possible.""" + """ + Test running a block with as many CLZ with different input as possible. + """ tx_gas_limit = fork.transaction_gas_limit_cap() or env.gas_limit max_code_size = fork.max_code_size() diff --git a/benchmark/test_worst_memory.py b/benchmark/test_worst_memory.py index 8952c05a45..689dcf0632 100644 --- a/benchmark/test_worst_memory.py +++ b/benchmark/test_worst_memory.py @@ -1,7 +1,4 @@ """ -abstract: Tests that benchmark EVMs in the worst-case memory opcodes. - Tests that benchmark EVMs in the worst-case memory opcodes. - Tests that benchmark EVMs in the worst-case memory opcodes. """ @@ -74,8 +71,9 @@ def test_worst_calldatacopy( if size == 0 and non_zero_data: pytest.skip("Non-zero data with size 0 is not applicable.") - # If `non_zero_data` is True, we fill the calldata with deterministic random data. - # Note that if `size == 0` and `non_zero_data` is a skipped case. + # If `non_zero_data` is True, we fill the calldata with deterministic + # random data. Note that if `size == 0` and `non_zero_data` is a skipped + # case. data = Bytes([i % 256 for i in range(size)]) if non_zero_data else Bytes() intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() @@ -83,10 +81,11 @@ def test_worst_calldatacopy( if min_gas > gas_benchmark_value: pytest.skip("Minimum gas required for calldata ({min_gas}) is greater than the gas limit") - # We create the contract that will be doing the CALLDATACOPY multiple times. - # - # If `non_zero_data` is True, we leverage CALLDATASIZE for the copy length. Otherwise, since we - # don't send zero data explicitly via calldata, PUSH the target size and use DUP1 to copy it. + # We create the contract that will be doing the CALLDATACOPY multiple + # times. + # If `non_zero_data` is True, we leverage CALLDATASIZE for the copy length. + # Otherwise, since we don't send zero data explicitly via calldata, PUSH + # the target size and use DUP1 to copy it. prefix = Bytecode() if non_zero_data or size == 0 else Op.PUSH3(size) src_dst = 0 if fixed_src_dst else Op.MOD(Op.GAS, 7) attack_block = Op.CALLDATACOPY( @@ -97,11 +96,11 @@ def test_worst_calldatacopy( tx_target = code_address - # If the origin is CALL, we need to create a contract that will call the target contract with - # the calldata. + # If the origin is CALL, we need to create a contract that will call the + # target contract with the calldata. if origin == CallDataOrigin.CALL: - # If `non_zero_data` is False we leverage just using zeroed memory. Otherwise, we - # copy the calldata received from the transaction. + # If `non_zero_data` is False we leverage just using zeroed memory. + # Otherwise, we copy the calldata received from the transaction. prefix = ( Op.CALLDATACOPY(Op.PUSH0, Op.PUSH0, Op.CALLDATASIZE) if non_zero_data else Bytecode() ) + Op.JUMPDEST @@ -161,9 +160,9 @@ def test_worst_codecopy( attack_block = Op.CODECOPY(src_dst, src_dst, Op.DUP1) # DUP1 copies size. code = code_loop_precompile_call(code_prefix, attack_block, fork) - # The code generated above is not guaranteed to be of max_code_size, so we pad it since - # a test parameter targets CODECOPYing a contract with max code size. Padded bytecode values - # are not relevant. + # The code generated above is not guaranteed to be of max_code_size, so we + # pad it since a test parameter targets CODECOPYing a contract with max + # code size. Padded bytecode values are not relevant. code = code + Op.INVALID * (max_code_size - len(code)) assert len(code) == max_code_size, ( f"Code size {len(code)} is not equal to max code size {max_code_size}." @@ -209,9 +208,10 @@ def test_worst_returndatacopy( """Test running a block filled with RETURNDATACOPY executions.""" max_code_size = fork.max_code_size() - # Create the contract that will RETURN the data that will be used for RETURNDATACOPY. - # Random-ish data is injected at different points in memory to avoid making the content - # predictable. If `size` is 0, this helper contract won't be used. + # Create the contract that will RETURN the data that will be used for + # RETURNDATACOPY. Random-ish data is injected at different points in memory + # to avoid making the content predictable. If `size` is 0, this helper + # contract won't be used. code = ( Op.MSTORE8(0, Op.GAS) + Op.MSTORE8(size // 2, Op.GAS) @@ -220,7 +220,8 @@ def test_worst_returndatacopy( ) helper_contract = pre.deploy_contract(code=code) - # We create the contract that will be doing the RETURNDATACOPY multiple times. + # We create the contract that will be doing the RETURNDATACOPY multiple + # times. returndata_gen = Op.STATICCALL(address=helper_contract) if size > 0 else Bytecode() dst = 0 if fixed_dst else Op.MOD(Op.GAS, 7) attack_iter = Op.RETURNDATACOPY(dst, Op.PUSH0, Op.RETURNDATASIZE) @@ -236,8 +237,8 @@ def test_worst_returndatacopy( # STATICCALL(address=helper_contract) # JUMP(#) # ``` - # The goal is that once per (big) loop iteration, the helper contract is called to - # generate fresh returndata to continue calling RETURNDATACOPY. + # The goal is that once per (big) loop iteration, the helper contract is + # called to generate fresh returndata to continue calling RETURNDATACOPY. max_iters_loop = ( max_code_size - 2 * len(returndata_gen) - len(jumpdest) - len(jump_back) ) // len(attack_iter) diff --git a/benchmark/test_worst_opcode.py b/benchmark/test_worst_opcode.py index e4e6e3bcf1..9ee805a628 100644 --- a/benchmark/test_worst_opcode.py +++ b/benchmark/test_worst_opcode.py @@ -1,8 +1,5 @@ """ -abstract: Tests benchmark worst-case opcode scenarios. - Tests benchmark worst-case opcode scenarios. - -Tests running worst-case opcodes scenarios for benchmarking purposes. +Tests benchmark worst-case opcode scenarios. """ import pytest diff --git a/benchmark/test_worst_stateful_opcodes.py b/benchmark/test_worst_stateful_opcodes.py index f68783e61c..f5cd6c0289 100644 --- a/benchmark/test_worst_stateful_opcodes.py +++ b/benchmark/test_worst_stateful_opcodes.py @@ -1,7 +1,4 @@ """ -abstract: Tests that benchmark EVMs for worst-case stateful opcodes. - Tests that benchmark EVMs for worst-case stateful opcodes. - Tests that benchmark EVMs for worst-case stateful opcodes. """ @@ -55,14 +52,17 @@ def test_worst_address_state_cold( env: Environment, gas_benchmark_value: int, ): - """Test running a block with as many stateful opcodes accessing cold accounts.""" + """ + Test running a block with as many stateful opcodes accessing cold accounts. + """ attack_gas_limit = gas_benchmark_value gas_costs = fork.gas_costs() intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() - # For calculation robustness, the calculation below ignores "glue" opcodes like PUSH and POP. - # It should be considered a worst-case number of accounts, and a few of them might not be - # targeted before the attacking transaction runs out of gas. + # For calculation robustness, the calculation below ignores "glue" opcodes + # like PUSH and POP. It should be considered a worst-case number of + # accounts, and a few of them might not be targeted before the attacking + # transaction runs out of gas. num_target_accounts = ( attack_gas_limit - intrinsic_gas_cost_calc() ) // gas_costs.G_COLD_ACCOUNT_ACCESS @@ -70,10 +70,10 @@ def test_worst_address_state_cold( blocks = [] post = {} - # Setup - # The target addresses are going to be constructed (in the case of absent=False) and called - # as addr_offset + i, where i is the index of the account. This is to avoid - # collisions with the addresses indirectly created by the testing framework. + # Setup The target addresses are going to be constructed (in the case of + # absent=False) and called as addr_offset + i, where i is the index of the + # account. This is to avoid collisions with the addresses indirectly + # created by the testing framework. addr_offset = int.from_bytes(pre.fund_eoa(amount=0)) if not absent_accounts: @@ -142,7 +142,10 @@ def test_worst_address_state_warm( absent_target: bool, gas_benchmark_value: int, ): - """Test running a block with as many stateful opcodes doing warm access for an account.""" + """ + Test running a block with as many stateful opcodes doing warm access for an + account. + """ max_code_size = fork.max_code_size() attack_gas_limit = gas_benchmark_value @@ -253,7 +256,9 @@ def test_worst_storage_access_cold( gas_benchmark_value: int, tx_result: TransactionResult, ): - """Test running a block with as many cold storage slot accesses as possible.""" + """ + Test running a block with as many cold storage slot accesses as possible. + """ gas_costs = fork.gas_costs() intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() attack_gas_limit = gas_benchmark_value @@ -280,7 +285,8 @@ def test_worst_storage_access_cold( execution_code_body = Op.SSTORE(Op.DUP1, Op.DUP1) loop_cost += gas_costs.G_VERY_LOW * 2 elif storage_action == StorageAction.WRITE_NEW_VALUE: - # The new value 2^256-1 is guaranteed to be different from the initial value. + # The new value 2^256-1 is guaranteed to be different from the initial + # value. execution_code_body = Op.SSTORE(Op.DUP2, Op.NOT(0)) loop_cost += gas_costs.G_VERY_LOW * 3 elif storage_action == StorageAction.READ: @@ -336,8 +342,9 @@ def test_worst_storage_access_cold( condition=Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO, ) - # To create the contract, we apply the slots_init code to initialize the storage slots - # (int the case of absent_slots=False) and then copy the execution code to the contract. + # To create the contract, we apply the slots_init code to initialize the + # storage slots (int the case of absent_slots=False) and then copy the + # execution code to the contract. creation_code = ( slots_init + Op.EXTCODECOPY( @@ -393,7 +400,9 @@ def test_worst_storage_access_warm( env: Environment, gas_benchmark_value: int, ): - """Test running a block with as many warm storage slot accesses as possible.""" + """ + Test running a block with as many warm storage slot accesses as possible. + """ attack_gas_limit = gas_benchmark_value blocks = [] @@ -455,7 +464,10 @@ def test_worst_blockhash( pre: Alloc, gas_benchmark_value: int, ): - """Test running a block with as many blockhash accessing oldest allowed block as possible.""" + """ + Test running a block with as many blockhash accessing oldest allowed block + as possible. + """ # Create 256 dummy blocks to fill the blockhash window. blocks = [Block()] * 256 @@ -560,7 +572,10 @@ def test_worst_selfdestruct_existing( env: Environment, gas_benchmark_value: int, ): - """Test running a block with as many SELFDESTRUCTs as possible for existing contracts.""" + """ + Test running a block with as many SELFDESTRUCTs as possible for existing + contracts. + """ attack_gas_limit = gas_benchmark_value fee_recipient = pre.fund_eoa(amount=1) @@ -574,12 +589,14 @@ def test_worst_selfdestruct_existing( ) + Op.RETURN(0, Op.EXTCODESIZE(selfdestructable_contract_addr)) initcode_address = pre.deploy_contract(code=initcode) - # Calculate the number of contracts that can be deployed with the available gas. + # Calculate the number of contracts that can be deployed with the available + # gas. gas_costs = fork.gas_costs() intrinsic_gas_cost_calc = fork.transaction_intrinsic_cost_calculator() loop_cost = ( gas_costs.G_KECCAK_256 # KECCAK static cost - + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic cost for CREATE2 + + math.ceil(85 / 32) * gas_costs.G_KECCAK_256_WORD # KECCAK dynamic + # cost for CREATE2 + gas_costs.G_VERY_LOW * 3 # ~MSTOREs+ADDs + gas_costs.G_COLD_ACCOUNT_ACCESS # CALL to self-destructing contract + gas_costs.G_SELF_DESTRUCT @@ -598,9 +615,9 @@ def test_worst_selfdestruct_existing( num_contracts = (attack_gas_limit - base_costs) // loop_cost expected_benchmark_gas_used = num_contracts * loop_cost + base_costs - # Create a factory that deployes a new SELFDESTRUCT contract instance pre-funded depending on - # the value_bearing parameter. We use CREATE2 so the caller contract can easily reproduce - # the addresses in a loop for CALLs. + # Create a factory that deployes a new SELFDESTRUCT contract instance pre- + # funded depending on the value_bearing parameter. We use CREATE2 so the + # caller contract can easily reproduce the addresses in a loop for CALLs. factory_code = ( Op.EXTCODECOPY( address=initcode_address, @@ -621,7 +638,8 @@ def test_worst_selfdestruct_existing( + Op.RETURN(0, 32) ) - required_balance = num_contracts if value_bearing else 0 # 1 wei per contract + required_balance = num_contracts if value_bearing else 0 # 1 wei per + # contract factory_address = pre.deploy_contract(code=factory_code, balance=required_balance) factory_caller_code = Op.CALLDATALOAD(0) + While( @@ -648,8 +666,8 @@ def test_worst_selfdestruct_existing( + While( body=Op.POP(Op.CALL(address=Op.SHA3(32 - 20 - 1, 85))) + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)), - # Only loop if we have enough gas to cover another iteration plus the - # final storage gas. + # Only loop if we have enough gas to cover another iteration plus + # the final storage gas. condition=Op.GT(Op.GAS, final_storage_gas + loop_cost), ) + Op.SSTORE(0, 42) # Done for successful tx execution assertion below. @@ -700,8 +718,8 @@ def test_worst_selfdestruct_created( gas_benchmark_value: int, ): """ - Test running a block with as many SELFDESTRUCTs as possible for deployed contracts in - the same transaction. + Test running a block with as many SELFDESTRUCTs as possible for deployed + contracts in the same transaction. """ fee_recipient = pre.fund_eoa(amount=1) env.fee_recipient = fee_recipient @@ -779,7 +797,8 @@ def test_worst_selfdestruct_created( sender=pre.fund_eoa(), ) - post = {code_addr: Account(storage={0: 42})} # Check for successful execution. + post = {code_addr: Account(storage={0: 42})} # Check for successful + # execution. state_test( env=env, pre=pre, @@ -798,7 +817,10 @@ def test_worst_selfdestruct_initcode( env: Environment, gas_benchmark_value: int, ): - """Test running a block with as many SELFDESTRUCTs as possible executed in initcode.""" + """ + Test running a block with as many SELFDESTRUCTs as possible executed in + initcode. + """ fee_recipient = pre.fund_eoa(amount=1) env.fee_recipient = fee_recipient @@ -861,7 +883,8 @@ def test_worst_selfdestruct_initcode( sender=pre.fund_eoa(), ) - post = {code_addr: Account(storage={0: 42})} # Check for successful execution. + post = {code_addr: Account(storage={0: 42})} # Check for successful + # execution. state_test( env=env, pre=pre, diff --git a/berlin/eip2929_gas_cost_increases/__init__.py b/berlin/eip2929_gas_cost_increases/__init__.py index 9646b2063c..baedc1cb64 100644 --- a/berlin/eip2929_gas_cost_increases/__init__.py +++ b/berlin/eip2929_gas_cost_increases/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929) - Test cases for [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929). -""" # noqa: E501 +Tests for [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929). +""" diff --git a/berlin/eip2929_gas_cost_increases/test_precompile_warming.py b/berlin/eip2929_gas_cost_increases/test_precompile_warming.py index 696f68b2d5..f8ad64a3d4 100644 --- a/berlin/eip2929_gas_cost_increases/test_precompile_warming.py +++ b/berlin/eip2929_gas_cost_increases/test_precompile_warming.py @@ -1,7 +1,10 @@ """ -abstract: Tests [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929) - Test cases for [EIP-2929: Gas cost increases for state access opcodes](https://eips.ethereum.org/EIPS/eip-2929). -""" # noqa: E501 +Tests EIP-2929 precompile warming behavior. + +Tests precompile warming behavior across fork transitions from +[EIP-2929: Gas cost increases for state access opcodes] + (https://eips.ethereum.org/EIPS/eip-2929). +""" from typing import Iterator, Tuple @@ -31,14 +34,17 @@ def precompile_addresses_in_predecessor_successor( fork: Fork, ) -> Iterator[Tuple[Address, bool, bool]]: """ - Yield the addresses of precompiled contracts and whether they existed in the parent fork. + Yield the addresses of precompiled contracts and whether they existed in + the parent fork. Args: - fork (Fork): The transition fork instance containing precompiled contract information. + fork (Fork): The transition fork instance containing precompiled + contract information. Yields: - Iterator[Tuple[str, bool]]: A tuple containing the address in hexadecimal format and a - boolean indicating whether the address has existed in the predecessor. + Iterator[Tuple[str, bool]]: A tuple containing the address in + hexadecimal format and a boolean indicating whether the address + has existed in the predecessor. """ precompile_range = range(0x01, 0x100) @@ -84,14 +90,16 @@ def test_precompile_warming( """ Call BALANCE of a precompile addresses before and after a fork. - According to EIP-2929, when a transaction begins, accessed_addresses is initialized to include: + According to EIP-2929, when a transaction begins, accessed_addresses is + initialized to include: - tx.sender, tx.to - and the set of all precompiles This test verifies that: - 1. Precompiles that exist in the predecessor fork are always "warm" (lower gas cost) - 2. New precompiles added in a fork are "cold" before the fork and become "warm" after - + 1. Precompiles that exist in the predecessor fork are always "warm" (lower + gas cost). + 2. New precompiles added in a fork are "cold" before the fork and become + "warm" after. """ sender = pre.fund_eoa() call_cost_slot = 0 diff --git a/berlin/eip2930_access_list/__init__.py b/berlin/eip2930_access_list/__init__.py index 24be6dfd09..25187646f7 100644 --- a/berlin/eip2930_access_list/__init__.py +++ b/berlin/eip2930_access_list/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930) - Test cases for [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930). +Tests for [EIP-2930: Optional access lists](https://eips.ethereum.org/EIPS/eip-2930). """ diff --git a/berlin/eip2930_access_list/test_tx_intrinsic_gas.py b/berlin/eip2930_access_list/test_tx_intrinsic_gas.py index 77ec323172..cb5fe94b96 100644 --- a/berlin/eip2930_access_list/test_tx_intrinsic_gas.py +++ b/berlin/eip2930_access_list/test_tx_intrinsic_gas.py @@ -1,6 +1,8 @@ """ -abstract: Tests [EIP-2930: Access list transaction](https://eips.ethereum.org/EIPS/eip-2930). -Original test by Ori: https://github.com/ethereum/tests/blob/v15.0/src/GeneralStateTestsFiller/stEIP1559/intrinsicGen.js. +Tests [EIP-2930: Access list transaction](https://eips.ethereum.org/EIPS/eip-2930). + +Original test by Ori: +https://github.com/ethereum/tests/blob/v15.0/src/GeneralStateTestsFiller/stEIP1559/intrinsicGen.js. """ from typing import List @@ -163,7 +165,8 @@ def test_tx_intrinsic_gas( if data_floor_gas_cost > intrinsic_gas_cost: exception = TransactionException.INTRINSIC_GAS_BELOW_FLOOR_GAS_COST elif data_floor_gas_cost == intrinsic_gas_cost: - # Depending on the implementation, client might raise either exception. + # Depending on the implementation, client might raise either + # exception. exception = [ TransactionException.INTRINSIC_GAS_TOO_LOW, TransactionException.INTRINSIC_GAS_BELOW_FLOOR_GAS_COST, diff --git a/byzantium/eip198_modexp_precompile/helpers.py b/byzantium/eip198_modexp_precompile/helpers.py index 9cc44fd25a..6439c3bfe0 100644 --- a/byzantium/eip198_modexp_precompile/helpers.py +++ b/byzantium/eip198_modexp_precompile/helpers.py @@ -1,4 +1,6 @@ -"""Helper functions for the EIP-198 ModExp precompile tests.""" +""" +Helper functions for the EIP-198 ModExp precompile tests. +""" from typing import Tuple @@ -9,15 +11,16 @@ class ModExpInput(TestParameterGroup): """ - Helper class that defines the MODEXP precompile inputs and creates the - call data from them. + Helper class that defines the MODEXP precompile inputs and creates the call + data from them. Attributes: base (str): The base value for the MODEXP precompile. exponent (str): The exponent value for the MODEXP precompile. modulus (str): The modulus value for the MODEXP precompile. - extra_data (str): Defines extra padded data to be added at the end of the calldata - to the precompile. Defaults to an empty string. + extra_data (str): Defines extra padded data to be added at the end of + the calldata to the precompile. + Defaults to an empty string. """ @@ -134,9 +137,11 @@ class ModExpOutput(TestParameterGroup): Expected test result. Attributes: - call_success (bool): The return_code from CALL, 0 indicates unsuccessful call - (out-of-gas), 1 indicates call succeeded. - returned_data (str): The output returnData is the expected output of the call + call_success (bool): The return_code from CALL, 0 indicates + unsuccessful call (out-of-gas), 1 indicates call + succeeded. + returned_data(str): The output returnData is the expected + output of the call. """ diff --git a/byzantium/eip198_modexp_precompile/test_modexp.py b/byzantium/eip198_modexp_precompile/test_modexp.py index 859a73b8e1..978963ec6d 100644 --- a/byzantium/eip198_modexp_precompile/test_modexp.py +++ b/byzantium/eip198_modexp_precompile/test_modexp.py @@ -1,7 +1,8 @@ """ -abstract: Test [EIP-198: MODEXP Precompile](https://eips.ethereum.org/EIPS/eip-198) - Tests the MODEXP precompile, located at address 0x0000..0005. Test cases from the EIP are - labelled with `EIP-198-caseX` in the test id. +Test [EIP-198: MODEXP Precompile](https://eips.ethereum.org/EIPS/eip-198). + +Tests the MODEXP precompile, located at address 0x0000..0005. Test cases +from the EIP are labelled with `EIP-198-caseX` in the test id. """ import pytest @@ -94,7 +95,8 @@ ), id="EIP-198-case2", ), - pytest.param( # Note: This is the only test case which goes out-of-gas. + pytest.param( # Note: This is the only test case which goes out-of- + # gas. Bytes( "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000020" @@ -135,7 +137,8 @@ id="EIP-198-case5-raw-input", ), ], - ids=lambda param: param.__repr__(), # only required to remove parameter names (input/output) + ids=lambda param: param.__repr__(), # only required to remove parameter + # names (input/output) ) def test_modexp( state_test: StateTestFiller, @@ -153,17 +156,18 @@ def test_modexp( # Store the returned CALL status (success = 1, fail = 0) into slot 0: + Op.SSTORE( 0, - # Setup stack to CALL into ModExp with the CALLDATA and CALL into it (+ pop value) + # Setup stack to CALL into ModExp with the CALLDATA and CALL into + # it (+ pop value) Op.CALL(Op.GAS(), 0x05, 0, 0, Op.CALLDATASIZE(), 0, 0), ) - # Store contract deployment code to deploy the returned data from ModExp as - # contract code (16 bytes) + # Store contract deployment code to deploy the returned data from + # ModExp as contract code (16 bytes) + Op.MSTORE( 0, ( - # Need to `ljust` this PUSH32 in order to ensure the code starts - # in memory at offset 0 (memory right-aligns stack items which are not - # 32 bytes) + # Need to `ljust` this PUSH32 in order to ensure the code + # starts in memory at offset 0 (memory right-aligns stack items + # which are not 32 bytes) Op.PUSH32( bytes( Op.CODECOPY(0, 16, Op.SUB(Op.CODESIZE(), 16)) @@ -172,9 +176,11 @@ def test_modexp( ) ), ) - # RETURNDATACOPY the returned data from ModExp into memory (offset 16 bytes) + # RETURNDATACOPY the returned data from ModExp into memory (offset 16 + # bytes) + Op.RETURNDATACOPY(16, 0, Op.RETURNDATASIZE()) - # CREATE contract with the deployment code + the returned data from ModExp + # CREATE contract with the deployment code + the returned data from + # ModExp + Op.CREATE(0, 0, Op.ADD(16, Op.RETURNDATASIZE())) # STOP (handy for tracing) + Op.STOP(), diff --git a/cancun/eip1153_tstore/__init__.py b/cancun/eip1153_tstore/__init__.py index 1ef8a2efb7..dabae5a7d5 100644 --- a/cancun/eip1153_tstore/__init__.py +++ b/cancun/eip1153_tstore/__init__.py @@ -1,4 +1,6 @@ -"""EIP-1153 Tests.""" +""" +[EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) Tests. +""" from enum import Enum, unique from pprint import pprint @@ -13,8 +15,8 @@ class PytestParameterEnum(Enum): """ Helper class for defining Pytest parameters used in test cases. - This class helps define enum `value`s as `pytest.param` objects that then can - be used to create a parametrize decorator that can be applied to tests, + This class helps define enum `value`s as `pytest.param` objects that then + can be used to create a parametrize decorator that can be applied to tests, for example, ```python @@ -23,25 +25,23 @@ def test_function(test_value): pass ``` - Classes which derive from this class must define each test case as a different enum - field with a dictionary as value. + Classes which derive from this class must define each test case as a + different enum field with a dictionary as value. The dictionary must contain: - i. A `description` key with a string value describing the test case. - ii. (Optional) A `pytest_marks` key with a single mark or list of pytest - marks to apply to the test case. For example, - - ``` - pytest_marks=pytest.mark.xfail - ``` - or - - ``` - pytest_marks=[pytest.mark.xfail, pytest.mark.skipif] - ``` - iii. (Optional) An `id` key with the name of the test. - - The rest of the keys in the dictionary are the parameters of the test case. + i. A `description` key with a string value describing the test case. + ii. (Optional) A `pytest_marks` key with a single mark or list of pytest + marks to apply to the test case. For example: + ``` + pytest_marks=pytest.mark.xfail + ``` + or + ``` + pytest_marks=[pytest.mark.xfail, pytest.mark.skipif] + ``` + iii. (Optional) An `id` key with the name of the test. + + The rest of the keys in the dictionary are the parameters of the test case. The test case ID is set as the enum name converted to lowercase. """ @@ -67,11 +67,15 @@ def param(self, names: List[str]): @classmethod def special_keywords(cls) -> List[str]: - """Return the special dictionary keywords that are not test parameters.""" + """ + Return the special dictionary keywords that are not test parameters. + """ return ["description", "pytest_marks", "pytest_id"] def names(self) -> List[str]: - """Return the names of all the parameters included in the enum value dict.""" + """ + Return the names of all the parameters included in the enum value dict. + """ return sorted([k for k in self._value_.keys() if k not in self.special_keywords()]) @property diff --git a/cancun/eip1153_tstore/test_tload_calls.py b/cancun/eip1153_tstore/test_tload_calls.py index 27837bc797..120f2060d6 100644 --- a/cancun/eip1153_tstore/test_tload_calls.py +++ b/cancun/eip1153_tstore/test_tload_calls.py @@ -1,6 +1,5 @@ """ -Ethereum Transient Storage EIP Tests -https://eips.ethereum.org/EIPS/eip-1153. +[EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) Transient Storage tests. """ import pytest @@ -26,11 +25,11 @@ def test_tload_calls(state_test: StateTestFiller, pre: Alloc, call_type: Op): """ Ported .json vectors. - (04_tloadAfterCallFiller.yml) - Loading a slot after a call to another contract is 0. + (04_tloadAfterCallFiller.yml) Loading a slot after a call to another + contract is 0. - (12_tloadDelegateCallFiller.yml) - delegatecall reads transient storage in the context of the current address + (12_tloadDelegateCallFiller.yml) delegatecall reads transient storage in + the context of the current address """ # Storage variables slot_a_tload_after_subcall_result = 0 @@ -71,10 +70,12 @@ def make_call(call_type: Op, address: Address) -> Bytecode: post = { address_to: Account( storage={ - # other calls don't change context, there for tload updated in this account + # other calls don't change context, there for tload updated in + # this account slot_a_tload_after_subcall_result: 10 if call_type == Op.CALL else 20, slot_a_subcall_result: 1, - # since context unchanged the subcall works as if continued execution + # since context unchanged the subcall works as if continued + # execution slot_b_subcall_tload_result: 0 if call_type == Op.CALL else 10, slot_b_subcall_updated_tload_result: 0 if call_type == Op.CALL else 20, } diff --git a/cancun/eip1153_tstore/test_tload_reentrancy.py b/cancun/eip1153_tstore/test_tload_reentrancy.py index 4d66ea5115..e0d7cc9909 100644 --- a/cancun/eip1153_tstore/test_tload_reentrancy.py +++ b/cancun/eip1153_tstore/test_tload_reentrancy.py @@ -1,6 +1,5 @@ """ -Ethereum Transient Storage EIP Tests -https://eips.ethereum.org/EIPS/eip-1153. +[EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) Transient Storage tests. """ from enum import Enum @@ -53,8 +52,8 @@ def test_tload_reentrancy( """ Ported .json vectors. - (05_tloadReentrancyFiller.yml) - Reentrant calls access the same transient storage + (05_tloadReentrancyFiller.yml) Reentrant calls access the same transient + storage """ tload_value = 44 empty_value = 0 @@ -138,7 +137,8 @@ def make_call(call_type: Op) -> Bytecode: slot_tload_in_subcall_result: ( 0xFF # if call OOG, we fail to obtain the result if call_return == Om.OOG - # else delegate and callcode are working in the same context so tload works + # else delegate and callcode are working in the same + # context so tload works else ( tload_value if call_type == Op.DELEGATECALL or call_type == Op.CALLCODE diff --git a/cancun/eip1153_tstore/test_tstorage.py b/cancun/eip1153_tstore/test_tstorage.py index 990cd804e3..95b576bd0f 100644 --- a/cancun/eip1153_tstore/test_tstorage.py +++ b/cancun/eip1153_tstore/test_tstorage.py @@ -1,9 +1,9 @@ """ -abstract: Tests [EIP-1153: Transient Storage Opcodes](https://eips.ethereum.org/EIPS/eip-1153) - Test [EIP-1153: Transient Storage Opcodes](https://eips.ethereum.org/EIPS/eip-1153). Ports - and extends some tests from - [ethereum/tests/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage). -""" # noqa: E501 +EIP-1153 Transient Storage opcode tests. + +Ports and extends some tests from +[ethereum/tests/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage). +""" from enum import unique @@ -33,11 +33,15 @@ def test_transient_storage_unset_values(state_test: StateTestFiller, pre: Alloc): """ - Test that tload returns zero for unset values. Loading an arbitrary value is - 0 at beginning of transaction: TLOAD(x) is 0. - - Based on [ethereum/tests/.../01_tloadBeginningTxnFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/01_tloadBeginningTxnFiller.yml)", - """ # noqa: E501 + Test that tload returns zero for unset values. Loading an arbitrary value + is 0 at beginning of transaction: TLOAD(x) is 0. + + Based on + [ethereum/tests/.../01_tloadBeginningTxnFiller.yml] + (https://github.com/ethereum/tests/blob/ + 9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/ + stEIP1153-transientStorage/01_tloadBeginningTxnFiller.yml)", + """ env = Environment() slots_under_test = [0, 1, 2, 2**128, 2**256 - 1] @@ -69,8 +73,12 @@ def test_tload_after_tstore(state_test: StateTestFiller, pre: Alloc): Loading after storing returns the stored value: TSTORE(x, y), TLOAD(x) returns y. - Based on [ethereum/tests/.../02_tloadAfterTstoreFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/02_tloadAfterTstoreFiller.yml)", - """ # noqa: E501 + Based on + [ethereum/tests/.../02_tloadAfterTstoreFiller.yml] + (https://github.com/ethereum/tests/blob/ + 9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/ + stEIP1153-transientStorage/02_tloadAfterTstoreFiller.yml)", + """ env = Environment() slots_under_test = [0, 1, 2, 2**128, 2**256 - 1] @@ -103,8 +111,13 @@ def test_tload_after_sstore(state_test: StateTestFiller, pre: Alloc): Loading after storing returns the stored value: TSTORE(x, y), TLOAD(x) returns y. - Based on [ethereum/tests/.../18_tloadAfterStoreFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/18_tloadAfterStoreFiller.yml)", - """ # noqa: E501 + Based on + [ethereum/tests/.../18_tloadAfterStoreFiller.yml] + (https://github.com/ethereum/tests/blob/ + 9b00b68593f5869eb51a6659e1cc983e875e616b/src/ + EIPTestsFiller/StateTests/stEIP1153-transientStorage/ + 18_tloadAfterStoreFiller.yml)", + """ env = Environment() slots_under_test = [1, 3, 2**128, 2**256 - 1] @@ -143,8 +156,12 @@ def test_tload_after_tstore_is_zero(state_test: StateTestFiller, pre: Alloc): """ Test that tload returns zero after tstore is called with zero. - Based on [ethereum/tests/.../03_tloadAfterStoreIs0Filler.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/03_tloadAfterStoreIs0Filler.yml)", - """ # noqa: E501 + Based on [ethereum/tests/.../03_tloadAfterStoreIs0Filler.yml] + (https://github.com/ethereum/tests/blob/ + 9b00b68593f5869eb51a6659e1cc983e875e616b/src/ + EIPTestsFiller/StateTests/ + stEIP1153-transientStorage/03_tloadAfterStoreIs0Filler.yml)", + """ env = Environment() slots_to_write = [1, 4, 2**128, 2**256 - 2] diff --git a/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py b/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py index 8cf988bd76..fc7e75fd48 100644 --- a/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py +++ b/cancun/eip1153_tstore/test_tstorage_clear_after_tx.py @@ -1,7 +1,4 @@ -""" -Ethereum Transient Storage EIP Tests -https://eips.ethereum.org/EIPS/eip-1153. -""" +"""EIP-1153 Transient Storage tests.""" from typing import Optional @@ -34,10 +31,10 @@ def test_tstore_clear_after_deployment_tx( evm_code_type: EVMCodeType, ): """ - First creates a contract, which TSTOREs a value 1 in slot 1. - After creating the contract, a new tx will call this contract, storing TLOAD(1) into slot 1. - The transient storage should be cleared after creating the contract (at tx-level), so - the storage should stay empty. + First creates a contract, which TSTOREs a value 1 in slot 1. After creating + the contract, a new tx will call this contract, storing TLOAD(1) into slot + 1. The transient storage should be cleared after creating the contract (at + tx-level), so the storage should stay empty. """ env = Environment() @@ -81,9 +78,9 @@ def test_tstore_clear_after_tx( pre: Alloc, ): """ - First SSTOREs the TLOAD value of key 1 in slot 1. Then, it TSTOREs 1 in slot 1. - The second tx will re-call the contract. The storage should stay empty, - because the transient storage is cleared after the transaction. + First SSTOREs the TLOAD value of key 1 in slot 1. Then, it TSTOREs 1 in + slot 1. The second tx will re-call the contract. The storage should stay + empty, because the transient storage is cleared after the transaction. """ env = Environment() diff --git a/cancun/eip1153_tstore/test_tstorage_create_contexts.py b/cancun/eip1153_tstore/test_tstorage_create_contexts.py index 5ce6c65c68..efe83bcd13 100644 --- a/cancun/eip1153_tstore/test_tstorage_create_contexts.py +++ b/cancun/eip1153_tstore/test_tstorage_create_contexts.py @@ -1,7 +1,6 @@ """ -abstract: Tests for [EIP-1153: Transient Storage](https://eips.ethereum.org/EIPS/eip-1153) - Test cases for `TSTORE` and `TLOAD` opcode calls in contract initcode. -""" # noqa: E501 +Test transient storage in contract creation contexts. +""" from enum import unique @@ -32,8 +31,8 @@ @unique class InitcodeTestCases(PytestParameterEnum): """ - Defines test cases for transient storage opcode usage in contract constructor - and deployed code. + Defines test cases for transient storage opcode usage in contract + constructor and deployed code. """ ONLY_CONSTRUCTOR_CODE = { @@ -41,9 +40,11 @@ class InitcodeTestCases(PytestParameterEnum): "Test TLOAD and TSTORE behavior in contract constructor without deployed code" ), "constructor_code": ( - # test creator's transient storage inaccessible from constructor code + # test creator's transient storage inaccessible from constructor + # code Op.SSTORE(0, Op.TLOAD(0)) - # test constructor code can use its own transient storage & creator storage unaffected + # test constructor code can use its own transient storage & creator + # storage unaffected + Op.TSTORE(0, 1) + Op.SSTORE(1, Op.TLOAD(0)) ), @@ -53,13 +54,15 @@ class InitcodeTestCases(PytestParameterEnum): IN_CONSTRUCTOR_AND_DEPLOYED_CODE = { "description": "Test TLOAD and TSTORE behavior in contract constructor and deployed code", "constructor_code": ( - # test creator's transient storage inaccessible from constructor code + # test creator's transient storage inaccessible from constructor + # code Op.SSTORE(0, Op.TLOAD(0)) ), "deploy_code": ( # test creator's transient storage inaccessible from deployed code Op.SSTORE(1, Op.TLOAD(0)) - # test deploy code can use its own transient storage & creator storage unaffected + # test deploy code can use its own transient storage & creator + # storage unaffected + Op.TSTORE(1, 1) + Op.SSTORE(2, Op.TLOAD(1)) ), @@ -68,15 +71,18 @@ class InitcodeTestCases(PytestParameterEnum): ACROSS_CONSTRUCTOR_AND_DEPLOYED_CODE_V0 = { "description": ("Test TSTORE behavior across contract constructor and deploy code. "), "constructor_code": ( - # constructor code should be able to store its own transient storage + # constructor code should be able to store its own transient + # storage Op.TSTORE(1, 1) ), "deploy_code": ( # test creator's transient storage inaccessible from deployed code Op.SSTORE(0, Op.TLOAD(0)) - # test deploy code can use its own transient storage stored from constructor code + # test deploy code can use its own transient storage stored from + # constructor code + Op.SSTORE(1, Op.TLOAD(1)) - # test deploy code can use its own transient storage stored from deployed code + # test deploy code can use its own transient storage stored from + # deployed code + Op.TSTORE(2, 1) + Op.SSTORE(2, Op.TLOAD(2)) ), @@ -89,17 +95,19 @@ class InitcodeTestCases(PytestParameterEnum): "constructor_code": ( # test creator's transient storage inaccessible from constructor Op.SSTORE(0, Op.TLOAD(0)) - # constructor code should be able to use its own transient storage / creator storage - # unaffected + # constructor code should be able to use its own transient storage + # / creator storage unaffected + Op.TSTORE(1, 1) + Op.SSTORE(1, Op.TLOAD(1)) ), "deploy_code": ( # test creator's transient storage inaccessible from deployed code Op.SSTORE(2, Op.TLOAD(0)) - # test deploy code can use its own transient storage stored from constructor code + # test deploy code can use its own transient storage stored from + # constructor code + Op.SSTORE(3, Op.TLOAD(1)) - # test deploy code can use its own transient storage stored from deployed code + # test deploy code can use its own transient storage stored from + # deployed code + Op.TSTORE(2, 1) + Op.SSTORE(4, Op.TLOAD(2)) ), @@ -113,7 +121,8 @@ class InitcodeTestCases(PytestParameterEnum): "deploy_code": ( # test creator's transient storage inaccessible from deployed code Op.SSTORE(0, Op.TLOAD(0)) - # test deployed code can use its own transient storage & creator storage unaffected + # test deployed code can use its own transient storage & creator + # storage unaffected + Op.TSTORE(0, 1) + Op.SSTORE(1, Op.TLOAD(0)) ), @@ -126,10 +135,12 @@ class InitcodeTestCases(PytestParameterEnum): class TestTransientStorageInContractCreation: """ Test transient storage in contract creation contexts. - - TSTORE/TLOAD in initcode should not be able to access the creator's transient storage. - - TSTORE/TLOAD in initcode should be able to access the created contract's transient - storage. - - TSTORE/TLOAD in creator contract should be able to use its own transient storage. + - TSTORE/TLOAD in initcode should not be able to access the creator's + transient storage. + - TSTORE/TLOAD in initcode should be able to access the created contract's + transient storage. + - TSTORE/TLOAD in creator contract should be able to use its own + transient storage. """ @pytest.fixture() @@ -165,8 +176,8 @@ def creator_contract_code( # noqa: D102 ) ), ) - # Save the state of transient storage following call to storage; the transient - # storage should not have been overwritten + # Save the state of transient storage following call to storage; + # the transient storage should not have been overwritten + Op.SSTORE(0, Op.TLOAD(0)) + Op.SSTORE(1, Op.TLOAD(1)) + Op.SSTORE(2, Op.TLOAD(2)) diff --git a/cancun/eip1153_tstore/test_tstorage_execution_contexts.py b/cancun/eip1153_tstore/test_tstorage_execution_contexts.py index 99c83f0556..b710ff493e 100644 --- a/cancun/eip1153_tstore/test_tstorage_execution_contexts.py +++ b/cancun/eip1153_tstore/test_tstorage_execution_contexts.py @@ -1,7 +1,6 @@ """ -abstract: Tests for [EIP-1153: Transient Storage](https://eips.ethereum.org/EIPS/eip-1153) - Test cases for `TSTORE` and `TLOAD` opcode calls in different execution contexts. -""" # noqa: E501 +Test EIP-1153 Transient Storage in execution contexts. +""" from enum import EnumMeta, unique from typing import Dict, Mapping @@ -33,9 +32,9 @@ class DynamicCallContextTestCases(EnumMeta): """ - Create dynamic transient storage test cases for contract sub-calls - using CALLCODE and DELEGATECALL (these opcodes share the same - signatures and test cases). + Create dynamic transient storage test cases for contract sub-calls using + CALLCODE and DELEGATECALL (these opcodes share the same signatures and test + cases). """ def __new__(cls, name, bases, classdict): # noqa: D102 @@ -258,14 +257,14 @@ class CallContextTestCases(PytestParameterEnum, metaclass=DynamicCallContextTest + Op.SSTORE(1, Op.TLOAD(0)) + Op.STOP ), - "callee_bytecode": Op.TSTORE(0, unchecked=True) # calling with stack underflow still fails - + Op.STOP, + # calling with stack underflow still fails + "callee_bytecode": Op.TSTORE(0, unchecked=True) + Op.STOP, "expected_caller_storage": {0: 0, 1: 420}, "expected_callee_storage": {}, } STATICCALL_CAN_CALL_TLOAD = { - # TODO: Not a very useful test; consider removing after implementing ethereum/tests - # staticcall tests + # TODO: Not a very useful test; consider removing after implementing + # ethereum/tests staticcall tests "pytest_id": "staticcalled_context_can_call_tload", "description": ("A STATICCALL callee can not use transient storage."), "caller_bytecode": ( @@ -274,7 +273,8 @@ class CallContextTestCases(PytestParameterEnum, metaclass=DynamicCallContextTest + Op.SSTORE(1, Op.TLOAD(0)) + Op.STOP ), - "callee_bytecode": Op.TLOAD(0) + Op.STOP, # calling tload does not cause the call to fail + # calling tload does not cause the call to fail + "callee_bytecode": Op.TLOAD(0) + Op.STOP, "expected_caller_storage": {0: 1, 1: 420}, "expected_callee_storage": {}, } diff --git a/cancun/eip1153_tstore/test_tstorage_reentrancy_contexts.py b/cancun/eip1153_tstore/test_tstorage_reentrancy_contexts.py index 18fed8cea9..05044ef8ac 100644 --- a/cancun/eip1153_tstore/test_tstorage_reentrancy_contexts.py +++ b/cancun/eip1153_tstore/test_tstorage_reentrancy_contexts.py @@ -1,7 +1,6 @@ """ -abstract: Tests for [EIP-1153: Transient Storage](https://eips.ethereum.org/EIPS/eip-1153) - Test cases for `TSTORE` and `TLOAD` opcode calls in reentrancy contexts. -""" # noqa: E501 +Tests transient storage in reentrancy contexts. +""" from enum import EnumMeta, unique from typing import Dict @@ -59,11 +58,15 @@ def __new__(cls, name, bases, classdict): # noqa: D102 classdict[f"TSTORE_BEFORE_{opcode._name_}_HAS_NO_EFFECT"] = { "description": ( - f"{opcode._name_} undoes the transient storage write from the failed call: " - f"TSTORE(x, y), CALL(self, ...), TSTORE(x, z), {opcode._name_}, TLOAD(x) " - "returns y." - "", - "Based on [ethereum/tests/.../08_revertUndoesTransientStoreFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/08_revertUndoesTransientStoreFiller.yml)", # noqa: E501 + f"{opcode._name_} undoes the transient storage write " + "from the failed call: " + "TSTORE(x, y), CALL(self, ...), TSTORE(x, z), " + f"{opcode._name_}, TLOAD(x) returns y.", + "Based on [ethereum/tests/.../08_revertUndoes" + "TransientStoreFiller.yml](https://github.com/ethereum/" + "tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src" + "/EIPTestsFiller/StateTests/stEIP1153-transientStorage/" + "08_revertUndoesTransientStoreFiller.yml)", ), "bytecode": Conditional( condition=SETUP_CONDITION, @@ -84,11 +87,13 @@ def __new__(cls, name, bases, classdict): # noqa: D102 classdict[f"{opcode._name_}_UNDOES_ALL"] = { "description": ( - f"{opcode._name_} undoes all the transient storage writes to the same key ", - "from a failed call. TSTORE(x, y), CALL(self, ...), TSTORE(x, z), ", - f"TSTORE(x, z + 1) {opcode._name_}, TLOAD(x) returns y.", + f"{opcode._name_} undoes all the transient storage writes " + "to the same key from a failed call. " + "TSTORE(x, y), CALL(self, ...), TSTORE(x, z), " + f"TSTORE(x, z + 1) {opcode._name_}, TLOAD(x) returns y." "", - "Based on [ethereum/tests/.../09_revertUndoesAllFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/09_revertUndoesAllFiller.yml).", # noqa: E501 + "Based on " + "[ethereum/tests/.../09_revertUndoesAllFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/09_revertUndoesAllFiller.yml).", ), "bytecode": Conditional( condition=SETUP_CONDITION, @@ -106,7 +111,8 @@ def __new__(cls, name, bases, classdict): # noqa: D102 ), # reenter if_false=( - # store twice and revert/invalid; none of the stores should take effect + # store twice and revert/invalid; none of the stores + # should take effect Op.TSTORE(0xFE, 0x201) + Op.TSTORE(0xFE, 0x202) + Op.TSTORE(0xFF, 0x201) @@ -128,11 +134,17 @@ def __new__(cls, name, bases, classdict): # noqa: D102 classdict[f"{opcode._name_}_UNDOES_TSTORAGE_AFTER_SUCCESSFUL_CALL"] = { "description": ( - f"{opcode._name_} undoes transient storage writes from inner calls that " - "successfully returned. TSTORE(x, y), CALL(self, ...), CALL(self, ...), " - f"TSTORE(x, y + 1), RETURN, {opcode._name_}, TLOAD(x) returns y." - "", - "Based on [ethereum/tests/.../10_revertUndoesStoreAfterReturnFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/10_revertUndoesStoreAfterReturnFiller.yml).", # noqa: E501 + f"{opcode._name_} undoes transient storage writes from " + "inner calls that successfully returned. " + "TSTORE(x, y), CALL(self, ...), CALL(self, ...), " + f"TSTORE(x, y + 1), RETURN, {opcode._name_}, TLOAD(x) " + "returns y.", + "Based on [ethereum/tests/.../" + "10_revertUndoesStoreAfterReturnFiller.yml]" + "(https://github.com/ethereum/tests/blob/" + "9b00b68593f5869eb51a6659e1cc983e875e616b/src/" + "EIPTestsFiller/StateTests/stEIP1153-transientStorage/" + "10_revertUndoesStoreAfterReturnFiller.yml).", ), "bytecode": Switch( default_action=( # setup; make first reentrant sub-call @@ -149,11 +161,13 @@ def __new__(cls, name, bases, classdict): # noqa: D102 ret_size=32, ), ) - + Op.SSTORE(1, Op.MLOAD(32)) # should be 1 (successful call) + + Op.SSTORE(1, Op.MLOAD(32)) # should be 1 (successful + # call) + Op.SSTORE(3, Op.TLOAD(0xFF)) ), cases=[ - # the first, reentrant call, which reverts/receives invalid + # the first, reentrant call, which reverts/receives + # invalid CalldataCase( value=2, action=( @@ -162,7 +176,8 @@ def __new__(cls, name, bases, classdict): # noqa: D102 + opcode_call ), ), - # the second, reentrant call, which returns successfully + # the second, reentrant call, which returns + # successfully CalldataCase( value=3, action=Op.TSTORE(0xFF, 0x101), @@ -184,7 +199,10 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa "Reentrant calls access the same transient storage: " "TSTORE(x, y), CALL(self, ...), TLOAD(x) returns y." "" - "Based on [ethereum/tests/.../05_tloadReentrancyFiller.yml](https://github.com/ethereum/tests/tree/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage).", # noqa: E501 + "Based on [ethereum/tests/.../05_tloadReentrancyFiller.yml]" + "(https://github.com/ethereum/tests/tree/" + "9b00b68593f5869eb51a6659e1cc983e875e616b/src/" + "EIPTestsFiller/StateTests/stEIP1153-transientStorage).", ), "bytecode": Conditional( condition=SETUP_CONDITION, @@ -197,10 +215,16 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa } TLOAD_AFTER_REENTRANT_TSTORE = { "description": ( - "Successfully returned calls do not revert transient storage writes: " - "TSTORE(x, y), CALL(self, ...), TSTORE(x, z), RETURN, TLOAD(x) returns z." - "" - "Based on [ethereum/tests/.../07_tloadAfterReentrancyStoreFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/07_tloadAfterReentrancyStoreFiller.yml).", # noqa: E501 + "Successfully returned calls do not revert transient " + "storage writes: " + "TSTORE(x, y), CALL(self, ...), TSTORE(x, z), RETURN, TLOAD(x) " + "returns z." + "Based on [ethereum/tests/.../" + "07_tloadAfterReentrancyStoreFiller.yml](https://github.com/" + "ethereum/tests/blob/" + "9b00b68593f5869eb51a6659e1cc983e875e616b/src/" + "EIPTestsFiller/StateTests/stEIP1153-transientStorage/" + "07_tloadAfterReentrancyStoreFiller.yml).", ), "bytecode": Conditional( condition=SETUP_CONDITION, @@ -209,7 +233,8 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa Op.TSTORE(0xFF, 0x100) + Op.SSTORE(1, Op.TLOAD(0xFF)) + REENTRANT_CALL - + Op.SSTORE(2, Op.TLOAD(0xFF)) # test value updated during reentrant call + + Op.SSTORE(2, Op.TLOAD(0xFF)) # test value updated during + # reentrant call ), # reenter if_false=Op.TSTORE(0xFF, 0x101), @@ -221,7 +246,11 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa "Reentrant calls can manipulate the same transient storage: " "TSTORE(x, y), CALL(self, ...), TSTORE(x, z), TLOAD(x) returns z." "" - "Based on [ethereum/tests/.../06_tstoreInReentrancyCallFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/06_tstoreInReentrancyCallFiller.yml).", # noqa: E501 + "Based on [ethereum/tests/.../06_tstoreInReentrancyCallFiller.yml]" + "(https://github.com/ethereum/tests/blob/" + "9b00b68593f5869eb51a6659e1cc983e875e616b/src/" + "EIPTestsFiller/StateTests/stEIP1153-transientStorage/" + "06_tstoreInReentrancyCallFiller.yml).", ), "bytecode": Conditional( condition=SETUP_CONDITION, @@ -230,7 +259,8 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa Op.TSTORE(0xFF, 0x100) + Op.SSTORE(1, Op.TLOAD(0xFF)) + REENTRANT_CALL - + Op.SSTORE(3, Op.TLOAD(0xFF)) # test value updated during reentrant call + + Op.SSTORE(3, Op.TLOAD(0xFF)) # test value updated during + # reentrant call ), # reenter if_false=Op.TSTORE(0xFF, 0x101) + Op.SSTORE(2, Op.TLOAD(0xFF)), @@ -239,9 +269,16 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa } TSTORE_IN_CALL_THEN_TLOAD_RETURN_IN_STATICCALL = { "description": ( - "A reentrant call followed by a reentrant subcall can call tload correctly: " - "TSTORE(x, y), CALL(self, ...), STATICCALL(self, ...), TLOAD(x), RETURN returns y." - "Based on [ethereum/tests/.../10_revertUndoesStoreAfterReturnFiller.yml](https://github.com/ethereum/tests/blob/9b00b68593f5869eb51a6659e1cc983e875e616b/src/EIPTestsFiller/StateTests/stEIP1153-transientStorage/10_revertUndoesStoreAfterReturnFiller.yml).", # noqa: E501 + "A reentrant call followed by a reentrant subcall can " + "call tload correctly: " + "TSTORE(x, y), CALL(self, ...), STATICCALL(self, ...), " + "TLOAD(x), RETURN returns y." + "Based on [ethereum/tests/.../" + "10_revertUndoesStoreAfterReturnFiller.yml]" + "(https://github.com/ethereum/tests/blob/" + "9b00b68593f5869eb51a6659e1cc983e875e616b/src/" + "EIPTestsFiller/StateTests/stEIP1153-transientStorage/" + "10_revertUndoesStoreAfterReturnFiller.yml).", ), "bytecode": Switch( default_action=( # setup; make first reentrant sub-call @@ -252,7 +289,8 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa + Op.SSTORE(4, Op.TLOAD(0xFE)) ), cases=[ - # the first, reentrant call which calls tstore and a further reentrant staticcall + # the first, reentrant call which calls tstore and a further + # reentrant staticcall CalldataCase( value=2, action=( @@ -264,7 +302,8 @@ class ReentrancyTestCases(PytestParameterEnum, metaclass=DynamicReentrancyTestCa + Op.SSTORE(3, Op.MLOAD(0)) ), ), - # the second, reentrant call, which calls tload and return returns successfully + # the second, reentrant call, which calls tload and return + # returns successfully CalldataCase( value=3, action=Op.MSTORE(0, Op.TLOAD(0xFE)) + Op.RETURN(0, 32), diff --git a/cancun/eip1153_tstore/test_tstorage_selfdestruct.py b/cancun/eip1153_tstore/test_tstorage_selfdestruct.py index fadd9fde03..6237c83099 100644 --- a/cancun/eip1153_tstore/test_tstorage_selfdestruct.py +++ b/cancun/eip1153_tstore/test_tstorage_selfdestruct.py @@ -1,8 +1,9 @@ """ -abstract: Tests for [EIP-1153: Transient Storage](https://eips.ethereum.org/EIPS/eip-1153) - Test cases for `TSTORE` and `TLOAD` opcode calls in reentrancy after self-destruct, taking into - account the changes in EIP-6780. -""" # noqa: E501 +EIP-1153 Transient Storage with selfdestruct tests. + +Test cases for `TSTORE` and `TLOAD` opcode calls in reentrancy after +self-destruct, taking into account the changes in EIP-6780. +""" from enum import unique from typing import Dict @@ -36,7 +37,10 @@ def call_option(option_number: int) -> Bytecode: - """Return the bytecode for a call to the callee contract with the given option number.""" + """ + Return the bytecode for a call to the callee contract with the given option + number. + """ return Op.MSTORE(value=option_number) + Op.CALL( address=Op.SLOAD(0), args_offset=0, @@ -49,8 +53,8 @@ def call_option(option_number: int) -> Bytecode: @unique class SelfDestructCases(PytestParameterEnum): """ - Transient storage test cases for different reentrancy calls which involve the contract - self-destructing. + Transient storage test cases for different reentrancy calls which involve + the contract self-destructing. """ TLOAD_AFTER_SELFDESTRUCT_PRE_EXISTING_CONTRACT = { @@ -225,7 +229,10 @@ def test_reentrant_selfdestructing_call( callee_bytecode: Bytecode, expected_storage: Dict, ): - """Test transient storage in different reentrancy contexts after selfdestructing.""" + """ + Test transient storage in different reentrancy contexts after + selfdestructing. + """ env = Environment() caller_address = pre.deploy_contract(code=caller_bytecode) diff --git a/cancun/eip1153_tstore/test_tstore_reentrancy.py b/cancun/eip1153_tstore/test_tstore_reentrancy.py index 30d200b4fb..557eb211ee 100644 --- a/cancun/eip1153_tstore/test_tstore_reentrancy.py +++ b/cancun/eip1153_tstore/test_tstore_reentrancy.py @@ -1,7 +1,4 @@ -""" -Ethereum Transient Storage EIP Tests -https://eips.ethereum.org/EIPS/eip-1153. -""" +"""EIP-1153 Transient Storage tests.""" from enum import Enum @@ -69,10 +66,12 @@ def test_tstore_reentrancy( Revert undoes the transient storage writes from a call. (09_revertUndoesAllFiller.yml) - Revert undoes all the transient storage writes to the same key from the failed call. + Revert undoes all the transient storage writes to the same key + from the failed call. (11_tstoreDelegateCallFiller.yml) - delegatecall manipulates transient storage in the context of the current address. + delegatecall manipulates transient storage in the context of + the current address. (13_tloadStaticCallFiller.yml) Transient storage cannot be manipulated in a static context, tstore reverts @@ -200,7 +199,8 @@ def make_call(call_type: Op) -> Bytecode: if call_type == Op.STATICCALL or call_return == Om.OOG else tload_value_set_in_call ), - # external tstore overrides value in upper level only in delegate and callcode + # external tstore overrides value in upper level only in + # delegate and callcode slot_tload_after_call: ( tload_value_set_in_call if on_successful_delegate_or_callcode @@ -208,7 +208,8 @@ def make_call(call_type: Op) -> Bytecode: ), slot_tload_1_after_call: 12 if on_successful_delegate_or_callcode else 0, slot_tstore_overwrite: 50, - # tstore in static call not allowed, reentrancy means external call here + # tstore in static call not allowed, reentrancy means + # external call here slot_subcall_worked: 0 if on_failing_calls else 1, } ) diff --git a/cancun/eip4788_beacon_root/conftest.py b/cancun/eip4788_beacon_root/conftest.py index 3a28b279ce..12497eead1 100644 --- a/cancun/eip4788_beacon_root/conftest.py +++ b/cancun/eip4788_beacon_root/conftest.py @@ -34,7 +34,10 @@ def timestamp() -> int: # noqa: D103 @pytest.fixture def beacon_roots() -> Iterator[bytes]: - """By default, return an iterator that returns the keccak of an internal counter.""" + """ + By default, return an iterator that returns the keccak of an internal + counter. + """ class BeaconRoots: def __init__(self) -> None: @@ -97,7 +100,8 @@ def contract_call_code(call_type: Op, call_value: int, call_gas: int) -> Bytecod if call_type == Op.CALL or call_type == Op.CALLCODE: contract_call_code += Op.SSTORE( 0x00, # store the result of the contract call in storage[0] - call_type( # type: ignore # https://github.com/ethereum/execution-spec-tests/issues/348 # noqa: E501 + # https://github.com/ethereum/execution-spec-tests/issues/348 + call_type( # type: ignore call_gas, Spec.BEACON_ROOTS_ADDRESS, call_value, @@ -111,7 +115,8 @@ def contract_call_code(call_type: Op, call_value: int, call_gas: int) -> Bytecod # delegatecall and staticcall use one less argument contract_call_code += Op.SSTORE( 0x00, - call_type( # type: ignore # https://github.com/ethereum/execution-spec-tests/issues/348 # noqa: E501 + # https://github.com/ethereum/execution-spec-tests/issues/348 + call_type( # type: ignore call_gas, Spec.BEACON_ROOTS_ADDRESS, args_start, @@ -181,7 +186,9 @@ def auto_access_list() -> bool: @pytest.fixture def access_list(auto_access_list: bool, timestamp: int) -> List[AccessList]: - """Access list included in the transaction to call the beacon root contract.""" + """ + Access list included in the transaction to call the beacon root contract. + """ if auto_access_list: return [ AccessList( @@ -204,7 +211,8 @@ def tx_data(timestamp: int) -> bytes: @pytest.fixture def tx_type() -> int: """ - Transaction type to call the caller contract or the beacon root contract directly. + Transaction type to call the caller contract or the beacon root contract + directly. By default use a type 2 transaction. """ @@ -263,8 +271,8 @@ def post( call_beacon_root_contract: bool, ) -> Dict: """ - Prepare expected post state for a single contract call based upon the success or - failure of the call, and the validity of the timestamp input. + Prepare expected post state for a single contract call based upon the + success or failure of the call, and the validity of the timestamp input. """ storage = Storage() if not call_beacon_root_contract: diff --git a/cancun/eip4788_beacon_root/test_beacon_root_contract.py b/cancun/eip4788_beacon_root/test_beacon_root_contract.py index 69db3d19ab..7ffb004920 100644 --- a/cancun/eip4788_beacon_root/test_beacon_root_contract.py +++ b/cancun/eip4788_beacon_root/test_beacon_root_contract.py @@ -1,21 +1,20 @@ """ -abstract: Tests beacon block root for [EIP-4788: Beacon block root in the EVM](https://eips.ethereum.org/EIPS/eip-4788) - Test the exposed beacon chain root in the EVM for [EIP-4788: Beacon block root in the EVM](https://eips.ethereum.org/EIPS/eip-4788). +Tests beacon block root for [EIP-4788: Beacon block root in the EVM](https://eips.ethereum.org/EIPS/eip-4788). -note: Adding a new test - Add a function that is named `test_` and takes at least the following arguments: +Note: To add a new test, add a function that is named `test_`. - - state_test - - env - - pre - - tx - - post - - valid_call +It must take at least the following arguments: - All other `pytest.fixtures` can be parametrized to generate new combinations and test - cases. +- `state_test` +- `env` +- `pre` +- `tx` +- `post` +- `valid_call` -""" # noqa: E501 +All other `pytest.fixtures` can be parametrized to generate new +combinations and test cases. +""" from itertools import count from typing import Callable, Dict, Iterator, List @@ -44,7 +43,10 @@ def count_factory(start: int, step: int = 1) -> Callable[[], Iterator[int]]: - """Create a factory that returns fresh count iterators to avoid state persistence.""" + """ + Create a factory that returns fresh count iterators to avoid state + persistence. + """ return lambda: count(start, step) @@ -80,7 +82,9 @@ def test_beacon_root_contract_calls( post: Dict, ): """ - Tests the beacon root contract call using various call contexts: + Test calling the beacon root contract in various call contexts. + + These call contexts are tested: - `CALL` - `DELEGATECALL` - `CALLCODE` @@ -90,10 +94,10 @@ def test_beacon_root_contract_calls( - extra gas (valid call) - insufficient gas (invalid call). - The expected result is that the contract call will be executed if the gas amount is met - and return the correct`parent_beacon_block_root`. Otherwise the call will be invalid, and not - be executed. This is highlighted within storage by storing the return value of each call - context. + The expected result is that the contract call will be executed if the gas + amount is met and return the correct`parent_beacon_block_root`. Otherwise + the call will be invalid, and not be executed. This is highlighted within + storage by storing the return value of each call context. """ blockchain_test( pre=pre, @@ -153,11 +157,12 @@ def test_beacon_root_contract_timestamps( post: Dict, ): """ - Tests the beacon root contract call across for various valid and invalid timestamps. + Tests the beacon root contract call across for various valid and invalid + timestamps. The expected result is that the contract call will return the correct - `parent_beacon_block_root` for a valid input timestamp and return the zero'd 32 bytes value - for an invalid input timestamp. + `parent_beacon_block_root` for a valid input timestamp and return the + zero'd 32 bytes value for an invalid input timestamp. """ blockchain_test( pre=pre, @@ -187,7 +192,9 @@ def test_calldata_lengths( tx: Transaction, post: Dict, ): - """Tests the beacon root contract call using multiple invalid input lengths.""" + """ + Tests the beacon root contract call using multiple invalid input lengths. + """ blockchain_test( pre=pre, blocks=[Block(txs=[tx], parent_beacon_block_root=beacon_root, timestamp=timestamp)], @@ -216,10 +223,11 @@ def test_beacon_root_equal_to_timestamp( post: Dict, ): """ - Tests the beacon root contract call where the beacon root is equal to the timestamp. + Tests the beacon root contract call where the beacon root is equal to the + timestamp. - The expected result is that the contract call will return the `parent_beacon_block_root`, - as all timestamps used are valid. + The expected result is that the contract call will return the + `parent_beacon_block_root`, as all timestamps used are valid. """ blockchain_test( pre=pre, @@ -240,7 +248,10 @@ def test_tx_to_beacon_root_contract( tx: Transaction, post: Dict, ): - """Tests the beacon root contract using a transaction with different types and data lengths.""" + """ + Tests the beacon root contract using a transaction with different types and + data lengths. + """ blockchain_test( pre=pre, blocks=[Block(txs=[tx], parent_beacon_block_root=beacon_root, timestamp=timestamp)], @@ -288,7 +299,10 @@ def test_beacon_root_selfdestruct( tx: Transaction, post: Dict, ): - """Tests that self destructing the beacon root address transfers actors balance correctly.""" + """ + Tests that self destructing the beacon root address transfers actors + balance correctly. + """ # self destruct actor self_destruct_actor_address = pre.deploy_contract( Op.SELFDESTRUCT(Spec.BEACON_ROOTS_ADDRESS), @@ -373,17 +387,20 @@ def test_multi_block_beacon_root_timestamp_calls( call_value: int, ): """ - Tests multiple blocks where each block writes a timestamp to storage and contains one - transaction that calls the beacon root contract multiple times. + Tests multiple blocks where each block writes a timestamp to storage and + contains one transaction that calls the beacon root contract multiple + times. - The blocks might overwrite the historical roots buffer, or not, depending on the `timestamps`, - and whether they increment in multiples of `Spec.HISTORY_BUFFER_LENGTH` or not. + The blocks might overwrite the historical roots buffer, or not, depending + on the `timestamps`, and whether they increment in multiples of + `Spec.HISTORY_BUFFER_LENGTH` or not. By default, the beacon roots are the keccak of the block number. - Each transaction checks the current timestamp and also all previous timestamps, and verifies - that the beacon root is correct for all of them if the timestamp is supposed to be in the - buffer, which might have been overwritten by a later block. + Each transaction checks the current timestamp and also all previous + timestamps, and verifies that the beacon root is correct for all of them if + the timestamp is supposed to be in the buffer, which might have been + overwritten by a later block. """ # Create fresh iterator to avoid state persistence between test phases timestamps = timestamps_factory() @@ -415,9 +432,9 @@ def test_multi_block_beacon_root_timestamp_calls( current_call_account_code = Bytecode() current_call_account_expected_storage = Storage() - # We are going to call the beacon roots contract once for every timestamp of the current - # and all previous blocks, and check that the returned beacon root is still correct only - # if it was not overwritten. + # We are going to call the beacon roots contract once for every + # timestamp of the current and all previous blocks, and check that the + # returned beacon root is still correct only if it was not overwritten. for t in all_timestamps: current_call_account_code += Op.MSTORE(0, t) call_valid = ( @@ -462,7 +479,8 @@ def test_multi_block_beacon_root_timestamp_calls( parent_beacon_block_root=beacon_root, timestamp=timestamp, withdrawals=[ - # Also withdraw to the beacon root contract and the system address + # Also withdraw to the beacon root contract and the system + # address Withdrawal( address=Spec.BEACON_ROOTS_ADDRESS, amount=1, @@ -503,8 +521,9 @@ def test_beacon_root_transition( fork: Fork, ): """ - Tests the fork transition to cancun and verifies that blocks with timestamp lower than the - transition timestamp do not contain beacon roots in the pre-deployed contract. + Tests the fork transition to cancun and verifies that blocks with timestamp + lower than the transition timestamp do not contain beacon roots in the + pre-deployed contract. """ # Create fresh iterator to avoid state persistence between test phases timestamps = timestamps_factory() @@ -527,7 +546,8 @@ def test_beacon_root_transition( transitioned = fork.header_beacon_root_required(i, timestamp) if transitioned: - # We've transitioned, the current timestamp must contain a value in the contract + # We've transitioned, the current timestamp must contain a value in + # the contract timestamps_in_beacon_root_contract.append(timestamp) timestamps_storage[timestamp_index] = timestamp roots_storage[timestamp_index] = beacon_root @@ -539,9 +559,10 @@ def test_beacon_root_transition( current_call_account_code = Bytecode() current_call_account_expected_storage = Storage() - # We are going to call the beacon roots contract once for every timestamp of the current - # and all previous blocks, and check that the returned beacon root is correct only - # if it was after the transition timestamp. + # We are going to call the beacon roots contract once for every + # timestamp of the current and all previous blocks, and check that the + # returned beacon root is correct only if it was after the transition + # timestamp. for t in all_timestamps: current_call_account_code += Op.MSTORE(0, t) call_valid = ( @@ -586,7 +607,8 @@ def test_beacon_root_transition( parent_beacon_block_root=beacon_root if transitioned else None, timestamp=timestamp, withdrawals=[ - # Also withdraw to the beacon root contract and the system address + # Also withdraw to the beacon root contract and the system + # address Withdrawal( address=Spec.BEACON_ROOTS_ADDRESS, amount=1, @@ -625,8 +647,8 @@ def test_no_beacon_root_contract_at_transition( fork: Fork, ): """ - Tests the fork transition to cancun in the case where the beacon root pre-deploy was not - deployed in time for the fork. + Tests the fork transition to cancun in the case where the beacon root + pre-deploy was not deployed in time for the fork. """ assert fork.header_beacon_root_required(1, timestamp) blocks: List[Block] = [ @@ -635,7 +657,8 @@ def test_no_beacon_root_contract_at_transition( parent_beacon_block_root=next(beacon_roots), timestamp=timestamp, withdrawals=[ - # Also withdraw to the beacon root contract and the system address + # Also withdraw to the beacon root contract and the system + # address Withdrawal( address=Spec.BEACON_ROOTS_ADDRESS, amount=1, @@ -652,7 +675,8 @@ def test_no_beacon_root_contract_at_transition( ) ] pre[Spec.BEACON_ROOTS_ADDRESS] = Account( - code=b"", # Remove the code that is automatically allocated on Cancun fork + code=b"", # Remove the code that is automatically allocated on Cancun + # fork nonce=0, balance=0, ) @@ -667,9 +691,8 @@ def test_no_beacon_root_contract_at_transition( balance=int(1e9), ), caller_address: Account( - storage={ - 0: 1 - }, # Successful call because the contract is not there, but nothing else is stored + storage={0: 1}, # Successful call because the contract is not there, but + # nothing else is stored ), } blockchain_test( @@ -704,8 +727,8 @@ def test_beacon_root_contract_deploy( fork: Fork, ): """ - Tests the fork transition to cancun deploying the contract during Shanghai and verifying the - code deployed and its functionality after Cancun. + Tests the fork transition to cancun deploying the contract during Shanghai + and verifying the code deployed and its functionality after Cancun. """ assert fork.header_beacon_root_required(1, timestamp) tx_gas_limit = 0x3D090 @@ -746,7 +769,8 @@ def test_beacon_root_contract_deploy( ), timestamp=timestamp // 2, withdrawals=[ - # Also withdraw to the beacon root contract and the system address + # Also withdraw to the beacon root contract and the + # system address Withdrawal( address=Spec.BEACON_ROOTS_ADDRESS, amount=1, @@ -773,7 +797,8 @@ def test_beacon_root_contract_deploy( parent_beacon_block_root=beacon_root, timestamp=timestamp, withdrawals=[ - # Also withdraw to the beacon root contract and the system address + # Also withdraw to the beacon root contract and the + # system address Withdrawal( address=Spec.BEACON_ROOTS_ADDRESS, amount=1, @@ -800,7 +825,8 @@ def test_beacon_root_contract_deploy( expected_code = fork.pre_allocation_blockchain()[Spec.BEACON_ROOTS_ADDRESS]["code"] pre[Spec.BEACON_ROOTS_ADDRESS] = Account( - code=b"", # Remove the code that is automatically allocated on Cancun fork + code=b"", # Remove the code that is automatically allocated on Cancun + # fork nonce=0, balance=0, ) diff --git a/cancun/eip4844_blobs/conftest.py b/cancun/eip4844_blobs/conftest.py index 2388a053c8..6da44f93c1 100644 --- a/cancun/eip4844_blobs/conftest.py +++ b/cancun/eip4844_blobs/conftest.py @@ -64,7 +64,9 @@ def parent_excess_blob_gas( parent_excess_blobs: int | None, blob_gas_per_blob: int, ) -> int | None: - """Calculate the excess blob gas of the parent block from the excess blobs.""" + """ + Calculate the excess blob gas of the parent block from the excess blobs. + """ if parent_excess_blobs is None: return None assert parent_excess_blobs >= 0 @@ -79,7 +81,8 @@ def excess_blob_gas( block_base_fee_per_gas: int, ) -> int | None: """ - Calculate the excess blob gas of the block under test from the parent block. + Calculate the excess blob gas of the block under test from the parent + block. Value can be overloaded by a test case to provide a custom excess blob gas. """ @@ -100,7 +103,8 @@ def correct_excess_blob_gas( block_base_fee_per_gas: int, ) -> int: """ - Calculate the correct excess blob gas of the block under test from the parent block. + Calculate the correct excess blob gas of the block under test from the + parent block. Should not be overloaded by a test case. """ @@ -160,7 +164,9 @@ def env( block_base_fee_per_gas: int, genesis_excess_blob_gas: int, ) -> Environment: - """Prepare the environment of the genesis block for all blockchain tests.""" + """ + Prepare the environment of the genesis block for all blockchain tests. + """ return Environment( excess_blob_gas=genesis_excess_blob_gas, blob_gas_used=0, @@ -213,7 +219,8 @@ def tx_max_priority_fee_per_gas() -> int: @pytest.fixture def tx_max_fee_per_blob_gas_multiplier() -> int: """ - Return default max fee per blob gas multiplier for transactions sent during test. + Return default max fee per blob gas multiplier for transactions sent during + test. Can be overloaded by a test case to provide a custom max fee per blob gas multiplier. @@ -224,7 +231,8 @@ def tx_max_fee_per_blob_gas_multiplier() -> int: @pytest.fixture def tx_max_fee_per_blob_gas_delta() -> int: """ - Return default max fee per blob gas delta for transactions sent during test. + Return default max fee per blob gas delta for transactions sent during + test. Can be overloaded by a test case to provide a custom max fee per blob gas delta. @@ -263,22 +271,21 @@ def non_zero_blob_gas_used_genesis_block( block_base_fee_per_gas: int, ) -> Block | None: """ - For test cases with a non-zero blobGasUsed field in the - original genesis block header we must instead utilize an - intermediate block to act on its behalf. - - Genesis blocks with a non-zero blobGasUsed field are invalid as - they do not have any blob txs. - - For the intermediate block to align with default genesis values, - we must add TARGET_BLOB_GAS_PER_BLOCK to the excessBlobGas of the - genesis value, expecting an appropriate drop to the intermediate block. - Similarly, we must add parent_blobs to the intermediate block within - a blob tx such that an equivalent blobGasUsed field is wrote. - - For forks >= Osaka where the MAX_BLOBS_PER_TX is introduced, we - split the blobs across multiple transactions to respect the - MAX_BLOBS_PER_TX limit. + For test cases with a non-zero blobGasUsed field in the original genesis + block header we must instead utilize an intermediate block to act on its + behalf. + + Genesis blocks with a non-zero blobGasUsed field are invalid as they do not + have any blob txs. + + For the intermediate block to align with default genesis values, we must + add TARGET_BLOB_GAS_PER_BLOCK to the excessBlobGas of the genesis value, + expecting an appropriate drop to the intermediate block. Similarly, we must + add parent_blobs to the intermediate block within a blob tx such that an + equivalent blobGasUsed field is wrote. + + For forks >= Osaka where the MAX_BLOBS_PER_TX is introduced, we split the + blobs across multiple transactions to respect the MAX_BLOBS_PER_TX limit. """ if parent_blobs == 0: return None @@ -300,9 +307,10 @@ def non_zero_blob_gas_used_genesis_block( empty_account_destination = pre.fund_eoa(0) blob_gas_price_calculator = fork.blob_gas_price_calculator(block_number=1) - # Split blobs into chunks when MAX_BLOBS_PER_TX < MAX_BLOBS_PER_BLOCK to respect per-tx limits. - # Allows us to keep single txs for forks where per-tx and per-block limits are equal, hitting - # coverage for block level blob gas validation when parent_blobs > MAX_BLOBS_PER_BLOCK. + # Split blobs into chunks when MAX_BLOBS_PER_TX < MAX_BLOBS_PER_BLOCK to + # respect per-tx limits. Allows us to keep single txs for forks where per- + # tx and per-block limits are equal, hitting coverage for block level blob + # gas validation when parent_blobs > MAX_BLOBS_PER_BLOCK. max_blobs_per_tx = ( fork.max_blobs_per_tx() if fork.max_blobs_per_tx() < fork.max_blobs_per_block() diff --git a/cancun/eip4844_blobs/spec.py b/cancun/eip4844_blobs/spec.py index 5eb5a29a7e..a531fb81ac 100644 --- a/cancun/eip4844_blobs/spec.py +++ b/cancun/eip4844_blobs/spec.py @@ -87,8 +87,8 @@ def get_min_excess_blob_gas_for_blob_gas_price( blob_gas_price: int, ) -> int: """ - Get the minimum required excess blob gas value to get a given blob gas cost in a - block. + Get the minimum required excess blob gas value to get a given blob gas + cost in a block. """ current_excess_blob_gas = 0 current_blob_gas_price = 1 @@ -106,7 +106,10 @@ def get_min_excess_blobs_for_blob_gas_price( fork: Fork, blob_gas_price: int, ) -> int: - """Get the minimum required excess blobs to get a given blob gas cost in a block.""" + """ + Get the minimum required excess blobs to get a given blob gas cost in a + block. + """ gas_per_blob = fork.blob_gas_per_blob() return ( cls.get_min_excess_blob_gas_for_blob_gas_price( @@ -122,23 +125,27 @@ def get_blob_combinations( blob_count: int, max_blobs_per_tx: int, ) -> List[Tuple[int, ...]]: - """Get all possible combinations of blobs that result in a given blob count.""" + """ + Get all possible combinations of blobs that result in a given blob + count. + """ combinations = [ seq for i in range( blob_count + 1, 0, -1 - ) # We can have from 1 to at most MAX_BLOBS_PER_BLOCK blobs per block + ) # We can have from 1 to at most MAX_BLOBS_PER_BLOCK blobs per + # block for seq in itertools.combinations_with_replacement( range(1, min(blob_count + 1, max_blobs_per_tx) + 1), i ) # We iterate through all possible combinations - if sum(seq) - == blob_count # And we only keep the ones that match the expected blob count - and all(tx_blobs <= max_blobs_per_tx for tx_blobs in seq) # Validate each tx + # And we only keep the ones that match the expected blob count + if sum(seq) == blob_count and all(tx_blobs <= max_blobs_per_tx for tx_blobs in seq) + # Validate each tx ] - # We also add the reversed version of each combination, only if it's not - # already in the list. E.g. (4, 1) is added from (1, 4) but not - # (1, 1, 1, 1, 1) because its reversed version is identical. + # We also add the reversed version of each combination, only if it's + # not already in the list. E.g. (4, 1) is added from (1, 4) but not (1, + # 1, 1, 1, 1) because its reversed version is identical. combinations += [ tuple(reversed(x)) for x in combinations if tuple(reversed(x)) not in combinations ] @@ -147,8 +154,8 @@ def get_blob_combinations( @classmethod def all_valid_blob_combinations(cls, fork: Fork) -> List[Tuple[int, ...]]: """ - Return all valid blob tx combinations for a given block, - assuming the given MAX_BLOBS_PER_BLOCK, whilst respecting MAX_BLOBS_PER_TX. + Return all valid blob tx combinations for a given block, assuming the + given MAX_BLOBS_PER_BLOCK, whilst respecting MAX_BLOBS_PER_TX. """ max_blobs_per_block = fork.max_blobs_per_block() max_blobs_per_tx = fork.max_blobs_per_tx() diff --git a/cancun/eip4844_blobs/test_blob_txs.py b/cancun/eip4844_blobs/test_blob_txs.py index 166fb5ced4..b242595ef6 100644 --- a/cancun/eip4844_blobs/test_blob_txs.py +++ b/cancun/eip4844_blobs/test_blob_txs.py @@ -1,19 +1,18 @@ """ -abstract: Tests blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) - Test blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). +Tests blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). +Note: To add a new test, add a function that is named `test_`. -note: Adding a new test - Add a function that is named `test_` and takes at least the following arguments: +It must at least use the following arguments: - - blockchain_test or state_test - - pre - - env - - block or txs +- `blockchain_test` or `state_test` +- `pre` +- `env` +- `block` or `txs`. - All other `pytest.fixture` fixtures can be parametrized to generate new combinations and test cases. - -""" # noqa: E501 +All other `pytest.fixture` fixtures can be parametrized to generate new +combinations and test cases. +""" from typing import List, Optional, Tuple @@ -126,8 +125,8 @@ def total_account_minimum_balance( # noqa: D103 blob_hashes_per_tx: List[List[bytes]], ) -> int: """ - Calculate minimum balance required for the account to be able to send - the transactions in the block of the test. + Calculate minimum balance required for the account to be able to send the + transactions in the block of the test. """ minimum_cost = 0 for tx_blob_count in [len(x) for x in blob_hashes_per_tx]: @@ -147,7 +146,9 @@ def total_account_transactions_fee( # noqa: D103 tx_max_priority_fee_per_gas: int, blob_hashes_per_tx: List[List[bytes]], ) -> int: - """Calculate actual fee for the blob transactions in the block of the test.""" + """ + Calculate actual fee for the blob transactions in the block of the test. + """ total_cost = 0 for tx_blob_count in [len(x) for x in blob_hashes_per_tx]: blob_cost = blob_gas_price * blob_gas_per_blob * tx_blob_count @@ -175,8 +176,8 @@ def tx_error() -> Optional[TransactionException]: """ Error produced by the block transactions (no error). - Can be overloaded on test cases where the transactions are expected - to fail. + Can be overloaded on test cases where the transactions are expected to + fail. """ return None @@ -230,8 +231,8 @@ def txs( # noqa: D103 @pytest.fixture def account_balance_modifier() -> int: """ - Account balance modifier for the source account of all tests. - See `pre` fixture. + Account balance modifier for the source account of all tests. See `pre` + fixture. """ return 0 @@ -243,9 +244,9 @@ def state_env( """ Prepare the environment for all state test cases. - Main difference is that the excess blob gas is not increased by the target, as - there is no genesis block -> block 1 transition, and therefore the excess blob gas - is not decreased by the target. + Main difference is that the excess blob gas is not increased by the target, + as there is no genesis block -> block 1 transition, and therefore the + excess blob gas is not decreased by the target. """ return Environment( excess_blob_gas=excess_blob_gas if excess_blob_gas else 0, @@ -255,8 +256,8 @@ def state_env( @pytest.fixture def engine_api_error_code() -> Optional[EngineAPIError]: """ - Engine API error code to be returned by the client on consumption - of the erroneous block in hive. + Engine API error code to be returned by the client on consumption of the + erroneous block in hive. """ return None @@ -268,8 +269,8 @@ def block_error( """ Error produced by the block transactions (no error). - Can be overloaded on test cases where the transactions are expected - to fail. + Can be overloaded on test cases where the transactions are expected to + fail. """ return tx_error @@ -385,15 +386,16 @@ def test_valid_blob_tx_combinations( block: Block, ): """ - Test all valid blob combinations in a single block, assuming a given value of - `MAX_BLOBS_PER_BLOCK`. + Test all valid blob combinations in a single block, assuming a given value + of `MAX_BLOBS_PER_BLOCK`. - This assumes a block can include from 1 and up to `MAX_BLOBS_PER_BLOCK` transactions where all - transactions contain at least 1 blob, and the sum of all blobs in a block is at - most `MAX_BLOBS_PER_BLOCK`. + This assumes a block can include from 1 and up to `MAX_BLOBS_PER_BLOCK` + transactions where all transactions contain at least 1 blob, and the sum of + all blobs in a block is at most `MAX_BLOBS_PER_BLOCK`. - This test is parametrized with all valid blob transaction combinations for a given block, and - therefore if value of `MAX_BLOBS_PER_BLOCK` changes, this test is automatically updated. + This test is parametrized with all valid blob transaction combinations for + a given block, and therefore if value of `MAX_BLOBS_PER_BLOCK` changes, + this test is automatically updated. """ blockchain_test( pre=pre, @@ -407,8 +409,8 @@ def generate_invalid_tx_max_fee_per_blob_gas_tests( fork: Fork, ) -> List: """ - Return a list of tests for invalid blob transactions due to insufficient max fee per blob gas - parametrized for each different fork. + Return a list of tests for invalid blob transactions due to insufficient + max fee per blob gas parametrized for each different fork. """ min_base_fee_per_blob_gas = fork.min_base_fee_per_blob_gas() minimum_excess_blobs_for_first_increment = SpecHelpers.get_min_excess_blobs_for_blob_gas_price( @@ -422,9 +424,12 @@ def generate_invalid_tx_max_fee_per_blob_gas_tests( tests = [] tests.append( pytest.param( - minimum_excess_blobs_for_first_increment - 1, # blob gas price is 1 - fork.target_blobs_per_block() + 1, # blob gas cost increases to above the minimum - min_base_fee_per_blob_gas, # tx max_blob_gas_cost is the minimum + # blob gas price is 1 + minimum_excess_blobs_for_first_increment - 1, + # blob gas cost increases to above the minimum + fork.target_blobs_per_block() + 1, + # tx max_blob_gas_cost is the minimum + min_base_fee_per_blob_gas, TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS, id="insufficient_max_fee_per_blob_gas", marks=pytest.mark.exception_test, @@ -433,11 +438,12 @@ def generate_invalid_tx_max_fee_per_blob_gas_tests( if (next_base_fee_per_blob_gas - min_base_fee_per_blob_gas) > 1: tests.append( pytest.param( - minimum_excess_blobs_for_first_increment - - 1, # blob gas price is one less than the minimum - fork.target_blobs_per_block() + 1, # blob gas cost increases to above the minimum - next_base_fee_per_blob_gas - - 1, # tx max_blob_gas_cost is one less than the minimum + # blob gas price is one less than the minimum + minimum_excess_blobs_for_first_increment - 1, + # blob gas cost increases to above the minimum + fork.target_blobs_per_block() + 1, + # tx max_blob_gas_cost is one less than the minimum + next_base_fee_per_blob_gas - 1, TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS, id="insufficient_max_fee_per_blob_gas_one_less_than_next", marks=pytest.mark.exception_test, @@ -448,7 +454,8 @@ def generate_invalid_tx_max_fee_per_blob_gas_tests( pytest.param( 0, # blob gas price is the minimum 0, # blob gas cost stays put at 1 - min_base_fee_per_blob_gas - 1, # tx max_blob_gas_cost is one less than the minimum + # tx max_blob_gas_cost is one less than the minimum + min_base_fee_per_blob_gas - 1, TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS, id="insufficient_max_fee_per_blob_gas_one_less_than_min", marks=pytest.mark.exception_test, @@ -589,12 +596,12 @@ def test_invalid_block_blob_count( block: Block, ): """ - Test all invalid blob combinations in a single block, where the sum of all blobs in a block is - at `MAX_BLOBS_PER_BLOCK + 1`. + Test all invalid blob combinations in a single block, where the sum of all + blobs in a block is at `MAX_BLOBS_PER_BLOCK + 1`. This test is parametrized with all blob transaction combinations exceeding - `MAX_BLOBS_PER_BLOCK` by one for a given block, and - therefore if value of `MAX_BLOBS_PER_BLOCK` changes, this test is automatically updated. + `MAX_BLOBS_PER_BLOCK` by one for a given block, and therefore if value of + `MAX_BLOBS_PER_BLOCK` changes, this test is automatically updated. """ blockchain_test( pre=pre, @@ -636,7 +643,8 @@ def test_insufficient_balance_blob_tx( - Transactions with and without priority fee - Transactions with and without value - Transactions with and without calldata - - Transactions with max fee per blob gas lower or higher than the priority fee + - Transactions with max fee per blob gas lower or higher than the priority + fee """ assert len(txs) == 1 state_test( @@ -677,14 +685,15 @@ def test_sufficient_balance_blob_tx( txs: List[Transaction], ): """ - Check that transaction is accepted when user can exactly afford the blob gas specified (and - max_fee_per_gas would be enough for current block). + Check that transaction is accepted when user can exactly afford the blob + gas specified (and max_fee_per_gas would be enough for current block). - Transactions with max fee equal or higher than current block base fee - Transactions with and without priority fee - Transactions with and without value - Transactions with and without calldata - - Transactions with max fee per blob gas lower or higher than the priority fee + - Transactions with max fee per blob gas lower or higher than the priority + fee """ assert len(txs) == 1 state_test( @@ -728,15 +737,16 @@ def test_sufficient_balance_blob_tx_pre_fund_tx( header_verify: Optional[Header], ): """ - Check that transaction is accepted when user can exactly afford the blob gas specified (and - max_fee_per_gas would be enough for current block) because a funding transaction is - prepended in the same block. + Check that transaction is accepted when user can exactly afford the blob + gas specified (and max_fee_per_gas would be enough for current block) + because a funding transaction is prepended in the same block. - Transactions with max fee equal or higher than current block base fee - Transactions with and without priority fee - Transactions with and without value - Transactions with and without calldata - - Transactions with max fee per blob gas lower or higher than the priority fee + - Transactions with max fee per blob gas lower or higher than the priority + fee """ pre_funding_sender = pre.fund_eoa(amount=(21_000 * 100) + total_account_minimum_balance) txs = [ @@ -808,14 +818,16 @@ def test_blob_gas_subtraction_tx( total_account_transactions_fee: int, ): """ - Check that the blob gas fee for a transaction is subtracted from the sender balance before the - transaction is executed. + Check that the blob gas fee for a transaction is subtracted from the sender + balance before the transaction is executed. - Transactions with max fee equal or higher than current block base fee - Transactions with and without value - Transactions with and without calldata - - Transactions with max fee per blob gas lower or higher than the priority fee - - Transactions where an externally owned account sends funds to the sender mid execution + - Transactions with max fee per blob gas lower or higher than the priority + fee + - Transactions where an externally owned account sends funds to the sender + mid execution """ assert len(txs) == 1 post = { @@ -851,10 +863,11 @@ def test_insufficient_balance_blob_tx_combinations( block: Block, ): """ - Reject all valid blob transaction combinations in a block, but block is invalid. + Reject all valid blob transaction combinations in a block, but block is + invalid. - - The amount of blobs is correct but the user cannot afford the - transaction total cost + - The amount of blobs is correct but the user cannot afford the transaction + total cost """ blockchain_test( pre=pre, @@ -867,7 +880,10 @@ def test_insufficient_balance_blob_tx_combinations( def generate_invalid_tx_blob_count_tests( fork: Fork, ) -> List: - """Return a list of tests for invalid blob transactions due to invalid blob counts.""" + """ + Return a list of tests for invalid blob transactions due to invalid blob + counts. + """ return [ pytest.param( [0], @@ -1007,7 +1023,8 @@ def test_invalid_blob_hash_versioning_multiple_txs( - Multiple blob transactions with single blob all with invalid version - Multiple blob transactions with multiple blobs all with invalid version - - Multiple blob transactions with multiple blobs only one with invalid version + - Multiple blob transactions with multiple blobs only one with invalid + version """ blockchain_test( pre=pre, @@ -1029,10 +1046,14 @@ def test_invalid_blob_tx_contract_creation( txs: List[Transaction], header_verify: Optional[Header], ): - """Reject blocks that include blob transactions that have nil to value (contract creating).""" + """ + Reject blocks that include blob transactions that have nil to value + (contract creating). + """ assert len(txs) == 1 assert txs[0].blob_versioned_hashes is not None and len(txs[0].blob_versioned_hashes) == 1 - # Replace the transaction with a contract creating one, only in the RLP version + # Replace the transaction with a contract creating one, only in the RLP + # version contract_creating_tx = txs[0].copy(to=None).with_signature_and_sender() txs[0].rlp_override = contract_creating_tx.rlp() blockchain_test( @@ -1047,8 +1068,8 @@ def test_invalid_blob_tx_contract_creation( ], header_verify=header_verify, # Skipped due to the T8N not receiving the invalid transaction, - # instead we are passing a valid transaction to T8N and then the transaction - # is replaced directly in the block RLP. + # instead we are passing a valid transaction to T8N and then + # the transaction is replaced directly in the block RLP. skip_exception_verification=True, ) ], @@ -1071,7 +1092,10 @@ def opcode( tx_max_priority_fee_per_gas: int, tx_value: int, ) -> Tuple[Bytecode, Storage.StorageDictType]: - """Build bytecode and post to test each opcode that accesses transaction information.""" + """ + Build bytecode and post to test each opcode that accesses transaction + information. + """ if request.param == Op.ORIGIN: return ( Op.SSTORE(0, Op.ORIGIN), @@ -1137,7 +1161,8 @@ def test_blob_tx_attribute_opcodes( state_env: Environment, ): """ - Test opcodes that read transaction attributes work properly for blob type transactions. + Test opcodes that read transaction attributes work properly for blob type + transactions. - ORIGIN - CALLER @@ -1189,7 +1214,9 @@ def test_blob_tx_attribute_value_opcode( opcode: Tuple[Bytecode, Storage.StorageDictType], state_env: Environment, ): - """Test the VALUE opcode with different blob type transaction value amounts.""" + """ + Test the VALUE opcode with different blob type transaction value amounts. + """ code, storage = opcode destination_account = pre.deploy_contract(code=code) tx = Transaction( @@ -1255,7 +1282,8 @@ def test_blob_tx_attribute_calldata_opcodes( state_env: Environment, ): """ - Test calldata related opcodes to verify their behavior is not affected by blobs. + Test calldata related opcodes to verify their behavior is not affected by + blobs. - CALLDATALOAD - CALLDATASIZE @@ -1289,9 +1317,12 @@ def test_blob_tx_attribute_calldata_opcodes( ) -@pytest.mark.parametrize("tx_max_priority_fee_per_gas", [0, 2]) # always below data fee -@pytest.mark.parametrize("tx_max_fee_per_blob_gas_delta", [0, 1]) # normal and above priority fee -@pytest.mark.parametrize("tx_max_fee_per_gas", [100]) # always above priority fee (FOR CANCUN) +# always below data fee: +@pytest.mark.parametrize("tx_max_priority_fee_per_gas", [0, 2]) +# normal and above priority fee: +@pytest.mark.parametrize("tx_max_fee_per_blob_gas_delta", [0, 1]) +# always above priority fee (FOR CANCUN) +@pytest.mark.parametrize("tx_max_fee_per_gas", [100]) @pytest.mark.parametrize("opcode", [Op.GASPRICE], indirect=True) @pytest.mark.parametrize("tx_gas", [500_000]) @pytest.mark.valid_from("Cancun") @@ -1311,7 +1342,8 @@ def test_blob_tx_attribute_gasprice_opcode( state_env: Environment, ): """ - Test GASPRICE opcode to sanity check that the blob gas fee does not affect its calculation. + Test GASPRICE opcode to sanity check that the blob gas fee does not affect + its calculation. - No priority fee - Priority fee below data fee @@ -1382,8 +1414,9 @@ def test_blob_type_tx_pre_fork( """ Reject blocks with blob type transactions before Cancun fork. - Blocks sent by NewPayloadV2 (Shanghai) that contain blob type transactions, furthermore blobs - field within NewPayloadV2 method must be computed as INVALID, due to an invalid block hash. + Blocks sent by NewPayloadV2 (Shanghai) that contain blob type transactions, + furthermore blobs field within NewPayloadV2 method must be computed as + INVALID, due to an invalid block hash. """ assert len(txs) == 1 state_test( diff --git a/cancun/eip4844_blobs/test_blob_txs_full.py b/cancun/eip4844_blobs/test_blob_txs_full.py index ba6c091a70..d71b81f22c 100644 --- a/cancun/eip4844_blobs/test_blob_txs_full.py +++ b/cancun/eip4844_blobs/test_blob_txs_full.py @@ -1,8 +1,4 @@ -""" -abstract: Tests full blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) - Test full blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). - -""" # noqa: E501 +"""Tests full blob type transactions for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844).""" from typing import List, Optional @@ -135,10 +131,10 @@ def tx_max_fee_per_blob_gas( # noqa: D103 @pytest.fixture def tx_error() -> Optional[TransactionException]: """ - Even though the final block we are producing in each of these tests is invalid, and some of the - transactions will be invalid due to the format in the final block, none of the transactions - should be rejected by the transition tool because they are being sent to it with the correct - format. + Even though the final block we are producing in each of these tests is + invalid, and some of the transactions will be invalid due to the format in + the final block, none of the transactions should be rejected by the + transition tool because they are being sent to it with the correct format. """ return None @@ -214,8 +210,8 @@ def blocks( header_blob_gas_used = 0 block_error = None if any(txs_wrapped_blobs): - # This is a block exception because the invalid block is only created in the RLP version, - # not in the transition tool. + # This is a block exception because the invalid block is only created + # in the RLP version, not in the transition tool. block_error = [ BlockException.RLP_STRUCTURES_ENCODING, TransactionException.TYPE_3_TX_WITH_FULL_BLOBS, @@ -289,8 +285,8 @@ def test_reject_valid_full_blob_in_block_rlp( blocks: List[Block], ): """ - Test valid blob combinations where one or more txs in the block - serialized version contain a full blob (network version) tx. + Test valid blob combinations where one or more txs in the block serialized + version contain a full blob (network version) tx. """ blockchain_test( pre=pre, diff --git a/cancun/eip4844_blobs/test_blobhash_opcode.py b/cancun/eip4844_blobs/test_blobhash_opcode.py index b22883be03..c265bd0214 100644 --- a/cancun/eip4844_blobs/test_blobhash_opcode.py +++ b/cancun/eip4844_blobs/test_blobhash_opcode.py @@ -1,21 +1,21 @@ """ -abstract: Tests `BLOBHASH` opcode in [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) - Test cases for the `BLOBHASH` opcode in - [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). +Tests `BLOBHASH` opcode in [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). -note: Adding a new test - Add a function that is named `test_` and takes at least the following arguments: +Note: Adding a new test Add a function that is named `test_` and +takes at least the following arguments. - - blockchain_test - - pre - - tx - - post +Required arguments: +- `blockchain_test` +- `pre` +- `tx` +- `post` - Additional custom `pytest.fixture` fixtures can be added and parametrized for new test cases. +Additional custom `pytest.fixture` fixtures can be added and parametrized +for +new test cases. - There is no specific structure to follow within this test module. - -""" # noqa: E501 +There is no specific structure to follow within this test module. +""" from typing import List @@ -81,11 +81,10 @@ class BlobhashScenario: @staticmethod def create_blob_hashes_list(length: int, max_blobs_per_tx: int) -> List[List[Hash]]: """ - Create list of MAX_BLOBS_PER_TX blob hashes - using `random_blob_hashes`. + Create list of MAX_BLOBS_PER_TX blob hashes using `random_blob_hashes`. - Cycle over random_blob_hashes to get a large list of - length: MAX_BLOBS_PER_TX * length + Cycle over random_blob_hashes to get a large list of length: + MAX_BLOBS_PER_TX * length -> [0x01, 0x02, 0x03, 0x04, ..., 0x0A, 0x0B, 0x0C, 0x0D] Then split list into smaller chunks of MAX_BLOBS_PER_TX @@ -104,9 +103,8 @@ def blobhash_sstore(index: int, max_blobs_per_tx: int): """ Return BLOBHASH sstore to the given index. - If the index is out of the valid bounds, 0x01 is written - in storage, as we later check it is overwritten by - the BLOBHASH sstore. + If the index is out of the valid bounds, 0x01 is written in storage, as + we later check it is overwritten by the BLOBHASH sstore. """ invalidity_check = Op.SSTORE(index, 0x01) if index < 0 or index >= max_blobs_per_tx: @@ -158,9 +156,9 @@ def test_blobhash_gas_cost( """ Tests `BLOBHASH` opcode gas cost using a variety of indexes. - Asserts that the gas consumption of the `BLOBHASH` opcode is correct by ensuring - it matches `HASH_OPCODE_GAS = 3`. Includes both valid and invalid random - index sizes from the range `[0, 2**256-1]`, for tx types 2 and 3. + Asserts that the gas consumption of the `BLOBHASH` opcode is correct by + ensuring it matches `HASH_OPCODE_GAS = 3`. Includes both valid and invalid + random index sizes from the range `[0, 2**256-1]`, for tx types 2 and 3. """ gas_measure_code = CodeGasMeasure( code=Op.BLOBHASH(blobhash_index), @@ -279,11 +277,11 @@ def test_blobhash_invalid_blob_index( max_blobs_per_tx: int, ): """ - Tests that the `BLOBHASH` opcode returns a zeroed `bytes32` value for invalid - indexes. + Tests that the `BLOBHASH` opcode returns a zeroed `bytes32` value for + invalid indexes. - Includes cases where the index is negative (`index < 0`) or - exceeds the maximum number of `blob_versioned_hash` values stored: + Includes cases where the index is negative (`index < 0`) or exceeds the + maximum number of `blob_versioned_hash` values stored: (`index >= len(tx.message.blob_versioned_hashes)`). It confirms that the returned value is a zeroed `bytes32` for each case. diff --git a/cancun/eip4844_blobs/test_blobhash_opcode_contexts.py b/cancun/eip4844_blobs/test_blobhash_opcode_contexts.py index b3ca64fd9c..41d85d2b25 100644 --- a/cancun/eip4844_blobs/test_blobhash_opcode_contexts.py +++ b/cancun/eip4844_blobs/test_blobhash_opcode_contexts.py @@ -1,9 +1,6 @@ """ -abstract: Tests `BLOBHASH` opcode in [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) - Test case for `BLOBHASH` opcode calls across different contexts - in [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). - -""" # noqa: E501 +Tests `BLOBHASH` opcode in [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). +""" from enum import Enum from typing import Iterable, List @@ -34,8 +31,8 @@ class BlobhashContext(Enum): """ - A utility class for mapping common EVM opcodes in different contexts - to specific bytecode (with BLOBHASH), addresses and contracts. + A utility class for mapping common EVM opcodes in different contexts to + specific bytecode (with BLOBHASH), addresses and contracts. """ BLOBHASH_SSTORE = "blobhash_sstore" @@ -52,9 +49,7 @@ def code(self, *, indexes=Iterable[int]): """ Map opcode context to bytecode that utilizes the BLOBHASH opcode. - Args: - indexes: The indexes to request using the BLOBHASH opcode - + Args: indexes: The indexes to request using the BLOBHASH opcode """ match self: case BlobhashContext.BLOBHASH_SSTORE: @@ -82,8 +77,8 @@ def deploy_contract( Deploy a contract with the given context and indexes. Args: - pre: The pre state to deploy the contract on - indexes: The indexes to request using the BLOBHASH opcode + pre: The pre state to deploy the contract on + indexes: The indexes to request using the BLOBHASH opcode """ match self: @@ -147,7 +142,9 @@ def deploy_contract( def simple_blob_hashes( max_blobs_per_tx: int, ) -> List[Hash]: - """Return a simple list of blob versioned hashes ranging from bytes32(1 to 4).""" + """ + Return a simple list of blob versioned hashes ranging from bytes32(1 to 4). + """ return add_kzg_version( [(1 << x) for x in range(max_blobs_per_tx)], Spec.BLOB_COMMITMENT_VERSION_KZG, @@ -177,11 +174,13 @@ def test_blobhash_opcode_contexts( state_test: StateTestFiller, ): """ - Tests that the `BLOBHASH` opcode functions correctly when called in different contexts. + Tests that the `BLOBHASH` opcode functions correctly when called in + different contexts. - `BLOBHASH` opcode on the top level of the call stack. - `BLOBHASH` opcode on the max value. - - `BLOBHASH` opcode on `CALL`, `DELEGATECALL`, `STATICCALL`, and `CALLCODE`. + - `BLOBHASH` opcode on `CALL`, `DELEGATECALL`, `STATICCALL`, and + `CALLCODE`. - `BLOBHASH` opcode on Initcode. - `BLOBHASH` opcode on `CREATE` and `CREATE2`. - `BLOBHASH` opcode on transaction types 0, 1 and 2. @@ -292,11 +291,13 @@ def test_blobhash_opcode_contexts_tx_types( state_test: StateTestFiller, ): """ - Tests that the `BLOBHASH` opcode functions correctly when called in different contexts. + Tests that the `BLOBHASH` opcode functions correctly when called in + different contexts. - `BLOBHASH` opcode on the top level of the call stack. - `BLOBHASH` opcode on the max value. - - `BLOBHASH` opcode on `CALL`, `DELEGATECALL`, `STATICCALL`, and `CALLCODE`. + - `BLOBHASH` opcode on `CALL`, `DELEGATECALL`, `STATICCALL`, and + `CALLCODE`. - `BLOBHASH` opcode on Initcode. - `BLOBHASH` opcode on `CREATE` and `CREATE2`. - `BLOBHASH` opcode on transaction types 0, 1 and 2. diff --git a/cancun/eip4844_blobs/test_excess_blob_gas.py b/cancun/eip4844_blobs/test_excess_blob_gas.py index b25ebc0dc0..298460ce7d 100644 --- a/cancun/eip4844_blobs/test_excess_blob_gas.py +++ b/cancun/eip4844_blobs/test_excess_blob_gas.py @@ -1,25 +1,29 @@ """ -abstract: Tests `excessBlobGas` and `blobGasUsed` block fields for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) - Test `excessBlobGas` and `blobGasUsed` block fields for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). - -note: Adding a new test - Add a function that is named `test_` and takes at least the following arguments: - - - blockchain_test - - env - - pre - - blocks - - post - - correct_excess_blob_gas - - The following arguments can be parametrized to generate new combinations and test cases: - - - new_blobs: Number of blobs in the block (automatically split across transactions as needed) - - All other `pytest.fixture` fixtures can be parametrized to generate new combinations and test - cases. - -""" # noqa: E501 +Tests `excessBlobGas` and `blobGasUsed` block fields for EIP-4844. + +Tests `excessBlobGas` and `blobGasUsed` block fields for +[EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) +Note: Adding a new test Add a function that is named `test_` and +takes at least the following arguments. + +Required arguments: +- `blockchain_test` +- `env` +- `pre` +- `blocks` +- `post` +- `correct_excess_blob_gas` + +The following arguments can be parametrized to generate new combinations +and +test cases: + +- new_blobs: Number of blobs in the block (automatically split across +transactions as needed) + +All other `pytest.fixture` fixtures can be parametrized to generate new +combinations and test cases. +""" import itertools from typing import Callable, Dict, Iterator, List, Mapping, Optional, Tuple @@ -55,7 +59,9 @@ @pytest.fixture def parent_excess_blobs(fork: Fork) -> int: # noqa: D103 - """By default we start with an intermediate value between the target and max.""" + """ + By default we start with an intermediate value between the target and max. + """ return (fork.max_blobs_per_block() + fork.target_blobs_per_block()) // 2 + 1 @@ -304,12 +310,14 @@ def test_correct_excess_blob_gas_calculation( correct_excess_blob_gas: int, ): """ - Test calculation of the `excessBlobGas` increase/decrease across - multiple blocks with and without blobs. + Test calculation of the `excessBlobGas` increase/decrease across multiple + blocks with and without blobs. - With parent block containing `[0, MAX_BLOBS_PER_BLOCK]` blobs - - With parent block containing `[0, TARGET_BLOBS_PER_BLOCK]` equivalent value of excess blob gas - """ # noqa: E501 + + - With parent block containing `[0, TARGET_BLOBS_PER_BLOCK]` equivalent + value of excess blob gas + """ blockchain_test( pre=pre, post=post, @@ -321,8 +329,8 @@ def test_correct_excess_blob_gas_calculation( def generate_blob_gas_cost_increases_tests(delta: int) -> Callable[[Fork], List[int]]: """ - Generate a list of block excess blob gas values where the blob gas price increases - based on fork properties. + Generate a list of block excess blob gas values where the blob gas price + increases based on fork properties. """ def generator_function(fork: Fork) -> List[int]: @@ -365,8 +373,8 @@ def test_correct_increasing_blob_gas_costs( correct_excess_blob_gas: int, ): """ - Test calculation of the `excessBlobGas` and blob gas tx costs at - value points where the cost increases to interesting amounts. + Test calculation of the `excessBlobGas` and blob gas tx costs at value + points where the cost increases to interesting amounts. - At the first blob gas cost increase (1 to 2) - At total transaction data cost increase to `> 2^32` @@ -402,8 +410,8 @@ def test_correct_decreasing_blob_gas_costs( correct_excess_blob_gas: int, ): """ - Test calculation of the `excessBlobGas` and blob gas tx costs at - value points where the cost decreases to interesting amounts. + Test calculation of the `excessBlobGas` and blob gas tx costs at value + points where the cost decreases to interesting amounts. See test_correct_increasing_blob_gas_costs. """ @@ -433,8 +441,8 @@ def test_invalid_zero_excess_blob_gas_in_header( ): """ Test rejection of blocks where the `excessBlobGas` in the header drops to - zero in a block with or without data blobs, but the excess blobs in the parent are - greater than target. + zero in a block with or without data blobs, but the excess blobs in the + parent are greater than target. """ if header_excess_blob_gas is None: raise Exception("test case is badly formatted") @@ -529,8 +537,10 @@ def test_invalid_excess_blob_gas_above_target_change( """ Test rejection of blocks where the `excessBlobGas`. - - decreases more than `TARGET_BLOB_GAS_PER_BLOCK` in a single block with zero blobs - - increases more than `TARGET_BLOB_GAS_PER_BLOCK` in a single block with max blobs + - decreases more than `TARGET_BLOB_GAS_PER_BLOCK` in a single block + with zero blobs. + - increases more than `TARGET_BLOB_GAS_PER_BLOCK` in a single block + with max blobs. """ if header_excess_blob_gas is None: raise Exception("test case is badly formatted") @@ -572,8 +582,8 @@ def test_invalid_static_excess_blob_gas( parent_excess_blob_gas: int, ): """ - Test rejection of blocks where the `excessBlobGas` remains unchanged - but the parent blobs included are not `TARGET_BLOBS_PER_BLOCK`. + Test rejection of blocks where the `excessBlobGas` remains unchanged but + the parent blobs included are not `TARGET_BLOBS_PER_BLOCK`. Test is parametrized to `MAX_BLOBS_PER_BLOCK` and `TARGET_BLOBS_PER_BLOCK`. """ @@ -659,7 +669,8 @@ def test_invalid_static_excess_blob_gas_from_zero_on_blobs_above_target( Test rejection of blocks where the `excessBlobGas` does not increase from zero, even when the included blobs is above target. - Test is parametrized to `[TARGET_BLOBS_PER_BLOCK+1, MAX_BLOBS_PER_BLOCK]` new blobs. + Test is parametrized to `[TARGET_BLOBS_PER_BLOCK+1, MAX_BLOBS_PER_BLOCK]` + new blobs. """ if header_excess_blob_gas is None: raise Exception("test case is badly formatted") @@ -708,9 +719,9 @@ def test_invalid_excess_blob_gas_change( Test rejection of blocks where the `excessBlobGas` changes to an invalid value. - Given a parent block containing `[0, MAX_BLOBS_PER_BLOCK]` blobs, test an invalid - `excessBlobGas` value by changing it by `[-TARGET_BLOBS_PER_BLOCK, TARGET_BLOBS_PER_BLOCK]` - from the correct value. + Given a parent block containing `[0, MAX_BLOBS_PER_BLOCK]` blobs, test an + invalid `excessBlobGas` value by changing it by `[-TARGET_BLOBS_PER_BLOCK, + TARGET_BLOBS_PER_BLOCK]` from the correct value. """ if header_excess_blob_gas is None: raise Exception("test case is badly formatted") @@ -760,8 +771,8 @@ def test_invalid_negative_excess_blob_gas( Test rejection of blocks where the `excessBlobGas` changes to the two's complement equivalent of the negative value after subtracting target blobs. - Reasoning is that the `excessBlobGas` is a `uint64`, so it cannot be negative, and - we test for a potential underflow here. + Reasoning is that the `excessBlobGas` is a `uint64`, so it cannot be + negative, and we test for a potential underflow here. """ if header_excess_blob_gas is None: raise Exception("test case is badly formatted") @@ -810,8 +821,10 @@ def test_invalid_non_multiple_excess_blob_gas( Test rejection of blocks where the `excessBlobGas` changes to a value that is not a multiple of Spec.GAS_PER_BLOB`. - - Parent block contains `TARGET_BLOBS_PER_BLOCK + 1` blobs, but `excessBlobGas` is off by +/-1 - - Parent block contains `TARGET_BLOBS_PER_BLOCK - 1` blobs, but `excessBlobGas` is off by +/-1 + - Parent block contains `TARGET_BLOBS_PER_BLOCK + 1` blobs, but + `excessBlobGas` is off by +/-1 + - Parent block contains `TARGET_BLOBS_PER_BLOCK - 1` blobs, but + `excessBlobGas` is off by +/-1 """ if header_excess_blob_gas is None: raise Exception("test case is badly formatted") diff --git a/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py b/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py index 1d11234da0..115a0569e0 100644 --- a/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py +++ b/cancun/eip4844_blobs/test_excess_blob_gas_fork_transition.py @@ -1,8 +1,8 @@ """ -abstract: Tests `excessBlobGas` and `blobGasUsed` block fields for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) at fork transition. - Test `excessBlobGas` and `blobGasUsed` block fields for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) at fork - transition. -""" # noqa: E501 +Test `excessBlobGas` & `blobGasUsed` block fields at fork transition. + +Tests for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). +""" from typing import List, Mapping @@ -49,8 +49,8 @@ def block_gas_limit(fork: Fork) -> int: # noqa: D103 @pytest.fixture def genesis_environment(block_gas_limit: int, block_base_fee_per_gas: int) -> Environment: """ - Genesis environment that enables existing transition tests to be used of BPO forks. - Compatible with all fork transitions. + Genesis environment that enables existing transition tests to be used of + BPO forks. Compatible with all fork transitions. """ return Environment( base_fee_per_gas=(block_base_fee_per_gas * BASE_FEE_MAX_CHANGE_DENOMINATOR) // 7, @@ -158,8 +158,8 @@ def pre_fork_excess_blobs( pre_fork_blocks: List[Block], ) -> int: """ - Return the cumulative excess blobs up until the fork given the pre_fork_blobs_per_block - and the target blobs in the fork prior. + Return the cumulative excess blobs up until the fork given the + pre_fork_blobs_per_block and the target blobs in the fork prior. """ if not fork.supports_blobs(timestamp=0): return 0 @@ -331,11 +331,12 @@ def test_invalid_pre_fork_block_with_blob_fields( blob_gas_used_present: bool, ): """ - Test block rejection when `excessBlobGas` and/or `blobGasUsed` fields are present on a pre-fork - block. + Test block rejection when `excessBlobGas` and/or `blobGasUsed` fields are + present on a pre-fork block. - Blocks sent by NewPayloadV2 (Shanghai) that contain `excessBlobGas` and `blobGasUsed` fields - must be rejected with the appropriate `EngineAPIError.InvalidParams` error error. + Blocks sent by NewPayloadV2 (Shanghai) that contain `excessBlobGas` and + `blobGasUsed` fields must be rejected with the appropriate + `EngineAPIError.InvalidParams` error error. """ header_modifier = Header( excess_blob_gas=0 if excess_blob_gas_present else None, @@ -376,11 +377,12 @@ def test_invalid_post_fork_block_without_blob_fields( blob_gas_used_missing: bool, ): """ - Test block rejection when `excessBlobGas` and/or `blobGasUsed` fields are missing on a - post-fork block. + Test block rejection when `excessBlobGas` and/or `blobGasUsed` fields are + missing on a post-fork block. - Blocks sent by NewPayloadV3 (Cancun) without `excessBlobGas` and `blobGasUsed` fields must be - rejected with the appropriate `EngineAPIError.InvalidParams` error. + Blocks sent by NewPayloadV3 (Cancun) without `excessBlobGas` and + `blobGasUsed` fields must be rejected with the appropriate + `EngineAPIError.InvalidParams` error. """ header_modifier = Header() if excess_blob_gas_missing: @@ -432,8 +434,8 @@ def test_fork_transition_excess_blob_gas_at_blob_genesis( """ Test `excessBlobGas` calculation in the header when the fork is activated. - Also produce enough blocks to test the blob gas price increase when the block is full with - `SpecHelpers.max_blobs_per_block()` blobs. + Also produce enough blocks to test the blob gas price increase when the + block is full with `SpecHelpers.max_blobs_per_block()` blobs. """ blockchain_test( pre=pre, @@ -499,7 +501,9 @@ def test_fork_transition_excess_blob_gas_post_blob_genesis( post_fork_blocks: List[Block], post: Mapping[Address, Account], ): - """Test `excessBlobGas` calculation in the header when the fork is activated.""" + """ + Test `excessBlobGas` calculation in the header when the fork is activated. + """ blockchain_test( pre=pre, post=post, diff --git a/cancun/eip4844_blobs/test_point_evaluation_precompile.py b/cancun/eip4844_blobs/test_point_evaluation_precompile.py index 44257dc67d..24562a11e2 100644 --- a/cancun/eip4844_blobs/test_point_evaluation_precompile.py +++ b/cancun/eip4844_blobs/test_point_evaluation_precompile.py @@ -1,31 +1,31 @@ """ -abstract: Tests point evaluation precompile for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) - Test point evaluation precompile for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). +Tests point evaluation precompile for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). -note: Adding a new test - Add a function that is named `test_` and takes at least the following arguments: +Note: Adding a new test Add a function that is named `test_` and +takes at least the following arguments. - - blockchain_test | state_test - - pre - - tx - - post +Required arguments: +- `blockchain_test` or `state_test` +- `pre` +- `tx` +- `post` - The following arguments *need* to be parametrized or the test will not be generated: +The following arguments *need* to be parametrized or the test will not be +generated: - - versioned_hash - - kzg_commitment - - z - - y - - kzg_proof - - result +- `versioned_hash` +- `kzg_commitment` +- `z` +- `y` +- `kzg_proof` +- `result` - These values correspond to a single call of the precompile, and `result` refers to - whether the call should succeed or fail. +These values correspond to a single call of the precompile, and `result` +refers to whether the call should succeed or fail. - All other `pytest.fixture` fixtures can be parametrized to generate new combinations and test - cases. - -""" # noqa: E501 +All other `pytest.fixture` fixtures can be parametrized to generate new +combinations and test cases. +""" import glob import json @@ -110,8 +110,8 @@ def call_gas() -> int: """ Amount of gas to pass to the precompile. - Defaults to Spec.POINT_EVALUATION_PRECOMPILE_GAS, but can be parametrized to - test different amounts. + Defaults to Spec.POINT_EVALUATION_PRECOMPILE_GAS, but can be parametrized + to test different amounts. """ return Spec.POINT_EVALUATION_PRECOMPILE_GAS @@ -144,7 +144,8 @@ def precompile_caller_code(call_opcode: Op, call_gas: int) -> Bytecode: precompile_caller_code = Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) precompile_caller_code += Op.SSTORE( key_call_return_code, - call_opcode( # type: ignore # https://github.com/ethereum/execution-spec-tests/issues/348 # noqa: E501 + # https://github.com/ethereum/execution-spec-tests/issues/348 + call_opcode( # type: ignore gas=call_gas, address=Spec.POINT_EVALUATION_PRECOMPILE_ADDRESS, args_offset=0x00, @@ -226,8 +227,8 @@ def post( precompile_input: bytes, ) -> Dict: """ - Prepare expected post for each test, depending on the success or - failure of the precompile call. + Prepare expected post for each test, depending on the success or failure of + the precompile call. """ expected_storage: Storage.StorageDictType = {} # CALL operation return code @@ -291,8 +292,9 @@ def test_valid_inputs( """ Test valid sanity precompile calls that are expected to succeed. - - `kzg_commitment` and `kzg_proof` are set to values such that `p(z)==0` for all values of `z`, - hence `y` is tested to be zero, and call to be successful. + - `kzg_commitment` and `kzg_proof` are set to values such that `p(z)==0` + for all values of `z`, hence `y` is tested to be zero, and call to be + successful. """ state_test( env=Environment(), @@ -348,7 +350,8 @@ def test_invalid_inputs( - Correct proof, commitment, z and y, but incorrect lengths - Null inputs - Zero inputs - - Correct proof, commitment, z and y, but incorrect version versioned hash + - Correct proof, commitment, z and y, but incorrect version versioned + hash """ state_test( env=Environment(), @@ -425,8 +428,8 @@ def get_point_evaluation_test_files_in_directory(path: str) -> list[str]: def all_external_vectors() -> List: """ - Test for the Point Evaluation Precompile from external sources, - contained in ./point_evaluation_vectors/. + Test for the Point Evaluation Precompile from external sources, contained + in ./point_evaluation_vectors/. """ test_cases = [] @@ -453,7 +456,8 @@ def test_external_vectors( post: Dict, ): """ - Test precompile calls using external test vectors compiled from different sources. + Test precompile calls using external test vectors compiled from different + sources. - `go_kzg_4844_verify_kzg_proof.json`: test vectors from the [go-kzg-4844](https://github.com/crate-crypto/go-kzg-4844) repository. @@ -531,16 +535,17 @@ def test_tx_entry_point( proof_correct: bool, ): """ - Test calling the Point Evaluation Precompile directly as - transaction entry point, and measure the gas consumption. + Test calling the Point Evaluation Precompile directly as transaction entry + point, and measure the gas consumption. - - Using `gas_limit` with exact necessary gas, insufficient gas and extra gas. + - Using `gas_limit` with exact necessary gas, insufficient gas and extra + gas. - Using correct and incorrect proofs """ sender = pre.fund_eoa() - # Starting from EIP-7623, we need to use an access list to raise the intrinsic gas cost to be - # above the floor data cost. + # Starting from EIP-7623, we need to use an access list to raise the + # intrinsic gas cost to be above the floor data cost. access_list = [AccessList(address=Address(i), storage_keys=[]) for i in range(1, 10)] # Gas is appended the intrinsic gas cost of the transaction @@ -614,7 +619,9 @@ def test_precompile_before_fork( tx: Transaction, precompile_caller_address: Address, ): - """Test calling the Point Evaluation Precompile before the appropriate fork.""" + """ + Test calling the Point Evaluation Precompile before the appropriate fork. + """ post = { precompile_caller_address: Account( storage={1: 1}, @@ -667,7 +674,9 @@ def test_precompile_during_fork( precompile_input: bytes, sender: EOA, ): - """Test calling the Point Evaluation Precompile during the appropriate fork.""" + """ + Test calling the Point Evaluation Precompile during the appropriate fork. + """ # Blocks before fork blocks = [ Block( diff --git a/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py b/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py index 02a80eb3de..f8eb3d96f2 100644 --- a/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py +++ b/cancun/eip4844_blobs/test_point_evaluation_precompile_gas.py @@ -1,8 +1,9 @@ """ -abstract: Tests gas usage on point evaluation precompile for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844) - Test gas usage on point evaluation precompile for [EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). +Tests gas usage on point evaluation precompile for EIP-4844. -""" # noqa: E501 +Tests gas usage on point evaluation precompile for +[EIP-4844: Shard Blob Transactions](https://eips.ethereum.org/EIPS/eip-4844). +""" from typing import Dict, Literal @@ -103,7 +104,8 @@ def precompile_caller_code( + copy_opcode_cost(fork, len(precompile_input)) ) if call_type == Op.CALL or call_type == Op.CALLCODE: - precompile_caller_code += call_type( # type: ignore # https://github.com/ethereum/execution-spec-tests/issues/348 # noqa: E501 + # https://github.com/ethereum/execution-spec-tests/issues/348 + precompile_caller_code += call_type( # type: ignore call_gas, Spec.POINT_EVALUATION_PRECOMPILE_ADDRESS, 0x00, @@ -115,7 +117,8 @@ def precompile_caller_code( overhead_cost += (push_operations_cost * 6) + (calldatasize_cost * 1) elif call_type == Op.DELEGATECALL or call_type == Op.STATICCALL: # Delegatecall and staticcall use one less argument - precompile_caller_code += call_type( # type: ignore # https://github.com/ethereum/execution-spec-tests/issues/348 # noqa: E501 + # https://github.com/ethereum/execution-spec-tests/issues/348 + precompile_caller_code += call_type( # type: ignore call_gas, Spec.POINT_EVALUATION_PRECOMPILE_ADDRESS, 0x00, @@ -163,8 +166,8 @@ def post( call_gas: int, ) -> Dict: """ - Prepare expected post for each test, depending on the success or - failure of the precompile call and the gas usage. + Prepare expected post for each test, depending on the success or failure of + the precompile call and the gas usage. """ if proof == "correct": expected_gas_usage = ( @@ -205,11 +208,12 @@ def test_point_evaluation_precompile_gas_usage( post: Dict, ): """ - Test point evaluation precompile gas usage under different call contexts and gas limits. + Test point evaluation precompile gas usage under different call contexts + and gas limits. - - Test using all call types (CALL, DELEGATECALL, CALLCODE, STATICCALL) - - Test using different gas limits (exact gas, insufficient gas, extra gas) - - Test using correct and incorrect proofs + - Test using all call types (CALL, DELEGATECALL, CALLCODE, STATICCALL) - + Test using different gas limits (exact gas, insufficient gas, extra gas) - + Test using correct and incorrect proofs """ state_test( env=Environment(), diff --git a/cancun/eip5656_mcopy/common.py b/cancun/eip5656_mcopy/common.py index 1c975f4f84..a4aef625ca 100644 --- a/cancun/eip5656_mcopy/common.py +++ b/cancun/eip5656_mcopy/common.py @@ -1,7 +1,7 @@ """ -Common procedures to test -[EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656). -""" # noqa: E501 +Common procedures to test [EIP-5656: MCOPY - Memory copying +instruction](https://eips.ethereum.org/EIPS/eip-5656). +""" from copy import copy @@ -16,7 +16,8 @@ def mcopy(*, src: int, dest: int, length: int, memory: bytes) -> bytes: res = bytearray(copy(memory)) - # If the destination or source are larger than the memory, we need to extend the memory + # If the destination or source are larger than the memory, we need to + # extend the memory max_byte_index = max(src, dest) + length if max_byte_index > len(memory): res.extend(b"\x00" * (max_byte_index - len(memory))) diff --git a/cancun/eip5656_mcopy/test_mcopy.py b/cancun/eip5656_mcopy/test_mcopy.py index cd1fdda802..0ad3967960 100644 --- a/cancun/eip5656_mcopy/test_mcopy.py +++ b/cancun/eip5656_mcopy/test_mcopy.py @@ -1,8 +1,6 @@ """ -abstract: Tests [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656) - Test copy operations of [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656). - -""" # noqa: E501 +Tests [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656). +""" from typing import Mapping @@ -54,8 +52,8 @@ def code_bytecode( code_storage: Storage, ) -> Bytecode: """ - Prepare bytecode and storage for the test, based on the starting memory and the final - memory that resulted from the copy. + Prepare bytecode and storage for the test, based on the starting memory and + the final memory that resulted from the copy. """ bytecode = Bytecode() @@ -90,8 +88,8 @@ def code_bytecode( Op.MLOAD(w * 0x20), ) - # If the memory was extended beyond the initial range, store the last word of the resulting - # memory into storage too + # If the memory was extended beyond the initial range, store the last word + # of the resulting memory into storage too if len(final_memory) > len(initial_memory): last_word = ceiling_division(len(final_memory), 0x20) - 1 bytecode += Op.SSTORE( @@ -187,7 +185,8 @@ def test_valid_mcopy_operations( tx: Transaction, ): """ - Perform MCOPY operations using different offsets and lengths: + Perform MCOPY operations using different offsets and lengths. + - Zero inputs - Memory rewrites (copy from and to the same location) - Memory overwrites (copy from and to different locations) @@ -214,7 +213,10 @@ def test_mcopy_on_empty_memory( post: Mapping[str, Account], tx: Transaction, ): - """Perform MCOPY operations on an empty memory, using different offsets and lengths.""" + """ + Perform MCOPY operations on an empty memory, using different offsets and + lengths. + """ state_test( env=Environment(), pre=pre, diff --git a/cancun/eip5656_mcopy/test_mcopy_contexts.py b/cancun/eip5656_mcopy/test_mcopy_contexts.py index 8504912809..33dcc5e3c7 100644 --- a/cancun/eip5656_mcopy/test_mcopy_contexts.py +++ b/cancun/eip5656_mcopy/test_mcopy_contexts.py @@ -1,8 +1,8 @@ """ -abstract: Tests [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656) - Test memory copy under different call contexts [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656). +Test memory copy under different call contexts. -""" # noqa: E501 +Tests for [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656). +""" from itertools import cycle, islice from typing import Mapping @@ -39,8 +39,8 @@ def callee_bytecode( call_opcode: Op, ) -> Bytecode: """ - Callee simply performs mcopy operations that should not have any effect on the - caller context. + Callee simply performs mcopy operations that should not have any effect on + the caller context. """ bytecode = Bytecode() @@ -76,7 +76,8 @@ def initial_memory( ret = bytes(list(islice(cycle(range(0x01, 0x100)), initial_memory_length))) if call_opcode in [Op.CREATE, Op.CREATE2]: - # We also need to put the callee_bytecode as initcode in memory for create operations + # We also need to put the callee_bytecode as initcode in memory for + # create operations ret = bytes(callee_bytecode) + ret[len(callee_bytecode) :] assert len(ret) == initial_memory_length @@ -97,8 +98,8 @@ def caller_bytecode( caller_storage: Storage, ) -> Bytecode: """ - Prepare bytecode and storage for the test, based on the starting memory and the final - memory that resulted from the copy. + Prepare bytecode and storage for the test, based on the starting memory and + the final memory that resulted from the copy. """ bytecode = Bytecode() @@ -116,8 +117,8 @@ def caller_bytecode( bytecode += Op.SSTORE(100_000, Op.MSIZE()) caller_storage[100_000] = ceiling_division(len(initial_memory), 0x20) * 0x20 - # Store all memory in the initial range to verify the MCOPY in the subcall did not affect - # this level's memory + # Store all memory in the initial range to verify the MCOPY in the subcall + # did not affect this level's memory for w in range(0, len(initial_memory) // 0x20): bytecode += Op.SSTORE(w, Op.MLOAD(w * 0x20)) caller_storage[w] = initial_memory[w * 0x20 : w * 0x20 + 0x20] @@ -171,8 +172,8 @@ def test_no_memory_corruption_on_upper_call_stack_levels( tx: Transaction, ): """ - Perform a subcall with any of the following opcodes, which uses MCOPY during its execution, - and verify that the caller's memory is unaffected. + Perform a subcall with any of the following opcodes, which uses MCOPY + during its execution, and verify that the caller's memory is unaffected. """ state_test( env=Environment(), @@ -197,8 +198,8 @@ def test_no_memory_corruption_on_upper_create_stack_levels( tx: Transaction, ): """ - Perform a subcall with any of the following opcodes, which uses MCOPY during its execution, - and verify that the caller's memory is unaffected: + Perform a subcall with any of the following opcodes, which uses MCOPY + during its execution, and verify that the caller's memory is unaffected: - `CREATE` - `CREATE2`. diff --git a/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py b/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py index 639d007542..6a9801d009 100644 --- a/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py +++ b/cancun/eip5656_mcopy/test_mcopy_memory_expansion.py @@ -1,9 +1,10 @@ """ -abstract: Tests [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656) - Test copy operations of [EIP-5656: MCOPY - Memory copying instruction](https://eips.ethereum.org/EIPS/eip-5656) - that produce a memory expansion, and potentially an out-of-gas error. +Test MCOPY with memory expansion and potential OOG errors. -""" # noqa: E501 +Test copy operations of [EIP-5656: MCOPY - Memory copying +instruction](https://eips.ethereum.org/EIPS/eip-5656) that produce +a memory expansion, and potentially an out-of-gas error. +""" import itertools from typing import List, Mapping @@ -74,11 +75,11 @@ def call_exact_cost( tx_access_list: List[AccessList], ) -> int: """ - Return the exact cost of the subcall, based on the initial memory and the length of the - copy. + Return the exact cost of the subcall, based on the initial memory and the + length of the copy. """ - # Starting from EIP-7623, we need to use an access list to raise the intrinsic gas cost to be - # above the floor data cost. + # Starting from EIP-7623, we need to use an access list to raise the + # intrinsic gas cost to be above the floor data cost. cost_memory_bytes = fork.memory_expansion_gas_calculator() gas_costs = fork.gas_costs() tx_intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() @@ -218,7 +219,10 @@ def test_mcopy_memory_expansion( post: Mapping[str, Account], tx: Transaction, ): - """Perform MCOPY operations that expand the memory, and verify the gas it costs to do so.""" + """ + Perform MCOPY operations that expand the memory, and verify the gas it + costs to do so. + """ state_test( env=env, pre=pre, @@ -279,8 +283,8 @@ def test_mcopy_huge_memory_expansion( tx: Transaction, ): """ - Perform MCOPY operations that expand the memory by huge amounts, and verify that it correctly - runs out of gas. + Perform MCOPY operations that expand the memory by huge amounts, and verify + that it correctly runs out of gas. """ state_test( env=env, diff --git a/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py b/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py index ea59c47f2c..d46db3d650 100644 --- a/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py +++ b/cancun/eip6780_selfdestruct/test_dynamic_create2_selfdestruct_collision.py @@ -51,20 +51,26 @@ def test_dynamic_create2_selfdestruct_collision( """ Dynamic Create2->Suicide->Create2 collision scenario. - Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys, - then on a different call, in the same tx, perform a self-destruct. + Perform a CREATE2, make sure that the initcode sets at least a couple of + storage keys, then on a different call, in the same tx, perform a + self-destruct. Then: - a) on the same tx, attempt to recreate the contract <=== Covered in this test - 1) and create2 contract already in the state - 2) and create2 contract is not in the state - b) on a different tx, attempt to recreate the contract - Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys, - then in a different tx, perform a self-destruct. + a) on the same tx, attempt to recreate the contract + -> Covered in this test + 1) and create2 contract already in the state + 2) and create2 contract is not in the state + b) on a different tx, attempt to recreate the contract + + Perform a CREATE2, make sure that the initcode sets at least a couple + of storage keys, then in a different tx, perform a self-destruct. + Then: - a) on the same tx, attempt to recreate the contract - b) on a different tx, attempt to recreate the contract - Verify that the test case described in - https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22156575/2024-01-06+Mainnet+Halting+Event + a) on the same tx, attempt to recreate the contract + b) on a different tx, attempt to recreate the contract + + Check the test case described in + https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/ + 22156575/2024-01-06+Mainnet+Halting+Event """ assert call_create2_contract_in_between or call_create2_contract_at_the_end, "invalid test" @@ -79,7 +85,8 @@ def test_dynamic_create2_selfdestruct_collision( create2_salt = 1 # Create EOA for sendall destination (receives selfdestruct funds) - sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct calls + sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct + # calls # Create storage contract that will be called during initialization address_create2_storage = pre.deploy_contract( @@ -131,7 +138,8 @@ def test_dynamic_create2_selfdestruct_collision( + Op.CALL(100000, address_code, 0, 0, 0, 0, 0) # Call to the created account to trigger selfdestruct + Op.CALL(100000, call_address_in_between, first_call_value, 0, 0, 0, 0) - # Make a subcall that do CREATE2 collision and returns its address as the result + # Make a subcall that do CREATE2 collision and returns its address as + # the result + Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE()) + Op.CALL(100000, address_code, second_create2_value, 0, Op.CALLDATASIZE(), 0, 32) + Op.SSTORE( @@ -149,7 +157,8 @@ def test_dynamic_create2_selfdestruct_collision( sender = pre.fund_eoa(7000000000000000000) if create2_dest_already_in_state: - # Create2 address already in the state, e.g. deployed in a previous block + # Create2 address already in the state, e.g. deployed in a previous + # block pre[create2_address] = Account( balance=pre_existing_create2_balance, nonce=1, @@ -182,7 +191,8 @@ def test_dynamic_create2_selfdestruct_collision( } ) - # Calculate the destination account expected balance for the selfdestruct/sendall calls + # Calculate the destination account expected balance for the + # selfdestruct/sendall calls sendall_destination_balance = ( pre_existing_create2_balance if create2_dest_already_in_state else first_create2_value ) @@ -224,20 +234,28 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions( """ Dynamic Create2->Suicide->Create2 collision scenario. - Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys, - then on a different call, in the same tx, perform a self-destruct. + Perform a CREATE2, make sure that the initcode sets at least a couple of + storage keys, then on a different call, in the same tx, perform a + self-destruct. + Then: - a) on the same tx, attempt to recreate the contract - 1) and create2 contract already in the state - 2) and create2 contract is not in the state - b) on a different tx, attempt to recreate the contract <=== Covered in this test - Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys, - then in a different tx, perform a self-destruct. + a) on the same tx, attempt to recreate the contract + 1) and create2 contract already in the state + 2) and create2 contract is not in the state + b) on a different tx, attempt to recreate the contract + -> Covered in this test + + Perform a CREATE2, make sure that the initcode sets at + least a couple of storage keys, then in a different tx, perform a + self-destruct. + Then: - a) on the same tx, attempt to recreate the contract - b) on a different tx, attempt to recreate the contract - Verify that the test case described in - https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22156575/2024-01-06+Mainnet+Halting+Event + a) on the same tx, attempt to recreate the contract + b) on a different tx, attempt to recreate the contract + + Check the test case described in + https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22156575/2024-01-06 + +Mainnet+Halting+Event """ # assert call_create2_contract_at_the_end, "invalid test" @@ -252,7 +270,8 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions( create2_salt = 1 # Create EOA for sendall destination (receives selfdestruct funds) - sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct calls + sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct + # calls # Create storage contract that will be called during initialization address_create2_storage = pre.deploy_contract( @@ -311,7 +330,8 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions( # Create the second contract that performs the second transaction address_to_second = pre.deploy_contract( code=Op.JUMPDEST() - # Make a subcall that do CREATE2 collision and returns its address as the result + # Make a subcall that do CREATE2 collision and returns its address as + # the result + Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE()) + Op.CALL(100000, address_code, second_create2_value, 0, Op.CALLDATASIZE(), 0, 32) + Op.SSTORE( @@ -329,7 +349,8 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions( sender = pre.fund_eoa(7000000000000000000) if create2_dest_already_in_state: - # Create2 address already in the state, e.g. deployed in a previous block + # Create2 address already in the state, e.g. deployed in a previous + # block pre[create2_address] = Account( balance=pre_existing_create2_balance, nonce=1, @@ -350,8 +371,9 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions( ) ) - # after Cancun Create2 initcode is only executed if the contract did not already exist - # and before it will always be executed as the first tx deletes the account + # after Cancun Create2 initcode is only executed if the contract did not + # already exist and before it will always be executed as the first tx + # deletes the account post[address_create2_storage] = Account( storage={ create2_constructor_worked: int(fork < Cancun or not create2_dest_already_in_state) @@ -369,9 +391,12 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions( post[address_to_second] = Account( storage={ code_worked: 0x01, - # Second create2 will not collide before Cancun as the first tx calls selfdestruct - # After cancun it will collide only if create2_dest_already_in_state otherwise the - # first tx creates and deletes it + # Second create2 will not collide before Cancun as the first tx + # calls selfdestruct + # + # After cancun it will collide only if + # create2_dest_already_in_state otherwise the first tx creates and + # deletes it second_create2_result: ( (0x00 if create2_dest_already_in_state else create2_address) if fork >= Cancun @@ -380,14 +405,16 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions( } ) - # Calculate the destination account expected balance for the selfdestruct/sendall calls + # Calculate the destination account expected balance for the + # selfdestruct/sendall calls sendall_destination_balance = 0 if create2_dest_already_in_state: sendall_destination_balance += pre_existing_create2_balance if fork >= Cancun: - # first create2 fails, but first calls ok. the account is not removed on cancun - # therefore with the second create2 it is not successful + # first create2 fails, but first calls ok. the account is not + # removed on cancun therefore with the second create2 it is not + # successful sendall_destination_balance += first_call_value else: # first create2 fails, first calls totally removes the account @@ -396,8 +423,9 @@ def test_dynamic_create2_selfdestruct_collision_two_different_transactions( if call_create2_contract_at_the_end: sendall_destination_balance += second_create2_value else: - # if no account in the state, first create2 successful, first call successful and removes - # because it is removed in the next transaction second create2 successful + # if no account in the state, first create2 successful, first call + # successful and removes because it is removed in the next transaction + # second create2 successful sendall_destination_balance = first_create2_value + first_call_value if call_create2_contract_at_the_end: sendall_destination_balance += second_create2_value @@ -448,20 +476,28 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx( blockchain_test: BlockchainTestFiller, ): """ - Dynamic Create2->Suicide->Create2 collision scenario over multiple transactions. + Dynamic Create2->Suicide->Create2 collision scenario over multiple + transactions. - Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys, - then on a different call, in the same or different tx but same block, perform a self-destruct. + Perform a CREATE2, make sure that the initcode sets at least a couple of + storage keys, then on a different call, in the same or different tx but + same block, perform a self-destruct. Then: - a) on the same tx, attempt to recreate the contract - b) on a different tx, attempt to recreate the contract - Perform a CREATE2, make sure that the initcode sets at least a couple of storage keys, - then in a different tx, perform a self-destruct. + a) on the same tx, attempt to recreate the contract + b) on a different tx, attempt to recreate the contract + + Perform a CREATE2, make sure that the initcode sets at least a + couple of storage keys, then in a different tx, perform a self-destruct. + Then: - a) on the same tx, attempt to recreate the contract <=== Covered in this test - b) on a different tx, attempt to recreate the contract <=== Covered in this test - Verify that the test case described in - https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22156575/2024-01-06+Mainnet+Halting+Event + a) on the same tx, attempt to recreate the contract + -> Covered in this test + b) on a different tx, attempt to recreate the contract + -> Covered in this test + + Check the test case described in + https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22156575/2024-01-06 + +Mainnet+Halting+Event """ if recreate_on_first_tx: assert selfdestruct_on_first_tx, "invalid test" @@ -477,7 +513,8 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx( create2_salt = 1 # Create EOA for sendall destination (receives selfdestruct funds) - sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct calls + sendall_destination = pre.fund_eoa(0) # Will be funded by selfdestruct + # calls # Create storage contract that will be called during initialization address_create2_storage = pre.deploy_contract( @@ -540,7 +577,8 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx( if recreate_on_first_tx: first_tx_code += ( - # Make a subcall that do CREATE2 collision and returns its address as the result + # Make a subcall that do CREATE2 collision and returns its address + # as the result Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE()) + Op.CALL(100000, address_code, second_create2_value, 0, Op.CALLDATASIZE(), 0, 32) + Op.SSTORE( @@ -551,7 +589,8 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx( else: second_tx_code += ( - # Make a subcall that do CREATE2 collision and returns its address as the result + # Make a subcall that do CREATE2 collision and returns its address + # as the result Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE()) + Op.CALL(100000, address_code, second_create2_value, 0, Op.CALLDATASIZE(), 0, 32) + Op.SSTORE( @@ -566,7 +605,8 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx( first_tx_code += Op.SSTORE(part_1_worked, 1) second_tx_code += Op.SSTORE(part_2_worked, 1) - # Create the main contract that uses conditional logic to handle both transactions + # Create the main contract that uses conditional logic to handle both + # transactions address_to = pre.deploy_contract( code=Conditional( # Depending on the tx, execute the first or second tx code @@ -585,8 +625,9 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx( # Create2 address only exists if it was pre-existing and after cancun account_will_exist_with_code = not selfdestruct_on_first_tx and fork >= Cancun - # If the contract is self-destructed and we also attempt to recreate it on the first tx, - # the second call on the second tx will only place balance in the account + # If the contract is self-destructed and we also attempt to recreate it on + # the first tx, the second call on the second tx will only place balance in + # the account account_will_exist_with_balance = selfdestruct_on_first_tx and recreate_on_first_tx post[create2_address] = ( @@ -609,14 +650,16 @@ def test_dynamic_create2_selfdestruct_collision_multi_tx( part_2_worked: 0x01, # First create2 always works first_create2_result: create2_address, - # Second create2 only works if we successfully self-destructed on the first tx + # Second create2 only works if we successfully self-destructed on + # the first tx second_create2_result: ( create2_address if selfdestruct_on_first_tx and not recreate_on_first_tx else 0x00 ), } ) - # Calculate the destination account expected balance for the selfdestruct/sendall calls + # Calculate the destination account expected balance for the + # selfdestruct/sendall calls sendall_destination_balance = first_create2_value + first_call_value if not account_will_exist_with_balance: diff --git a/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py b/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py index 9a851c6b26..36d13853c4 100644 --- a/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py +++ b/cancun/eip6780_selfdestruct/test_reentrancy_selfdestruct_revert.py @@ -1,7 +1,4 @@ -""" -Suicide scenario requested test -https://github.com/ethereum/tests/issues/1325. -""" +"""Suicide scenario requested test https://github.com/ethereum/tests/issues/1325.""" from typing import SupportsBytes @@ -163,12 +160,14 @@ def test_reentrancy_selfdestruct_revert( if first_suicide in [Op.CALLCODE, Op.DELEGATECALL]: if fork >= Cancun: - # On Cancun even callcode/delegatecall does not remove the account, so the value remain + # On Cancun even callcode/delegatecall does not remove the account, + # so the value remain post[executor_contract_address] = Account( storage={ 0x01: 0x01, # First call to contract S->suicide success 0x02: 0x00, # Second call to contract S->suicide reverted - 0x03: 16, # Reverted value to check that revert really worked + 0x03: 16, # Reverted value to check that revert really + # worked }, ) else: @@ -184,7 +183,8 @@ def test_reentrancy_selfdestruct_revert( balance=executor_contract_init_balance, ) - # On Cancun suicide no longer destroys the account from state, just cleans the balance + # On Cancun suicide no longer destroys the account from state, just cleans + # the balance if first_suicide in [Op.CALL]: post[executor_contract_address] = Account( storage={ @@ -194,7 +194,8 @@ def test_reentrancy_selfdestruct_revert( }, ) if fork >= Cancun: - # On Cancun suicide does not remove the account, just sends the balance + # On Cancun suicide does not remove the account, just sends the + # balance post[selfdestruct_contract_address] = Account( balance=0, code=selfdestruct_contract_bytecode, storage={} ) diff --git a/cancun/eip6780_selfdestruct/test_selfdestruct.py b/cancun/eip6780_selfdestruct/test_selfdestruct.py index b839626162..79daddd8d2 100644 --- a/cancun/eip6780_selfdestruct/test_selfdestruct.py +++ b/cancun/eip6780_selfdestruct/test_selfdestruct.py @@ -1,8 +1,8 @@ """ -abstract: Tests [EIP-6780: SELFDESTRUCT only in same transaction](https://eips.ethereum.org/EIPS/eip-6780) - Tests for [EIP-6780: SELFDESTRUCT only in same transaction](https://eips.ethereum.org/EIPS/eip-6780). +SELFDESTRUCT only in same transaction tests. -""" # noqa: E501 +Tests for [EIP-6780: SELFDESTRUCT only in same transaction](https://eips.ethereum.org/EIPS/eip-6780). +""" from itertools import cycle from typing import Dict, List @@ -37,8 +37,9 @@ Address of a pre-existing contract that self-destructs. """ -# Sentinel value to indicate that the self-destructing contract address should be used, only for -# use in `pytest.mark.parametrize`, not for use within the test method itself. +# Sentinel value to indicate that the self-destructing contract address should +# be used, only for use in `pytest.mark.parametrize`, not for use within the +# test method itself. SELF_ADDRESS = Address(0x01) # Sentinel value to indicate that the contract should not self-destruct. NO_SELFDESTRUCT = Address(0x00) @@ -59,9 +60,11 @@ def sendall_recipient_addresses(request: pytest.FixtureRequest, pre: Alloc) -> L """ List of addresses that receive the SENDALL operation in any test. - If the test case requires a pre-existing contract, it will be deployed here. + If the test case requires a pre-existing contract, it will be deployed + here. - By default the list is a single pre-deployed contract that unconditionally sets storage. + By default the list is a single pre-deployed contract that unconditionally + sets storage. """ address_list = getattr(request, "param", [PRE_DEPLOY_CONTRACT_1]) deployed_contracts: Dict[str, Address] = {} @@ -88,8 +91,8 @@ def selfdestruct_code_preset( bytecode = Op.SSTORE(0, Op.ADD(Op.SLOAD(0), 1)) if len(sendall_recipient_addresses) != 1: - # Load the recipient address from calldata, each test case needs to pass the addresses as - # calldata + # Load the recipient address from calldata, each test case needs to + # pass the addresses as calldata bytecode += Conditional( # We avoid having the caller to give us our own address by checking # against a constant that is a magic number @@ -119,8 +122,8 @@ def selfdestruct_code( sendall_recipient_addresses: List[Address], ) -> Bytecode: """ - Create default self-destructing bytecode, - which can be modified by each test if necessary. + Create default self-destructing bytecode, which can be modified by each + test if necessary. """ return selfdestruct_code_preset(sendall_recipient_addresses=sendall_recipient_addresses) @@ -190,19 +193,21 @@ def test_create_selfdestruct_same_tx( selfdestruct_contract_initial_balance: int, ): """ - Use CREATE or CREATE2 to create a self-destructing contract, and call it in the same - transaction. + Use CREATE or CREATE2 to create a self-destructing contract, and call it in + the same transaction. Behavior should be the same before and after EIP-6780. Test using: - - Different send-all recipient addresses: single, multiple, including self + - Different send-all recipient addresses: single, multiple, + including self - Different initial balances for the self-destructing contract - Different opcodes: CREATE, CREATE2 """ selfdestruct_contract_initcode = Initcode(deploy_code=selfdestruct_code) initcode_copy_from_address = pre.deploy_contract(selfdestruct_contract_initcode) - # Our entry point is an initcode that in turn creates a self-destructing contract + # Our entry point is an initcode that in turn creates a self-destructing + # contract entry_code_storage = Storage() # Bytecode used to create the contract, can be CREATE or CREATE2 @@ -225,9 +230,11 @@ def test_create_selfdestruct_same_tx( ) selfdestruct_contract_current_balance = selfdestruct_contract_initial_balance - # Entry code that will be executed, creates the contract and then calls it in the same tx + # Entry code that will be executed, creates the contract and then calls it + # in the same tx entry_code = ( - # Initcode is already deployed at `initcode_copy_from_address`, so just copy it + # Initcode is already deployed at `initcode_copy_from_address`, so just + # copy it Op.EXTCODECOPY( initcode_copy_from_address, 0, @@ -252,8 +259,8 @@ def test_create_selfdestruct_same_tx( Op.EXTCODEHASH(selfdestruct_contract_address), ) - # Call the self-destructing contract multiple times as required, increasing the wei sent each - # time + # Call the self-destructing contract multiple times as required, increasing + # the wei sent each time entry_code_balance = 0 for i, sendall_recipient in zip(range(call_times), cycle(sendall_recipient_addresses)): entry_code += Op.MSTORE(0, sendall_recipient) @@ -276,8 +283,9 @@ def test_create_selfdestruct_same_tx( if sendall_recipient != selfdestruct_contract_address: sendall_final_balances[sendall_recipient] += selfdestruct_contract_current_balance - # Self-destructing contract must always have zero balance after the call because the - # self-destruct always happens in the same transaction in this test + # Self-destructing contract must always have zero balance after the + # call because the self-destruct always happens in the same transaction + # in this test selfdestruct_contract_current_balance = 0 entry_code += Op.SSTORE( @@ -296,8 +304,8 @@ def test_create_selfdestruct_same_tx( Op.EXTCODEHASH(selfdestruct_contract_address), ) - # Lastly return zero so the entry point contract is created and we can retain the stored - # values for verification. + # Lastly return zero so the entry point contract is created and we can + # retain the stored values for verification. entry_code += Op.RETURN(max(len(selfdestruct_contract_initcode), 32), 1) tx = Transaction( @@ -336,7 +344,8 @@ def test_self_destructing_initcode( selfdestruct_code: Bytecode, sendall_recipient_addresses: List[Address], create_opcode: Op, - call_times: int, # Number of times to call the self-destructing contract in the same tx + call_times: int, # Number of times to call the self-destructing contract + # in the same tx selfdestruct_contract_initial_balance: int, ): """ @@ -347,10 +356,12 @@ def test_self_destructing_initcode( Test using: - Different initial balances for the self-destructing contract - Different opcodes: CREATE, CREATE2 - - Different number of calls to the self-destructing contract in the same tx + - Different number of calls to the self-destructing contract in + the same tx """ initcode_copy_from_address = pre.deploy_contract(selfdestruct_code) - # Our entry point is an initcode that in turn creates a self-destructing contract + # Our entry point is an initcode that in turn creates a self-destructing + # contract entry_code_storage = Storage() sendall_amount = 0 @@ -364,9 +375,11 @@ def test_self_destructing_initcode( opcode=create_opcode, ) - # Entry code that will be executed, creates the contract and then calls it in the same tx + # Entry code that will be executed, creates the contract and then calls it + # in the same tx entry_code = ( - # Initcode is already deployed at `initcode_copy_from_address`, so just copy it + # Initcode is already deployed at `initcode_copy_from_address`, so just + # copy it Op.EXTCODECOPY( initcode_copy_from_address, 0, @@ -391,8 +404,8 @@ def test_self_destructing_initcode( Op.EXTCODEHASH(selfdestruct_contract_address), ) - # Call the self-destructing contract multiple times as required, increasing the wei sent each - # time + # Call the self-destructing contract multiple times as required, increasing + # the wei sent each time entry_code_balance = 0 for i in range(call_times): entry_code += Op.SSTORE( @@ -414,8 +427,8 @@ def test_self_destructing_initcode( Op.BALANCE(selfdestruct_contract_address), ) - # Lastly return zero so the entry point contract is created and we can retain the stored - # values for verification. + # Lastly return zero so the entry point contract is created and we can + # retain the stored values for verification. entry_code += Op.RETURN(max(len(selfdestruct_code), 32), 1) if selfdestruct_contract_initial_balance > 0: @@ -463,8 +476,8 @@ def test_self_destructing_initcode_create_tx( Behavior should be the same before and after EIP-6780. Test using: - - Different initial balances for the self-destructing contract - - Different transaction value amounts + - Different initial balances for the self-destructing contract + - Different transaction value amounts """ tx = Transaction( sender=sender, @@ -476,7 +489,8 @@ def test_self_destructing_initcode_create_tx( selfdestruct_contract_address = tx.created_contract pre.fund_address(selfdestruct_contract_address, selfdestruct_contract_initial_balance) - # Our entry point is an initcode that in turn creates a self-destructing contract + # Our entry point is an initcode that in turn creates a self-destructing + # contract sendall_amount = selfdestruct_contract_initial_balance + tx_value post: Dict[Address, Account] = { @@ -487,7 +501,8 @@ def test_self_destructing_initcode_create_tx( state_test(pre=pre, post=post, tx=tx) -@pytest.mark.parametrize("create_opcode", [Op.CREATE2]) # Can only recreate using CREATE2 +# Can only recreate using CREATE2 +@pytest.mark.parametrize("create_opcode", [Op.CREATE2]) @pytest.mark.parametrize( "sendall_recipient_addresses", [ @@ -514,18 +529,20 @@ def test_recreate_self_destructed_contract_different_txs( selfdestruct_contract_initial_balance: int, sendall_recipient_addresses: List[Address], create_opcode: Op, - recreate_times: int, # Number of times to recreate the contract in different transactions - call_times: int, # Number of times to call the self-destructing contract in the same tx + # Number of times to recreate the contract in different transactions + recreate_times: int, + # Number of times to call the self-destructing contract in the same tx + call_times: int, ): """ - Test that a contract can be recreated after it has self-destructed, over the lapse - of multiple transactions. + Test that a contract can be recreated after it has self-destructed, over + the lapse of multiple transactions. Behavior should be the same before and after EIP-6780. Test using: - - Different initial balances for the self-destructing contract - - Contract creating opcodes that are not CREATE + - Different initial balances for the self-destructing contract + - Contract creating opcodes that are not CREATE """ selfdestruct_contract_initcode = Initcode(deploy_code=selfdestruct_code) initcode_copy_from_address = pre.deploy_contract(selfdestruct_contract_initcode) @@ -538,7 +555,8 @@ def test_recreate_self_destructed_contract_different_txs( # Entry code that will be executed, creates the contract and then calls it entry_code = ( - # Initcode is already deployed at initcode_copy_from_address, so just copy it + # Initcode is already deployed at initcode_copy_from_address, so just + # copy it Op.EXTCODECOPY( initcode_copy_from_address, 0, @@ -663,15 +681,17 @@ def test_selfdestruct_pre_existing( call_times: int, ): """ - Test calling a previously created account that contains a selfdestruct, and verify its balance - is sent to the destination address. + Test calling a previously created account that contains a selfdestruct, and + verify its balance is sent to the destination address. - After EIP-6780, the balance should be sent to the send-all recipient address, similar to - the behavior before the EIP, but the account is not deleted. + After EIP-6780, the balance should be sent to the send-all recipient + address, similar to the behavior before the EIP, but the account is not + deleted. Test using: - - Different send-all recipient addresses: single, multiple, including self - - Different initial balances for the self-destructing contract + - Different send-all recipient addresses: single, multiple, + including self + - Different initial balances for the self-destructing contract """ selfdestruct_contract_address = pre.deploy_contract( selfdestruct_code, balance=selfdestruct_contract_initial_balance @@ -688,12 +708,12 @@ def test_selfdestruct_pre_existing( ) selfdestruct_contract_current_balance = selfdestruct_contract_initial_balance - # Entry code in this case will simply call the pre-existing self-destructing contract, - # as many times as required + # Entry code in this case will simply call the pre-existing self- + # destructing contract, as many times as required entry_code = Bytecode() - # Call the self-destructing contract multiple times as required, increasing the wei sent each - # time + # Call the self-destructing contract multiple times as required, increasing + # the wei sent each time entry_code_balance = 0 for i, sendall_recipient in zip(range(call_times), cycle(sendall_recipient_addresses)): entry_code += Op.MSTORE(0, sendall_recipient) @@ -716,8 +736,9 @@ def test_selfdestruct_pre_existing( if sendall_recipient != selfdestruct_contract_address: sendall_final_balances[sendall_recipient] += selfdestruct_contract_current_balance - # Balance is only kept by the self-destructing contract if we are sending to self and the - # EIP is activated, otherwise the balance is destroyed + # Balance is only kept by the self-destructing contract if we are + # sending to self and the EIP is activated, otherwise the balance is + # destroyed if sendall_recipient != selfdestruct_contract_address or not eip_enabled: selfdestruct_contract_current_balance = 0 @@ -737,8 +758,8 @@ def test_selfdestruct_pre_existing( Op.EXTCODEHASH(selfdestruct_contract_address), ) - # Lastly return zero so the entry point contract is created and we can retain the stored - # values for verification. + # Lastly return zero so the entry point contract is created and we can + # retain the stored values for verification. entry_code += Op.RETURN(32, 1) tx = Transaction( @@ -787,8 +808,9 @@ def test_selfdestruct_created_same_block_different_tx( call_times: int, ): """ - Test that if an account created in the same block that contains a selfdestruct is - called, its balance is sent to the send-all address, but the account is not deleted. + Test that if an account created in the same block that contains a + selfdestruct is called, its balance is sent to the send-all address, but + the account is not deleted. """ selfdestruct_code = selfdestruct_code_preset( sendall_recipient_addresses=sendall_recipient_addresses, @@ -800,11 +822,11 @@ def test_selfdestruct_created_same_block_different_tx( sendall_amount = selfdestruct_contract_initial_balance entry_code = Bytecode() - # Entry code in this case will simply call the pre-existing self-destructing contract, - # as many times as required + # Entry code in this case will simply call the pre-existing self- + # destructing contract, as many times as required - # Call the self-destructing contract multiple times as required, increasing the wei sent each - # time + # Call the self-destructing contract multiple times as required, increasing + # the wei sent each time entry_code_balance = 0 for i in range(call_times): entry_code += Op.SSTORE( @@ -838,8 +860,8 @@ def test_selfdestruct_created_same_block_different_tx( Op.EXTCODEHASH(selfdestruct_contract_address), ) - # Lastly return zero so the entry point contract is created and we can retain the stored - # values for verification. + # Lastly return zero so the entry point contract is created and we can + # retain the stored values for verification. entry_code += Op.RETURN(32, 1) post: Dict[Address, Account] = { @@ -890,15 +912,17 @@ def test_calling_from_new_contract_to_pre_existing_contract( selfdestruct_contract_initial_balance: int, ): """ - Test that if an account created in the current transaction delegate-call a previously created - account that executes self-destruct, the calling account is deleted. + Test that if an account created in the current transaction delegate-call a + previously created account that executes self-destruct, the calling account + is deleted. """ pre_existing_selfdestruct_address = pre.deploy_contract( selfdestruct_code_preset( sendall_recipient_addresses=sendall_recipient_addresses, ), ) - # Our entry point is an initcode that in turn creates a self-destructing contract + # Our entry point is an initcode that in turn creates a self-destructing + # contract entry_code_storage = Storage() sendall_amount = 0 @@ -915,9 +939,11 @@ def test_calling_from_new_contract_to_pre_existing_contract( # Bytecode used to create the contract, can be CREATE or CREATE2 create_bytecode = create_opcode(size=len(selfdestruct_contract_initcode)) - # Entry code that will be executed, creates the contract and then calls it in the same tx + # Entry code that will be executed, creates the contract and then calls it + # in the same tx entry_code = ( - # Initcode is already deployed at `initcode_copy_from_address`, so just copy it + # Initcode is already deployed at `initcode_copy_from_address`, so just + # copy it Op.EXTCODECOPY( initcode_copy_from_address, 0, @@ -942,8 +968,8 @@ def test_calling_from_new_contract_to_pre_existing_contract( Op.EXTCODEHASH(selfdestruct_contract_address), ) - # Call the self-destructing contract multiple times as required, increasing the wei sent each - # time + # Call the self-destructing contract multiple times as required, increasing + # the wei sent each time entry_code_balance = 0 for i in range(call_times): entry_code += Op.SSTORE( @@ -977,8 +1003,8 @@ def test_calling_from_new_contract_to_pre_existing_contract( Op.EXTCODEHASH(selfdestruct_contract_address), ) - # Lastly return zero so the entry point contract is created and we can retain the stored - # values for verification. + # Lastly return zero so the entry point contract is created and we can + # retain the stored values for verification. entry_code += Op.RETURN(max(len(selfdestruct_contract_initcode), 32), 1) if selfdestruct_contract_initial_balance > 0: @@ -1025,9 +1051,9 @@ def test_calling_from_pre_existing_contract_to_new_contract( pre_existing_contract_initial_balance: int, ): """ - Test that if an account created in the current transaction contains a self-destruct and is - delegate-called by an account created before the current transaction, the calling account - is not deleted. + Test that if an account created in the current transaction contains a + self-destruct and is delegate-called by an account created before the + current transaction, the calling account is not deleted. """ selfdestruct_contract_initcode = Initcode(deploy_code=selfdestruct_code) initcode_copy_from_address = pre.deploy_contract( @@ -1051,13 +1077,16 @@ def test_calling_from_pre_existing_contract_to_new_contract( balance=pre_existing_contract_initial_balance, ) - # Our entry point is an initcode that in turn creates a self-destructing contract + # Our entry point is an initcode that in turn creates a self-destructing + # contract entry_code_storage = Storage() sendall_amount = pre_existing_contract_initial_balance - # Entry code that will be executed, creates the contract and then calls it in the same tx + # Entry code that will be executed, creates the contract and then calls it + # in the same tx entry_code = ( - # Initcode is already deployed at `initcode_copy_from_address`, so just copy it + # Initcode is already deployed at `initcode_copy_from_address`, so just + # copy it Op.EXTCODECOPY( initcode_copy_from_address, 0, @@ -1085,8 +1114,9 @@ def test_calling_from_pre_existing_contract_to_new_contract( Op.EXTCODEHASH(caller_address), ) - # Now instead of calling the newly created contract directly, we delegate call to it - # from a pre-existing contract, and the contract must not self-destruct + # Now instead of calling the newly created contract directly, we delegate + # call to it from a pre-existing contract, and the contract must not self- + # destruct entry_code_balance = selfdestruct_contract_initial_balance for i in range(call_times): entry_code += Op.SSTORE( @@ -1120,8 +1150,8 @@ def test_calling_from_pre_existing_contract_to_new_contract( Op.EXTCODEHASH(caller_address), ) - # Lastly return zero so the entry point contract is created and we can retain the stored - # values for verification. + # Lastly return zero so the entry point contract is created and we can + # retain the stored values for verification. entry_code += Op.RETURN(max(len(selfdestruct_contract_initcode), 32), 1) tx = Transaction( @@ -1177,8 +1207,9 @@ def test_create_selfdestruct_same_tx_increased_nonce( selfdestruct_contract_initial_balance: int, ): """ - Verify that a contract can self-destruct if it was created in the same transaction, even when - its nonce has been increased due to contract creation. + Verify that a contract can self-destruct if it was created in the same + transaction, even when its nonce has been increased due to contract + creation. """ initcode = Op.RETURN(0, 1) selfdestruct_pre_bytecode = Op.MSTORE(0, Op.PUSH32(bytes(initcode))) + Op.POP( @@ -1196,7 +1227,8 @@ def test_create_selfdestruct_same_tx_increased_nonce( ) if selfdestruct_contract_initial_balance > 0: pre.fund_address(selfdestruct_contract_address, selfdestruct_contract_initial_balance) - # Our entry point is an initcode that in turn creates a self-destructing contract + # Our entry point is an initcode that in turn creates a self-destructing + # contract entry_code_storage = Storage() # Create a dict to record the expected final balances @@ -1208,9 +1240,11 @@ def test_create_selfdestruct_same_tx_increased_nonce( # Bytecode used to create the contract, can be CREATE or CREATE2 create_bytecode = create_opcode(size=len(selfdestruct_contract_initcode)) - # Entry code that will be executed, creates the contract and then calls it in the same tx + # Entry code that will be executed, creates the contract and then calls it + # in the same tx entry_code = ( - # Initcode is already deployed at `initcode_copy_from_address`, so just copy it + # Initcode is already deployed at `initcode_copy_from_address`, so just + # copy it Op.EXTCODECOPY( initcode_copy_from_address, 0, @@ -1235,8 +1269,8 @@ def test_create_selfdestruct_same_tx_increased_nonce( Op.EXTCODEHASH(selfdestruct_contract_address), ) - # Call the self-destructing contract multiple times as required, increasing the wei sent each - # time + # Call the self-destructing contract multiple times as required, increasing + # the wei sent each time entry_code_balance = 0 for i, sendall_recipient in zip(range(call_times), cycle(sendall_recipient_addresses)): entry_code += Op.MSTORE(0, sendall_recipient) @@ -1259,8 +1293,9 @@ def test_create_selfdestruct_same_tx_increased_nonce( if sendall_recipient != selfdestruct_contract_address: sendall_final_balances[sendall_recipient] += selfdestruct_contract_current_balance - # Self-destructing contract must always have zero balance after the call because the - # self-destruct always happens in the same transaction in this test + # Self-destructing contract must always have zero balance after the + # call because the self-destruct always happens in the same transaction + # in this test selfdestruct_contract_current_balance = 0 entry_code += Op.SSTORE( @@ -1279,8 +1314,8 @@ def test_create_selfdestruct_same_tx_increased_nonce( Op.EXTCODEHASH(selfdestruct_contract_address), ) - # Lastly return zero so the entry point contract is created and we can retain the stored - # values for verification. + # Lastly return zero so the entry point contract is created and we can + # retain the stored values for verification. entry_code += Op.RETURN(max(len(selfdestruct_contract_initcode), 32), 1) tx = Transaction( @@ -1307,7 +1342,8 @@ def test_create_selfdestruct_same_tx_increased_nonce( for address, balance in sendall_final_balances.items(): post[address] = Account(balance=balance, storage={0: 1}) - # Check the new contracts created from the self-destructing contract were correctly created. + # Check the new contracts created from the self-destructing contract were + # correctly created. for address in [ compute_create_address(address=selfdestruct_contract_address, nonce=i + 1) for i in range(call_times) diff --git a/cancun/eip6780_selfdestruct/test_selfdestruct_revert.py b/cancun/eip6780_selfdestruct/test_selfdestruct_revert.py index c13dfb8526..e42f98c6d1 100644 --- a/cancun/eip6780_selfdestruct/test_selfdestruct_revert.py +++ b/cancun/eip6780_selfdestruct/test_selfdestruct_revert.py @@ -1,4 +1,4 @@ -"""tests for selfdestruct interaction with revert.""" +"""Tests for selfdestruct interaction with revert.""" from typing import Dict @@ -64,9 +64,10 @@ def recursive_revert_contract_code( ) -> Bytecode: """ Contract code that: - Given selfdestructable contract A, transfer value to A and call A.selfdestruct. - Then, recurse into a new call which transfers value to A, - call A.selfdestruct, and reverts. + Given selfdestructable contract A, transfer value to A + and call A.selfdestruct. + Then, recurse into a new call which transfers value to A, + call A.selfdestruct, and reverts. """ # Common prefix for all three cases: # case 1: selfdestruct_on_outer_call=1 @@ -244,7 +245,9 @@ def selfdestruct_with_transfer_contract_address( selfdestruct_with_transfer_contract_code: Bytecode, same_tx: bool, ) -> Address: - """Contract address for contract that can selfdestruct and receive value.""" + """ + Contract address for contract that can selfdestruct and receive value. + """ if same_tx: return compute_create_address(address=entry_code_address, nonce=1) # We need to deploy the contract before. @@ -303,7 +306,9 @@ def selfdestruct_with_transfer_initcode_copy_from_address( pre: Alloc, selfdestruct_with_transfer_contract_initcode: Bytecode, ) -> Address: - """Address of a pre-existing contract we use to simply copy initcode from.""" + """ + Address of a pre-existing contract we use to simply copy initcode from. + """ addr = pre.deploy_contract(selfdestruct_with_transfer_contract_initcode) return addr @@ -340,11 +345,13 @@ def test_selfdestruct_created_in_same_tx_with_revert( # noqa SC200 ): """ Given: - Contract A which has methods to receive balance and selfdestruct, and was created in current tx + Contract A which has methods to receive balance and selfdestruct, + and was created in current tx. + Test the following call sequence: - Transfer value to A and call A.selfdestruct. - Recurse into a new call from transfers value to A, calls A.selfdestruct, and reverts. - """ # noqa: E501 + Transfer value to A and call A.selfdestruct. Recurse into a new call + from transfers value to A, calls A.selfdestruct, and reverts. + """ entry_code = Op.EXTCODECOPY( selfdestruct_with_transfer_initcode_copy_from_address, 0, @@ -357,7 +364,8 @@ def test_selfdestruct_created_in_same_tx_with_revert( # noqa SC200 Op.CREATE( 0, 0, - len(bytes(selfdestruct_with_transfer_contract_initcode)), # Value # Offset + # Value Offset + len(bytes(selfdestruct_with_transfer_contract_initcode)), ), ) @@ -400,7 +408,8 @@ def test_selfdestruct_created_in_same_tx_with_revert( # noqa SC200 code=selfdestruct_with_transfer_contract_code, storage=Storage( { - # 2 value transfers (1 in outer call, 1 in reverted inner call) + # 2 value transfers (1 in outer call, 1 in reverted inner + # call) 0: 1, # type: ignore # 1 selfdestruct in reverted inner call 1: 0, # type: ignore @@ -454,8 +463,8 @@ def test_selfdestruct_not_created_in_same_tx_with_revert( recursive_revert_contract_code: Bytecode, ): """ - Same test as selfdestruct_created_in_same_tx_with_revert except selfdestructable contract - is pre-existing. + Same test as selfdestruct_created_in_same_tx_with_revert except + selfdestructable contract is pre-existing. """ entry_code = Op.CALL( Op.GASLIMIT(), @@ -477,7 +486,8 @@ def test_selfdestruct_not_created_in_same_tx_with_revert( code=selfdestruct_with_transfer_contract_code, storage=Storage( { - # 2 value transfers: 1 in outer call, 1 in reverted inner call + # 2 value transfers: 1 in outer call, 1 in reverted inner + # call 0: 1, # type: ignore # 1 selfdestruct in reverted inner call 1: 1, # type: ignore @@ -493,9 +503,11 @@ def test_selfdestruct_not_created_in_same_tx_with_revert( code=selfdestruct_with_transfer_contract_code, storage=Storage( { - # 2 value transfers: 1 in outer call, 1 in reverted inner call + # 2 value transfers: + # 1 in outer call, 1 in reverted inner call 0: 1, # type: ignore - # 2 selfdestructs: 1 in outer call, 1 in reverted inner call # noqa SC100 + # 2 selfdestructs: + # 1 in outer call, 1 in reverted inner call 1: 0, # type: ignore } ), diff --git a/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py b/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py index 6f1f170ed8..8fc048309b 100644 --- a/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py +++ b/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py @@ -1,8 +1,8 @@ """ -abstract: Tests [EIP-7516: BLOBBASEFEE opcode](https://eips.ethereum.org/EIPS/eip-7516) - Test BLOBGASFEE opcode [EIP-7516: BLOBBASEFEE opcode](https://eips.ethereum.org/EIPS/eip-7516). +BLOBBASEFEE opcode tests. -""" # noqa: E501 +Tests for [EIP-7516: BLOBBASEFEE opcode](https://eips.ethereum.org/EIPS/eip-7516). +""" from itertools import count @@ -57,13 +57,19 @@ def caller_code( @pytest.fixture def caller_pre_storage() -> Storage: - """Storage of the account containing the bytecode that calls the test contract.""" + """ + Storage of the account containing the bytecode that calls the test + contract. + """ return Storage() @pytest.fixture def caller_address(pre: Alloc, caller_code: Bytecode, caller_pre_storage) -> Address: - """Address of the account containing the bytecode that calls the test contract.""" + """ + Address of the account containing the bytecode that calls the test + contract. + """ return pre.deploy_contract(caller_code) @@ -96,7 +102,10 @@ def test_blobbasefee_stack_overflow( tx: Transaction, call_fails: bool, ): - """Tests that the BLOBBASEFEE opcode produces a stack overflow by using it repeatedly.""" + """ + Tests that the BLOBBASEFEE opcode produces a stack overflow by using it + repeatedly. + """ post = { caller_address: Account( storage={1: 0 if call_fails else 1}, @@ -155,7 +164,10 @@ def test_blobbasefee_before_fork( callee_address: Address, tx: Transaction, ): - """Tests that the BLOBBASEFEE opcode results on exception when called before the fork.""" + """ + Tests that the BLOBBASEFEE opcode results on exception when called before + the fork. + """ # Fork happens at timestamp 15_000 timestamp = 7_500 post = { @@ -193,8 +205,8 @@ def test_blobbasefee_during_fork( tx: Transaction, ): """ - Tests that the BLOBBASEFEE opcode results on exception when called before the fork and - succeeds when called after the fork. + Tests that the BLOBBASEFEE opcode results on exception when called before + the fork and succeeds when called after the fork. """ code_caller_post_storage = Storage() diff --git a/constantinople/eip1014_create2/__init__.py b/constantinople/eip1014_create2/__init__.py index c63c990d8b..724704b181 100644 --- a/constantinople/eip1014_create2/__init__.py +++ b/constantinople/eip1014_create2/__init__.py @@ -1,5 +1,3 @@ """ -abstract: Test [EIP-1014: Skinny CREATE2](https://eips.ethereum.org/EIPS/eip-1014). - - Tests for [EIP-1014: Skinny CREATE2](https://eips.ethereum.org/EIPS/eip-1014). +Tests for [EIP-1014: Skinny CREATE2](https://eips.ethereum.org/EIPS/eip-1014). """ diff --git a/constantinople/eip1014_create2/test_create_returndata.py b/constantinople/eip1014_create2/test_create_returndata.py index 3e64af7dae..99b6690d05 100644 --- a/constantinople/eip1014_create2/test_create_returndata.py +++ b/constantinople/eip1014_create2/test_create_returndata.py @@ -1,7 +1,7 @@ """ -Return data management around create2 -Port call_outsize_then_create2_successful_then_returndatasizeFiller.json test -Port call_then_create2_successful_then_returndatasizeFiller.json test. +Return data management around create2 Port +call_outsize_then_create2_successful_then_returndatasizeFiller.json test Port +call_then_create2_successful_then_returndatasizeFiller.json test. """ import pytest @@ -36,7 +36,10 @@ def test_create2_return_data( pre: Alloc, state_test: StateTestFiller, ): - """Validate that create2 return data does not interfere with previously existing memory.""" + """ + Validate that create2 return data does not interfere with previously + existing memory. + """ # Storage vars slot_returndatasize_before_create = 0 slot_returndatasize_after_create = 1 @@ -104,7 +107,8 @@ def test_create2_return_data( slot_returndatacopy_before_create: expected_returndatacopy, slot_returndatacopy_before_create_2: 0, # - # the actual bytes returned by returndatacopy opcode after create + # the actual bytes returned by returndatacopy opcode after + # create slot_returndatacopy_after_create: ( return_data_in_create if return_type_in_create == Op.REVERT else 0 ), @@ -122,7 +126,8 @@ def test_create2_return_data( else keccak256(int.to_bytes(return_data_in_create, 32, byteorder="big")) ), # - # check that create 2 didn't mess up with initial memory space declared for return + # check that create 2 didn't mess up with initial memory space + # declared for return slot_begin_memory_after_create: expected_returndatacopy, } # type: ignore ) diff --git a/constantinople/eip1014_create2/test_recreate.py b/constantinople/eip1014_create2/test_recreate.py index 702eca9bb7..116bbeb452 100644 --- a/constantinople/eip1014_create2/test_recreate.py +++ b/constantinople/eip1014_create2/test_recreate.py @@ -30,8 +30,8 @@ def test_recreate( recreate_on_separate_block: bool, ): """ - Test that the storage is cleared when a contract is first destructed then re-created using - CREATE2. + Test that the storage is cleared when a contract is first destructed then + re-created using CREATE2. """ creator_contract_code = Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + Op.CREATE2( 0, 0, Op.CALLDATASIZE, 0 diff --git a/constantinople/eip145_bitwise_shift/__init__.py b/constantinople/eip145_bitwise_shift/__init__.py index 5fc43725bb..bdca58cbe6 100644 --- a/constantinople/eip145_bitwise_shift/__init__.py +++ b/constantinople/eip145_bitwise_shift/__init__.py @@ -1,5 +1,3 @@ """ -abstract: Test [EIP-145: Bitwise shifting instructions in EVM](https://eips.ethereum.org/EIPS/eip-145). - - Tests for [EIP-145: Bitwise shifting instructions in EVM](https://eips.ethereum.org/EIPS/eip-145). +Test [EIP-145: Bitwise shifting instructions in EVM](https://eips.ethereum.org/EIPS/eip-145). """ diff --git a/constantinople/eip145_bitwise_shift/spec.py b/constantinople/eip145_bitwise_shift/spec.py index 5b272a9e22..b8649ae2ad 100644 --- a/constantinople/eip145_bitwise_shift/spec.py +++ b/constantinople/eip145_bitwise_shift/spec.py @@ -21,8 +21,8 @@ class Spec: https://eips.ethereum.org/EIPS/eip-145. """ - # Below are GPT o4-mini-high implementation of shift functions - # It can contain bugs, treat it with caution and refer to EVM implementations + # Below are GPT o4-mini-high implementation of shift functions It can + # contain bugs, treat it with caution and refer to EVM implementations @staticmethod def sar(shift: int, value: int) -> int: """ diff --git a/frontier/create/test_create_one_byte.py b/frontier/create/test_create_one_byte.py index 0cd90521e1..2c3a1312f4 100644 --- a/frontier/create/test_create_one_byte.py +++ b/frontier/create/test_create_one_byte.py @@ -1,6 +1,6 @@ """ -The test calls CREATE in a loop deploying 1-byte contracts with all possible byte values, -records in storage the values that failed to deploy. +The test calls CREATE in a loop deploying 1-byte contracts with all possible +byte values, records in storage the values that failed to deploy. """ import pytest diff --git a/frontier/identity_precompile/common.py b/frontier/identity_precompile/common.py index 6aef16f982..be7dc17c42 100644 --- a/frontier/identity_precompile/common.py +++ b/frontier/identity_precompile/common.py @@ -39,17 +39,18 @@ def generate_identity_call_bytecode( call_succeeds: bool, ) -> Bytecode: """ - Generate bytecode for calling the identity precompile with given memory values. + Generate bytecode for calling the identity precompile with given memory + values. Args: - storage (Storage): The storage object to use for storing values. - call_type (Op): The type of call opcode (CALL or CALLCODE). - memory_values (Tuple[int, ...]): Values to store in memory before the call. - call_args (CallArgs): Arguments for the CALL opcode. - call_succeeds (bool): Whether the call should succeed or not. + storage (Storage): The storage object to use for storing values. + call_type (Op): The type of call opcode (CALL or CALLCODE). + memory_values(Tuple[int, ...]): Values to store in memory before + the call. + call_args(CallArgs): Arguments for the CALL opcode. + call_succeeds (bool): Whether the call should succeed or not. - Returns: - Bytecode: The generated bytecode for the identity precompile call. + Returns: Bytecode: The generated bytecode for the identity precompile call. """ code = Bytecode() @@ -65,7 +66,8 @@ def generate_identity_call_bytecode( if mstore_count > i + 1: mstore_offset += 0x20 - # Call the identity precompile, then check that the last value in memory has not changed + # Call the identity precompile, then check that the last value in memory + # has not changed code += ( Op.SSTORE( storage.store_next(call_succeeds), diff --git a/frontier/identity_precompile/test_identity.py b/frontier/identity_precompile/test_identity.py index dc3222cfaf..653c763564 100644 --- a/frontier/identity_precompile/test_identity.py +++ b/frontier/identity_precompile/test_identity.py @@ -1,4 +1,4 @@ -"""abstract: Test identity precompile output size.""" +"""Test identity precompile output size.""" from typing import Tuple @@ -118,7 +118,10 @@ def test_call_identity_precompile( tx_gas_limit: int, contract_balance: int, ): - """Test identity precompile RETURNDATA is sized correctly based on the input size.""" + """ + Test identity precompile RETURNDATA is sized correctly based on the input + size. + """ env = Environment() storage = Storage() diff --git a/frontier/identity_precompile/test_identity_returndatasize.py b/frontier/identity_precompile/test_identity_returndatasize.py index 45538b0c94..6e352664dc 100644 --- a/frontier/identity_precompile/test_identity_returndatasize.py +++ b/frontier/identity_precompile/test_identity_returndatasize.py @@ -1,4 +1,4 @@ -"""abstract: Test identity precompile output size.""" +"""Test identity precompile output size.""" import pytest @@ -37,7 +37,10 @@ def test_identity_precompile_returndata( output_size: int, expected_returndatasize: int, ): - """Test identity precompile RETURNDATA is sized correctly based on the input size.""" + """ + Test identity precompile RETURNDATA is sized correctly based on the input + size. + """ env = Environment() storage = Storage() diff --git a/frontier/opcodes/test_all_opcodes.py b/frontier/opcodes/test_all_opcodes.py index 458c332dd3..1d0301c7ce 100644 --- a/frontier/opcodes/test_all_opcodes.py +++ b/frontier/opcodes/test_all_opcodes.py @@ -1,6 +1,6 @@ """ -Call every possible opcode and test that the subcall is successful -if the opcode is supported by the fork supports and fails otherwise. +Call every possible opcode and test that the subcall is successful if the +opcode is supported by the fork supports and fails otherwise. """ from typing import Dict @@ -56,9 +56,9 @@ def prepare_suffix(opcode: Opcode) -> Bytecode: @pytest.mark.valid_from("Frontier") def test_all_opcodes(state_test: StateTestFiller, pre: Alloc, fork: Fork): """ - Test each possible opcode on the fork with a single contract that - calls each opcode in succession. Check that each subcall passes - if the opcode is supported and fails otherwise. + Test each possible opcode on the fork with a single contract that calls + each opcode in succession. Check that each subcall passes if the opcode is + supported and fails otherwise. """ code_worked = 1000 @@ -75,8 +75,8 @@ def test_all_opcodes(state_test: StateTestFiller, pre: Alloc, fork: Fork): code=sum( Op.SSTORE( Op.PUSH1(opcode.int()), - # Limit gas to limit the gas consumed by the exceptional aborts in each - # subcall that uses an undefined opcode. + # Limit gas to limit the gas consumed by the exceptional aborts + # in each subcall that uses an undefined opcode. Op.CALL(35_000, opcode_address, 0, 0, 0, 0, 0), ) for opcode, opcode_address in code_contract.items() diff --git a/frontier/opcodes/test_call.py b/frontier/opcodes/test_call.py index e7feb662db..e5fead6786 100644 --- a/frontier/opcodes/test_call.py +++ b/frontier/opcodes/test_call.py @@ -14,8 +14,9 @@ from ethereum_test_vm import Opcodes as Op -# TODO: There's an issue with gas definitions on forks previous to Berlin, remove this when fixed. -# https://github.com/ethereum/execution-spec-tests/pull/1952#discussion_r2237634275 +# TODO: There's an issue with gas definitions on forks previous to Berlin, +# remove this when fixed. https://github.com/ethereum/execution-spec- +# tests/pull/1952#discussion_r2237634275 @pytest.mark.valid_from("Berlin") def test_call_large_offset_mstore( state_test: StateTestFiller, @@ -23,10 +24,11 @@ def test_call_large_offset_mstore( fork: Fork, ): """ - CALL with ret_offset larger than memory size and ret_size zero - Then do an MSTORE in that offset to see if memory was expanded in CALL. + CALL with ret_offset larger than memory size and ret_size zero Then do an + MSTORE in that offset to see if memory was expanded in CALL. - This is for bug in a faulty EVM implementation where memory is expanded when it shouldn't. + This is for bug in a faulty EVM implementation where memory is expanded + when it shouldn't. """ sender = pre.fund_eoa() @@ -35,14 +37,16 @@ def test_call_large_offset_mstore( call_measure = CodeGasMeasure( code=Op.CALL(gas=0, ret_offset=mem_offset, ret_size=0), - overhead_cost=gsc.G_VERY_LOW * len(Op.CALL.kwargs), # Cost of pushing CALL args + # Cost of pushing CALL args + overhead_cost=gsc.G_VERY_LOW * len(Op.CALL.kwargs), extra_stack_items=1, # Because CALL pushes 1 item to the stack sstore_key=0, stop=False, # Because it's the first CodeGasMeasure ) mstore_measure = CodeGasMeasure( code=Op.MSTORE(offset=mem_offset, value=1), - overhead_cost=gsc.G_VERY_LOW * len(Op.MSTORE.kwargs), # Cost of pushing MSTORE args + # Cost of pushing MSTORE args + overhead_cost=gsc.G_VERY_LOW * len(Op.MSTORE.kwargs), extra_stack_items=0, sstore_key=1, ) @@ -77,8 +81,9 @@ def test_call_large_offset_mstore( ) -# TODO: There's an issue with gas definitions on forks previous to Berlin, remove this when fixed. -# https://github.com/ethereum/execution-spec-tests/pull/1952#discussion_r2237634275 +# TODO: There's an issue with gas definitions on forks previous to Berlin, +# remove this when fixed. https://github.com/ethereum/execution-spec- +# tests/pull/1952#discussion_r2237634275 @pytest.mark.valid_from("Berlin") def test_call_memory_expands_on_early_revert( state_test: StateTestFiller, @@ -87,27 +92,33 @@ def test_call_memory_expands_on_early_revert( ): """ When CALL reverts early (e.g. because of not enough balance by the sender), - memory should be expanded anyway. - We check this with an MSTORE. + memory should be expanded anyway. We check this with an MSTORE. - This is for a bug in an EVM implementation where memory is expanded after executing a CALL, but - not when an early revert happens. + This is for a bug in an EVM implementation where memory is expanded after + executing a CALL, but not when an early revert happens. """ sender = pre.fund_eoa() gsc = fork.gas_costs() - ret_size = 128 # arbitrary number, greater than memory size to trigger an expansion + # arbitrary number, greater than memory size to trigger an expansion + ret_size = 128 call_measure = CodeGasMeasure( - code=Op.CALL(gas=0, value=100, ret_size=ret_size), # CALL with value - overhead_cost=gsc.G_VERY_LOW * len(Op.CALL.kwargs), # Cost of pushing CALL args - extra_stack_items=1, # Because CALL pushes 1 item to the stack + # CALL with value + code=Op.CALL(gas=0, value=100, ret_size=ret_size), + # Cost of pushing CALL args + overhead_cost=gsc.G_VERY_LOW * len(Op.CALL.kwargs), + # Because CALL pushes 1 item to the stack + extra_stack_items=1, sstore_key=0, - stop=False, # Because it's the first CodeGasMeasure + # Because it's the first CodeGasMeasure + stop=False, ) mstore_measure = CodeGasMeasure( - code=Op.MSTORE(offset=ret_size // 2, value=1), # Low offset for not expanding memory - overhead_cost=gsc.G_VERY_LOW * len(Op.MSTORE.kwargs), # Cost of pushing MSTORE args + # Low offset for not expanding memory + code=Op.MSTORE(offset=ret_size // 2, value=1), + # Cost of pushing MSTORE args + overhead_cost=gsc.G_VERY_LOW * len(Op.MSTORE.kwargs), extra_stack_items=0, sstore_key=1, ) @@ -123,7 +134,8 @@ def test_call_memory_expands_on_early_revert( ) memory_expansion_gas_calc = fork.memory_expansion_gas_calculator() - # call cost: address_access_cost + new_acc_cost + memory_expansion_cost + value - stipend + # call cost: + # address_access_cost+new_acc_cost+memory_expansion_cost+value-stipend call_cost = ( gsc.G_COLD_ACCOUNT_ACCESS + gsc.G_NEW_ACCOUNT @@ -132,7 +144,8 @@ def test_call_memory_expands_on_early_revert( - gsc.G_CALL_STIPEND ) - # mstore cost: base cost. No memory expansion cost needed, it was expanded on CALL. + # mstore cost: base cost. No memory expansion cost needed, it was expanded + # on CALL. mstore_cost = gsc.G_MEMORY state_test( env=Environment(), @@ -149,8 +162,9 @@ def test_call_memory_expands_on_early_revert( ) -# TODO: There's an issue with gas definitions on forks previous to Berlin, remove this when fixed. -# https://github.com/ethereum/execution-spec-tests/pull/1952#discussion_r2237634275 +# TODO: There's an issue with gas definitions on forks previous to Berlin, +# remove this when fixed. https://github.com/ethereum/execution-spec- +# tests/pull/1952#discussion_r2237634275 @pytest.mark.with_all_call_opcodes @pytest.mark.valid_from("Berlin") def test_call_large_args_offset_size_zero( @@ -170,7 +184,8 @@ def test_call_large_args_offset_size_zero( call_measure = CodeGasMeasure( code=call_opcode(gas=0, args_offset=very_large_offset, args_size=0), - overhead_cost=gsc.G_VERY_LOW * len(call_opcode.kwargs), # Cost of pushing xCALL args + # Cost of pushing xCALL args + overhead_cost=gsc.G_VERY_LOW * len(call_opcode.kwargs), extra_stack_items=1, # Because xCALL pushes 1 item to the stack sstore_key=0, ) diff --git a/frontier/opcodes/test_call_and_callcode_gas_calculation.py b/frontier/opcodes/test_call_and_callcode_gas_calculation.py index 740253dbb5..61ac377bac 100644 --- a/frontier/opcodes/test_call_and_callcode_gas_calculation.py +++ b/frontier/opcodes/test_call_and_callcode_gas_calculation.py @@ -1,26 +1,33 @@ """ -abstract: Tests the nested CALL/CALLCODE opcode gas consumption with a positive value transfer. - This test is designed to investigate an issue identified in EthereumJS, as reported in: - https://github.com/ethereumjs/ethereumjs-monorepo/issues/3194. - - The issue pertains to the incorrect gas calculation for CALL/CALLCODE operations with a - positive value transfer, due to the pre-addition of the gas stipend (2300) to the currently - available gas instead of adding it to the new call frame. This bug was specific to the case - where insufficient gas was provided for the CALL/CALLCODE operation. Due to the pre-addition - of the stipend to the currently available gas, the case for insufficient gas was not properly - failing with an out-of-gas error. - - Test setup: Given two smart contract accounts, 0x0A (caller) and 0x0B (callee): - 1) An arbitrary transaction calls into the contract 0x0A. - 2) Contract 0x0A executes a CALL to contract 0x0B with a specific gas limit (X). - 3) Contract 0x0B then attempts a CALL/CALLCODE to a non-existent contract 0x0C, - with a positive value transfer (activating the gas stipend). - 4) If the gas X provided by contract 0x0A to 0x0B is sufficient, contract 0x0B - will push 0x01 onto the stack after returning to the call frame in 0x0A. Otherwise, it - should push 0x00, indicating the insufficiency of gas X (for the bug in EthereumJS, the - CALL/CALLCODE operation would return 0x01 due to the pre-addition of the gas stipend). - 5) The resulting stack value is saved into contract 0x0A's storage, allowing us to - verify whether the provided gas was sufficient or insufficient. +Tests nested CALL/CALLCODE gas usage with positive value transfer. + +This test investigates an issue identified in EthereumJS, as reported in: +https://github.com/ethereumjs/ethereumjs-monorepo/issues/3194. + +The issue pertains to the incorrect gas calculation for CALL/CALLCODE +operations with a positive value transfer, due to the pre-addition of the +gas stipend (2300) to the currently available gas instead of adding it to +the new call frame. This bug was specific to the case where insufficient +gas was provided for the CALL/CALLCODE operation. Due to the pre-addition +of the stipend to the currently available gas, the case for insufficient +gas was not properly failing with an out-of-gas error. + +Test setup: + +Given two smart contract accounts, 0x0A (caller) and 0x0B (callee): +1. An arbitrary transaction calls into the contract 0x0A. +2. Contract 0x0A executes a CALL to contract 0x0B with a specific gas limit +(X). +3. Contract 0x0B then attempts a CALL/CALLCODE to a non-existent contract +0x0C, with a positive value transfer (activating the gas stipend). +4. If the gas X provided by contract 0x0A to 0x0B is sufficient, contract +0x0B will push 0x01 onto the stack after returning to the call frame in +0x0A. Otherwise, it should push 0x00, indicating the insufficiency of +gas X (for the bug in EthereumJS, the CALL/CALLCODE operation would +return 0x01 due to the pre-addition of the gas stipend). +5. The resulting stack value is saved into contract 0x0A's storage, +allowing us to verify whether the provided gas was sufficient or +insufficient. """ from typing import Dict @@ -41,13 +48,15 @@ """ PUSH opcode cost is 3, GAS opcode cost is 2. -We need 6 PUSH's and one GAS to fill the stack for both CALL & CALLCODE, in the callee contract. +We need 6 PUSH's and one GAS to fill the stack for both CALL & CALLCODE, +in the callee contract. """ CALLEE_INIT_STACK_GAS = 6 * 3 + 2 """ CALL gas breakdowns: (https://www.evm.codes/#f1) -memory_exp_cost + code_exec_cost + address_access_cost + positive_value_cost + empty_account_cost +memory_exp_cost + code_exec_cost + address_access_cost + +positive_value_cost + empty_account_cost = 0 + 0 + 2600 + 9000 + 25000 = 36600 """ CALL_GAS = 36600 @@ -55,8 +64,8 @@ """ CALLCODE gas breakdowns: (https://www.evm.codes/#f2) -memory_exp_cost + code_exec_cost + address_access_cost + positive_value_cost -= 0 + 0 + 2600 + 9000 = 11600 +memory_exp_cost + code_exec_cost + address_access_cost + +positive_value_cost = 0 + 0 + 2600 + 9000 = 11600 """ CALLCODE_GAS = 11600 CALLCODE_SUFFICIENT_GAS = CALLCODE_GAS + CALLEE_INIT_STACK_GAS @@ -66,14 +75,14 @@ def callee_code(pre: Alloc, callee_opcode: Op) -> Bytecode: """ Code called by the caller contract: - PUSH1 0x00 * 4 - PUSH1 0x01 <- for positive value transfer - PUSH2 Contract.nonexistent - GAS <- value doesn't matter - CALL/CALLCODE. + PUSH1 0x00 * 4 + PUSH1 0x01 <- for positive value transfer + PUSH2 Contract.nonexistent + GAS <- value doesn't matter + CALL/CALLCODE. """ - # The address needs to be empty and different for each execution of the fixture, - # otherwise the calculations (empty_account_cost) are incorrect. + # The address needs to be empty and different for each execution of the + # fixture, otherwise the calculations (empty_account_cost) are incorrect. return callee_opcode(Op.GAS(), pre.empty_account(), 1, 0, 0, 0, 0) @@ -93,12 +102,12 @@ def callee_address(pre: Alloc, callee_code: Bytecode) -> Address: def caller_code(caller_gas_limit: int, callee_address: Address) -> Bytecode: """ Code to CALL the callee contract: - PUSH1 0x00 * 5 - PUSH2 Contract.callee - PUSH2 caller_gas <- gas limit set for CALL to callee contract - CALL - PUSH1 0x00 - SSTORE. + PUSH1 0x00 * 5 + PUSH2 Contract.callee + PUSH2 caller_gas <- gas limit set for CALL to callee contract + CALL + PUSH1 0x00 + SSTORE. """ return Op.SSTORE(0, Op.CALL(caller_gas_limit, callee_address, 0, 0, 0, 0, 0)) @@ -107,12 +116,12 @@ def caller_code(caller_gas_limit: int, callee_address: Address) -> Bytecode: def caller_address(pre: Alloc, caller_code: Bytecode) -> Address: """ Code to CALL the callee contract: - PUSH1 0x00 * 5 - PUSH2 Contract.callee - PUSH2 caller_gas <- gas limit set for CALL to callee contract - CALL - PUSH1 0x00 - SSTORE. + PUSH1 0x00 * 5 + PUSH2 Contract.callee + PUSH2 caller_gas <- gas limit set for CALL to callee contract + CALL + PUSH1 0x00 + SSTORE. """ return pre.deploy_contract(caller_code, balance=0x03) @@ -151,5 +160,8 @@ def test_value_transfer_gas_calculation( caller_tx: Transaction, post: Dict[str, Account], ): - """Tests the nested CALL/CALLCODE opcode gas consumption with a positive value transfer.""" + """ + Tests the nested CALL/CALLCODE opcode gas consumption with a positive value + transfer. + """ state_test(env=Environment(), pre=pre, post=post, tx=caller_tx) diff --git a/frontier/opcodes/test_calldataload.py b/frontier/opcodes/test_calldataload.py index 41f03f1284..9776e66e05 100644 --- a/frontier/opcodes/test_calldataload.py +++ b/frontier/opcodes/test_calldataload.py @@ -53,10 +53,15 @@ def test_calldataload( Test `CALLDATALOAD` opcode. Tests two scenarios: - - calldata_source is "contract": CALLDATALOAD reads from calldata passed by another contract - - calldata_source is "tx": CALLDATALOAD reads directly from transaction calldata + - calldata_source is "contract": CALLDATALOAD reads from calldata + passed by another contract + - calldata_source is "tx": CALLDATALOAD reads directly from + transaction calldata - Based on https://github.com/ethereum/tests/blob/ae4791077e8fcf716136e70fe8392f1a1f1495fb/src/GeneralStateTestsFiller/VMTests/vmTests/calldatacopyFiller.yml + Based on + https://github.com/ethereum/tests/blob/ + ae4791077e8fcf716136e70fe8392f1a1f1495fb/src/ + GeneralStateTestsFiller/VMTests/vmTests/calldatacopyFiller.yml """ contract_address = pre.deploy_contract( Op.SSTORE(0, Op.CALLDATALOAD(offset=calldata_offset)) + Op.STOP, diff --git a/frontier/opcodes/test_calldatasize.py b/frontier/opcodes/test_calldatasize.py index d06a7330da..2106524015 100644 --- a/frontier/opcodes/test_calldatasize.py +++ b/frontier/opcodes/test_calldatasize.py @@ -30,10 +30,15 @@ def test_calldatasize( Test `CALLDATASIZE` opcode. Tests two scenarios: - - calldata_source is "contract": CALLDATASIZE reads from calldata passed by another contract - - calldata_source is "tx": CALLDATASIZE reads directly from transaction calldata + - calldata_source is "contract": CALLDATASIZE reads from calldata + passed by another contract + - calldata_source is "tx": CALLDATASIZE reads directly from + transaction calldata - Based on https://github.com/ethereum/tests/blob/81862e4848585a438d64f911a19b3825f0f4cd95/src/GeneralStateTestsFiller/VMTests/vmTests/calldatasizeFiller.yml + Based on + https://github.com/ethereum/tests/blob/ + 81862e4848585a438d64f911a19b3825f0f4cd95/src/ + GeneralStateTestsFiller/VMTests/vmTests/calldatasizeFiller.yml """ contract_address = pre.deploy_contract(Op.SSTORE(key=0x0, value=Op.CALLDATASIZE)) calldata = b"\x01" * args_size diff --git a/frontier/opcodes/test_dup.py b/frontier/opcodes/test_dup.py index a4d3d3e85f..ee8cbd3c14 100644 --- a/frontier/opcodes/test_dup.py +++ b/frontier/opcodes/test_dup.py @@ -1,8 +1,4 @@ -""" -abstract: Test DUP - Test the DUP opcodes. - -""" +"""Test DUP Test the DUP opcodes.""" import pytest @@ -43,9 +39,13 @@ def test_dup( """ Test the DUP1-DUP16 opcodes. - Note: Test case ported from [ethereum/tests](https://github.com/ethereum/tests) - Test ported from [ethereum/tests/GeneralStateTests/VMTests/vmTests/dup.json](https://github.com/ethereum/tests/blob/v14.0/GeneralStateTests/VMTests/vmTests/dup.json) by Ori Pomerantz. - """ # noqa: E501 + Note: Test case ported from + [ethereum/tests](https://github.com/ethereum/tests). + + Test ported from [ethereum/tests/GeneralStateTests/VMTests/ + vmTests/dup.json](https://github.com/ethereum/tests/blob/ + v14.0/GeneralStateTests/VMTests/vmTests/dup.json) by Ori Pomerantz. + """ env = Environment() sender = pre.fund_eoa() post = {} diff --git a/frontier/opcodes/test_push.py b/frontier/opcodes/test_push.py index a97abaa982..fc407f9c4d 100644 --- a/frontier/opcodes/test_push.py +++ b/frontier/opcodes/test_push.py @@ -1,7 +1,11 @@ """ A State test for the set of `PUSH*` opcodes. -Ported from: https://github.com/ethereum/tests/blob/4f65a0a7cbecf4442415c226c65e089acaaf6a8b/src/GeneralStateTestsFiller/VMTests/vmTests/pushFiller.yml. -""" # noqa: E501 + +Ported from: +https://github.com/ethereum/tests/blob/ +4f65a0a7cbecf4442415c226c65e089acaaf6a8b/src/ +GeneralStateTestsFiller/VMTests/vmTests/pushFiller.yml. +""" import pytest @@ -30,7 +34,8 @@ def get_input_for_push_opcode(opcode: Op) -> bytes: ) @pytest.mark.parametrize( "push_opcode", - [getattr(Op, f"PUSH{i}") for i in range(1, 33)], # Dynamically parametrize PUSH opcodes + # Dynamically parametrize PUSH opcodes + [getattr(Op, f"PUSH{i}") for i in range(1, 33)], ids=lambda op: str(op), ) @pytest.mark.valid_from("Frontier") @@ -38,9 +43,8 @@ def test_push(state_test: StateTestFiller, fork: Fork, pre: Alloc, push_opcode: """ The set of `PUSH*` opcodes pushes data onto the stack. - In this test, we ensure that the set of `PUSH*` opcodes writes - a portion of an excerpt from the Ethereum yellow paper to - storage. + In this test, we ensure that the set of `PUSH*` opcodes writes a portion of + an excerpt from the Ethereum yellow paper to storage. """ # Input used to test the `PUSH*` opcode. excerpt = get_input_for_push_opcode(push_opcode) @@ -90,19 +94,24 @@ def test_push(state_test: StateTestFiller, fork: Fork, pre: Alloc, push_opcode: def test_stack_overflow( state_test: StateTestFiller, fork: Fork, pre: Alloc, push_opcode: Op, stack_height: int ): - """A test to ensure that the stack overflows when the stack limit of 1024 is exceeded.""" + """ + A test the stack overflows when the stack limit of 1024 is exceeded. + """ env = Environment() # Input used to test the `PUSH*` opcode. excerpt = get_input_for_push_opcode(push_opcode) """ - Essentially write a n-byte message to storage by pushing [1024,1025] times to stack. This - simulates a "jump" over the stack limit of 1024. - The message is UTF-8 encoding of excerpt (say 0x45 for PUSH1). Within the stack limit, - the message is written to the to the storage at the same offset (0x45 for PUSH1). - The last iteration will overflow the stack and the storage slot will be empty. + + Essentially write a n-byte message to storage by pushing [1024,1025] times + to stack. This simulates a "jump" over the stack limit of 1024. + + The message is UTF-8 encoding of excerpt (say 0x45 for PUSH1). Within the + stack limit, the message is written to the to the storage at the same + offset (0x45 for PUSH1). The last iteration will overflow the stack and the + storage slot will be empty. ** Bytecode explanation ** +---------------------------------------------------+ @@ -115,7 +124,8 @@ def test_stack_overflow( """ contract_code: Bytecode = Bytecode() for _ in range(stack_height - 2): - contract_code += Op.PUSH1(0) # mostly push 0 to avoid contract size limit exceeded + # mostly push 0 to avoid contract size limit exceeded + contract_code += Op.PUSH1(0) contract_code += push_opcode(excerpt) * 2 + Op.SSTORE contract = pre.deploy_contract(contract_code) diff --git a/frontier/opcodes/test_selfdestruct.py b/frontier/opcodes/test_selfdestruct.py index e165684a0d..bedddbf679 100644 --- a/frontier/opcodes/test_selfdestruct.py +++ b/frontier/opcodes/test_selfdestruct.py @@ -10,9 +10,9 @@ @pytest.mark.valid_until("Homestead") def test_double_kill(blockchain_test: BlockchainTestFiller, pre: Alloc): """ - Test that when two transactions attempt to destruct a contract, - the second transaction actually resurrects the contract as an empty account (prior to Spurious - Dragon). + Test that when two transactions attempt to destruct a contract, the second + transaction actually resurrects the contract as an empty account (prior to + Spurious Dragon). """ sender = pre.fund_eoa() diff --git a/frontier/precompiles/test_precompile_absence.py b/frontier/precompiles/test_precompile_absence.py index 1982ad2f21..46b9dd44ec 100644 --- a/frontier/precompiles/test_precompile_absence.py +++ b/frontier/precompiles/test_precompile_absence.py @@ -1,4 +1,4 @@ -"""abstract: Test Calling Precompile Range (close to zero).""" +"""Test Calling Precompile Range (close to zero).""" import pytest @@ -33,7 +33,10 @@ def test_precompile_absence( fork: Fork, calldata_size: int, ): - """Test that addresses close to zero are not precompiles unless active in the fork.""" + """ + Test that addresses close to zero are not precompiles unless active in the + fork. + """ active_precompiles = fork.precompiles() storage = Storage() call_code = Bytecode() diff --git a/frontier/precompiles/test_precompiles.py b/frontier/precompiles/test_precompiles.py index 24ef1b0045..b7ba6b9142 100644 --- a/frontier/precompiles/test_precompiles.py +++ b/frontier/precompiles/test_precompiles.py @@ -18,14 +18,16 @@ def precompile_addresses(fork: Fork) -> Iterator[Tuple[Address, bool]]: """ - Yield the addresses of precompiled contracts and their support status for a given fork. + Yield the addresses of precompiled contracts and their support status for a + given fork. Args: - fork (Fork): The fork instance containing precompiled contract information. + fork (Fork): The fork instance containing precompiled + contract information. - Yields: - Iterator[Tuple[str, bool]]: A tuple containing the address in hexadecimal format and a - boolean indicating whether the address is a supported precompile. + Yields: Iterator[Tuple[str, bool]]: A tuple containing the address in + hexadecimal format and a boolean indicating whether the address is a + supported precompile. """ supported_precompiles = fork.precompiles() @@ -60,17 +62,19 @@ def test_precompiles( Tests the behavior of precompiled contracts in the Ethereum state test. Args: - state_test (StateTestFiller): The state test filler object used to run the test. - address (str): The address of the precompiled contract to test. - precompile_exists (bool): A flag indicating whether the precompiled contract exists at the - given address. - pre (Alloc): The allocation object used to deploy the contract and set up the initial - state. - - This test deploys a contract that performs two CALL operations to the specified address and a - fixed address (0x10000), measuring the gas used for each call. It then stores the difference - in gas usage in storage slot 0. The test verifies the expected storage value based on - whether the precompiled contract exists at the given address. + state_test (StateTestFiller): The state test filler object used to + run the test. + address (str): The address of the precompiled contract to test. + precompile_exists (bool): A flag indicating whether the precompiled + contract exists at the given address. + pre (Alloc): The allocation object used to deploy the contract and + set up the initial state. + + This test deploys a contract that performs two CALL operations to the + specified address and a fixed address (0x10000), measuring the gas used for + each call. It then stores the difference in gas usage in storage slot 0. + The test verifies the expected storage value based on whether the + precompiled contract exists at the given address. """ env = Environment() diff --git a/frontier/scenarios/common.py b/frontier/scenarios/common.py index 7142ca685e..1d7a95296c 100644 --- a/frontier/scenarios/common.py +++ b/frontier/scenarios/common.py @@ -30,9 +30,9 @@ class ScenarioExpectOpcode(Enum): @dataclass class ScenarioEnvironment: """ - Scenario evm environment - Each scenario must define an environment on which program is executed - This is so post state verification could check results of evm opcodes. + Scenario evm environment Each scenario must define an environment on which + program is executed This is so post state verification could check results + of evm opcodes. """ code_address: Address # Op.ADDRESS, address scope for program @@ -63,9 +63,10 @@ class ProgramResult: Describe expected result of a program. Attributes: - result (int | ScenarioExpectOpcode): The result of the program - from_fork (Fork): The result is only valid from this fork (default: Frontier) - static_support (bool): Can be verified in static context (default: True) + result (int | ScenarioExpectOpcode): The result of the program + from_fork (Fork): The result is only valid from this fork + (default: Frontier) + static_support (bool): Can be verified in static context (default: True) """ @@ -79,8 +80,8 @@ def translate_result( self, env: ScenarioEnvironment, exec_env: ExecutionEnvironment ) -> int | Address: """ - Translate expected program result code into concrete value, - given the scenario evm environment and test execution environment. + Translate expected program result code into concrete value, given the + scenario evm environment and test execution environment. """ if exec_env.fork < self.from_fork: return 0 @@ -154,10 +155,10 @@ class ScenarioGeneratorInput: Parameters for the scenario generator function. Attributes: - fork (Fork): Fork for which we ask to generate scenarios - pre (Alloc): Access to the state to be able to deploy contracts into pre - operation (Bytecode): Evm bytecode program that will be tested - external_address (Address): Static external address for ext opcodes + fork (Fork): Fork for which we ask to generate scenarios + pre(Alloc): Access to the state to be able to deploy contracts into pre + operation (Bytecode): Evm bytecode program that will be tested + external_address (Address): Static external address for ext opcodes """ @@ -172,11 +173,12 @@ class Scenario: Describe test scenario that will be run in test for each program. Attributes: - category (str): Scenario category name - name (str): Scenario name for the test vector - code (Address): Address that is an entry point for scenario code - env (ScenarioEnvironment): Evm values for ScenarioExpectAddress map - reverting (bool): If scenario reverts program execution, making result 0 (default: False) + category (str): Scenario category name + name (str): Scenario name for the test vector + code (Address): Address that is an entry point for scenario code + env (ScenarioEnvironment): Evm values for ScenarioExpectAddress map + reverting (bool): If scenario reverts program execution, + making result 0 (default: False) """ @@ -189,10 +191,10 @@ class Scenario: def make_gas_hash_contract(pre: Alloc) -> Address: """ - Contract that spends unique amount of gas based on input - Used for the values we can't predict, can be gas consuming on high values - So that if we can't check exact value in expect section, - we at least could spend unique gas amount. + Contract that spends unique amount of gas based on input. + Used for the values we can't predict, can be gas consuming on high values. + So that if we can't check exact value in expect section, we at least + could spend unique gas amount. """ gas_hash_address = pre.deploy_contract( code=Op.MSTORE(0, 0) @@ -215,8 +217,9 @@ def make_gas_hash_contract(pre: Alloc) -> Address: def make_invalid_opcode_contract(pre: Alloc, fork: Fork) -> Address: """ - Deploy a contract that will execute any asked byte as an opcode from calldataload - Deploy 20 empty stack elements. Jump to opcode instruction. if worked, return 0. + Deploy a contract that will execute any asked byte as an opcode from + calldataload Deploy 20 empty stack elements. Jump to opcode instruction. if + worked, return 0. """ invalid_opcode_caller = pre.deploy_contract( code=Op.PUSH1(0) * 20 diff --git a/frontier/scenarios/programs/all_frontier_opcodes.py b/frontier/scenarios/programs/all_frontier_opcodes.py index 83978c7509..72d8fa459a 100644 --- a/frontier/scenarios/programs/all_frontier_opcodes.py +++ b/frontier/scenarios/programs/all_frontier_opcodes.py @@ -1,4 +1,7 @@ -"""Define a program for scenario test that executes all frontier opcodes and entangles it's result.""" # noqa: E501 +""" +Define a program for scenario test that executes all frontier opcodes and +entangles it's result. +""" from functools import cached_property @@ -15,7 +18,9 @@ def make_all_opcode_program() -> Bytecode: - """Make a program that call each Frontier opcode and verifies it's result.""" + """ + Make a program that call each Frontier opcode and verifies it's result. + """ code: Bytecode = ( # Test opcode 01 - ADD Conditional( diff --git a/frontier/scenarios/programs/context_calls.py b/frontier/scenarios/programs/context_calls.py index 0693d18110..ea4d893838 100644 --- a/frontier/scenarios/programs/context_calls.py +++ b/frontier/scenarios/programs/context_calls.py @@ -15,7 +15,9 @@ class ProgramAddress(ScenarioTestProgram): - """Check that ADDRESS is really the code execution address in all scenarios.""" + """ + Check that ADDRESS is really the code execution address in all scenarios. + """ def make_test_code(self, pre: Alloc, fork: Fork) -> Bytecode: """Test code.""" diff --git a/frontier/scenarios/scenarios/call_combinations.py b/frontier/scenarios/scenarios/call_combinations.py index e8e091307c..318c48d08e 100644 --- a/frontier/scenarios/scenarios/call_combinations.py +++ b/frontier/scenarios/scenarios/call_combinations.py @@ -55,15 +55,17 @@ def __init__(self, scenario_input: ScenarioGeneratorInput): def generate(self) -> List[Scenario]: """ - Generate Scenarios for call combinations - We take code that we want to test at scenario_input.operation_contract - and put it in the context of call combinations. + Generate Scenarios for call combinations We take code that we want to + test at scenario_input.operation_contract and put it in the context of + call combinations. Example: - root_contract -> call -> scenario_contract -> first_call -> sub_contract - sub_contact -> second_call -> code - We assume that code always returns it's result - That we pass as return value in scenario_contract for the post state verification + root_contract -> call -> scenario_contract -> first_call -> + sub_contract sub_contact -> second_call -> code + + We assume that code always returns its result. + That we pass as return value in scenario_contract for the + post state verification. """ scenarios_list: List[Scenario] = [] @@ -80,8 +82,8 @@ def generate(self) -> List[Scenario]: def _generate_one_call_scenario(self, first_call: Opcode) -> Scenario: """ - Generate scenario for only one call - root_contract -(CALL)-> scenario_contract -(first_call)-> operation_contract. + Generate scenario for only one call root_contract -(CALL)-> + scenario_contract -(first_call)-> operation_contract. """ scenario_input: ScenarioGeneratorInput = self.scenario_input pre: Alloc = scenario_input.pre @@ -162,15 +164,16 @@ def _generate_one_call_scenario(self, first_call: Opcode) -> Scenario: def _generate_two_call_scenario(self, first_call: Opcode, second_call: Opcode) -> Scenario: """ - Generate scenario for two types of calls combination - root_contract -(CALL)-> scenario_contract -(first_call)-> sub_contract - sub_contract -(second_call) -> operation_contract. + Generate scenario for two types of calls combination root_contract + -(CALL)-> scenario_contract -(first_call)-> sub_contract sub_contract + -(second_call) -> operation_contract. """ def _compute_code_caller() -> Address: """ - Calculate who is the code caller in program_contract's code in given sequence - root -CALL-> scenario_contract -(first_call)-> sub_contract -(second_call)-> program. + Calculate who is the code caller in program_contract's code in + given sequence root -CALL-> scenario_contract -(first_call) + -> sub_contract -(second_call)-> program. """ code_caller: Address = root_contract if first_call == Op.DELEGATECALL: @@ -188,8 +191,9 @@ def _compute_code_caller() -> Address: def _compute_selfbalance() -> int: """ - Calculate the result of Op.SELFBALANCE in program scope in given sequence - root -CALL-> scenario_contract -(first_call)-> sub_contract -(second_call)-> program. + Calculate the result of Op.SELFBALANCE in program scope in given + sequence root -CALL-> scenario_contract -(first_call)-> + sub_contract -(second_call)-> program. """ selfbalance: int = 0 if second_call in [Op.CALL]: @@ -214,7 +218,8 @@ def _compute_selfbalance() -> int: def _compute_callvalue() -> int: """ Calculate the expected callvalue in program scope given sequence: - root -CALL-> scenario_contract -(first_call)-> sub_contract -(second_call)-> program. + root -CALL-> scenario_contract -(first_call)-> sub_contract + -(second_call)-> program. """ if second_call == Op.STATICCALL: return 0 diff --git a/frontier/scenarios/scenarios/create_combinations.py b/frontier/scenarios/scenarios/create_combinations.py index d560391324..0a5040a873 100644 --- a/frontier/scenarios/scenarios/create_combinations.py +++ b/frontier/scenarios/scenarios/create_combinations.py @@ -27,7 +27,10 @@ def scenarios_create_combinations(scenario_input: ScenarioGeneratorInput) -> Lis """Generate Scenarios for create combinations.""" def _compute_selfbalance() -> int: - """Compute selfbalance opcode for root -> call -> scenario -> create | [call*] -> program.""" # noqa: E501 + """ + Compute selfbalance opcode for root -> call -> scenario -> + create | [call*] -> program. + """ if call in [Op.DELEGATECALL, Op.CALLCODE]: return ( balance.scenario_contract_balance + balance.root_call_value - balance.create_value @@ -51,7 +54,8 @@ def _compute_selfbalance() -> int: salt = [0] if create == Op.CREATE2 else [] operation_contract = scenario_input.pre.deploy_contract(code=scenario_input.operation_code) - # the code result in init code will be actually code of a deployed contract + # the code result in init code will be actually code of a deployed + # contract scenario_contract = scenario_input.pre.deploy_contract( balance=3, code=Op.EXTCODECOPY(operation_contract, 0, 0, Op.EXTCODESIZE(operation_contract)) diff --git a/frontier/scenarios/test_scenarios.py b/frontier/scenarios/test_scenarios.py index 585aa6aab7..bb820d81d0 100644 --- a/frontier/scenarios/test_scenarios.py +++ b/frontier/scenarios/test_scenarios.py @@ -1,6 +1,6 @@ """ -Call every possible opcode and test that the subcall is successful -if the opcode is supported by the fork and fails otherwise. +Call every possible opcode and test that the subcall is successful if the +opcode is supported by the fork and fails otherwise. """ from typing import List @@ -76,7 +76,10 @@ @pytest.fixture def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List[Scenario]: - """Define fixture vectors of all possible scenarios, given the current pre state input.""" + """ + Define fixture vectors of all possible scenarios, given the current pre + state input. + """ scenarios_list: List[Scenario] = [] scenario_input = ScenarioGeneratorInput( @@ -118,9 +121,13 @@ def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List @pytest.mark.valid_from("Frontier") @pytest.mark.parametrize( # select program to debug ("program_id","scenario_name") - # program="" select all programs - # scenario_name="" select all scenarios - # Example: [ScenarioDebug(program_id=ProgramSstoreSload().id, scenario_name="scenario_CALL_CALL")], # noqa: E501 + # program="" + # select all programs scenario_name="" + # select all scenarios + # + # Example: + # [ScenarioDebug(program_id=ProgramSstoreSload().id, + # scenario_name="scenario_CALL_CALL")] "debug", [ ScenarioDebug( @@ -178,13 +185,13 @@ def test_scenarios( scenarios, ): """ - Test given operation in different scenarios - Verify that it's return value equal to expected result on every scenario, - that is valid for the given fork. + Test given operation in different scenarios Verify that it's return value + equal to expected result on every scenario, that is valid for the given + fork. - Note: Don't use pytest parametrize for scenario production, because scenarios will be complex - Generate one test file for [each operation] * [each scenario] to save space - As well as operations will be complex too + Note: Don't use pytest parametrize for scenario production, because + scenarios will be complex Generate one test file for [each operation] * + [each scenario] to save space As well as operations will be complex too """ tx_env = Environment() tx_origin: Address = pre.fund_eoa() @@ -213,7 +220,8 @@ def test_scenarios( fork=fork, origin=tx_origin, gasprice=tx_gasprice, - timestamp=tx_env.timestamp, # we can't know timestamp before head, use gas hash + timestamp=tx_env.timestamp, # we can't know timestamp before head, + # use gas hash number=len(blocks) + 1, gaslimit=tx_env.gas_limit, coinbase=tx_env.fee_recipient, diff --git a/homestead/coverage/test_coverage.py b/homestead/coverage/test_coverage.py index b0120d113f..5274307642 100644 --- a/homestead/coverage/test_coverage.py +++ b/homestead/coverage/test_coverage.py @@ -1,4 +1,7 @@ -"""Tests that address coverage gaps that result from updating `ethereum/tests` into EEST tests.""" +""" +Tests that address coverage gaps that result from updating `ethereum/tests` +into EEST tests. +""" import pytest @@ -17,11 +20,11 @@ def test_coverage( fork: Fork, ): """ - Cover gaps that result from transforming Yul code into - our Python opcode wrapper bytecode. + Cover gaps that result from transforming Yul code into our Python opcode + wrapper bytecode. - E.g. Yul tends to optimize stack items by using `SWAP1` and `DUP1` opcodes, which are not - regularly used in python code. + E.g. Yul tends to optimize stack items by using `SWAP1` and `DUP1` opcodes, + which are not regularly used in python code. Modify this test to cover more Yul code if required in the future. """ diff --git a/istanbul/eip1344_chainid/__init__.py b/istanbul/eip1344_chainid/__init__.py index bb41fcd2e7..3669063cbe 100644 --- a/istanbul/eip1344_chainid/__init__.py +++ b/istanbul/eip1344_chainid/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-1344: ChainID Opcode](https://eips.ethereum.org/EIPS/eip-1344) - Test cases for [EIP-1344: ChainID Opcode](https://eips.ethereum.org/EIPS/eip-1344). +Tests for [EIP-1344: ChainID Opcode](https://eips.ethereum.org/EIPS/eip-1344). """ diff --git a/istanbul/eip1344_chainid/test_chainid.py b/istanbul/eip1344_chainid/test_chainid.py index 72c670268c..da878691b2 100644 --- a/istanbul/eip1344_chainid/test_chainid.py +++ b/istanbul/eip1344_chainid/test_chainid.py @@ -1,6 +1,5 @@ """ -abstract: Tests [EIP-1344: CHAINID opcode](https://eips.ethereum.org/EIPS/eip-1344) - Test cases for [EIP-1344: CHAINID opcode](https://eips.ethereum.org/EIPS/eip-1344). +Tests [EIP-1344: CHAINID opcode](https://eips.ethereum.org/EIPS/eip-1344). """ import pytest diff --git a/istanbul/eip152_blake2/__init__.py b/istanbul/eip152_blake2/__init__.py index 1f034e456f..040419e930 100644 --- a/istanbul/eip152_blake2/__init__.py +++ b/istanbul/eip152_blake2/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-152: BLAKE2 compression precompile](https://eips.ethereum.org/EIPS/eip-152) - Test cases for [EIP-152: BLAKE2 compression precompile](https://eips.ethereum.org/EIPS/eip-152). +Tests [EIP-152: BLAKE2 compression precompile](https://eips.ethereum.org/EIPS/eip-152). """ diff --git a/istanbul/eip152_blake2/common.py b/istanbul/eip152_blake2/common.py index 7081a31a2e..2f0ab7ba7c 100644 --- a/istanbul/eip152_blake2/common.py +++ b/istanbul/eip152_blake2/common.py @@ -14,15 +14,19 @@ class Blake2bInput(TestParameterGroup): call data from them. Returns all inputs encoded as bytes. Attributes: - rounds_length (int): An optional integer representing the bytes length - for the number of rounds. Defaults to the expected length of 4. - rounds (int | str): A hex string or integer value representing the number of rounds. - h (str): A hex string that represents the state vector. - m (str): A hex string that represents the message block vector. - t_0 (int | str): A hex string or integer value that represents the first offset counter. - t_1 (int | str): A hex string or integer value that represents the second offset counter. - f (bool): An optional boolean that represents the final block indicator flag. - Defaults to True. + rounds_length (int): An optional integer representing the bytes + length for the number of rounds. + Defaults to the expected length of 4. + rounds (int | str): A hex string or integer value representing the number + of rounds. + h (str): A hex string that represents the state vector. + m (str): A hex string that represents the message block vector. + t_0 (int | str): A hex string or integer value that represents + the first offset counter. + t_1(int | str): A hex string or integer value that represents the second + offset counter. + f (bool): An optional boolean that represents the final block indicator + flag. Defaults to True. """ @@ -58,10 +62,10 @@ class ExpectedOutput(TestParameterGroup): Expected test result. Attributes: - call_succeeds (str | bool): A hex string or boolean to indicate whether the call was - successful or not. - data_1 (str): String value of the first updated state vector. - data_2 (str): String value of the second updated state vector. + call_succeeds (str | bool): A hex string or boolean to indicate + whether the call was successful or not. + data_1 (str): String value of the first updated state vector. + data_2 (str): String value of the second updated state vector. """ diff --git a/istanbul/eip152_blake2/conftest.py b/istanbul/eip152_blake2/conftest.py index ed544ec291..a6fbc26be1 100644 --- a/istanbul/eip152_blake2/conftest.py +++ b/istanbul/eip152_blake2/conftest.py @@ -11,8 +11,8 @@ @pytest.fixture def blake2b_contract_bytecode(call_opcode: Op) -> Bytecode: """ - Contract code that performs the provided opcode (CALL or CALLCODE) to the BLAKE2b precompile - and stores the result. + Contract code that performs the provided opcode (CALL or CALLCODE) to the + BLAKE2b precompile and stores the result. """ return ( Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE()) diff --git a/istanbul/eip152_blake2/spec.py b/istanbul/eip152_blake2/spec.py index 38413b7189..021c94a28d 100644 --- a/istanbul/eip152_blake2/spec.py +++ b/istanbul/eip152_blake2/spec.py @@ -35,7 +35,8 @@ class Spec: BLAKE2_PRECOMPILE_T_1_LENGTH = 8 BLAKE2_PRECOMPILE_F_LENGTH = 1 - # Constants for BLAKE2b and BLAKE2s spec defined at https://datatracker.ietf.org/doc/html/rfc7693#section-3.2 + # Constants for BLAKE2b and BLAKE2s spec defined at + # https://datatracker.ietf.org/doc/html/rfc7693#section-3.2 BLAKE2B_PRECOMPILE_ROUNDS = 12 BLAKE2B_PRECOMPILE_H_LENGTH = 64 @@ -47,8 +48,19 @@ class SpecTestVectors: """Defines common test parameters for the BLAKE2b precompile.""" # The following constants are used to define common test parameters - # Origin of vectors defined at https://datatracker.ietf.org/doc/html/rfc7693.html#appendix-A - BLAKE2_STATE_VECTOR = "48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b" # noqa:E501 - BLAKE2_MESSAGE_BLOCK_VECTOR = "6162630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" # noqa:E501 + # Origin of vectors defined at + # https://datatracker.ietf.org/doc/html/rfc7693.html#appendix-A + BLAKE2_STATE_VECTOR = ( + "48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1" + "361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f" + "79217e1319cde05b" + ) + BLAKE2_MESSAGE_BLOCK_VECTOR = ( + "616263000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000" + ) BLAKE2_OFFSET_COUNTER_0 = 3 BLAKE2_OFFSET_COUNTER_1 = 0 diff --git a/istanbul/eip152_blake2/test_blake2.py b/istanbul/eip152_blake2/test_blake2.py index dab5c9e6ba..6e575947c8 100644 --- a/istanbul/eip152_blake2/test_blake2.py +++ b/istanbul/eip152_blake2/test_blake2.py @@ -1,6 +1,5 @@ """ -abstract: Tests [EIP-152: BLAKE2b compression precompile](https://eips.ethereum.org/EIPS/eip-152) - Test cases for [EIP-152: BLAKE2b compression precompile](https://eips.ethereum.org/EIPS/eip-152). +Tests [EIP-152: BLAKE2b compression precompile](https://eips.ethereum.org/EIPS/eip-152). """ from typing import List diff --git a/istanbul/eip152_blake2/test_blake2_delegatecall.py b/istanbul/eip152_blake2/test_blake2_delegatecall.py index b7ed40ba4a..79ecfb664b 100644 --- a/istanbul/eip152_blake2/test_blake2_delegatecall.py +++ b/istanbul/eip152_blake2/test_blake2_delegatecall.py @@ -1,4 +1,6 @@ -"""abstract: Test delegatecall to Blake2B Precompile before and after it was added.""" +""" +Test delegatecall to Blake2B Precompile before and after added. +""" import pytest @@ -21,7 +23,10 @@ @pytest.mark.valid_from("ConstantinopleFix") def test_blake2_precompile_delegatecall(state_test: StateTestFiller, pre: Alloc, fork: Fork): - """Test delegatecall consumes specified gas for the Blake2B precompile when it exists.""" + """ + Test delegatecall consumes specified gas for the Blake2B precompile when it + exists. + """ env = Environment() account = pre.deploy_contract( @@ -43,7 +48,8 @@ def test_blake2_precompile_delegatecall(state_test: StateTestFiller, pre: Alloc, protected=True, ) - # If precompile exists, DELEGATECALL will fail, otherwise DELEGATECALL will succeed + # If precompile exists, DELEGATECALL will fail, otherwise DELEGATECALL will + # succeed post = { account: Account( storage={ diff --git a/osaka/__init__.py b/osaka/__init__.py index 5eceac229b..81fc13f353 100644 --- a/osaka/__init__.py +++ b/osaka/__init__.py @@ -1 +1,4 @@ -"""Test cases for EVM functionality introduced in Osaka, [EIP-7607: Hardfork Meta - Fusaka](https://eip.directory/eips/eip-7607).""" # noqa: E501 +""" +Test cases for EVM functionality introduced in Osaka, [EIP-7607: Hardfork Meta +- Fusaka](https://eip.directory/eips/eip-7607). +""" diff --git a/osaka/eip7594_peerdas/__init__.py b/osaka/eip7594_peerdas/__init__.py index 3b5d044978..43cd5354b7 100644 --- a/osaka/eip7594_peerdas/__init__.py +++ b/osaka/eip7594_peerdas/__init__.py @@ -1,4 +1,5 @@ """ Test suite for -[EIP-7594: PeerDAS - Peer Data Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594). +[EIP-7594: PeerDAS - Peer Data Availability +Sampling](https://eips.ethereum.org/EIPS/eip-7594). """ diff --git a/osaka/eip7594_peerdas/test_get_blobs.py b/osaka/eip7594_peerdas/test_get_blobs.py index 2d349fd93b..a38fcf36c5 100644 --- a/osaka/eip7594_peerdas/test_get_blobs.py +++ b/osaka/eip7594_peerdas/test_get_blobs.py @@ -1,7 +1,9 @@ """ -abstract: Tests get blobs engine endpoint for [EIP-7594: PeerDAS - Peer Data Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594) - Test get blobs engine endpoint for [EIP-7594: PeerDAS - Peer Data Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594). -""" # noqa: E501 +Get blobs engine endpoint tests. + +Tests for get blobs engine endpoint in [EIP-7594: PeerDAS - Peer Data +Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594). +""" from hashlib import sha256 from typing import List, Optional @@ -92,7 +94,8 @@ def excess_blob_gas( block_base_fee_per_gas: int, ) -> int | None: """ - Calculate the excess blob gas of the block under test from the parent block. + Calculate the excess blob gas of the block under test from the parent + block. Value can be overloaded by a test case to provide a custom excess blob gas. """ @@ -148,10 +151,10 @@ def tx_max_fee_per_blob_gas( # noqa: D103 @pytest.fixture def tx_error() -> Optional[TransactionException]: """ - Even though the final block we are producing in each of these tests is invalid, and some of the - transactions will be invalid due to the format in the final block, none of the transactions - should be rejected by the transition tool because they are being sent to it with the correct - format. + Even though the final block we are producing in each of these tests is + invalid, and some of the transactions will be invalid due to the format in + the final block, none of the transactions should be rejected by the + transition tool because they are being sent to it with the correct format. """ return None @@ -319,8 +322,8 @@ def test_get_blobs( txs: List[NetworkWrappedTransaction | Transaction], ): """ - Test valid blob combinations where one or more txs in the block - serialized version contain a full blob (network version) tx. + Test valid blob combinations where one or more txs in the block serialized + version contain a full blob (network version) tx. """ blobs_test(pre=pre, txs=txs) @@ -336,6 +339,9 @@ def test_get_blobs_nonexisting( pre: Alloc, txs: List[NetworkWrappedTransaction | Transaction], ): - """Test that ensures clients respond with 'null' when at least one requested blob is not available.""" # noqa: E501 + """ + Test that ensures clients respond with 'null' when at least one requested + blob is not available. + """ nonexisting_blob_hashes = [Hash(sha256(str(i).encode()).digest()) for i in range(5)] blobs_test(pre=pre, txs=txs, nonexisting_blob_hashes=nonexisting_blob_hashes) diff --git a/osaka/eip7594_peerdas/test_max_blob_per_tx.py b/osaka/eip7594_peerdas/test_max_blob_per_tx.py index c9d0114738..4dcf4ce205 100644 --- a/osaka/eip7594_peerdas/test_max_blob_per_tx.py +++ b/osaka/eip7594_peerdas/test_max_blob_per_tx.py @@ -1,7 +1,9 @@ """ -abstract: Tests `MAX_BLOBS_PER_TX` limit for [EIP-7594: PeerDAS - Peer Data Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594) - Tests `MAX_BLOBS_PER_TX` limit for [EIP-7594: PeerDAS - Peer Data Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594). -""" # noqa: E501 +MAX_BLOBS_PER_TX limit tests. + +Tests for `MAX_BLOBS_PER_TX` limit in [EIP-7594: PeerDAS - Peer Data +Availability Sampling](https://eips.ethereum.org/EIPS/eip-7594). +""" import pytest @@ -88,9 +90,9 @@ def test_valid_max_blobs_per_tx( tx: Transaction, ): """ - Test that transactions with blob count from 1 to MAX_BLOBS_PER_TX are accepted. - Verifies that individual transactions can contain up to the maximum allowed - number of blobs per transaction. + Test that transactions with blob count from 1 to MAX_BLOBS_PER_TX are + accepted. Verifies that individual transactions can contain up to the + maximum allowed number of blobs per transaction. """ state_test( env=env, @@ -120,10 +122,10 @@ def test_invalid_max_blobs_per_tx( blob_count: int, ): """ - Test that transactions exceeding MAX_BLOBS_PER_TX are rejected. - Verifies that individual transactions cannot contain more than the maximum - allowed number of blobs per transaction, even if the total would be within - the block limit. + Test that transactions exceeding MAX_BLOBS_PER_TX are rejected. Verifies + that individual transactions cannot contain more than the maximum allowed + number of blobs per transaction, even if the total would be within the + block limit. """ state_test( env=env, diff --git a/osaka/eip7823_modexp_upper_bounds/__init__.py b/osaka/eip7823_modexp_upper_bounds/__init__.py index 20ebfaec01..b41a84cc6c 100644 --- a/osaka/eip7823_modexp_upper_bounds/__init__.py +++ b/osaka/eip7823_modexp_upper_bounds/__init__.py @@ -1,4 +1,5 @@ """ -abstract: Tests [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823) - Test cases for [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823). +Tests [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823). + +Test cases for EIP-7823: Set upper bounds for MODEXP. """ diff --git a/osaka/eip7823_modexp_upper_bounds/conftest.py b/osaka/eip7823_modexp_upper_bounds/conftest.py index 9a89e91db3..663cd5456d 100644 --- a/osaka/eip7823_modexp_upper_bounds/conftest.py +++ b/osaka/eip7823_modexp_upper_bounds/conftest.py @@ -16,8 +16,8 @@ @pytest.fixture def call_contract_post_storage() -> Storage: """ - Storage of the test contract after the transaction is executed. - Note: Fixture `call_contract_code` fills the actual expected storage values. + Storage of the test contract after the transaction is executed. Note: + Fixture `call_contract_code` fills the actual expected storage values. """ return Storage() @@ -27,8 +27,8 @@ def call_succeeds( total_gas_used: int, fork: Fork, env: Environment, modexp_input: ModExpInput ) -> bool: """ - By default, depending on the expected output, we can deduce if the call is expected to succeed - or fail. + By default, depending on the expected output, we can deduce if the call is + expected to succeed or fail. """ # Transaction gas limit exceeded tx_gas_limit_cap = fork.transaction_gas_limit_cap() or env.gas_limit @@ -57,14 +57,15 @@ def gas_measure_contract( call_succeeds: bool, ) -> Address: """ - Deploys a contract that measures ModExp gas consumption and execution result. + Deploys a contract that measures ModExp gas consumption and execution + result. Always stored: - storage[0]: precompile call success - storage[1]: return data length from precompile + storage[0]: precompile call success + storage[1]: return data length from precompile Only if the precompile call succeeds: - storage[2]: gas consumed by precompile - storage[3]: hash of return data from precompile + storage[2]: gas consumed by precompile + storage[3]: hash of return data from precompile """ call_code = Op.CALL( precompile_gas, @@ -122,14 +123,17 @@ def gas_measure_contract( @pytest.fixture def precompile_gas(fork: Fork, modexp_input: ModExpInput) -> int: - """Calculate gas cost for the ModExp precompile and verify it matches expected gas.""" + """ + Calculate gas cost for the ModExp precompile and verify it matches expected + gas. + """ spec = Spec if fork < Osaka else Spec7883 try: calculated_gas = spec.calculate_gas_cost(modexp_input) return calculated_gas except Exception: - # Used for `test_modexp_invalid_inputs` we expect the call to not succeed. - # Return is for completeness. + # Used for `test_modexp_invalid_inputs` we expect the call to not + # succeed. Return is for completeness. return 500 if fork >= Osaka else 200 @@ -153,7 +157,9 @@ def tx( def total_gas_used( fork: Fork, modexp_expected: bytes, modexp_input: ModExpInput, precompile_gas: int ) -> int: - """Transaction gas limit used for the test (Can be overridden in the test).""" + """ + Transaction gas limit used for the test (Can be overridden in the test). + """ intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() extra_gas = 500_000 @@ -170,7 +176,9 @@ def total_gas_used( @pytest.fixture def tx_gas_limit(total_gas_used: int, fork: Fork, env: Environment) -> int: - """Transaction gas limit used for the test (Can be overridden in the test).""" + """ + Transaction gas limit used for the test (Can be overridden in the test). + """ tx_gas_limit_cap = fork.transaction_gas_limit_cap() or env.gas_limit return min(tx_gas_limit_cap, total_gas_used) diff --git a/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py b/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py index fca1e18127..d91c4d3c71 100644 --- a/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py +++ b/osaka/eip7823_modexp_upper_bounds/test_modexp_upper_bounds.py @@ -1,6 +1,5 @@ """ -abstract: Test [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823) - Tests upper bounds of the MODEXP precompile. +Test [EIP-7823: Set upper bounds for MODEXP](https://eips.ethereum.org/EIPS/eip-7823). """ from typing import Dict @@ -76,7 +75,8 @@ pytest.param( ModExpInput( base=b"", - # Non-zero exponent is cancelled with zero multiplication complexity pre EIP-7823. + # Non-zero exponent is cancelled with zero multiplication + # complexity pre EIP-7823. exponent=b"\xff" * (Spec.MAX_LENGTH_BYTES + 1), modulus=b"", ), @@ -293,7 +293,10 @@ def test_modexp_upper_bounds_fork_transition( modexp_input: ModExpInput, modexp_expected: bytes, ): - """Test MODEXP upper bounds enforcement transition from before to after Osaka hard fork.""" + """ + Test MODEXP upper bounds enforcement transition from before to after Osaka + hard fork. + """ call_code = Op.CALL( address=Spec.MODEXP_ADDRESS, args_size=Op.CALLDATASIZE, diff --git a/osaka/eip7825_transaction_gas_limit_cap/__init__.py b/osaka/eip7825_transaction_gas_limit_cap/__init__.py index ecc57bb22b..6ad1209d93 100644 --- a/osaka/eip7825_transaction_gas_limit_cap/__init__.py +++ b/osaka/eip7825_transaction_gas_limit_cap/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-7825: Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825). - Test cases for [EIP-7825: Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825). +Tests [EIP-7825: Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825). """ diff --git a/osaka/eip7825_transaction_gas_limit_cap/spec.py b/osaka/eip7825_transaction_gas_limit_cap/spec.py index 58a93203a4..319c70e398 100644 --- a/osaka/eip7825_transaction_gas_limit_cap/spec.py +++ b/osaka/eip7825_transaction_gas_limit_cap/spec.py @@ -17,7 +17,9 @@ class ReferenceSpec: @dataclass(frozen=True) class Spec: - """Constants and helpers for the EIP-7825 Transaction Gas Limit Cap tests.""" + """ + Constants and helpers for the EIP-7825 Transaction Gas Limit Cap tests. + """ # Gas limit constants tx_gas_limit_cap = 2**24 # 16,777,216 diff --git a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py index 254cf62dec..5c23a5571b 100644 --- a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py +++ b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit.py @@ -1,6 +1,8 @@ """ -abstract: Tests [EIP-7825 Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825) - Test cases for [EIP-7825 Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825)]. +Transaction gas limit cap tests. + +Tests for transaction gas limit cap in [EIP-7825: Transaction Gas Limit +Cap](https://eips.ethereum.org/EIPS/eip-7825). """ from typing import List @@ -37,12 +39,13 @@ def tx_gas_limit_cap_tests(fork: Fork) -> List[ParameterSet]: """ - Return a list of tests for transaction gas limit cap parametrized for each different - fork. + Return a list of tests for transaction gas limit cap parametrized for each + different fork. """ fork_tx_gas_limit_cap = fork.transaction_gas_limit_cap() if fork_tx_gas_limit_cap is None: - # Use a default value for forks that don't have a transaction gas limit cap + # Use a default value for forks that don't have a transaction gas limit + # cap return [ pytest.param(Spec.tx_gas_limit_cap + 1, None, id="tx_gas_limit_cap_none"), ] @@ -69,7 +72,9 @@ def test_transaction_gas_limit_cap( error: TransactionException | None, tx_type: int, ): - """Test the transaction gas limit cap behavior for all transaction types.""" + """ + Test the transaction gas limit cap behavior for all transaction types. + """ env = Environment() sender = pre.fund_eoa() @@ -179,7 +184,9 @@ def test_tx_gas_larger_than_block_gas_limit( fork: Fork, exceed_block_gas_limit: bool, ): - """Test multiple transactions with total gas larger than the block gas limit.""" + """ + Test multiple transactions with total gas larger than the block gas limit. + """ tx_gas_limit_cap = fork.transaction_gas_limit_cap() assert tx_gas_limit_cap is not None, "Fork does not have a transaction gas limit cap" @@ -302,7 +309,8 @@ def test_tx_gas_limit_cap_full_calldata( num_of_bytes += int(exceed_tx_gas_limit) - # Gas cost calculation based on EIP-7623: (https://eips.ethereum.org/EIPS/eip-7623) + # Gas cost calculation based on EIP-7623: + # (https://eips.ethereum.org/EIPS/eip-7623) # # Simplified in this test case: # - No execution gas used (no opcodes are executed) @@ -377,12 +385,12 @@ def test_tx_gas_limit_cap_contract_creation( code = Op.JUMPDEST * num_of_bytes - # Craft a contract creation transaction that exceeds the transaction gas limit cap + # Craft a contract creation transaction that exceeds the transaction gas + # limit cap # # Total cost = # intrinsic cost (base tx cost + contract creation cost) - # + calldata cost - # + init code execution cost + # + calldata cost + init code execution cost # # The contract body is filled with JUMPDEST instructions, so: # total cost = intrinsic cost + calldata cost + (num_of_jumpdest * 1 gas) @@ -424,7 +432,10 @@ def test_tx_gas_limit_cap_access_list_with_diff_keys( pre: Alloc, fork: Fork, ): - """Test the transaction gas limit cap behavior for access list with different storage keys.""" + """ + Test the transaction gas limit cap behavior for access list with different + storage keys. + """ intrinsic_cost = fork.transaction_intrinsic_cost_calculator() tx_gas_limit_cap = fork.transaction_gas_limit_cap() assert tx_gas_limit_cap is not None, "Fork does not have a transaction gas limit cap" @@ -500,7 +511,10 @@ def test_tx_gas_limit_cap_access_list_with_diff_addr( exceed_tx_gas_limit: bool, correct_intrinsic_cost_in_transaction_gas_limit: bool, ): - """Test the transaction gas limit cap behavior for access list with different addresses.""" + """ + Test the transaction gas limit cap behavior for access list with different + addresses. + """ intrinsic_cost = fork.transaction_intrinsic_cost_calculator() tx_gas_limit_cap = fork.transaction_gas_limit_cap() assert tx_gas_limit_cap is not None, "Fork does not have a transaction gas limit cap" @@ -588,14 +602,13 @@ def test_tx_gas_limit_cap_authorized_tx( ) # EIP-7702 authorization transaction cost: + # 21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes + 1900 * + # access list storage key count + 2400 * access list address count + + # PER_EMPTY_ACCOUNT_COST * authorization list length # - # 21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes - # + 1900 * access list storage key count - # + 2400 * access list address count - # + PER_EMPTY_ACCOUNT_COST * authorization list length + # There is no calldata and no storage keys in this test case and the access + # address list count is equal to the authorization list length # - # There is no calldata and no storage keys in this test case - # and the access address list count is equal to the authorization list length # total cost = 21000 + (2400 + 25_000) * auth_list_length auth_address = pre.deploy_contract(code=Op.STOP) diff --git a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py index eb992e8ded..c28cd62dbc 100644 --- a/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py +++ b/osaka/eip7825_transaction_gas_limit_cap/test_tx_gas_limit_transition_fork.py @@ -1,6 +1,8 @@ """ -abstract: Tests [EIP-7825 Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825) - Test cases for [EIP-7825 Transaction Gas Limit Cap](https://eips.ethereum.org/EIPS/eip-7825)]. +Transaction gas limit cap fork transition tests. + +Tests for fork transition behavior in [EIP-7825: Transaction Gas Limit +Cap](https://eips.ethereum.org/EIPS/eip-7825). """ import pytest @@ -44,8 +46,8 @@ def test_transaction_gas_limit_cap_at_transition( """ Test transaction gas limit cap behavior at the Osaka transition. - Before timestamp 15000: No gas limit cap (transactions with gas > 2^24 are valid) - At/after timestamp 15000: Gas limit cap of 2^24 is enforced + Before timestamp 15000: No gas limit cap (transactions with gas > 2^24 are + valid) At/after timestamp 15000: Gas limit cap of 2^24 is enforced """ contract_address = pre.deploy_contract( code=Op.SSTORE(Op.TIMESTAMP, Op.ADD(Op.SLOAD(Op.TIMESTAMP), 1)) + Op.STOP, @@ -58,7 +60,8 @@ def test_transaction_gas_limit_cap_at_transition( # Test boundary: cap + 1 should fail after fork activation above_cap = tx_gas_cap + 1 - # Before fork activation: both cap and above_cap transactions should succeed + # Before fork activation: both cap and above_cap transactions should + # succeed at_cap_tx_before_fork = Transaction( ty=0, # Legacy transaction to=contract_address, @@ -86,7 +89,8 @@ def test_transaction_gas_limit_cap_at_transition( blocks = [] - # Before transition (timestamp < 15000): both cap and above_cap transactions should succeed + # Before transition (timestamp < 15000): both cap and above_cap + # transactions should succeed blocks.append( Block( timestamp=14_999, diff --git a/osaka/eip7883_modexp_gas_increase/__init__.py b/osaka/eip7883_modexp_gas_increase/__init__.py index 4b43f2c9ed..7987a367c2 100644 --- a/osaka/eip7883_modexp_gas_increase/__init__.py +++ b/osaka/eip7883_modexp_gas_increase/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883) - Test cases for [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883). +Tests for [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883). """ diff --git a/osaka/eip7883_modexp_gas_increase/conftest.py b/osaka/eip7883_modexp_gas_increase/conftest.py index 1a68553154..2740800c66 100644 --- a/osaka/eip7883_modexp_gas_increase/conftest.py +++ b/osaka/eip7883_modexp_gas_increase/conftest.py @@ -42,8 +42,8 @@ def call_opcode() -> Op: @pytest.fixture def call_contract_post_storage() -> Storage: """ - Storage of the test contract after the transaction is executed. - Note: Fixture `call_contract_code` fills the actual expected storage values. + Storage of the test contract after the transaction is executed. Note: + Fixture `call_contract_code` fills the actual expected storage values. """ return Storage() @@ -83,9 +83,10 @@ def expected_tx_cap_fail() -> bool: @pytest.fixture def call_succeeds(exceeds_tx_gas_cap: bool, expected_tx_cap_fail: bool) -> bool: """ - Determine whether the ModExp precompile call should succeed or fail. - By default, depending on the expected output, we assume it succeeds. - Under EIP-7825, transactions requiring more gas than the cap should fail only if unexpected. + Determine whether the ModExp precompile call should succeed or fail. By + default, depending on the expected output, we assume it succeeds. Under + EIP-7825, transactions requiring more gas than the cap should fail only if + unexpected. """ if exceeds_tx_gas_cap and not expected_tx_cap_fail: pytest.fail( @@ -107,14 +108,16 @@ def gas_measure_contract( call_succeeds: bool, ) -> Address: """ - Deploys a contract that measures ModExp gas consumption and execution result. + Deploys a contract that measures ModExp gas consumption and execution + result. Always stored: - storage[0]: precompile call success - storage[1]: return data length from precompile + storage[0]: precompile call success + storage[1]: return data length from precompile + Only if the precompile call succeeds: - storage[2]: gas consumed by precompile - storage[3]: hash of return data from precompile + storage[2]: gas consumed by precompile + storage[3]: hash of return data from precompile """ assert call_opcode in [Op.CALL, Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL] value = [0] if call_opcode in [Op.CALL, Op.CALLCODE] else [] @@ -183,7 +186,10 @@ def gas_measure_contract( def precompile_gas( fork: Fork, modexp_input: ModExpInput, gas_old: int | None, gas_new: int | None ) -> int: - """Calculate gas cost for the ModExp precompile and verify it matches expected gas.""" + """ + Calculate gas cost for the ModExp precompile and verify it matches expected + gas. + """ spec = Spec if fork < Osaka else Spec7883 try: calculated_gas = spec.calculate_gas_cost(modexp_input) @@ -199,8 +205,8 @@ def precompile_gas( ) return calculated_gas except Exception: - # Used for `test_modexp_invalid_inputs` we expect the call to not succeed. - # Return is for completeness. + # Used for `test_modexp_invalid_inputs` we expect the call to not + # succeed. Return is for completeness. return 500 if fork >= Osaka else 200 @@ -228,7 +234,9 @@ def tx( @pytest.fixture def tx_gas_limit(total_tx_gas_needed: int, fork: Fork, env: Environment) -> int: - """Transaction gas limit used for the test (Can be overridden in the test).""" + """ + Transaction gas limit used for the test (Can be overridden in the test). + """ tx_gas_limit_cap = fork.transaction_gas_limit_cap() or env.gas_limit return min(tx_gas_limit_cap, total_tx_gas_needed) diff --git a/osaka/eip7883_modexp_gas_increase/helpers.py b/osaka/eip7883_modexp_gas_increase/helpers.py index 62819fea4b..dc1e05536f 100644 --- a/osaka/eip7883_modexp_gas_increase/helpers.py +++ b/osaka/eip7883_modexp_gas_increase/helpers.py @@ -31,7 +31,10 @@ class Vector(BaseModel): model_config = ConfigDict(alias_generator=to_pascal) def to_pytest_param(self): - """Convert the test vector to a tuple that can be used as a parameter in a pytest test.""" + """ + Convert the test vector to a tuple that can be used as a parameter in a + pytest test. + """ return pytest.param( self.modexp_input, self.modexp_expected, self.gas_old, self.gas_new, id=self.name ) diff --git a/osaka/eip7883_modexp_gas_increase/spec.py b/osaka/eip7883_modexp_gas_increase/spec.py index 74908e60b9..bd399595af 100644 --- a/osaka/eip7883_modexp_gas_increase/spec.py +++ b/osaka/eip7883_modexp_gas_increase/spec.py @@ -18,8 +18,8 @@ class ReferenceSpec: def ceiling_division(a: int, b: int) -> int: """ - Calculate the ceil without using floating point. - Used by many of the EVM's formulas. + Calculate the ceil without using floating point. Used by many of the EVM's + formulas. """ return -(a // -b) @@ -63,9 +63,9 @@ def calculate_multiplication_complexity(cls, base_length: int, modulus_length: i @classmethod def calculate_iteration_count(cls, modexp_input: ModExpInput) -> int: """ - Calculate the iteration count of the ModExp precompile. - This handles length mismatch cases by using declared lengths from the raw input - and only the first 32 bytes of exponent data for iteration calculation. + Calculate the iteration count of the ModExp precompile. This handles + length mismatch cases by using declared lengths from the raw input and + only the first 32 bytes of exponent data for iteration calculation. """ _, exponent_length, _ = modexp_input.get_declared_lengths() exponent_head = modexp_input.get_exponent_head() @@ -83,8 +83,9 @@ def calculate_iteration_count(cls, modexp_input: ModExpInput) -> int: @classmethod def calculate_gas_cost(cls, modexp_input: ModExpInput) -> int: """ - Calculate the ModExp gas cost according to EIP-2565 specification, overridden by the - constants within `Spec7883` when calculating for the EIP-7883 specification. + Calculate the ModExp gas cost according to EIP-2565 specification, + overridden by the constants within `Spec7883` when calculating for the + EIP-7883 specification. """ base_length, _, modulus_length = modexp_input.get_declared_lengths() multiplication_complexity = cls.calculate_multiplication_complexity( @@ -97,8 +98,8 @@ def calculate_gas_cost(cls, modexp_input: ModExpInput) -> int: @dataclass(frozen=True) class Spec7883(Spec): """ - Constants and helpers for the ModExp gas cost increase EIP. - These override the original Spec class variables for EIP-7883. + Constants and helpers for the ModExp gas cost increase EIP. These override + the original Spec class variables for EIP-7883. """ MODEXP_ADDRESS = 0x05 @@ -110,7 +111,10 @@ class Spec7883(Spec): @classmethod def calculate_multiplication_complexity(cls, base_length: int, modulus_length: int) -> int: - """Calculate the multiplication complexity of the ModExp precompile for EIP-7883.""" + """ + Calculate the multiplication complexity of the ModExp precompile for + EIP-7883. + """ max_length = max(base_length, modulus_length) words = ceiling_division(max_length, cls.WORD_SIZE) complexity = 16 diff --git a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py index 4132bbfdf6..9264d3db7f 100644 --- a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py +++ b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py @@ -1,6 +1,8 @@ """ -abstract: Tests [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883) - Test cases for [EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883). +EIP-7883 ModExp gas cost increase tests. + +Tests for ModExp gas cost increase in +[EIP-7883: ModExp Gas Cost Increase](https://eips.ethereum.org/EIPS/eip-7883). """ from typing import Dict @@ -75,8 +77,8 @@ def test_vectors_from_legacy_tests( @pytest.mark.parametrize( "modexp_input,", [ - # These invalid inputs are from EIP-7823. - # Ref: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7823.md#analysis + # These invalid inputs are from EIP-7823. Ref: + # https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7823.md#analysis pytest.param( bytes.fromhex("9e5faafc"), id="invalid-case-1", @@ -254,7 +256,10 @@ def test_modexp_gas_usage_contract_wrapper( tx: Transaction, post: Dict, ): - """Test ModExp gas cost with different gas modifiers using contract wrapper calls.""" + """ + Test ModExp gas cost with different gas modifiers using contract wrapper + calls. + """ state_test(pre=pre, tx=tx, post=post) @@ -306,7 +311,10 @@ def test_modexp_used_in_transaction_entry_points( tx_gas_limit: int, call_values: int, ): - """Test ModExp using in transaction entry points with different precompile gas modifiers.""" + """ + Test ModExp using in transaction entry points with different precompile gas + modifiers. + """ tx = Transaction( to=Spec.MODEXP_ADDRESS, sender=pre.fund_eoa(), @@ -459,11 +467,10 @@ def create_modexp_variable_gas_test_cases(): """ Create test cases for ModExp variable gas cost testing. - Returns: - List of pytest.param objects for the test cases - + Returns: List of pytest.param objects for the test cases """ - # Test case definitions: (base, exponent, modulus, expected_result, gas_usage, test_id) + # Test case definitions: (base, exponent, modulus, expected_result, + # gas_usage, test_id) test_cases = [ ("", "", "", "", 500, "Z0"), ("01" * 32, "00" * 32, "", "", 500, "Z1"), @@ -540,12 +547,15 @@ def create_modexp_variable_gas_test_cases(): # Gas calculation parameters: # - # Please refer to EIP-7883 for details of each function in the gas calculation. + # Please refer to EIP-7883 for details of each function in the gas + # calculation. # Link: https://eips.ethereum.org/EIPS/eip-7883 # # - calculate_multiplication_complexity: - # - Comp: if max_length <= 32 bytes, it is Small (S), otherwise it is Large (L) - # - Rel (Length Relation): base < modulus (<), base = modulus (=), base > modulus (>) + # - Comp: if max_length <= 32 bytes, it is Small (S), otherwise it is + # Large (L) + # - Rel (Length Relation): base < modulus (<), base = modulus (=), + # base > modulus (>) # # - calculate_iteration_count # - Iter (Iteration Case): @@ -555,68 +565,72 @@ def create_modexp_variable_gas_test_cases(): # - D: exp>32 and low256≠0 # # - calculate_gas_cost - # - Clamp: True if raw gas < 500 (clamped to 500), False if raw gas ≥ 500 (no clamping) - - # Test case coverage table: - # ┌─────┬──────┬─────┬──────┬───────┬─────────┬───────────────────────────────────────────────┐ - # │ ID │ Comp │ Rel │ Iter │ Clamp │ Gas │ Description │ - # ├─────┼──────┼─────┼──────┼───────┼─────────┼───────────────────────────────────────────────┤ - # │ Z0 │ - │ - │ - │ - │ 500 │ Zero case – empty inputs │ - # │ Z1 │ S │ - │ A │ True │ 500 │ Non-zero base, zero exp, empty modulus │ - # │ Z2 │ L │ - │ A │ False │ 32768 │ Large base (1024B), zero exp, empty modulus │ - # │ Z3 │ S │ - │ C │ False |253952 │ Base, large zero exp (1024B), empty modulus │ - # │ Z4 │ S │ - │ D │ False │253952 │ Base, large exp (last byte=1), empty modulus │ - # │ Z5 │ S │ < │ A │ True │ 500 │ Empty base/exp, non-zero modulus only │ - # │ Z6 │ S │ < │ B │ False │ 3968 │ Empty base, non-zero exp and modulus │ - # │ Z7 │ L │ < │ B │ False │ 32768 │ Empty base, small exp, large modulus │ - # │ S0 │ S │ = │ A │ True │ 500 │ Small, equal, zero exp, clamped │ - # │ S1 │ S │ = │ B │ True │ 500 │ Small, equal, small exp, clamped │ - # │ S2 │ S │ = │ B │ False │ 4080 │ Small, equal, large exp, unclamped │ - # │ S3 │ S │ = │ C │ False │ 2048 │ Small, equal, large exp + zero low256 │ - # │ S4 │ S │ = │ D │ False │ 2048 │ Small, equal, large exp + non-zero low256 │ - # │ S5 │ S │ > │ A │ True │ 500 │ Small, base > mod, zero exp, clamped │ - # │ S6 │ S │ < │ B │ True │ 500 │ Small, base < mod, small exp, clamped │ - # │ L0 │ L │ = │ A │ True │ 500 │ Large, equal, zero exp, clamped │ - # │ L1 │ L │ = │ B │ False │ 12750 │ Large, equal, large exp, unclamped │ - # │ L2 │ L │ = │ C │ False │ 6400 │ Large, equal, large exp + zero low256 │ - # │ L3 │ L │ = │ D │ False │ 6400 │ Large, equal, large exp + non-zero low256 │ - # │ L4 │ L │ > │ B │ True │ 500 │ Large, base > mod, small exp, clamped │ - # │ L5 │ L │ < │ C │ False │ 9216 │ Large, base < mod, large exp + zero low256 │ - # │ B1 │ L │ < │ B │ True │ 500 │ Cross 32-byte boundary (31/33) │ - # │ B2 │ L │ > │ B │ True │ 500 │ Cross 32-byte boundary (33/31) │ - # │ B4 │ L │ = │ B │ True │ 500 │ Just over 32-byte boundary │ - # │ Z8 │ S │ = │ A │ True │ 500 │ All zeros except modulus │ - # │ Z9 │ S │ = │ A │ True │ 500 │ Zero modulus special case │ - # │ Z10 │ S │ = │ B │ False │ 3968 │ Zero base, large exponent │ - # │ Z11 │ S │ = │ C │ True │ 500 │ Zero base, 33B zero exp, non-zero modulus │ - # │ Z12 │ S │ = │ C │ False |253952 │ Zero base, large zero exp, non-zero modulus │ - # │ Z13 │ L │ > │ A │ False │ 32768 │ Large zero base, zero exp, non-zero modulus │ - # │ Z14 │ S │ = │ C │ False |253952 │ Base, large zero exp, zero modulus │ - # │ Z15 │ L │ < │ B │ False │ 32768 │ Base, small exp, large zero modulus │ - # │ Z16 │ L │ < │ C │ False │520060928│ Zero base, zero exp, large modulus (gas cap) | - # │ M1 │ L │ = │ D │ False │ 98176 │ Maximum values stress test │ - # │ M2 │ S │ = │ B │ True │ 500 │ Max base/mod, small exponent │ - # │ M3 │ L │ < │ D │ False │ 98176 │ Small base, max exponent/mod │ - # │ T2 │ S │ = │ B │ True │ 500 │ Tiny maximum values │ - # │ P2 │ S │ = │ B │ False │ 4080 │ High bit in exponent │ - # │ P3 │ L │ = │ D │ False │ 1150 │ Specific bit pattern in large exponent │ - # │ A1 │ L │ < │ C │ False │ 65536 │ Asymmetric: tiny base, large exp/mod │ - # │ A2 │ L │ > │ B │ True │ 500 │ Asymmetric: large base, tiny exp/mod │ - # │ A3 │ L │ > │ C │ False │ 65536 │ Asymmetric: large base/exp, tiny modulus │ - # │ W2 │ S │ = │ B │ True │ 500 │ Exactly 8-byte words │ - # │ E1 │ S │ = │ D │ True │ 500 │ Exponent exactly 33 bytes │ - # │ E2 │ S │ = │ B │ False │ 4080 │ High bit in exponent first byte │ - # │ E3 │ S │ = │ B │ True │ 500 │ High bit in exponent last byte │ - # │ E4 │ S │ = │ B │ False │ 4064 │ Maximum 32-byte exponent │ - # │ IC1 │ L │ = │ B │ True │ 500 │ Bit shift vs multiplication @ 33 bytes │ - # │ IC3 │ S │ = │ B │ True │ 500 │ Ceiling division at 7 bytes │ - # │ IC4 │ S │ = │ B │ True │ 500 │ Ceiling division at 9 bytes │ - # │ IC5 │ S │ = │ B │ False │ 2160 │ Bit counting in middle of exponent │ - # │ IC6 │ L │ = │ B │ True │ 500 │ Native library even byte optimization │ - # │ IC7 │ L │ = │ B │ True │ 500 │ Vector optimization 128-bit boundary │ - # │ IC9 │ S │ = │ B │ N/A │ N/A │ Zero modulus handling │ - # │ IC10│ S │ = │ B │ False │ 4080 │ Power-of-2 boundary with high bit │ - # └─────┴──────┴─────┴──────┴───────┴─────────┴───────────────────────────────────────────────┘ + # - Clamp: True if raw gas < 500 (clamped to 500), False if raw gas ≥ 500 + # (no clamping) + + """ + Test case coverage table: + + ┌─────┬──────┬─────┬──────┬───────┬─────────┬───────────────────────────────────────────────┐ + │ ID │ Comp │ Rel │ Iter │ Clamp │ Gas │ Description │ + ├─────┼──────┼─────┼──────┼───────┼─────────┼───────────────────────────────────────────────┤ + │ Z0 │ - │ - │ - │ - │ 500 │ Zero case – empty inputs │ + │ Z1 │ S │ - │ A │ True │ 500 │ Non-zero base, zero exp, empty modulus │ + │ Z2 │ L │ - │ A │ False │ 32768 │ Large base (1024B), zero exp, empty modulus │ + │ Z3 │ S │ - │ C │ False |253952 │ Base, large zero exp (1024B), empty modulus │ + │ Z4 │ S │ - │ D │ False │253952 │ Base, large exp (last byte=1), empty modulus │ + │ Z5 │ S │ < │ A │ True │ 500 │ Empty base/exp, non-zero modulus only │ + │ Z6 │ S │ < │ B │ False │ 3968 │ Empty base, non-zero exp and modulus │ + │ Z7 │ L │ < │ B │ False │ 32768 │ Empty base, small exp, large modulus │ + │ S0 │ S │ = │ A │ True │ 500 │ Small, equal, zero exp, clamped │ + │ S1 │ S │ = │ B │ True │ 500 │ Small, equal, small exp, clamped │ + │ S2 │ S │ = │ B │ False │ 4080 │ Small, equal, large exp, unclamped │ + │ S3 │ S │ = │ C │ False │ 2048 │ Small, equal, large exp + zero low256 │ + │ S4 │ S │ = │ D │ False │ 2048 │ Small, equal, large exp + non-zero low256 │ + │ S5 │ S │ > │ A │ True │ 500 │ Small, base > mod, zero exp, clamped │ + │ S6 │ S │ < │ B │ True │ 500 │ Small, base < mod, small exp, clamped │ + │ L0 │ L │ = │ A │ True │ 500 │ Large, equal, zero exp, clamped │ + │ L1 │ L │ = │ B │ False │ 12750 │ Large, equal, large exp, unclamped │ + │ L2 │ L │ = │ C │ False │ 6400 │ Large, equal, large exp + zero low256 │ + │ L3 │ L │ = │ D │ False │ 6400 │ Large, equal, large exp + non-zero low256 │ + │ L4 │ L │ > │ B │ True │ 500 │ Large, base > mod, small exp, clamped │ + │ L5 │ L │ < │ C │ False │ 9216 │ Large, base < mod, large exp + zero low256 │ + │ B1 │ L │ < │ B │ True │ 500 │ Cross 32-byte boundary (31/33) │ + │ B2 │ L │ > │ B │ True │ 500 │ Cross 32-byte boundary (33/31) │ + │ B4 │ L │ = │ B │ True │ 500 │ Just over 32-byte boundary │ + │ Z8 │ S │ = │ A │ True │ 500 │ All zeros except modulus │ + │ Z9 │ S │ = │ A │ True │ 500 │ Zero modulus special case │ + │ Z10 │ S │ = │ B │ False │ 3968 │ Zero base, large exponent │ + │ Z11 │ S │ = │ C │ True │ 500 │ Zero base, 33B zero exp, non-zero modulus │ + │ Z12 │ S │ = │ C │ False |253952 │ Zero base, large zero exp, non-zero modulus │ + │ Z13 │ L │ > │ A │ False │ 32768 │ Large zero base, zero exp, non-zero modulus │ + │ Z14 │ S │ = │ C │ False |253952 │ Base, large zero exp, zero modulus │ + │ Z15 │ L │ < │ B │ False │ 32768 │ Base, small exp, large zero modulus │ + │ Z16 │ L │ < │ C │ False │520060928│ Zero base, zero exp, large modulus (gas cap) | + │ M1 │ L │ = │ D │ False │ 98176 │ Maximum values stress test │ + │ M2 │ S │ = │ B │ True │ 500 │ Max base/mod, small exponent │ + │ M3 │ L │ < │ D │ False │ 98176 │ Small base, max exponent/mod │ + │ T2 │ S │ = │ B │ True │ 500 │ Tiny maximum values │ + │ P2 │ S │ = │ B │ False │ 4080 │ High bit in exponent │ + │ P3 │ L │ = │ D │ False │ 1150 │ Specific bit pattern in large exponent │ + │ A1 │ L │ < │ C │ False │ 65536 │ Asymmetric: tiny base, large exp/mod │ + │ A2 │ L │ > │ B │ True │ 500 │ Asymmetric: large base, tiny exp/mod │ + │ A3 │ L │ > │ C │ False │ 65536 │ Asymmetric: large base/exp, tiny modulus │ + │ W2 │ S │ = │ B │ True │ 500 │ Exactly 8-byte words │ + │ E1 │ S │ = │ D │ True │ 500 │ Exponent exactly 33 bytes │ + │ E2 │ S │ = │ B │ False │ 4080 │ High bit in exponent first byte │ + │ E3 │ S │ = │ B │ True │ 500 │ High bit in exponent last byte │ + │ E4 │ S │ = │ B │ False │ 4064 │ Maximum 32-byte exponent │ + │ IC1 │ L │ = │ B │ True │ 500 │ Bit shift vs multiplication @ 33 bytes │ + │ IC3 │ S │ = │ B │ True │ 500 │ Ceiling division at 7 bytes │ + │ IC4 │ S │ = │ B │ True │ 500 │ Ceiling division at 9 bytes │ + │ IC5 │ S │ = │ B │ False │ 2160 │ Bit counting in middle of exponent │ + │ IC6 │ L │ = │ B │ True │ 500 │ Native library even byte optimization │ + │ IC7 │ L │ = │ B │ True │ 500 │ Vector optimization 128-bit boundary │ + │ IC9 │ S │ = │ B │ N/A │ N/A │ Zero modulus handling │ + │ IC10│ S │ = │ B │ False │ 4080 │ Power-of-2 boundary with high bit │ + └─────┴──────┴─────┴──────┴───────┴─────────┴───────────────────────────────────────────────┘ + """ # noqa: W505 for base, exponent, modulus, expected_result, gas_usage, test_id in test_cases: yield pytest.param( ModExpInput(base=base, exponent=exponent, modulus=modulus), @@ -662,13 +676,14 @@ def test_modexp_variable_gas_cost( @pytest.mark.valid_from("Berlin") def test_modexp_variable_gas_cost_exceed_tx_gas_cap(state_test, pre, tx, post): """ - Test ModExp variable gas cost. - Inputs with an expected gas cost over the EIP-7825 tx gas cap. - """ - # Test case coverage table (gas cap): - # ┌─────┬──────┬─────┬──────┬───────┬─────────┬───────────────────────────────────────────────┐ - # │ ID │ Comp │ Rel │ Iter │ Clamp │ Gas │ Description │ - # ├─────┼──────┼─────┼──────┼───────┼─────────┼───────────────────────────────────────────────┤ - # │ Z16 │ L │ < │ C │ False │520060928│ Zero base, zero exp, large modulus (gas cap) | - # └─────┴──────┴─────┴──────┴───────┴─────────┴───────────────────────────────────────────────┘ + Test ModExp variable gas cost. Inputs with an expected gas cost over the + EIP-7825 tx gas cap. + + Test case coverage table (gas cap): + ┌─────┬──────┬─────┬──────┬───────┬─────────┬───────────────────────────────────────────────┐ + │ ID │ Comp │ Rel │ Iter │ Clamp │ Gas │ Description │ + ├─────┼──────┼─────┼──────┼───────┼─────────┼───────────────────────────────────────────────┤ + │ Z16 │ L │ < │ C │ False │520060928│ Zero base, zero exp, large modulus (gas cap) | + └─────┴──────┴─────┴──────┴───────┴─────────┴───────────────────────────────────────────────┘ + """ # noqa: W505 state_test(pre=pre, tx=tx, post=post) diff --git a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py index 5c4499ace6..5d779ae627 100644 --- a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py +++ b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds_transition.py @@ -1,4 +1,6 @@ -"""Test ModExp gas cost transition from EIP-7883 before and after the Osaka hard fork.""" +""" +Test ModExp gas cost transition from EIP-7883 before & after the Osaka fork. +""" import pytest @@ -38,7 +40,10 @@ def test_modexp_fork_transition( modexp_input: ModExpInput, modexp_expected: bytes, ): - """Test ModExp gas cost transition from EIP-7883 before and after the Osaka hard fork.""" + """ + Test ModExp gas cost transition from EIP-7883 before and after the Osaka + hard fork. + """ call_code = Op.CALL( address=Spec.MODEXP_ADDRESS, args_size=Op.CALLDATASIZE, diff --git a/osaka/eip7918_blob_reserve_price/conftest.py b/osaka/eip7918_blob_reserve_price/conftest.py index 027cf97134..4f5f9d81bd 100644 --- a/osaka/eip7918_blob_reserve_price/conftest.py +++ b/osaka/eip7918_blob_reserve_price/conftest.py @@ -56,7 +56,9 @@ def parent_excess_blob_gas( parent_excess_blobs: int | None, blob_gas_per_blob: int, ) -> int | None: - """Calculate the excess blob gas of the parent block from the excess blobs.""" + """ + Calculate the excess blob gas of the parent block from the excess blobs. + """ if parent_excess_blobs is None: return None assert parent_excess_blobs >= 0 @@ -68,7 +70,8 @@ def blobs_per_tx() -> int: """ Total number of blobs per transaction. - Can be overloaded by a test case to provide a custom blobs per transaction count. + Can be overloaded by a test case to provide a custom blobs per transaction + count. """ return 1 @@ -85,7 +88,10 @@ def block_base_fee_per_gas( parent_excess_blobs: int | None, block_base_fee_per_gas_delta: int, ) -> int: - """Block base fee per gas. Default is 7 unless a delta is provided or overloaded.""" + """ + Block base fee per gas. Default is 7 unless a delta is provided or + overloaded. + """ if block_base_fee_per_gas_delta != 0: if parent_excess_blobs is None: blob_base_fee = 1 @@ -106,7 +112,8 @@ def excess_blob_gas( block_base_fee_per_gas: int, ) -> int | None: """ - Calculate the excess blob gas of the block under test from the parent block. + Calculate the excess blob gas of the block under test from the parent + block. Value can be overloaded by a test case to provide a custom excess blob gas. """ @@ -127,7 +134,8 @@ def correct_excess_blob_gas( block_base_fee_per_gas: int, ) -> int: """ - Calculate the correct excess blob gas of the block under test from the parent block. + Calculate the correct excess blob gas of the block under test from the + parent block. Should not be overloaded by a test case. """ @@ -193,7 +201,9 @@ def env( block_base_fee_per_gas: int, genesis_excess_blob_gas: int, ) -> Environment: - """Prepare the environment of the genesis block for all blockchain tests.""" + """ + Prepare the environment of the genesis block for all blockchain tests. + """ return Environment( excess_blob_gas=genesis_excess_blob_gas, blob_gas_used=0, diff --git a/osaka/eip7918_blob_reserve_price/spec.py b/osaka/eip7918_blob_reserve_price/spec.py index 32c162bb45..60d480da5a 100644 --- a/osaka/eip7918_blob_reserve_price/spec.py +++ b/osaka/eip7918_blob_reserve_price/spec.py @@ -20,8 +20,8 @@ class ReferenceSpec: @dataclass(frozen=True) class Spec(EIP4844Spec): """ - Parameters from the EIP-7918 specifications. - Extends EIP-4844 spec with the new reserve price constant and functionality. + Parameters from the EIP-7918 specifications. Extends EIP-4844 spec with the + new reserve price constant and functionality. """ BLOB_BASE_COST = 2**13 @@ -50,6 +50,8 @@ def calc_effective_blob_base_fee( base_fee_per_gas: int, blob_base_fee: int, ) -> int: - """Calculate the effective blob base fee considering the reserve price.""" + """ + Calculate the effective blob base fee considering the reserve price. + """ reserve_price = cls.get_reserve_price(base_fee_per_gas) return max(reserve_price, blob_base_fee) diff --git a/osaka/eip7918_blob_reserve_price/test_blob_base_fee.py b/osaka/eip7918_blob_reserve_price/test_blob_base_fee.py index 1b1d902b31..820f19b54a 100644 --- a/osaka/eip7918_blob_reserve_price/test_blob_base_fee.py +++ b/osaka/eip7918_blob_reserve_price/test_blob_base_fee.py @@ -1,8 +1,9 @@ """ -abstract: [EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918) - Test the blob base fee reserve price mechanism for [EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918). + [EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918). -""" # noqa: E501 +Test the blob base fee reserve price mechanism for +[EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918). +""" from typing import Dict, List @@ -145,7 +146,10 @@ def test_reserve_price_various_base_fee_scenarios( block: Block, post: Dict[Address, Account], ): - """Test reserve price mechanism across various block base fee and excess blob gas scenarios.""" + """ + Test reserve price mechanism across various block base fee and excess blob + gas scenarios. + """ blockchain_test( pre=pre, post=post, @@ -156,7 +160,8 @@ def test_reserve_price_various_base_fee_scenarios( @pytest.mark.parametrize_by_fork( "parent_excess_blobs", - # Keep max assuming this will be greater than 20 in the future, to test a blob fee of > 1 :) + # Keep max assuming this will be greater than 20 in the future, to test a + # blob fee of > 1 :) lambda fork: [0, 3, fork.target_blobs_per_block(), fork.max_blobs_per_block()], ) @pytest.mark.parametrize("block_base_fee_per_gas_delta", [-2, -1, 0, 1, 10, 100]) @@ -168,17 +173,30 @@ def test_reserve_price_boundary( post: Dict[Address, Account], ): """ - Tests the reserve price boundary mechanism. Note the default block base fee per gas is 7 (delta is 0). - With a non zero delta the block base fee per gas is set to (boundary * blob base fee) + delta. - - Example scenarios from parametrization, assume parent_excess_blobs = 3: - delta=-2: blob_base_fee=1, boundary=8, block_base_fee_per_gas=8+(-2)=6, 6 < 8, reserve inactive, effective_fee=1 - delta=0: blob_base_fee=1, boundary=8, block_base_fee_per_gas=7, 7 < 8, reserve inactive, effective_fee=1 - delta=100: blob_base_fee=1, boundary=8, block_base_fee_per_gas=8+100=108, 108 > 8, reserve active, effective_fee=max(108/8, 1)=13 - - All values give a blob base_ fee of 1 because we need a much higher excess blob gas - to increase the blob fee. This only increases to 2 at 20 excess blobs. - """ # noqa: E501 + Tests the reserve price boundary mechanism. Note the default block base fee + per gas is 7 (delta is 0). With a non zero delta the block base fee per gas + is set to (boundary * blob base fee) + delta. + + Example scenarios from parametrization: + Assume + parent_excess_blobs = 3: + delta=-2: + blob_base_fee=1, + boundary=8, + block_base_fee_per_gas=8+(-2)=6, 6 < 8, + reserve inactive, + effective_fee=1 delta=0: + blob_base_fee=1, boundary=8, + block_base_fee_per_gas=7, 7 < 8, + reserve inactive, effective_fee=1 + delta=100: blob_base_fee=1, + boundary=8, block_base_fee_per_gas=8+100=108, 108 > 8, + reserve active, effective_fee=max(108/8, 1)=13 + + All values give a blob base_ fee of 1 because we need a much higher excess + blob gas to increase the blob fee. This only increases to 2 at 20 excess + blobs. + """ blockchain_test( genesis_environment=env, pre=pre, diff --git a/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo.py b/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo.py index 07e1d69711..b52dce2943 100644 --- a/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo.py +++ b/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo.py @@ -1,8 +1,7 @@ """ -abstract: [EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918) - Test the blob base fee reserve price mechanism for [EIP-7918: Blob base fee bounded by execution cost](https://eips.ethereum.org/EIPS/eip-7918). - -""" # noqa: E501 + [EIP-7918: Blob base fee bounded by execution +cost](https://eips.ethereum.org/EIPS/eip-7918). +""" import pytest diff --git a/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo_transitions.py b/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo_transitions.py index 7bf2883b26..b41b9eb298 100644 --- a/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo_transitions.py +++ b/osaka/eip7918_blob_reserve_price/test_blob_reserve_price_with_bpo_transitions.py @@ -99,8 +99,8 @@ def genesis_base_fee_per_gas( parent_base_fee_per_gas: int, ) -> int: """Genesis base fee per gas.""" - # Base fee always drops from genesis to block 1 because the genesis block never uses - # any tx gas. + # Base fee always drops from genesis to block 1 because the genesis block + # never uses any tx gas. return (parent_base_fee_per_gas * fork.base_fee_max_change_denominator()) // 7 @@ -151,10 +151,12 @@ def env( ) -> Environment: """Environment for the test.""" return Environment( - # Excess blob gas always drops from genesis to block 1 because genesis uses no blob gas. + # Excess blob gas always drops from genesis to block 1 because genesis + # uses no blob gas. excess_blob_gas=genesis_excess_blob_gas, base_fee_per_gas=genesis_base_fee_per_gas, - gas_limit=16_000_000, # To make it easier to reach the requirement with a single tx + gas_limit=16_000_000, # To make it easier to reach the requirement + # with a single tx ) @@ -234,8 +236,8 @@ def parent_block_txs( """ Transactions included in the block prior to the fork transition fork. - Includes blob transactions to raise the `parent_blob_gas_used` and normal transactions - to raise/lower the base fee per gas. + Includes blob transactions to raise the `parent_blob_gas_used` and normal + transactions to raise/lower the base fee per gas. """ parent_block_blob_txs = get_blob_transactions( blob_count=parent_blob_count, @@ -386,8 +388,8 @@ def target_blob_gas_per_block(self) -> int: def calculate_excess_blob_gas(self, parent_header: ParentHeader) -> int: """ - Calculate the excess blob gas for the current block based - on the gas used in the parent block. + Calculate the excess blob gas for the current block based on the gas + used in the parent block. """ excess_blob_gas_calculator = self.fork.excess_blob_gas_calculator(timestamp=self.timestamp) return excess_blob_gas_calculator( @@ -400,8 +402,8 @@ def execution_base_fee_threshold_from_excess_blob_gas( self, excess_blob_gas: int ) -> int | None: """ - Return the minimum base fee required to trigger the reserve mechanism, or None - for blob schedules that don't have a reserve price mechanism. + Return the minimum base fee required to trigger the reserve mechanism, + or None for blob schedules that don't have a reserve price mechanism. """ if self.blob_base_cost is None: return None @@ -414,8 +416,8 @@ def execution_base_fee_threshold_from_excess_blob_gas( def get_fork_scenarios(fork: Fork) -> Iterator[ParameterSet]: """ - Return the list of scenarios at the fork boundary depending on the source fork and - transition fork properties. + Return the list of scenarios at the fork boundary depending on the source + fork and transition fork properties. """ source_blob_schedule = BlobSchedule(fork=fork, timestamp=0) transition_blob_schedule = BlobSchedule(fork=fork, timestamp=15_000) @@ -439,16 +441,16 @@ def get_fork_scenarios(fork: Fork) -> Iterator[ParameterSet]: source_execution_threshold != transition_execution_threshold and transition_execution_threshold is not None ): - # The source base fee reserve threshold is different from the transition one - # given the excess blob gas. - # We can verify that the BPO is activated correctly by using the a setup block - # with transition_execution_threshold to trigger the reserve. + # The source base fee reserve threshold is different from the + # transition one given the excess blob gas. We can verify that the + # BPO is activated correctly by using the a setup block with + # transition_execution_threshold to trigger the reserve. for source_blob_count in [0, source_blob_schedule.target, source_blob_schedule.max]: - # Scenario 1: Parent base fee per gas is below the threshold at the - # parent of the transition block, so even though the base fee increases on - # the transition block to reach the value required to activate the reserve, - # since the base fee per gas of the parent is used, the reserve must not be - # activated. + # Scenario 1: Parent base fee per gas is below the threshold at + # the parent of the transition block, so even though the base + # fee increases on the transition block to reach the value + # required to activate the reserve, since the base fee per gas + # of the parent is used, the reserve must not be activated. parent_base_fee = transition_execution_threshold - 1 transition_base_fee = transition_execution_threshold parent_header = ParentHeader( @@ -477,9 +479,9 @@ def get_fork_scenarios(fork: Fork) -> Iterator[ParameterSet]: ), ) - # Scenario 2: Parent base fee per gas is at the threshold, so the reserve - # is activated even though the base fee per gas decreases below the - # threshold on the transition block. + # Scenario 2: Parent base fee per gas is at the threshold, so + # the reserve is activated even though the base fee per gas + # decreases below the threshold on the transition block. parent_base_fee = transition_execution_threshold transition_base_fee = transition_execution_threshold - 1 parent_header = ParentHeader( @@ -509,7 +511,8 @@ def get_fork_scenarios(fork: Fork) -> Iterator[ParameterSet]: ) if fork == BPO2ToBPO3AtTime15k: - # Explicitly add the exact scenario that triggered the Fusaka Devnet-4 fork. + # Explicitly add the exact scenario that triggered the Fusaka Devnet-4 + # fork. yield pytest.param( 0x32, 0x125BF5F, @@ -541,7 +544,10 @@ def test_reserve_price_at_transition( transition_block: Block, env: Environment, ): - """Test reserve price mechanism across various block base fee and excess blob gas scenarios.""" + """ + Test reserve price mechanism across various block base fee and excess blob + gas scenarios. + """ blockchain_test( pre=pre, post={}, diff --git a/osaka/eip7934_block_rlp_limit/__init__.py b/osaka/eip7934_block_rlp_limit/__init__.py index 5c84ada870..f2bdbe0226 100644 --- a/osaka/eip7934_block_rlp_limit/__init__.py +++ b/osaka/eip7934_block_rlp_limit/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934) - Test cases for [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934). +Tests for [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934). """ diff --git a/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py b/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py index 575c8c002c..8fb3550b71 100644 --- a/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py +++ b/osaka/eip7934_block_rlp_limit/test_max_block_rlp_size.py @@ -1,6 +1,5 @@ """ -abstract: Test [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934) - Tests for [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934). +Tests for [EIP-7934: RLP Execution Block Size Limit](https://eips.ethereum.org/EIPS/eip-7934). """ from functools import lru_cache @@ -59,7 +58,9 @@ def block_size_limit(fork: Fork) -> int: @pytest.fixture def block_errors() -> List[BlockException]: - """Block exceptions expected for blocks that exceed the `MAX_RLP_BLOCK_SIZE`.""" + """ + Block exceptions expected for blocks that exceed the `MAX_RLP_BLOCK_SIZE`. + """ return [BlockException.RLP_BLOCK_LIMIT_EXCEEDED] @@ -121,8 +122,8 @@ def exact_size_transactions( """ Generate transactions that fill a block to exactly the RLP size limit. - The calculation uses caching to avoid recalculating the same block rlp for each - fork. Calculate the block and fill with real sender for testing. + The calculation uses caching to avoid recalculating the same block rlp for + each fork. Calculate the block and fill with real sender for testing. Args: sender: The sender account @@ -131,7 +132,8 @@ def exact_size_transactions( pre: Required if emit_logs is True, used to deploy the log contract gas_limit: The gas limit for the block emit_logs: If True, transactions will call a contract that emits logs - specific_transaction_to_include: If provided, this transaction will be included + specific_transaction_to_include: If provided, this transaction will + be included """ log_contract = None @@ -190,8 +192,8 @@ def _exact_size_transactions_cached( emit_logs_contract: Address | None = None, ) -> Tuple[List[Transaction], int]: """ - Generate transactions that fill a block to exactly the RLP size limit. Abstracted - with hashable arguments for caching block calculations. + Generate transactions that fill a block to exactly the RLP size limit. + Abstracted with hashable arguments for caching block calculations. """ return _exact_size_transactions_impl( block_size_limit, @@ -212,8 +214,8 @@ def _exact_size_transactions_impl( emit_logs_contract: Address | None = None, ) -> Tuple[List[Transaction], int]: """ - Calculate the exact size of transactions to be included. Shared by both cached and - non-cached paths. + Calculate the exact size of transactions to be included. Shared by both + cached and non-cached paths. """ transactions = [] nonce = 0 @@ -224,9 +226,10 @@ def _exact_size_transactions_impl( data_large = Bytes(b"\x00" * 500_000) gas_limit_large = calculator(calldata=data_large) - # block with 16 transactions + large calldata remains safely below the limit - # add 15 generic transactions to fill the block and one typed transaction - # if tx_type is specified, otherwise just add 16 generic transactions + # block with 16 transactions + large calldata remains safely below the + # limit add 15 generic transactions to fill the block and one typed + # transaction if tx_type is specified, otherwise just add 16 generic + # transactions not_all_generic_txs = any( kwarg is not None for kwarg in [specific_transaction_to_include, emit_logs_contract] ) @@ -492,7 +495,10 @@ def test_block_at_rlp_limit_with_logs( fork: Fork, block_size_limit: int, ): - """Test that a block at the RLP size limit is valid even when transactions emit logs.""" + """ + Test that a block at the RLP size limit is valid even when transactions + emit logs. + """ transactions, gas_used = exact_size_transactions( sender, block_size_limit, diff --git a/osaka/eip7939_count_leading_zeros/__init__.py b/osaka/eip7939_count_leading_zeros/__init__.py index 23769774cf..1e9f1a4156 100644 --- a/osaka/eip7939_count_leading_zeros/__init__.py +++ b/osaka/eip7939_count_leading_zeros/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939) - Test cases for [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939). +Tests [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939). """ diff --git a/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py b/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py index 04cb4f2a26..f2592a8189 100644 --- a/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py +++ b/osaka/eip7939_count_leading_zeros/test_count_leading_zeros.py @@ -1,6 +1,5 @@ """ -abstract: Tests [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939) - Test cases for [EIP-7939: Count leading zeros (CLZ) opcode](https://eips.ethereum.org/EIPS/eip-7939). +Tests [EIP-7939: Count leading zeros (CLZ)](https://eips.ethereum.org/EIPS/eip-7939). """ import pytest @@ -97,7 +96,8 @@ def test_clz_opcode_scenarios( Test CLZ opcode functionality. Cases: - - Format 0xb000...111: leading zeros followed by ones (2**256 - 1 >> bits) + - Format 0xb000...111: leading zeros followed by ones + (2**256 - 1 >> bits) - Format 0xb010...000: single bit set at position (1 << bits) Test coverage: @@ -186,7 +186,9 @@ def test_clz_gas_cost_boundary( @EIPChecklist.Opcode.Test.StackComplexOperations.StackHeights.Zero() @pytest.mark.valid_from("Osaka") def test_clz_stack_underflow(state_test: StateTestFiller, pre: Alloc): - """Test CLZ opcode with empty stack (should revert due to stack underflow).""" + """ + Test CLZ opcode with empty stack (should revert due to stack underflow). + """ sender = pre.fund_eoa() callee_address = pre.deploy_contract( code=Op.CLZ + Op.STOP, # No stack items, should underflow @@ -330,9 +332,12 @@ def test_clz_fork_transition(blockchain_test: BlockchainTestFiller, pre: Alloc): ), callee_address: Account( storage={ - 14_999: "0xdeadbeef", # CLZ not valid before fork, storage unchanged - 15_000: 155, # CLZ valid on transition block, CLZ(1 << 100) = 155 - 15_001: 155, # CLZ continues to be valid after transition + # CLZ not valid before fork, storage unchanged + 14_999: "0xdeadbeef", + # CLZ valid on transition block, CLZ(1 << 100) = 155 + 15_000: 155, + # CLZ continues to be valid after transition + 15_001: 155, } ), }, @@ -468,7 +473,8 @@ def test_clz_code_copy_operation(state_test: StateTestFiller, pre: Alloc, bits: address=target_address, dest_offset=0, offset=clz_code_offset, size=1 ) ) - + Op.SSTORE(storage.store_next(mload_value), Op.MLOAD(0)) # Store loaded CLZ byte + # Store loaded CLZ byte + + Op.SSTORE(storage.store_next(mload_value), Op.MLOAD(0)) ), storage={"0x00": "0xdeadbeef"}, ) @@ -505,8 +511,9 @@ def test_clz_with_memory_operation(state_test: StateTestFiller, pre: Alloc, bits # MSTORE # # This sequence stores a 32-byte value in memory. - # Later, we copy the immediate value from the PUSH32 instruction into memory - # using CODECOPY or EXTCODECOPY, and then load it with MLOAD for the CLZ test. + # Later, we copy the immediate value from the PUSH32 instruction into + # memory using CODECOPY or EXTCODECOPY, and then load it with MLOAD for + # the CLZ test. target_code = Op.PUSH32(1 << bits) offset = 1 diff --git a/osaka/eip7951_p256verify_precompiles/__init__.py b/osaka/eip7951_p256verify_precompiles/__init__.py index dc20209ead..a5fa2c7cfc 100644 --- a/osaka/eip7951_p256verify_precompiles/__init__.py +++ b/osaka/eip7951_p256verify_precompiles/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951) - Test cases for [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951)]. +Tests [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951). """ diff --git a/osaka/eip7951_p256verify_precompiles/conftest.py b/osaka/eip7951_p256verify_precompiles/conftest.py index 17833d4408..179eebd87c 100644 --- a/osaka/eip7951_p256verify_precompiles/conftest.py +++ b/osaka/eip7951_p256verify_precompiles/conftest.py @@ -16,9 +16,11 @@ def vector_gas_value() -> int | None: """ Gas value from the test vector if any. - If `None` it means that the test scenario did not come from a file, so no comparison is needed. + If `None` it means that the test scenario did not come from a file, so no + comparison is needed. - The `vectors_from_file` function reads the gas value from the file and overwrites this fixture. + The `vectors_from_file` function reads the gas value from the file and + overwrites this fixture. """ return None @@ -38,9 +40,10 @@ def precompile_gas_modifier() -> int: """ Modify the gas passed to the precompile, for testing purposes. - By default the call is made with the exact gas amount required for the given opcode, - but when this fixture is overridden, the gas amount can be modified to, e.g., test - a lower amount and test if the precompile call fails. + By default the call is made with the exact gas amount required for the + given opcode, but when this fixture is overridden, the gas amount can be + modified to, e.g., test a lower amount and test if the precompile call + fails. """ return 0 @@ -59,7 +62,10 @@ def call_opcode() -> Op: def call_contract_post_storage() -> Storage: """ Storage of the test contract after the transaction is executed. - Note: Fixture `call_contract_code` fills the actual expected storage values. + + Note: + Fixture `call_contract_code` fills the actual expected storage values. + """ return Storage() @@ -67,8 +73,8 @@ def call_contract_post_storage() -> Storage: @pytest.fixture def call_succeeds() -> bool: """ - By default, depending on the expected output, we can deduce if the call is expected to succeed - or fail. + By default, depending on the expected output, we can deduce if the call is + expected to succeed or fail. """ return True @@ -130,7 +136,9 @@ def post(call_contract_address: Address, call_contract_post_storage: Storage): @pytest.fixture def tx_gas_limit(fork: Fork, input_data: bytes, precompile_gas: int) -> int: - """Transaction gas limit used for the test (Can be overridden in the test).""" + """ + Transaction gas limit used for the test (Can be overridden in the test). + """ intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() extra_gas = 100_000 diff --git a/osaka/eip7951_p256verify_precompiles/helpers.py b/osaka/eip7951_p256verify_precompiles/helpers.py index c220f0e517..320f04e4e3 100644 --- a/osaka/eip7951_p256verify_precompiles/helpers.py +++ b/osaka/eip7951_p256verify_precompiles/helpers.py @@ -9,7 +9,10 @@ def current_python_script_directory(*args: str) -> str: - """Get the current Python script directory, optionally appending additional path components.""" + """ + Get the current Python script directory, optionally appending additional + path components. + """ return os.path.join(os.path.dirname(os.path.realpath(__file__)), *args) @@ -24,7 +27,10 @@ class Vector(BaseModel): model_config = ConfigDict(alias_generator=to_pascal) def to_pytest_param(self): - """Convert the test vector to a tuple that can be used as a parameter in a pytest test.""" + """ + Convert the test vector to a tuple that can be used as a parameter in a + pytest test. + """ return pytest.param(self.input, self.expected, self.gas, id=self.name) @@ -38,7 +44,10 @@ class FailVector(BaseModel): model_config = ConfigDict(alias_generator=to_pascal) def to_pytest_param(self): - """Convert the test vector to a tuple that can be used as a parameter in a pytest test.""" + """ + Convert the test vector to a tuple that can be used as a parameter in a + pytest test. + """ return pytest.param(self.input, id=self.name) diff --git a/osaka/eip7951_p256verify_precompiles/spec.py b/osaka/eip7951_p256verify_precompiles/spec.py index 84532af2e8..eacb89633b 100644 --- a/osaka/eip7951_p256verify_precompiles/spec.py +++ b/osaka/eip7951_p256verify_precompiles/spec.py @@ -104,7 +104,8 @@ class Spec: INVALID_RETURN_VALUE = b"" DELEGATION_DESIGNATION = Bytes("ef0100") - # Test constants (from https://github.com/C2SP/wycheproof/blob/4a6c2bf5dc4c0b67c770233ad33961ee653996a0/testvectors/ecdsa_secp256r1_sha256_test.json#L35) + # Test constants, from: + # https://github.com/C2SP/wycheproof/blob/4a6c2bf5dc4c0b67c770233ad33961ee653996a0/testvectors/ecdsa_secp256r1_sha256_test.json#L35 H0 = H(0xBB5A52F42F9C9261ED4361F59422A1E30036E7C32B270C8807A419FECA605023) R0 = R(0x2BA3A8BE6B94D5EC80A6D9D1190A436EFFE50D85A1EEE859B8CC6AF9BD5C2E18) S0 = S(0x4CD60B855D442F5B3C7B11EB6C4E0AE7525FE710FAB9AA7C77A67F79E6FADD76) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index bd188a84ca..e908fe2310 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -1,6 +1,5 @@ """ -abstract: Tests [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951) - Test cases for [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951)]. +Tests for [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951). """ import pytest @@ -36,8 +35,9 @@ + vectors_from_file("secp256r1_u1_u2.json") + vectors_from_file("secp256r1_k_and_s.json") + vectors_from_file("secp256r1_public_key.json"), - # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 test suite, valid cases - # Source: https://github.com/C2SP/wycheproof/blob/main/testvectors/ecdsa_secp256r1_sha256_test.json + # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 test + # suite, valid cases are from this source: + # https://github.com/C2SP/wycheproof/blob/main/testvectors/ecdsa_secp256r1_sha256_test.json ) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) @EIPChecklist.Precompile.Test.CallContexts.Normal() @@ -52,15 +52,20 @@ def test_wycheproof_valid(state_test: StateTestFiller, pre: Alloc, post: dict, t "input_data,expected_output,vector_gas_value", vectors_from_file("secp256r1_special_case_r_s.json") + vectors_from_file("secp256r1_modified_r_s.json"), - # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 test suite, invalid cases - # Source: https://github.com/C2SP/wycheproof/blob/main/testvectors/ecdsa_secp256r1_sha256_test.json + # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 + # test suite, invalid cases + # Source: https://github.com/C2SP/wycheproof/blob/main/ + # testvectors/ecdsa_secp256r1_sha256_test.json ) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) @EIPChecklist.Precompile.Test.CallContexts.Normal() @EIPChecklist.Precompile.Test.Inputs.Invalid() @EIPChecklist.Precompile.Test.Inputs.MaxValues() def test_wycheproof_invalid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): - """Test P256Verify precompile with Wycheproof test suite (invalid cases).""" + """ + Test P256Verify precompile with Wycheproof test suite + (invalid cases). + """ state_test(env=Environment(), pre=pre, post=post, tx=tx) @@ -68,15 +73,19 @@ def test_wycheproof_invalid(state_test: StateTestFiller, pre: Alloc, post: dict, "input_data,expected_output,vector_gas_value", vectors_from_file("secp256r1_small_large_r_s.json") + vectors_from_file("secp256r1_special_points.json"), - # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 test suite, - # valid/invalid cases - # Source: https://github.com/C2SP/wycheproof/blob/main/testvectors/ecdsa_secp256r1_sha256_test.json + # Test vectors generated from Wycheproof's ECDSA secp256r1 SHA-256 + # test suite, valid/invalid cases + # Source: https://github.com/C2SP/wycheproof/blob/main/ + # testvectors/ecdsa_secp256r1_sha256_test.json ) @pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) @EIPChecklist.Precompile.Test.CallContexts.Normal() @EIPChecklist.Precompile.Test.Inputs.MaxValues() def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): - """Test P256Verify precompile with Wycheproof test suite (mixed valid/invalid cases).""" + """ + Test P256Verify precompile with Wycheproof test suite + (mixed valid/invalid cases). + """ state_test(env=Environment(), pre=pre, post=post, tx=tx) @@ -169,11 +178,14 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t id="near_field_boundary_p_minus_3", ), pytest.param( - # Invalid curve attack: This point satisfies y² = x³ - 3x + 1 (mod p) - # instead of the correct P-256 equation y² = x³ - 3x + b where - # b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B - # This tests that the implementation properly validates the curve equation - # and rejects points on different curves (CVE-2020-0601 class vulnerability) + # Invalid curve attack: This point satisfies y² = x³ - 3x + 1 (mod + # p) instead of the correct P-256 equation y² = x³ - 3x + b where + # b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53... + # ...B0F63BCE3C3E27D2604B + # + # This tests that the implementation properly validates the curve + # equation and rejects points on different curves (CVE-2020-0601 + # class vulnerability) Spec.H0 + Spec.R0 + Spec.S0 @@ -183,9 +195,12 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: Singular curve with b = 0 - # Point satisfies y² = x³ - 3x (mod p) - a singular/degenerate curve - # Singular curves have discriminant = 0 and provide no security guarantees - # This tests rejection of points on curves with catastrophic security failures + # Point satisfies y² = x³ - 3x (mod p) - a singular/degenerate + # curve + # Singular curves have discriminant = 0 and provide no security + # guarantees. + # This tests rejection of points on curves with catastrophic + # security failures Spec.H0 + Spec.R0 + Spec.S0 @@ -196,8 +211,11 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t pytest.param( # Invalid curve attack: Boundary value b = p-1 # Point satisfies y² = x³ - 3x + (p-1) (mod p) - # Tests proper parameter validation at modular arithmetic boundaries - # Ensures implementations handle field arithmetic edge cases correctly + # + # Tests proper parameter validation at + # modular arithmetic boundaries. + # Ensures implementations handle field arithmetic edge cases + # correctly. Spec.H0 + Spec.R0 + Spec.S0 @@ -208,8 +226,11 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t pytest.param( # Invalid curve attack: Small discriminant curve with b = 2 # Point satisfies y² = x³ - 3x + 2 (mod p) - # Curves with small discriminants are vulnerable to specialized attacks - # Tests rejection of cryptographically weak curve parameters + # + # Curves with small discriminants are vulnerable to specialized + # attacks. + # + # Tests rejection of cryptographically weak curve parameters. Spec.H0 + Spec.R0 + Spec.S0 + X(0x1) + Y(0x0), id="invalid_curve_attack_small_discriminant", ), @@ -228,7 +249,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t pytest.param( # Invalid curve attack: Composite order curve with b = -Spec.B # Random point which satisfies y² = x³ - 3x - Spec.B (mod p) - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0xC223E1538C4D7B5BBD3EF932736826FD64F4E8B5C80250D9E07A728689D13C38) + R(0x0C7CB59EF6BE7539397CC979AD9A87A3B73A0DD268BBA4990A3378C6391512D5) + S(0xF8C943685BCFE7864C0F8485CACD732D3A9F167531CAF26B67A3CB10B641F92C) @@ -239,7 +261,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t pytest.param( # Invalid curve attack: Composite order curve with b = -Spec.B # Random point which satisfies y² = x³ - 3x - Spec.B (mod p) - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0x982D25BF8E0E81FF41AC3C8033604C78ED5EF17C6EDDA977072EAB6821A7AD0A) + R(0x7C1996FA0EC911E4739AE7340B5345823272F494DFA32034A4FE5642C3DB91F2) + S(0x1E4D6CCF1AFB675D18BD27274770C8B84028D272D1D2641E70B30E1DF17AF3DC) @@ -249,7 +272,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0) + R(0xD21697149F598FEAE9A750DCA86AE6D5EFA654680BA748D2DF7053115101C129) + S(0xEF3FD943AD1F126B3EBA1A5900D79886755DB6DAFCB6B0117D86364340CE36CC) @@ -259,7 +283,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0) + R(0x52E47C5D6AAB66AB6A18A694359EB86FDD40F10E79EF5493C5469EC88BA03334) + S(0x7584C5BF3CA2869C7E383B1603A935EEB79D990B7F7152E055EC562E87FD715E) @@ -269,7 +294,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0) + R(0x81333B13B13F362253BD536D17563A72EB575F1993F55ED40E633E503F60B864) + S(0xE2208C4045F5241ECCF08F825399224C4B78595A10433EC33799DCAD7B0E1F4A) @@ -279,7 +305,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0) + R(0x3C593B5857D1D0EB83923D73E76A7A53EF191BB210267D8C0BE17A4E34AB2E73) + S(0xD022359310067882F713AFBECECE71CB80E4857368F46AB0346362DB033ED298) @@ -289,7 +316,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0) + R(0x425CFFCA652791CABFC81B1E4B7712DBA196599FABCE16978E06E6AF486B1FEC) + S(0x58B864B5A41CD17524E4773EC353C9590D792F601DA075AD9B3F40E8E7070E8A) @@ -299,7 +327,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0x2DA0A74BE3122AEAEF5704D0EB27881FBFB918B4A5252B660935263D0569BA92) + R(0x5543729CBCFD99EE6C3B422D7F245903E7177B3A6A4E3C20C0DC5F5E109795AE) + S(0x96403D5BB253EBD7DEF44BCBC062FCD4EA5E358B19B67C13E625EFDF6B977597) @@ -309,7 +338,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0x1F9D9B26DB42380C85F075174DDAF158F9DE4CD10C3104190D7AF96938DD8ECD) + R(0x159946DBC4F1DE68CD4096862A5B10E5986ACB32229D6E68884DC83DAB70A307) + S(0x63D80724A4074421F7DD255630794E3AEBE635B756D72B24652AAC07D01B289C) @@ -319,7 +349,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0xD380DA9251F1FB809ED48C70DC8F81E91C471F0E81BC95E7611C653278A5B6B4) + R(0xFF197EB72A9E531B17B872525247E6564B786CC014ED28B6849CE7D8C976BDF2) + S(0x7B0B2EFF9BB5409052B35FD3FF81DCE77D95A1F75C46989817045120DA5C3C9C) @@ -329,7 +360,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0x4B082B60497ED87FFE570612D521E73A2CD6C832744EF8E4E2E329E30D3D5879) + R(0x6665A88CB3FF30D339A1975FD46CF5EF480A68A093AB778550073D3528C3B609) + S(0xAEAADDB235E4AC6097356DB96161E27849EA8EDF1E971F74EB51E19A1CC950A1) @@ -339,7 +371,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0x6CC2B605CFBDB22B9E7B55EFE8C1DA0F1C5A0EC1AA8D82EEDFB5EA70E9846E88) + R(0x3C593B5857D1D0EB83923D73E76A7A53EF191BB210267D8C0BE17A4E34AB2E73) + S(0xD022359310067882F713AFBECECE71CB80E4857368F46AB0346362DB033ED298) @@ -349,7 +382,8 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t ), pytest.param( # Invalid curve attack: random point bytes. - # Without the curve check in the implementation, the signature checks out. + # Without the curve check in the implementation, + # the signature checks out. H(0x810C1D53EA96A700C93F6AF1C183197B040EA6FEAE10564877A1C78EC6074FF1) + R(0x34D0F0C8E14D39002B5DEA00808957963E849503DDFD626323433047D696C7C4) + S(0x6A7FE39C046304317F799FB900877073F2AE3C798DD4414795551A833ABCBA85) @@ -530,10 +564,12 @@ def test_precompile_will_return_success_with_tx_value( # This tests the modular comparison: r' ≡ r (mod N) pytest.param( Spec.H0 - # R: A value that when used in ECDSA verification produces an x-coordinate > N + # R: A value that when used in ECDSA verification produces an + # x-coordinate > N + R(0x000000000000000000000000000000004319055358E8617B0C46353D039CDAAB) + S(0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E) - # X, Y: Public key coordinates that will produce x-coordinate > N during verification + # X, Y: Public key coordinates that will produce x-coordinate > N + # during verification + X(0x0AD99500288D466940031D72A9F5445A4D43784640855BF0A69874D2DE5FE103) + Y(0xC5011E6EF2C42DCD50D5D3D29F99AE6EBA2C80C9244F4C5422F0979FF0C3BA5E), Spec.SUCCESS_RETURN_VALUE, @@ -545,7 +581,8 @@ def test_precompile_will_return_success_with_tx_value( + Spec.S0 + Spec.X0 + Spec.Y0, - Spec.INVALID_RETURN_VALUE, # Should fail because R = 1 is not a valid signature + Spec.INVALID_RETURN_VALUE, # Should fail because R = 1 is not a + # valid signature id="r_equals_n_plus_one", ), pytest.param( @@ -554,7 +591,8 @@ def test_precompile_will_return_success_with_tx_value( + Spec.S0 + Spec.X0 + Spec.Y0, - Spec.INVALID_RETURN_VALUE, # Should fail because R = 2 is not a valid signature + Spec.INVALID_RETURN_VALUE, # Should fail because R = 2 is not a + # valid signature id="r_equals_n_plus_two", ), ], @@ -566,9 +604,9 @@ def test_modular_comparison(state_test: StateTestFiller, pre: Alloc, post: dict, """ Test the modular comparison condition for secp256r1 precompile. - This tests that when the x-coordinate of R' exceeds the curve order N, - the verification should use modular arithmetic: - r' ≡ r (mod N) instead of direct equality r' == r. + This tests that when the x-coordinate of R' exceeds the curve order N, the + verification should use modular arithmetic: r' ≡ r (mod N) instead of + direct equality r' == r. """ state_test(env=Environment(), pre=pre, post=post, tx=tx) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py b/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py index b331b55c36..9f8f692ad3 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify_before_fork.py @@ -1,7 +1,11 @@ """ -abstract: Tests P256VERIFY precompiles of [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951) - Tests P256VERIFY precompiles of [EIP-7951: Precompile for secp256r1 Curve Support](https://eips.ethereum.org/EIPS/eip-7951) - before the Osaka hard fork is active. +Tests P256VERIFY precompiles of [EIP-7951: Precompile for secp256r1 +Curve Support](https://eips.ethereum.org/EIPS/eip-7951). + +Tests P256VERIFY +precompiles of [EIP-7951: Precompile for secp256r1 Curve +Support](https://eips.ethereum.org/EIPS/eip-7951) before the Osaka hard fork is +active. """ import pytest diff --git a/paris/security/test_selfdestruct_balance_bug.py b/paris/security/test_selfdestruct_balance_bug.py index 1122d2f460..99bed4248a 100644 --- a/paris/security/test_selfdestruct_balance_bug.py +++ b/paris/security/test_selfdestruct_balance_bug.py @@ -1,13 +1,15 @@ """ -bug: Tests the Consensus Flaw During Block Processing related to SELFDESTRUCT - Tests the consensus-vulnerability reported in - [go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4](https://github.com/ethereum/go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4). +Tests the Consensus Flaw During Block Processing related to SELFDESTRUCT. + +Tests the consensus-vulnerability reported in +[go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4](https://github.com/ethere +um/go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4). To reproduce the issue with this test case: 1. Fill the test with the most recent geth evm version. -2. Run the fixture output within a vulnerable geth version: v1.9.20 > geth >= - v1.9.4. +2. Run the fixture output within a vulnerable geth version: + v1.9.20 > geth >= v1.9.4. """ import pytest @@ -33,18 +35,18 @@ def test_tx_selfdestruct_balance_bug(blockchain_test: BlockchainTestFiller, pre: `0xaa` contract after executing specific transactions. 1. Start with contract `0xaa` which has initial balance of 3 wei. - `0xaa` contract code simply performs a self-destruct to itself. + `0xaa` contract code simply performs a self-destruct to itself. - 2. Send a transaction (tx 1) to invoke caller contract `0xcc` (which - has a balance of 1 wei), which in turn invokes `0xaa` with a 1 wei call. + 2. Send a transaction (tx 1) to invoke caller contract `0xcc` (which has a + balance of 1 wei), which in turn invokes `0xaa` with a 1 wei call. - 3. Store the balance of `0xaa` after the first transaction - is processed. `0xaa` self-destructed. Expected outcome: 0 wei. + 3. Store the balance of `0xaa` after the first transaction is processed. + `0xaa` self-destructed. Expected outcome: 0 wei. 4. Send another transaction (tx 2) to call 0xaa with 5 wei. - 5. Store the balance of `0xaa` after the second transaction - is processed. No self-destruct. Expected outcome: 5 wei. + 5. Store the balance of `0xaa` after the second transaction is processed. + No self-destruct. Expected outcome: 5 wei. 6. Verify that: - Call within tx 1 is successful, i.e `0xaa` self-destructed. diff --git a/prague/__init__.py b/prague/__init__.py index 9a0cd1ac6c..7a26fa5de3 100644 --- a/prague/__init__.py +++ b/prague/__init__.py @@ -1,5 +1,6 @@ """ -Test cases for EVM functionality introduced in Prague, [EIP-7600: Hardfork Meta - Pectra](https://eip.directory/eips/eip-7600). +Test cases for EVM functionality introduced in Prague, [EIP-7600: Hardfork Meta +- Pectra](https://eip.directory/eips/eip-7600). Devnet Specifications: @@ -8,4 +9,4 @@ - [ethpandaops/pectra-devnet-3](https://notes.ethereum.org/@ethpandaops/pectra-devnet-3). - [ethpandaops/pectra-devnet-2](https://notes.ethereum.org/@ethpandaops/pectra-devnet-2). - [ethpandaops/pectra-devnet-1](https://notes.ethereum.org/@ethpandaops/pectra-devnet-1). -""" # noqa: E501 +""" diff --git a/prague/eip2537_bls_12_381_precompiles/__init__.py b/prague/eip2537_bls_12_381_precompiles/__init__.py index 2cede19405..bc90dfa975 100644 --- a/prague/eip2537_bls_12_381_precompiles/__init__.py +++ b/prague/eip2537_bls_12_381_precompiles/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests for [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Tests [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). +""" diff --git a/prague/eip2537_bls_12_381_precompiles/conftest.py b/prague/eip2537_bls_12_381_precompiles/conftest.py index a4780065df..8ae554bff0 100644 --- a/prague/eip2537_bls_12_381_precompiles/conftest.py +++ b/prague/eip2537_bls_12_381_precompiles/conftest.py @@ -17,9 +17,11 @@ def vector_gas_value() -> int | None: """ Gas value from the test vector if any. - If `None` it means that the test scenario did not come from a file, so no comparison is needed. + If `None` it means that the test scenario did not come from a file, so no + comparison is needed. - The `vectors_from_file` function reads the gas value from the file and overwrites this fixture. + The `vectors_from_file` function reads the gas value from the file and + overwrites this fixture. """ return None @@ -42,9 +44,10 @@ def precompile_gas_modifier() -> int: """ Modify the gas passed to the precompile, for testing purposes. - By default the call is made with the exact gas amount required for the given opcode, - but when this fixture is overridden, the gas amount can be modified to, e.g., test - a lower amount and test if the precompile call fails. + By default the call is made with the exact gas amount required for the + given opcode, but when this fixture is overridden, the gas amount can be + modified to, e.g., test a lower amount and test if the precompile call + fails. """ return 0 @@ -63,7 +66,10 @@ def call_opcode() -> Op: def call_contract_post_storage() -> Storage: """ Storage of the test contract after the transaction is executed. - Note: Fixture `call_contract_code` fills the actual expected storage values. + + Note: + Fixture `call_contract_code` fills the actual expected storage values. + """ return Storage() @@ -73,8 +79,8 @@ def call_succeeds( expected_output: bytes | SupportsBytes, ) -> bool: """ - By default, depending on the expected output, we can deduce if the call is expected to succeed - or fail. + By default, depending on the expected output, we can deduce if the call is + expected to succeed or fail. """ return len(bytes(expected_output)) > 0 @@ -93,24 +99,23 @@ def call_contract_code( Code of the test contract. Args: - precompile_address: - Address of the precompile to call. - precompile_gas: - Gas cost for the precompile, which is automatically calculated by the `precompile_gas` - fixture, but can be overridden in the test. - precompile_gas_modifier: - Gas cost modifier for the precompile, which is automatically set to zero by the - `precompile_gas_modifier` fixture, but can be overridden in the test. - expected_output: - Expected output of the precompile call. This value is used to determine if the call is - expected to succeed or fail. - call_succeeds: - Boolean that indicates if the call is expected to succeed or fail. - call_opcode: - Type of call used to call the precompile (Op.CALL, Op.CALLCODE, Op.DELEGATECALL, - Op.STATICCALL). - call_contract_post_storage: - Storage of the test contract after the transaction is executed. + precompile_address: Address of the precompile to call. + precompile_gas: Gas cost for the precompile, which is automatically + calculated by the `precompile_gas` fixture, but can + be overridden in the test. + precompile_gas_modifier: Gas cost modifier for the precompile, which + is automatically set to zero by the + `precompile_gas_modifier` fixture, but + can be overridden in the test. + expected_output: Expected output of the precompile call. + This value is used to determine if the call is + expected to succeed or fail. + call_succeeds: Boolean that indicates if the call is expected to + succeed or fail. + call_opcode: Type of call used to call the precompile (Op.CALL, + Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL). + call_contract_post_storage: Storage of the test contract after the + transaction is executed. """ expected_output = bytes(expected_output) @@ -177,7 +182,9 @@ def post(call_contract_address: Address, call_contract_post_storage: Storage): @pytest.fixture def tx_gas_limit(fork: Fork, input_data: bytes, precompile_gas: int) -> int: - """Transaction gas limit used for the test (Can be overridden in the test).""" + """ + Transaction gas limit used for the test (Can be overridden in the test). + """ intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() extra_gas = 100_000 diff --git a/prague/eip2537_bls_12_381_precompiles/helpers.py b/prague/eip2537_bls_12_381_precompiles/helpers.py index afadc8bb60..0fe1547152 100644 --- a/prague/eip2537_bls_12_381_precompiles/helpers.py +++ b/prague/eip2537_bls_12_381_precompiles/helpers.py @@ -14,7 +14,10 @@ def current_python_script_directory(*args: str) -> str: - """Get the current Python script directory, optionally appending additional path components.""" + """ + Get the current Python script directory, optionally appending additional + path components. + """ return os.path.join(os.path.dirname(os.path.realpath(__file__)), *args) @@ -29,7 +32,10 @@ class Vector(BaseModel): model_config = ConfigDict(alias_generator=to_pascal) def to_pytest_param(self): - """Convert the test vector to a tuple that can be used as a parameter in a pytest test.""" + """ + Convert the test vector to a tuple that can be used as a parameter in a + pytest test. + """ return pytest.param(self.input, self.expected, self.gas, id=self.name) @@ -43,7 +49,10 @@ class FailVector(BaseModel): model_config = ConfigDict(alias_generator=to_pascal) def to_pytest_param(self): - """Convert the test vector to a tuple that can be used as a parameter in a pytest test.""" + """ + Convert the test vector to a tuple that can be used as a parameter in a + pytest test. + """ return pytest.param(self.input, id=self.name) @@ -71,6 +80,7 @@ def vectors_from_file(filename: str) -> List: def add_points_g1(point_a: PointG1, point_b: PointG1) -> PointG1: """ Add two points in G1 using standard formulas. + For points P = (x, y) and Q = (u, v), compute R = P + Q. """ if point_a.x == 0 and point_a.y == 0: @@ -88,7 +98,9 @@ def add_points_g1(point_a: PointG1, point_b: PointG1) -> PointG1: def add_points_g2(point_a: PointG2, point_b: PointG2) -> PointG2: """ Add two points in G2 using standard formulas. - For points P = ((x_0, x_1), (y_0, y_1)) and Q = ((u_0, u_1), (v_0, v_1)), compute R = P + Q. + + For points P = ((x_0, x_1), (y_0, y_1)) and + Q = ((u_0, u_1), (v_0, v_1)), compute R = P + Q. """ if point_a.x == (0, 0) and point_a.y == (0, 0): return point_b @@ -112,10 +124,11 @@ class BLSPointGenerator: - on the standard curve - in the correct r-order subgroup or not - on the curve or not - - on an isomorphic curve (not standard curve) but in the correct r-order subgroup + - on an isomorphic curve (not standard curve) but in the correct + r-order subgroup Additional resource that helped the class implementation: - https://hackmd.io/@benjaminion/bls12-381 + https://hackmd.io/@benjaminion/bls12-381 """ # Constants for G1 curve equations @@ -125,7 +138,8 @@ class BLSPointGenerator: # This is a known parameter of the BLS12-381 curve specification STANDARD_B_G1 = Spec.B_COEFFICIENT - # Isomorphic G1 curve uses b=24 (can be any b value for an isomorphic curve) + # Isomorphic G1 curve uses b=24 (can be any b value for an isomorphic + # curve) ISOMORPHIC_B_G1 = 24 # Isomorphic curve: y^2 = x^3 + 24 # Constants for G2 curve equations @@ -192,8 +206,8 @@ def check_in_g2_subgroup(point: PointG2) -> bool: @staticmethod def sqrt_fq(a: FQ) -> Optional[FQ]: """ - Compute smallest square root of FQ element (if it exists). Used when finding valid - y-coordinates for a given x-coordinate on the G1 curve. + Compute smallest square root of FQ element (if it exists). Used when + finding valid y-coordinates for a given x-coordinate on the G1 curve. """ assert field_modulus % 4 == 3, "This sqrt method requires p % 4 == 3" candidate = a ** ((field_modulus + 1) // 4) @@ -206,8 +220,8 @@ def sqrt_fq(a: FQ) -> Optional[FQ]: @staticmethod def sqrt_fq2(a: FQ2) -> Optional[FQ2]: """ - Compute square root of FQ2 element (if it exists). Used when finding valid - y-coordinates for a given x-coordinate on the G2 curve. + Compute square root of FQ2 element (if it exists). Used when finding + valid y-coordinates for a given x-coordinate on the G2 curve. """ if a == FQ2([0, 0]): return FQ2([0, 0]) @@ -222,8 +236,9 @@ def sqrt_fq2(a: FQ2) -> Optional[FQ2]: @classmethod def multiply_by_cofactor(cls, point: Any, is_g2: bool = False): """ - Multiply a point by the cofactor to ensure it's in the correct r-order subgroup. - Used for creating points in the correct r-order subgroup when using isomorphic curves. + Multiply a point by the cofactor to ensure it's in the correct r-order + subgroup. Used for creating points in the correct r-order subgroup when + using isomorphic curves. """ cofactor = cls.G2_COFACTOR if is_g2 else cls.G1_COFACTOR try: @@ -251,8 +266,8 @@ def multiply_by_cofactor(cls, point: Any, is_g2: bool = False): @memory.cache def find_g1_point_by_x(cls, x_value: int, in_subgroup: bool, on_curve: bool = True) -> PointG1: """ - Find a G1 point with x-coordinate at or near the given value, - with the specified subgroup membership and curve membership. + Find a G1 point with x-coordinate at or near the given value, with the + specified subgroup membership and curve membership. """ max_offset = 5000 isomorphic_b = cls.ISOMORPHIC_B_G1 @@ -267,7 +282,8 @@ def find_g1_point_by_x(cls, x_value: int, in_subgroup: bool, on_curve: bool = Tr try: x = FQ(try_x) - # Calculate y² = x³ + b (standard curve or isomorphic curve) + # Calculate y² = x³ + b (standard curve or isomorphic + # curve) b_value = cls.STANDARD_B_G1 if on_curve else isomorphic_b y_squared = x**3 + FQ(b_value) @@ -280,7 +296,8 @@ def find_g1_point_by_x(cls, x_value: int, in_subgroup: bool, on_curve: bool = Tr raw_point = (int(x), int(y)) raw_point2 = (int(x), Spec.P - int(y)) - # For isomorphic curve points in subgroup, apply cofactor multiplication + # For isomorphic curve points in subgroup, apply cofactor + # multiplication if not on_curve and in_subgroup: try: subgroup_point = cls.multiply_by_cofactor(raw_point, is_g2=False) @@ -327,8 +344,8 @@ def find_g2_point_by_x( cls, x_value: tuple, in_subgroup: bool, on_curve: bool = True ) -> PointG2: """ - Find a G2 point with x-coordinate at or near the given value, - with the specified subgroup membership and curve membership. + Find a G2 point with x-coordinate at or near the given value, with the + specified subgroup membership and curve membership. """ max_offset = 5000 isomorphic_b = cls.ISOMORPHIC_B_G2 @@ -344,7 +361,8 @@ def find_g2_point_by_x( try: x = FQ2(try_x) - # Calculate y² = x³ + b (standard curve or isomorphic curve) + # Calculate y² = x³ + b (standard curve or isomorphic + # curve) b_value = cls.STANDARD_B_G2 if on_curve else isomorphic_b y_squared = x**3 + FQ2(b_value) @@ -363,7 +381,8 @@ def find_g2_point_by_x( (Spec.P - int(y.coeffs[0]), Spec.P - int(y.coeffs[1])), ) - # For isomorphic curve points in subgroup, apply cofactor multiplication + # For isomorphic curve points in subgroup, apply cofactor + # multiplication if not on_curve and in_subgroup: try: subgroup_point = cls.multiply_by_cofactor(raw_point, is_g2=True) @@ -413,26 +432,36 @@ def find_g2_point_by_x( # G1 points by x coordinate (near or on the x value) @classmethod def generate_g1_point_in_subgroup_by_x(cls, x_value: int) -> PointG1: - """G1 point that is in the r-order subgroup with x-coordinate by/on the given value.""" + """ + G1 point that is in the r-order subgroup with x-coordinate by/on the + given value. + """ return cls.find_g1_point_by_x(x_value, in_subgroup=True, on_curve=True) @classmethod def generate_g1_point_not_in_subgroup_by_x(cls, x_value: int) -> PointG1: - """G1 point that is NOT in the r-order subgroup with x-coordinate by/on the given value.""" + """ + G1 point that is NOT in the r-order subgroup with x-coordinate by/on + the given value. + """ return cls.find_g1_point_by_x(x_value, in_subgroup=False, on_curve=True) @classmethod def generate_g1_point_not_on_curve_by_x(cls, x_value: int) -> PointG1: - """G1 point that is NOT on the curve with x-coordinate by/on the given value.""" + """ + G1 point that is NOT on the curve with x-coordinate by/on the given + value. + """ return cls.find_g1_point_by_x(x_value, in_subgroup=False, on_curve=False) @classmethod def generate_g1_point_on_isomorphic_curve_by_x(cls, x_value: int) -> PointG1: """ - G1 point that is on an isomorphic curve (not standard curve) - but in the r-order subgroup with x-coordinate by/on the given value. + G1 point that is on an isomorphic curve (not standard curve) but in the + r-order subgroup with x-coordinate by/on the given value. - Uses cofactor multiplication to ensure the point is in the correct subgroup. + Uses cofactor multiplication to ensure the point is in the correct + subgroup. """ return cls.find_g1_point_by_x(x_value, in_subgroup=True, on_curve=False) @@ -464,10 +493,11 @@ def generate_random_g1_point_not_on_curve(cls, seed: int) -> PointG1: @classmethod def generate_random_g1_point_on_isomorphic_curve(cls, seed: int) -> PointG1: """ - Generate a random G1 point that is on an isomorphic curve (not standard curve) - but in the r-order subgroup. + Generate a random G1 point that is on an isomorphic curve (not standard + curve) but in the r-order subgroup. - Uses cofactor multiplication to ensure the point is in the correct subgroup. + Uses cofactor multiplication to ensure the point is in the correct + subgroup. """ seed_bytes = seed.to_bytes(32, "big") hash_output = hashlib.sha384(seed_bytes + b"on_isomorphic_curve").digest() @@ -477,26 +507,36 @@ def generate_random_g1_point_on_isomorphic_curve(cls, seed: int) -> PointG1: # G2 point generators - by x coordinate (near or on the x value) @classmethod def generate_g2_point_in_subgroup_by_x(cls, x_value: tuple) -> PointG2: - """G2 point that is in the r-order subgroup with x-coordinate by/on the given value.""" + """ + G2 point that is in the r-order subgroup with x-coordinate by/on the + given value. + """ return cls.find_g2_point_by_x(x_value, in_subgroup=True, on_curve=True) @classmethod def generate_g2_point_not_in_subgroup_by_x(cls, x_value: tuple) -> PointG2: - """G2 point that is NOT in the r-order subgroup with x-coordinate by/on the given value.""" + """ + G2 point that is NOT in the r-order subgroup with x-coordinate by/on + the given value. + """ return cls.find_g2_point_by_x(x_value, in_subgroup=False, on_curve=True) @classmethod def generate_g2_point_not_on_curve_by_x(cls, x_value: tuple) -> PointG2: - """G2 point that is NOT on the curve with x-coordinate by/on the given value.""" + """ + G2 point that is NOT on the curve with x-coordinate by/on the given + value. + """ return cls.find_g2_point_by_x(x_value, in_subgroup=False, on_curve=False) @classmethod def generate_g2_point_on_isomorphic_curve_by_x(cls, x_value: tuple) -> PointG2: """ - G2 point that is on an isomorphic curve (not standard curve) - but in the r-order subgroup with x-coordinate near the given value. + G2 point that is on an isomorphic curve (not standard curve) but in the + r-order subgroup with x-coordinate near the given value. - Uses cofactor multiplication to ensure the point is in the correct subgroup. + Uses cofactor multiplication to ensure the point is in the correct + subgroup. """ return cls.find_g2_point_by_x(x_value, in_subgroup=True, on_curve=False) @@ -537,9 +577,9 @@ def generate_random_g2_point_not_on_curve(cls, seed: int) -> PointG2: @classmethod def generate_random_g2_point_on_isomorphic_curve(cls, seed: int) -> PointG2: """ - Generate a random G2 point that is on an isomorphic curve (not standard curve) - but in the r-order subgroup. - Uses cofactor multiplication to ensure the point is in the correct subgroup. + Generate a random G2 point that is on an isomorphic curve (not standard + curve) but in the r-order subgroup. Uses cofactor multiplication to + ensure the point is in the correct subgroup. """ seed_bytes = seed.to_bytes(32, "big") hash_output = hashlib.sha384(seed_bytes + b"g2_on_isomorphic_curve").digest() @@ -553,81 +593,127 @@ def generate_random_g2_point_on_isomorphic_curve(cls, seed: int) -> PointG2: @classmethod def generate_g1_map_isogeny_kernel_points(cls) -> List[FP]: """ - Return precomputed kernel points for the BLS12-381 G1 map to curve function. These map to - the G1 identity point `Spec.INF_G1`. They are generated using sage math externally with the - following script as its significantly faster than using `py_ecc` (200-1000x faster). - - For reference we can imagine the map to curve function as a simple 2 step process, where an - input t value is mapped to a point on the auxiliary curve via a SWU map, and then that - point is mapped to the BLS curve via an 11-isogeny. For reference: - - https://eips.ethereum.org/assets/eip-2537/field_to_curve + Return precomputed kernel points for the BLS12-381 G1 map to curve + function. These map to the G1 identity point `Spec.INF_G1`. They are + generated using sage math externally with the following script as its + significantly faster than using `py_ecc` (200-1000x faster). + + For reference we can imagine the map to curve function as a simple 2 + step process, where an input t value is mapped to a point on the + auxiliary curve via a SWU map, and then that point is mapped to the BLS + curve via an 11-isogeny. For reference: + https://eips.ethereum.org/assets/eip-2537/field_to_curve + + Note we cannot use sage math directly within EEST as it is not a pure + python library and requires an external dependency to be installed on + the system machine. + + Thanks to @petertdavies (Peter Miller) for the sage math script to + generate these points: ```sage + q = 0x1A0111EA397FE69A4B1BA7B6434BACD764774B84F3 + 8512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB - Note we cannot use sage math directly within EEST as it is not a pure python library and - requires an external dependency to be installed on the system machine. - - Thanks to @petertdavies (Peter Miller) for the sage math script to generate these points: - ```sage - q = 0x1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB Fq = GF(q) E1 = EllipticCurve(Fq, (0, 4)) # BLS12-381 curve - ISO_11_A = Fq(0x144698A3B8E9433D693A02C96D4982B0EA985383EE66A8D8E8981AEFD881AC98936F8DA0E0F97F5CF428082D584C1D) - ISO_11_B = Fq(0x12E2908D11688030018B12E8753EEE3B2016C1F0F24F4070A0B9C14FCEF35EF55A23215A316CEAA5D1CC48E98E172BE0) + + ISO_11_A = Fq(0x144698A3B8E9433D693A02C96D4982B0EA985383EE66A8D8E + 8981AEFD881AC98936F8DA0E0F97F5CF428082D584C1D) + + ISO_11_B = Fq(0x12E2908D11688030018B12E8753EEE3B2016C1F0F24F4070A0B + 9C14FCEF35EF55A23215A316CEAA5D1CC48E98E172BE0) + ISO_11_Z = Fq(11) + Ei = EllipticCurve(Fq, (ISO_11_A, ISO_11_B)) - iso = EllipticCurveIsogeny(E=E1, kernel=None, codomain=Ei, degree=11).dual() + + iso = EllipticCurveIsogeny( + E=E1, + kernel=None, + codomain=Ei, + degree=11).dual() + for (x, _) in iso.kernel_polynomial().roots(): discriminant = 1 - 4 / (ISO_11_A / ISO_11_B * x + 1) if not discriminant.is_square(): continue + for sign in [1, -1]: zt2 = (-1 + sign * discriminant.sqrt()) / 2 + t2 = zt2 / ISO_11_Z + if t2.is_square(): t = t2.sqrt() - assert x == -ISO_11_B / ISO_11_A * (1 + 1 / (ISO_11_Z**2 * t**4 + ISO_11_Z * t**2)) + assert x == -ISO_11_B / ISO_11_A * (1 + 1 / (ISO_11_Z**2 * + t**4 + ISO_11_Z * t**2)) + print(t) ``` - To reproduce, add the script contents to a file called `points.sage`, then run `sage points.sage`! + To reproduce, add the script contents to a file called `points.sage`, + then run `sage points.sage`! - Please see the sage math installation guide to replicate: - - https://doc.sagemath.org/html/en/installation/index.html + Please see the sage math installation guide to replicate: - + https://doc.sagemath.org/html/en/installation/index.html - As G1 uses an 11-degree isogeny, its kernel contains exactly 11 points on the auxiliary - curve that maps to the point at infinity on the BLS curve. This includes the point at - infinity (doesn't concern us as the initial SWU map can never output infinity from any int - t) and 10 other unique kernel points. + As G1 uses an 11-degree isogeny, its kernel contains exactly 11 points + on the auxiliary curve that maps to the point at infinity on the BLS + curve. This includes the point at infinity (doesn't concern us as the + initial SWU map can never output infinity from any int t) and 10 other + unique kernel points. - These 10 other kernel points correspond to 5 x-coords on the curve (since each x-coord - yields two points with y and -y). However, not all of these kernel points can be reached by - the SWU map, which is why we only have 4 unique t values below. + These 10 other kernel points correspond to 5 x-coords on the curve + (since each x-coord yields two points with y and -y). However, not all + of these kernel points can be reached by the SWU map, which is why we + only have 4 unique t values below. - The kernel polynomial has 5 roots (x-coords), and each root can potentially yield two - t values that map to kernel points via the SWU function. Analysis shows that only 2 of - these roots yield valid t values because the other 3 roots fail either the discriminant - square check or the t^2 square check in the SWU inverse calculation. From these 2 valid - roots, we get the 4 unique t values listed below. + The kernel polynomial has 5 roots (x-coords), and each root can + potentially yield two t values that map to kernel points via the SWU + function. Analysis shows that only 2 of these roots yield valid t + values because the other 3 roots fail either the discriminant square + check or the t^2 square check in the SWU inverse calculation. From + these 2 valid roots, we get the 4 unique t values listed below. The roots and their properties are as follows: - - Root 1 (x=3447232547282837364692125741875673748077489238391001187748258124039623697289612052402753422028380156396811587142615): - Fails because its discriminant is not a square. - - Root 2 (x=3086251397349454634226049654186198282625136597600255705376316455943570106637401671127489553534256598630507009270951): - Fails because its discriminant is not a square. - - Root 3 (x=2512099095366387796245759085729510986367032014959769672734622752070562589059815523018960565849753051338812932816014): - Has a square discriminant, but both sign options yield t^2 values that are not squares. - - Root 4 (x=2077344747421819657086473418925078480898358265217674456436079722467637536216749299440611432676849905020722484031356): - Yields two valid t values: - - 1731081574565817469321317449275278355306982786154072576198758675751495027640363897075486577327802192163339186341827 - - 861410691052762088300790587394810074303505896628048305535645284922135116676755956131724844456716837983264353875219 - - Root 5 (x=162902306530757011687648381458039960905879760854007434532151803806422383239905014872915974221245198317567396330740): - Yields two valid t values: - - 1006044755431560595281793557931171729984964515682961911911398807521437683216171091013202870577238485832047490326971 - - 1562001338336877267717400325455189014780228097985596277514975439801739125527323838522116502949589758528550231396418 - - Additionally we also have the additive inverses of these t values, which are also valid - kernel (non-unique) points. These are generated using the relationship: - `(-t) mod p === (p - t) mod p` - """ # noqa: E501 + - Root 1 + (x=3447232547282837364692125741875673748077489238391001187748258 + 124039623697289612052402753422028380156396811587142615): + Fails because its discriminant is not a square. + + - Root 2 + (x=3086251397349454634226049654186198282625136597600255705376316 + 455943570106637401671127489553534256598630507009270951): + Fails because its discriminant is not a square. + + - Root 3 + (x=2512099095366387796245759085729510986367032014959769672734622 + 752070562589059815523018960565849753051338812932816014): + Has a square discriminant, but both sign options yield t^2 values + that are not squares. + + - Root 4 + (x=2077344747421819657086473418925078480898358265217674456436079 + 722467637536216749299440611432676849905020722484031356): + Yields two valid t values: + - 173108157456581746932131744927527835530698278615407257619875 + 8675751495027640363897075486577327802192163339186341827 + and + - 861410691052762088300790587394810074303505896628048305535645 + 284922135116676755956131724844456716837983264353875219 + + - Root 5 + (x=1629023065307570116876483814580399609058797608540074345321518 + 03806422383239905014872915974221245198317567396330740): + Yields two valid t values: + - 100604475543156059528179355793117172998496451568296191191139 + 8807521437683216171091013202870577238485832047490326971 + - 15620013383368772677174003254551890147802280979855962 + 77514975439801739125527323838522116502949589758528550231396418 + + Additionally we also have the additive inverses of these t values, + which are also valid kernel (non-unique) points. These are generated + using the relationship: `(-t) mod p === (p - t) mod p` + """ unique_kernel_ts = [ 1731081574565817469321317449275278355306982786154072576198758675751495027640363897075486577327802192163339186341827, 861410691052762088300790587394810074303505896628048305535645284922135116676755956131724844456716837983264353875219, @@ -641,17 +727,20 @@ def generate_g1_map_isogeny_kernel_points(cls) -> List[FP]: @classmethod def generate_g2_map_isogeny_kernel_points(cls) -> List[FP2]: """ - Return precomputed kernel points for the BLS12-381 G2 map to curve function. These map to - the G2 identity point `Spec.INF_G2`. They are generated using sage math externally with the - following script as its significantly faster than using `py_ecc` (200-1000x faster). - - For reference we can imagine the map to curve function as a simple 2 step process, where an - input t value is mapped to a point on the auxiliary curve via a SWU map, and then that - point is mapped to the BLS curve via a 3-isogeny. For reference: + Return precomputed kernel points for the BLS12-381 G2 map to curve + function. These map to the G2 identity point `Spec.INF_G2`. They are + generated using sage math externally with the following script as its + significantly faster than using `py_ecc` (200-1000x faster). + + For reference we can imagine the map to curve function as a simple 2 + step process, where an input t value is mapped to a point on the + auxiliary curve via a SWU map, and then that point is mapped to the + BLS curve via a 3-isogeny. For reference: - https://eips.ethereum.org/assets/eip-2537/field_to_curve - Note we cannot use sage math directly within EEST as it is not a pure python library and - requires an external dependency to be installed on the system machine. + Note we cannot use sage math directly within EEST as it is not a pure + python library and requires an external dependency to be installed on + the system machine. ```sage q = 0x1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB @@ -694,30 +783,37 @@ def generate_g2_map_isogeny_kernel_points(cls) -> List[FP2]: print(t) ``` - Add the script contents to a file called `points.sage`, run `sage points.sage`! + Add the script contents to a file called `points.sage`, run `sage + points.sage`! Please see the sage math installation guide to replicate: - https://doc.sagemath.org/html/en/installation/index.html - As G2 uses an 3-degree isogeny, its kernel contains exactly 3 points on the auxiliary - curve that maps to the point at infinity on the BLS curve. This includes the point at - infinity (doesn't concern us as the initial SWU map can never output infinity from any int - t) and 2 other kernel points. - - These 2 other kernel points correspond to 1 x-coord on the curve (since each x-coord - yields two points with y and -y). Note that this root yields two equal t values due - to specific properties of the isogeny in Fp2. - - However, the G2 case is different from G1 and requires additional verification for y, we - must check that the computed y^2 actually has a square root in Fp2. Unlike G1, the G2 - singular isogeny kernel polynomial root does not correspond to a valid point on the - auxiliary curve due to the failure of the additional check. - - - Root 1 (x=6*u + 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559781): - Fails because its y^2 is not a square in Fp2. - - Due to the failure of the first root, we have no valid kernel points in G2 that map to the - point at infinity on the BLS curve. This is why we return an empty list here. It is kept - for consistency with the G1 case, and documentation purposes. - """ # noqa: E501 + As G2 uses an 3-degree isogeny, its kernel contains exactly 3 points on + the auxiliary curve that maps to the point at infinity on the BLS + curve. This includes the point at infinity (doesn't concern us as the + initial SWU map can never output infinity from any int t) and 2 other + kernel points. + + These 2 other kernel points correspond to 1 x-coord on the curve (since + each x-coord yields two points with y and -y). Note that this root + yields two equal t values due to specific properties of the isogeny in + Fp2. + + However, the G2 case is different from G1 and requires additional + verification for y, we must check that the computed y^2 actually has a + square root in Fp2. Unlike G1, the G2 singular isogeny kernel + polynomial root does not correspond to a valid point on the auxiliary + curve due to the failure of the additional check. + + - Root 1 (x=6*u + + 4002409555221667393417789825735904156556882819939007885332058136124031650490837 + 864442687629129015664037894272559781): Fails because its y^2 is not a + square in Fp2. + + Due to the failure of the first root, we have no valid kernel points in + G2 that map to the point at infinity on the BLS curve. This is why we + return an empty list here. It is kept for consistency with the G1 case, + and documentation purposes. + """ # noqa: E501, W505 return [] diff --git a/prague/eip2537_bls_12_381_precompiles/spec.py b/prague/eip2537_bls_12_381_precompiles/spec.py index 591ede1934..808bcf11c8 100644 --- a/prague/eip2537_bls_12_381_precompiles/spec.py +++ b/prague/eip2537_bls_12_381_precompiles/spec.py @@ -161,7 +161,8 @@ class Spec: ] # fmt: on - # Test constants (from https://github.com/ethereum/bls12-381-tests/tree/eip-2537) + # Test constants from + # https://github.com/ethereum/bls12-381-tests/tree/eip-2537 P1 = PointG1( # random point in G1 0x112B98340EEE2777CC3C14163DEA3EC97977AC3DC5C70DA32E6E87578F44912E902CCEF9EFE28D4A78B8999DFBCA9426, 0x186B28D92356C4DFEC4B5201AD099DBDEDE3781F8998DDF929B4CD7756192185CA7B8F4EF7088F813270AC3D48868A21, @@ -249,7 +250,10 @@ def msm_discount(group: BLS12Group, k: int) -> int: def msm_gas_func_gen( group: BLS12Group, len_per_pair: int, multiplication_cost: int ) -> Callable[[int], int]: - """Generate a function that calculates the gas cost for the G1MSM and G2MSM precompiles.""" + """ + Generate a function that calculates the gas cost for the G1MSM and G2MSM + precompiles. + """ def msm_gas(input_length: int) -> int: """Calculate gas cost for the G1MSM and G2MSM precompiles.""" diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py index 4dab178a35..6d6effdde0 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py @@ -1,7 +1,10 @@ """ -abstract: Tests BLS12_G1ADD precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests BLS12_G1ADD precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Tests BLS12_G1ADD precompile. + +Tests the BLS12_G1ADD precompile implementation from [EIP-2537: +Precompile for BLS12-381 curve operations] +(https://eips.ethereum.org/EIPS/eip-2537). +""" import pytest @@ -26,8 +29,8 @@ # Test vectors from the reference spec (from the cryptography team) vectors_from_file("add_G1_bls.json") + [ - # Identity (infinity) element test cases. - # Checks that any point added to the identity element (INF) equals itself. + # Identity (infinity) element test cases. Checks that any point added + # to the identity element (INF) equals itself. pytest.param( Spec.G1 + Spec.INF_G1, Spec.G1, @@ -114,15 +117,16 @@ None, id="point_plus_reflected_point", ), - # Not in the r-order subgroup test cases. - # Checks that any point on the curve but not in the subgroup is used for operations. + # Not in the r-order subgroup test cases. Checks that any point on the + # curve but not in the subgroup is used for operations. pytest.param( Spec.P1_NOT_IN_SUBGROUP + Spec.P1_NOT_IN_SUBGROUP, Spec.P1_NOT_IN_SUBGROUP_TIMES_2, None, id="non_sub_plus_non_sub", ), - pytest.param( # `P1_NOT_IN_SUBGROUP` has an small order subgroup of 3: 3P = INF. + pytest.param( # `P1_NOT_IN_SUBGROUP` has an small order subgroup of 3: + # 3P = INF. Spec.P1_NOT_IN_SUBGROUP + Spec.P1_NOT_IN_SUBGROUP_TIMES_2, Spec.INF_G1, None, @@ -164,7 +168,8 @@ None, id="doubled_non_sub_plus_neg", ), - # More not in the r-order subgroup test cases, but using random generated points. + # More not in the r-order subgroup test cases, but using random + # generated points. pytest.param( G1_POINTS_NOT_IN_SUBGROUP[0] + Spec.P1, add_points_g1(G1_POINTS_NOT_IN_SUBGROUP[0], Spec.P1), diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py index fb69d0e406..8d5a4e89c3 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py @@ -1,7 +1,9 @@ """ -abstract: Tests BLS12_G1MSM precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests BLS12_G1MSM precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Test the BLS12_G1MSM precompile. + +Test the BLS12_G1MSM precompile introduced in +[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). +""" import pytest @@ -69,7 +71,8 @@ None, id="multiple_points_zero_scalar", ), - # Cases with maximum discount table (test vector for gas cost calculation) + # Cases with maximum discount table (test vector for gas cost + # calculation) pytest.param( (Spec.P1 + Scalar(Spec.Q)) * (len(Spec.G1MSM_DISCOUNT_TABLE) - 1), Spec.INF_G1, @@ -173,7 +176,8 @@ def test_valid( id="scalar_too_large", ), pytest.param( - Spec.G1 + Scalar(1).x.to_bytes(16, byteorder="big"), # Invalid scalar length + # Invalid scalar length + Spec.G1 + Scalar(1).x.to_bytes(16, byteorder="big"), id="scalar_too_short", ), pytest.param( @@ -198,7 +202,8 @@ def test_valid( id="y_above_p_pos_1", ), ], - # Input length tests can be found in ./test_bls12_variable_length_input_contracts.py + # Input length tests can be found in + # ./test_bls12_variable_length_input_contracts.py ) @pytest.mark.parametrize( "precompile_gas_modifier", [100_000], ids=[""] diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_g1mul.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_g1mul.py index 721d63a50b..9824f875bd 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_g1mul.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_g1mul.py @@ -1,7 +1,10 @@ """ -abstract: Tests BLS12_G1MUL precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests BLS12_G1MUL precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Tests BLS12_G1MUL precompile. + +Tests the BLS12_G1MUL precompile implementation from [EIP-2537: +Precompile for BLS12-381 curve operations] +(https://eips.ethereum.org/EIPS/eip-2537). +""" import pytest @@ -84,8 +87,8 @@ pytest.param( Spec.P1 + Scalar(2**256 - 1), PointG1( - 0x3DA1F13DDEF2B8B5A46CD543CE56C0A90B8B3B0D6D43DEC95836A5FD2BACD6AA8F692601F870CF22E05DDA5E83F460B, # noqa: E501 - 0x18D64F3C0E9785365CBDB375795454A8A4FA26F30B9C4F6E33CA078EB5C29B7AEA478B076C619BC1ED22B14C95569B2D, # noqa: E501 + 0x3DA1F13DDEF2B8B5A46CD543CE56C0A90B8B3B0D6D43DEC95836A5FD2BACD6AA8F692601F870CF22E05DDA5E83F460B, + 0x18D64F3C0E9785365CBDB375795454A8A4FA26F30B9C4F6E33CA078EB5C29B7AEA478B076C619BC1ED22B14C95569B2D, ), None, id="max_scalar_times_point", @@ -182,7 +185,8 @@ def test_valid( id="swapped_coordinates_times_0", ), pytest.param( - PointG1(0x01, 0x07) + Scalar(0), # Point on wrong curve y^2 = x^3 + 5 + # Point on wrong curve y^2 = x^3 + 5 + PointG1(0x01, 0x07) + Scalar(0), id="point_on_wrong_curve_times_0", ), pytest.param( @@ -294,7 +298,8 @@ def test_valid( Spec.P1_NOT_IN_SUBGROUP + Scalar(Spec.Q + 1), id="not_in_subgroup_times_q_plus_1", ), - # More not in the r-order subgroup test cases, but using random generated points. + # More not in the r-order subgroup test cases, but using random + # generated points. pytest.param( G1_POINTS_NOT_IN_SUBGROUP[0] + Scalar(1), id="rand_not_in_subgroup_0_times_1", diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_g2add.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_g2add.py index 17282fdd92..71e71ed7eb 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_g2add.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_g2add.py @@ -1,7 +1,10 @@ """ -abstract: Tests BLS12_G2ADD precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests BLS12_G2ADD precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Tests BLS12_G2ADD precompile. + +Tests the BLS12_G2ADD precompile implementation from [EIP-2537: +Precompile for BLS12-381 curve operations] +(https://eips.ethereum.org/EIPS/eip-2537). +""" import pytest @@ -26,8 +29,8 @@ # Test vectors from the reference spec (from the cryptography team) vectors_from_file("add_G2_bls.json") + [ - # Identity (infinity) element test cases. - # Checks that any point added to the identity element (INF) equals itself. + # Identity (infinity) element test cases. Checks that any point added + # to the identity element (INF) equals itself. pytest.param( Spec.G2 + Spec.INF_G2, Spec.G2, @@ -115,8 +118,8 @@ None, id="point_plus_reflected_point", ), - # Not in the r-order subgroup test cases. - # Checks that any point on the curve but not in the subgroup is used for operations. + # Not in the r-order subgroup test cases. Checks that any point on the + # curve but not in the subgroup is used for operations. pytest.param( Spec.P2_NOT_IN_SUBGROUP + Spec.P2_NOT_IN_SUBGROUP, Spec.P2_NOT_IN_SUBGROUP_TIMES_2, @@ -165,7 +168,8 @@ None, id="doubled_non_sub_plus_neg", ), - # More not in the r-order subgroup test cases, but using random generated points. + # More not in the r-order subgroup test cases, but using random + # generated points. pytest.param( G2_POINTS_NOT_IN_SUBGROUP[0] + Spec.P2, add_points_g2(G2_POINTS_NOT_IN_SUBGROUP[0], Spec.P2), diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py index c27b8f5599..87a9cf7785 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py @@ -1,7 +1,9 @@ """ -abstract: Tests BLS12_G2MSM precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests BLS12_G2MSM precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Test the BLS12_G2MSM precompile. + +Test the BLS12_G2MSM precompile introduced in +[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). +""" import pytest @@ -69,7 +71,8 @@ None, id="multiple_points_zero_scalar", ), - # Cases with maximum discount table (test vector for gas cost calculation) + # Cases with maximum discount table (test vector for gas cost + # calculation) pytest.param( (Spec.P2 + Scalar(Spec.Q)) * (len(Spec.G2MSM_DISCOUNT_TABLE) - 1), Spec.INF_G2, @@ -171,7 +174,8 @@ def test_valid( id="scalar_too_large", ), pytest.param( - Spec.G2 + Scalar(1).x.to_bytes(16, byteorder="big"), # Invalid scalar length + # Invalid scalar length + Spec.G2 + Scalar(1).x.to_bytes(16, byteorder="big"), id="scalar_too_short", ), pytest.param( @@ -224,7 +228,8 @@ def test_valid( id="y_c1_above_p_pos_1", ), ], - # Input length tests can be found in ./test_bls12_variable_length_input_contracts.py + # Input length tests can be found in + # ./test_bls12_variable_length_input_contracts.py ) @pytest.mark.parametrize( "precompile_gas_modifier", [100_000], ids=[""] diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_g2mul.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_g2mul.py index db72f7d756..4256de3afc 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_g2mul.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_g2mul.py @@ -1,7 +1,9 @@ """ -abstract: Tests BLS12_G2MUL precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests BLS12_G2MUL precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Test the BLS12_G2MUL precompile. + +Test the BLS12_G2MUL precompile introduced in +[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). +""" import pytest @@ -85,12 +87,12 @@ Spec.P2 + Scalar(2**256 - 1), PointG2( ( - 0x2663E1C3431E174CA80E5A84489569462E13B52DA27E7720AF5567941603475F1F9BC0102E13B92A0A21D96B94E9B22, # noqa: E501 - 0x6A80D056486365020A6B53E2680B2D72D8A93561FC2F72B960936BB16F509C1A39C4E4174A7C9219E3D7EF130317C05, # noqa: E501 + 0x2663E1C3431E174CA80E5A84489569462E13B52DA27E7720AF5567941603475F1F9BC0102E13B92A0A21D96B94E9B22, + 0x6A80D056486365020A6B53E2680B2D72D8A93561FC2F72B960936BB16F509C1A39C4E4174A7C9219E3D7EF130317C05, ), ( - 0xC49EAD39E9EB7E36E8BC25824299661D5B6D0E200BBC527ECCB946134726BF5DBD861E8E6EC946260B82ED26AFE15FB, # noqa: E501 - 0x5397DAD1357CF8333189821B737172B18099ECF7EE8BDB4B3F05EBCCDF40E1782A6C71436D5ACE0843D7F361CBC6DB2, # noqa: E501 + 0xC49EAD39E9EB7E36E8BC25824299661D5B6D0E200BBC527ECCB946134726BF5DBD861E8E6EC946260B82ED26AFE15FB, + 0x5397DAD1357CF8333189821B737172B18099ECF7EE8BDB4B3F05EBCCDF40E1782A6C71436D5ACE0843D7F361CBC6DB2, ), ), None, @@ -312,7 +314,8 @@ def test_valid( Spec.P2_NOT_IN_SUBGROUP + Scalar(Spec.Q + 1), id="not_in_subgroup_times_q_plus_1", ), - # More not in the r-order subgroup test cases, but using random generated points. + # More not in the r-order subgroup test cases, but using random + # generated points. pytest.param( G2_POINTS_NOT_IN_SUBGROUP[0] + Scalar(1), id="rand_not_in_subgroup_0_times_1", diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp2_to_g2.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp2_to_g2.py index d2da70d7e9..095df9e888 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp2_to_g2.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp2_to_g2.py @@ -1,7 +1,9 @@ """ -abstract: Tests BLS12_MAP_FP2_TO_G2 precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests BLS12_MAP_FP2_TO_G2 precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Test the BLS12_MAP_FP2_TO_G2 precompile. + +Test the BLS12_MAP_FP2_TO_G2 precompile introduced in +[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). +""" import pytest @@ -22,12 +24,12 @@ G2_POINT_ZERO_FP = PointG2( ( - 0x18320896EC9EEF9D5E619848DC29CE266F413D02DD31D9B9D44EC0C79CD61F18B075DDBA6D7BD20B7FF27A4B324BFCE, # noqa: E501 - 0xA67D12118B5A35BB02D2E86B3EBFA7E23410DB93DE39FB06D7025FA95E96FFA428A7A27C3AE4DD4B40BD251AC658892, # noqa: E501 + 0x18320896EC9EEF9D5E619848DC29CE266F413D02DD31D9B9D44EC0C79CD61F18B075DDBA6D7BD20B7FF27A4B324BFCE, + 0xA67D12118B5A35BB02D2E86B3EBFA7E23410DB93DE39FB06D7025FA95E96FFA428A7A27C3AE4DD4B40BD251AC658892, ), ( - 0x260E03644D1A2C321256B3246BAD2B895CAD13890CBE6F85DF55106A0D334604FB143C7A042D878006271865BC35941, # noqa: E501 - 0x4C69777A43F0BDA07679D5805E63F18CF4E0E7C6112AC7F70266D199B4F76AE27C6269A3CEEBDAE30806E9A76AADF5C, # noqa: E501 + 0x260E03644D1A2C321256B3246BAD2B895CAD13890CBE6F85DF55106A0D334604FB143C7A042D878006271865BC35941, + 0x4C69777A43F0BDA07679D5805E63F18CF4E0E7C6112AC7F70266D199B4F76AE27C6269A3CEEBDAE30806E9A76AADF5C, ), ) @@ -47,12 +49,12 @@ FP2((Spec.P - 1, Spec.P - 1)), PointG2( ( - 0x9BF1B857D8C15F317F649ACCFA7023EF21CFC03059936B83B487DB476FF9D2FE64C6147140A5F0A436B875F51FFDF07, # noqa: E501 - 0xBB10E09BDF236CB2951BD7BCC044E1B9A6BB5FD4B2019DCC20FFDE851D52D4F0D1A32382AF9D7DA2C5BA27E0F1C69E6, # noqa: E501 + 0x9BF1B857D8C15F317F649ACCFA7023EF21CFC03059936B83B487DB476FF9D2FE64C6147140A5F0A436B875F51FFDF07, + 0xBB10E09BDF236CB2951BD7BCC044E1B9A6BB5FD4B2019DCC20FFDE851D52D4F0D1A32382AF9D7DA2C5BA27E0F1C69E6, ), ( - 0xDD416A927AB1C15490AB753C973FD377387B12EFCBE6BED2BF768B9DC95A0CA04D1A8F0F30DBC078A2350A1F823CFD3, # noqa: E501 - 0x171565CE4FCD047B35EA6BCEE4EF6FDBFEC8CC73B7ACDB3A1EC97A776E13ACDFEFFC21ED6648E3F0EEC53DDB6C20FB61, # noqa: E501 + 0xDD416A927AB1C15490AB753C973FD377387B12EFCBE6BED2BF768B9DC95A0CA04D1A8F0F30DBC078A2350A1F823CFD3, + 0x171565CE4FCD047B35EA6BCEE4EF6FDBFEC8CC73B7ACDB3A1EC97A776E13ACDFEFFC21ED6648E3F0EEC53DDB6C20FB61, ), ), None, @@ -61,8 +63,8 @@ pytest.param( FP2( ( - 3510328712861478240121438855244276237335901234329585006107499559909114695366216070652508985150831181717984778988906, # noqa: E501 - 2924545590598115509050131525615277284817672420174395176262156166974132393611647670391999011900253695923948997972401, # noqa: E501 + 3510328712861478240121438855244276237335901234329585006107499559909114695366216070652508985150831181717984778988906, + 2924545590598115509050131525615277284817672420174395176262156166974132393611647670391999011900253695923948997972401, ) ), Spec.INF_G2, @@ -101,16 +103,18 @@ def test_isogeny_kernel_values( tx: Transaction, ): """ - Test the BLS12_MAP_FP2_TO_G2 precompile with isogeny kernel values. Note this test only exists - to align with the G1 test. `G2_FIELD_POINTS_MAP_TO_IDENTITY` is empty so there are no cases. - - The isogeny kernel is simply the set of special field values, that after the two step mapping - (first SWU onto an auxiliary curve, then a 3-degree isogeny back to G2), collapse exactly - to the identity point. - - For the G2 case the only kernel element is the point at infinity, and SWU never produces the - identity point from a finite input t. Hence `G2_FIELD_POINTS_MAP_TO_IDENTITY` is empty. Please - proceed to the generator in `helpers.py` for more details. + Test the BLS12_MAP_FP2_TO_G2 precompile with isogeny kernel values. Note + this test only exists to align with the G1 test. + `G2_FIELD_POINTS_MAP_TO_IDENTITY` is empty so there are no cases. + + The isogeny kernel is simply the set of special field values, that after + the two step mapping (first SWU onto an auxiliary curve, then a 3-degree + isogeny back to G2), collapse exactly to the identity point. + + For the G2 case the only kernel element is the point at infinity, and SWU + never produces the identity point from a finite input t. Hence + `G2_FIELD_POINTS_MAP_TO_IDENTITY` is empty. Please proceed to the generator + in `helpers.py` for more details. """ state_test( env=Environment(), diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp_to_g1.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp_to_g1.py index 6612530513..d8c0d73a2c 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp_to_g1.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_map_fp_to_g1.py @@ -1,7 +1,9 @@ """ -abstract: Tests BLS12_MAP_FP_TO_G1 precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests BLS12_MAP_FP_TO_G1 precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Tests BLS12_MAP_FP_TO_G1 precompile. + +Tests the BLS12_MAP_FP_TO_G1 precompile implementation from +[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). +""" import pytest @@ -21,8 +23,8 @@ ] G1_POINT_ZERO_FP = PointG1( - 0x11A9A0372B8F332D5C30DE9AD14E50372A73FA4C45D5F2FA5097F2D6FB93BCAC592F2E1711AC43DB0519870C7D0EA415, # noqa: E501 - 0x92C0F994164A0719F51C24BA3788DE240FF926B55F58C445116E8BC6A47CD63392FD4E8E22BDF9FEAA96EE773222133, # noqa: E501 + 0x11A9A0372B8F332D5C30DE9AD14E50372A73FA4C45D5F2FA5097F2D6FB93BCAC592F2E1711AC43DB0519870C7D0EA415, + 0x92C0F994164A0719F51C24BA3788DE240FF926B55F58C445116E8BC6A47CD63392FD4E8E22BDF9FEAA96EE773222133, ) @@ -40,15 +42,15 @@ pytest.param( FP(Spec.P - 1), PointG1( - 0x1073311196F8EF19477219CCEE3A48035FF432295AA9419EED45D186027D88B90832E14C4F0E2AA4D15F54D1C3ED0F93, # noqa: E501 - 0x16B3A3B2E3DDDF6A11459DDAF657FDE21C4F10282A56029D9B55AB3CE1F41E1CF39AD27E0EA35823C7D3250E81FF3D66, # noqa: E501 + 0x1073311196F8EF19477219CCEE3A48035FF432295AA9419EED45D186027D88B90832E14C4F0E2AA4D15F54D1C3ED0F93, + 0x16B3A3B2E3DDDF6A11459DDAF657FDE21C4F10282A56029D9B55AB3CE1F41E1CF39AD27E0EA35823C7D3250E81FF3D66, ), None, id="fp_p_minus_1", ), pytest.param( FP( - 799950832265136997107648781861994410980648980263584507133499364313075404851459407870655748616451882783569609925573 # noqa: E501 + 799950832265136997107648781861994410980648980263584507133499364313075404851459407870655748616451882783569609925573 ), Spec.INF_G1, None, @@ -88,12 +90,12 @@ def test_isogeny_kernel_values( """ Test the BLS12_MAP_FP_TO_G1 precompile with isogeny kernel inputs. - The isogeny kernel is simply the set of special field values, that after the two step mapping - (first SWU onto an auxiliary curve, then an 11-degree isogeny back to G1), collapse exactly - to the identity point. + The isogeny kernel is simply the set of special field values, that after + the two step mapping (first SWU onto an auxiliary curve, then an 11-degree + isogeny back to G1), collapse exactly to the identity point. - Please proceed to the generator in `helpers.py` to see how the isogeny kernel values are - generated. + Please proceed to the generator in `helpers.py` to see how the isogeny + kernel values are generated. """ state_test( env=Environment(), diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_pairing.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_pairing.py index 4d1d5555eb..d8798201a4 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_pairing.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_pairing.py @@ -1,7 +1,9 @@ """ -abstract: Tests BLS12_PAIRING precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests BLS12_PAIRING precompile of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Tests BLS12_PAIRING precompile. + +Tests the BLS12_PAIRING precompile implementation from +[EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). +""" import pytest @@ -147,8 +149,8 @@ def test_valid_multi_inf( post: dict, ): """ - Test maximum input given the current environment gas limit for the BLS12_PAIRING - precompile. + Test maximum input given the current environment gas limit for the + BLS12_PAIRING precompile. """ intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() @@ -347,8 +349,8 @@ def test_invalid_multi_inf( post: dict, ): """ - Test maximum input given the current environment gas limit for the BLS12_PAIRING - precompile and an invalid tail. + Test maximum input given the current environment gas limit for the + BLS12_PAIRING precompile and an invalid tail. """ intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_precompiles_before_fork.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_precompiles_before_fork.py index 2e1cc8c008..9c56ff39ac 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_precompiles_before_fork.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_precompiles_before_fork.py @@ -1,8 +1,10 @@ """ -abstract: Tests BLS12 precompiles of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests BLS12 precompiles of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - before the Prague hard fork is active. -""" # noqa: E501 +Tests BLS12 precompiles before fork activation. + +Tests the BLS12 precompiles behavior before fork activation from +[EIP-2537: Precompile for BLS12-381 curve operations] +(https://eips.ethereum.org/EIPS/eip-2537). +""" import pytest diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py index 527adb2009..8cc70be6af 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py @@ -1,7 +1,11 @@ """ -abstract: Tests minimum gas and input length for BLS12_G1MSM, BLS12_G2MSM, BLS12_PAIRING precompiles of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537) - Tests minimum gas and input length for BLS12_G1MSM, BLS12_G2MSM, BLS12_PAIRING precompiles of [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537). -""" # noqa: E501 +Tests minimum gas and input length for BLS12 precompiles. + +Tests minimum gas and input length requirements for BLS12_G1MSM, +BLS12_G2MSM, and BLS12_PAIRING precompiles from [EIP-2537: Precompile +for BLS12-381 curve operations] +(https://eips.ethereum.org/EIPS/eip-2537). +""" from typing import Callable, List, SupportsBytes @@ -29,7 +33,10 @@ @pytest.fixture def input_data() -> bytes: - """Calldata of the transaction is empty because all input in these tests is zero.""" + """ + Calldata of the transaction is empty because all input in these tests is + zero. + """ return b"" @@ -41,7 +48,9 @@ def gas_modifier() -> int: @pytest.fixture def input_length_modifier() -> int: - """Input length modifier to apply to each element of the precompile_gas_list.""" + """ + Input length modifier to apply to each element of the precompile_gas_list. + """ return 0 @@ -71,38 +80,36 @@ def call_contract_code( call_contract_post_storage: Storage, ) -> Bytecode: """ - Code of the test contract to validate minimum expected gas in precompiles, as well as - expected input lengths on all variable-length input precompiles. + Code of the test contract to validate minimum expected gas in precompiles, + as well as expected input lengths on all variable-length input precompiles. - Code differs from the one used in all other tests in this file, because it accepts a list of - precompile gas values and a list of precompile data lengths, and for each pair of values, it - calls the precompile with the given gas and data length, data being passed to the precompile - is all zeros. + Code differs from the one used in all other tests in this file, because it + accepts a list of precompile gas values and a list of precompile data + lengths, and for each pair of values, it calls the precompile with the + given gas and data length, data being passed to the precompile is all + zeros. Args: - precompile_address: - Address of the precompile to call. - precompile_gas_list: - List of gas values to be used to call the precompile, one for each call. - precompile_data_length_list: - List of data lengths to be used to call the precompile, one for each call. - gas_modifier: - Integer to add to the gas passed to the precompile. - input_length_modifier: - Integer to add to the length of the input passed to the precompile. - expected_output: - Expected output of the contract, it is only used to determine if the call is expected - to succeed or fail. - call_opcode: - Type of call used to call the precompile (Op.CALL, Op.CALLCODE, Op.DELEGATECALL, - Op.STATICCALL). - call_contract_post_storage: - Storage of the test contract after the transaction is executed. + precompile_address: Address of the precompile to call. + precompile_gas_list: List of gas values to be used to call the + precompile, one for each call. + precompile_data_length_list: List of data lengths to be used to call + the precompile, one for each call. + gas_modifier: Integer to add to the gas passed to the precompile. + input_length_modifier: Integer to add to the length of the input + passed to the precompile. + expected_output: Expected output of the contract, it is only used to + determine if the call is expected to succeed or fail. + call_opcode: Type of call used to call the precompile (Op.CALL, + Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL). + call_contract_post_storage: Storage of the test contract after the + transaction is executed. """ expected_output = bytes(expected_output) - # Depending on the expected output, we can deduce if the call is expected to succeed or fail. + # Depending on the expected output, we can deduce if the call is expected + # to succeed or fail. call_succeeds = len(expected_output) > 0 assert len(precompile_gas_list) == len(precompile_data_length_list) @@ -114,8 +121,9 @@ def call_contract_code( for precompile_gas, precompile_args_length in zip( precompile_gas_list, precompile_data_length_list, strict=False ): - # For each given precompile gas value, and given arguments length, call the precompile - # with the given gas and call data (all zeros) and compare the result. + # For each given precompile gas value, and given arguments length, call + # the precompile with the given gas and call data (all zeros) and + # compare the result. code += Op.SSTORE( call_contract_post_storage.store_next(1 if call_succeeds else 0), Op.CALL( @@ -135,7 +143,10 @@ def call_contract_code( def tx_gas_limit_calculator( fork: Fork, precompile_gas_list: List[int], max_precompile_input_length: int ) -> int: - """Calculate the gas used to execute the transaction with the given precompile gas list.""" + """ + Calculate the gas used to execute the transaction with the given precompile + gas list. + """ intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() memory_expansion_gas_calculator = fork.memory_expansion_gas_calculator() extra_gas = 22_500 * len(precompile_gas_list) @@ -154,7 +165,9 @@ def tx_gas_limit( precompile_gas_list: List[int], precompile_data_length_list: List[int], ) -> int: - """Transaction gas limit used for the test (Can be overridden in the test).""" + """ + Transaction gas limit used for the test (Can be overridden in the test). + """ assert len(input_data) == 0, "Expected empty data in the transaction." return tx_gas_limit_calculator(fork, precompile_gas_list, max(precompile_data_length_list)) @@ -163,12 +176,13 @@ def get_split_discount_table_by_fork( gas_fn: Callable, discount_table_length: int, element_length: int ) -> Callable[[Fork], List[ParameterSet]]: """ - Get the number of test cases needed to cover the given discount table adjusted for the - fork transaction gas limit cap. + Get the number of test cases needed to cover the given discount table + adjusted for the fork transaction gas limit cap. - The function will return the full discount table as a single test case if the - fork has no transaction gas limit cap, otherwise it will iterate to determine the - splits required to fit the full discount table across multiple test cases. + The function will return the full discount table as a single test case if + the fork has no transaction gas limit cap, otherwise it will iterate to + determine the splits required to fit the full discount table across + multiple test cases. """ def parametrize_by_fork(fork: Fork) -> List[ParameterSet]: @@ -249,8 +263,9 @@ def test_valid_gas_g1msm( tx: Transaction, ): """ - Test the BLS12_G1MSM discount gas table in full, by expecting the call to succeed for - all possible input lengths because the appropriate amount of gas is provided. + Test the BLS12_G1MSM discount gas table in full, by expecting the call to + succeed for all possible input lengths because the appropriate amount of + gas is provided. If any of the calls fail, the test will fail. """ @@ -307,8 +322,9 @@ def test_invalid_gas_g1msm( tx: Transaction, ): """ - Test the BLS12_G1MSM discount gas table in full, by expecting the call to fail for - all possible input lengths because the appropriate amount of gas is not provided. + Test the BLS12_G1MSM discount gas table in full, by expecting the call to + fail for all possible input lengths because the appropriate amount of gas + is not provided. If any of the calls succeeds, the test will fail. """ @@ -371,8 +387,9 @@ def test_invalid_length_g1msm( tx: Transaction, ): """ - Test the BLS12_G1MSM discount gas table in full, by expecting the call to fail for - all possible input lengths provided because they are too long or short, or zero length. + Test the BLS12_G1MSM discount gas table in full, by expecting the call to + fail for all possible input lengths provided because they are too long or + short, or zero length. If any of the calls succeeds, the test will fail. """ @@ -402,8 +419,9 @@ def test_valid_gas_g2msm( tx: Transaction, ): """ - Test the BLS12_G2MSM discount gas table in full, by expecting the call to succeed for - all possible input lengths because the appropriate amount of gas is provided. + Test the BLS12_G2MSM discount gas table in full, by expecting the call to + succeed for all possible input lengths because the appropriate amount of + gas is provided. If any of the calls fail, the test will fail. """ @@ -460,8 +478,9 @@ def test_invalid_gas_g2msm( tx: Transaction, ): """ - Test the BLS12_G2MSM discount gas table in full, by expecting the call to fail for - all possible input lengths because the appropriate amount of gas is not provided. + Test the BLS12_G2MSM discount gas table in full, by expecting the call to + fail for all possible input lengths because the appropriate amount of gas + is not provided. If any of the calls succeeds, the test will fail. """ @@ -524,8 +543,9 @@ def test_invalid_length_g2msm( tx: Transaction, ): """ - Test the BLS12_G2MSM discount gas table in full, by expecting the call to fail for - all possible input lengths provided because they are too long or short, or zero length. + Test the BLS12_G2MSM discount gas table in full, by expecting the call to + fail for all possible input lengths provided because they are too long or + short, or zero length. If any of the calls succeeds, the test will fail. """ @@ -552,8 +572,8 @@ def test_valid_gas_pairing( tx: Transaction, ): """ - Test the BLS12_PAIRING precompile, by expecting the call to succeed for all possible input - lengths (up to k == PAIRINGS_TO_TEST). + Test the BLS12_PAIRING precompile, by expecting the call to succeed for all + possible input lengths (up to k == PAIRINGS_TO_TEST). If any of the calls fails, the test will fail. """ @@ -608,8 +628,9 @@ def test_invalid_gas_pairing( tx: Transaction, ): """ - Test the BLS12_PAIRING precompile, by expecting the call to fail for all possible input - lengths (up to k == PAIRINGS_TO_TEST) because the appropriate amount of gas is not provided. + Test the BLS12_PAIRING precompile, by expecting the call to fail for all + possible input lengths (up to k == PAIRINGS_TO_TEST) because the + appropriate amount of gas is not provided. If any of the calls succeeds, the test will fail. """ @@ -640,7 +661,9 @@ def test_invalid_zero_length_pairing( post: dict, tx: Transaction, ): - """Test the BLS12_PAIRING precompile by passing an input with zero length.""" + """ + Test the BLS12_PAIRING precompile by passing an input with zero length. + """ state_test( env=env, pre=pre, @@ -670,8 +693,9 @@ def test_invalid_length_pairing( tx: Transaction, ): """ - Test the BLS12_PAIRING precompile, by expecting the call to fail for all possible input - lengths (up to k == PAIRINGS_TO_TEST) because the incorrect input length was used. + Test the BLS12_PAIRING precompile, by expecting the call to fail for all + possible input lengths (up to k == PAIRINGS_TO_TEST) because the incorrect + input length was used. If any of the calls succeeds, the test will fail. """ diff --git a/prague/eip2935_historical_block_hashes_from_state/test_block_hashes.py b/prague/eip2935_historical_block_hashes_from_state/test_block_hashes.py index 5d9f77b801..28c8c0e341 100644 --- a/prague/eip2935_historical_block_hashes_from_state/test_block_hashes.py +++ b/prague/eip2935_historical_block_hashes_from_state/test_block_hashes.py @@ -1,7 +1,6 @@ """ -abstract: Tests [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935) - Test [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935). -""" # noqa: E501 +Tests [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935). +""" from typing import Dict, List @@ -33,14 +32,17 @@ def generate_block_check_code( check_contract_first: bool = False, ) -> Bytecode: """ - Generate EVM code to check that the block hashes are correctly stored in the state. + Generate EVM code to check that the block hashes are correctly stored in + the state. Args: - check_block_number (int): The block number to check. - current_block_number (int): The current block number where the check is taking place. - fork_block_number (int): The block number of the fork transition. - storage (Storage): The storage object to use. - check_contract_first (bool): Whether to check the contract first, for slot warming checks. + check_block_number (int): The block number to check. + current_block_number (int): The current block number where the check is + taking place. + fork_block_number (int): The block number of the fork transition. + storage (Storage): The storage object to use. + check_contract_first (bool): Whether to check the contract first, + for slot warming checks. """ contract_ret_offset = 32 @@ -108,13 +110,13 @@ def test_block_hashes_history_at_transition( blocks_after_fork: int, ): """ - Tests that block hashes are stored correctly at the system contract address after the fork - transition. Block hashes are stored incrementally at the transition until the - `HISTORY_SERVE_WINDOW` ring buffer is full. Afterwards the oldest block hash is replaced by the - new one. + Tests that block hashes are stored correctly at the system contract address + after the fork transition. Block hashes are stored incrementally at the + transition until the `HISTORY_SERVE_WINDOW` ring buffer is full. Afterwards + the oldest block hash is replaced by the new one. - Note: The block hashes before the fork are no longer stored in the contract at the moment of - the transition. + Note: The block hashes before the fork are no longer stored in the contract + at the moment of the transition. """ blocks: List[Block] = [] assert blocks_before_fork >= 1 and blocks_before_fork < Spec.FORK_TIMESTAMP @@ -127,9 +129,9 @@ def test_block_hashes_history_at_transition( for i in range(blocks_before_fork): txs: List[Transaction] = [] if i == blocks_before_fork - 1: - # On the last block before the fork, `BLOCKHASH` must return values for the last 256 - # blocks but not for the blocks before that. - # And `HISTORY_STORAGE_ADDRESS` should be empty. + # On the last block before the fork, `BLOCKHASH` must return values + # for the last 256 blocks but not for the blocks before that. And + # `HISTORY_STORAGE_ADDRESS` should be empty. code = Bytecode() storage = Storage() @@ -165,17 +167,18 @@ def test_block_hashes_history_at_transition( blocks.append(Block(timestamp=current_block_number, txs=txs)) current_block_number += 1 - # Add blocks after the fork transition to gradually fill up the `HISTORY_SERVE_WINDOW` + # Add blocks after the fork transition to gradually fill up the + # `HISTORY_SERVE_WINDOW` for i in range(blocks_after_fork): txs = [] - # On these blocks, `BLOCKHASH` will still return values for the last 256 blocks, and - # `HISTORY_STORAGE_ADDRESS` should now serve values for the previous blocks in the new - # fork. + # On these blocks, `BLOCKHASH` will still return values for the last + # 256 blocks, and `HISTORY_STORAGE_ADDRESS` should now serve values for + # the previous blocks in the new fork. code = Bytecode() storage = Storage() - # Check that each block can return previous blockhashes if `BLOCKHASH_OLD_WINDOW` and or - # `HISTORY_SERVE_WINDOW`. + # Check that each block can return previous blockhashes if + # `BLOCKHASH_OLD_WINDOW` and or `HISTORY_SERVE_WINDOW`. for j in range(current_block_number): code += generate_block_check_code( check_block_number=j, @@ -227,10 +230,10 @@ def test_block_hashes_history( check_contract_first: bool, ): """ - Tests that block hashes are stored correctly at the system contract address after the fork - transition. Block hashes are stored incrementally at the transition until the - `HISTORY_SERVE_WINDOW` ring buffer is full. Afterwards the oldest block hash is replaced by the - new one. + Tests that block hashes are stored correctly at the system contract address + after the fork transition. Block hashes are stored incrementally at the + transition until the `HISTORY_SERVE_WINDOW` ring buffer is full. Afterwards + the oldest block hash is replaced by the new one. """ blocks: List[Block] = [] @@ -245,9 +248,9 @@ def test_block_hashes_history( current_block_number += 1 txs = [] - # On these blocks, `BLOCKHASH` will still return values for the last 256 blocks, and - # `HISTORY_STORAGE_ADDRESS` should now serve values for the previous blocks in the new - # fork. + # On these blocks, `BLOCKHASH` will still return values for the last 256 + # blocks, and `HISTORY_STORAGE_ADDRESS` should now serve values for the + # previous blocks in the new fork. code = Bytecode() storage = Storage() @@ -321,7 +324,10 @@ def test_block_hashes_history( def test_block_hashes_call_opcodes( blockchain_test: BlockchainTestFiller, pre: Alloc, call_opcode: Op ): - """Test that the call opcodes can be used to call the history contract and get the block hashes.""" # noqa: E501 + """ + Test that the call opcodes can be used to call the history contract and get + the block hashes. + """ blocks = [] blocks.append(Block()) @@ -382,11 +388,11 @@ def test_invalid_history_contract_calls( reverts: bool, ): """ - Test calling the history contract with invalid block numbers, such as blocks from the future - or overflowing block numbers. + Test calling the history contract with invalid block numbers, such as + blocks from the future or overflowing block numbers. - Also test the BLOCKHASH opcode with the same block numbers, which should not affect the - behavior of the opcode, even after verkle. + Also test the BLOCKHASH opcode with the same block numbers, which should + not affect the behavior of the opcode, even after verkle. """ storage = Storage() diff --git a/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py b/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py index 2175b38338..6593bd4527 100644 --- a/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py +++ b/prague/eip2935_historical_block_hashes_from_state/test_contract_deployment.py @@ -1,7 +1,6 @@ """ -abstract: Tests [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935). - Test system contract deployment for [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935). -""" # noqa: E501 +Tests [EIP-2935: Serve historical block hashes from state](https://eips.ethereum.org/EIPS/eip-2935). +""" from os.path import realpath from pathlib import Path @@ -44,7 +43,8 @@ def test_system_contract_deployment( **kwargs, ): """Verify deployment of the block hashes system contract.""" - # Deploy a contract that calls the history contract and verifies the block hashes. + # Deploy a contract that calls the history contract and verifies the block + # hashes. yield Block() # Empty block just to have more history in the contract. # We are going to query blocks even before contract deployment. @@ -77,27 +77,31 @@ def test_system_contract_deployment( storage: Dict if test_type == DeploymentTestType.DEPLOY_BEFORE_FORK: - # Fork happens at block 2, and the contract is already there, so from block number 1 and - # after, the block hashes should be there. + # Fork happens at block 2, and the contract is already there, so from + # block number 1 and after, the block hashes should be there. storage = { 1: 1, # Block prior to the fork, it's the first hash saved. 2: 1, # Fork block, hash should be there. - 3: 1, # Empty block added at the start of this function, hash should be there. + 3: 1, # Empty block added at the start of this function, hash + # should be there. } elif test_type == DeploymentTestType.DEPLOY_ON_FORK_BLOCK: # The contract should have the block hashes after contract deployment. storage = { 1: 1, # Fork and deployment block, the first hash that gets added. 2: 1, # Deployment block, hash should be there. - 3: 1, # Empty block added at the start of this function, hash should be there. + 3: 1, # Empty block added at the start of this function, hash + # should be there. } elif test_type == DeploymentTestType.DEPLOY_AFTER_FORK: # The contract should have the block hashes after contract deployment. storage = { 1: 0, # Fork block, but contract is not there yet. - 2: 1, # Deployment block, this is the first hash that gets added because it's added on + 2: 1, # Deployment block, this is the first hash that gets added + # because it's added on # the next block. - 3: 1, # Empty block added at the start of this function, hash should be there. + 3: 1, # Empty block added at the start of this function, hash + # should be there. } post[deployed_contract] = Account( diff --git a/prague/eip6110_deposits/conftest.py b/prague/eip6110_deposits/conftest.py index 4c3e88e262..11d9a4bcab 100644 --- a/prague/eip6110_deposits/conftest.py +++ b/prague/eip6110_deposits/conftest.py @@ -13,8 +13,8 @@ @pytest.fixture def update_pre(pre: Alloc, requests: List[DepositInteractionBase]): """ - Init state of the accounts. Every deposit transaction defines their own pre-state - requirements, and this fixture aggregates them all. + Init state of the accounts. Every deposit transaction defines their own + pre-state requirements, and this fixture aggregates them all. """ for d in requests: d.update_pre(pre) @@ -34,7 +34,10 @@ def txs( @pytest.fixture def block_body_override_requests() -> List[DepositRequest] | None: - """List of requests that overwrite the requests in the header. None by default.""" + """ + List of requests that overwrite the requests in the header. None by + default. + """ return None @@ -48,7 +51,9 @@ def exception() -> BlockException | None: def included_requests( requests: List[DepositInteractionBase], ) -> List[DepositRequest]: - """Return the list of deposit requests that should be included in each block.""" + """ + Return the list of deposit requests that should be included in each block. + """ valid_requests: List[DepositRequest] = [] for d in requests: diff --git a/prague/eip6110_deposits/helpers.py b/prague/eip6110_deposits/helpers.py index b664f8413e..8c06c1f307 100644 --- a/prague/eip6110_deposits/helpers.py +++ b/prague/eip6110_deposits/helpers.py @@ -77,22 +77,16 @@ class DepositRequest(DepositRequestBase): """Deposit request descriptor.""" valid: bool = True - """ - Whether the deposit request is valid or not. - """ + """Whether the deposit request is valid or not.""" gas_limit: int = 1_000_000 - """ - Gas limit for the call. - """ + """Gas limit for the call.""" calldata_modifier: Callable[[bytes], bytes] = lambda x: x - """ - Calldata modifier function. - """ + """Calldata modifier function.""" extra_wei: int = 0 """ - Extra amount in wei to be sent with the deposit. - If this value modulo 10**9 is not zero, the deposit will be invalid. - The value can be negative but if the total value is negative, an exception will be raised. + Extra amount in wei to be sent with the deposit. If this value modulo 10**9 + is not zero, the deposit will be invalid. The value can be negative but if + the total value is negative, an exception will be raised. """ interaction_contract_address: ClassVar[Address] = Address(Spec.DEPOSIT_CONTRACT_ADDRESS) @@ -100,8 +94,8 @@ class DepositRequest(DepositRequestBase): @cached_property def value(self) -> int: """ - Return the value of the deposit transaction, equal to the amount in gwei plus the - extra amount in wei. + Return the value of the deposit transaction, equal to the amount in + gwei plus the extra amount in wei. """ value = (self.amount * 10**9) + self.extra_wei if value < 0: @@ -123,13 +117,14 @@ def deposit_data_root(self) -> Hash: @cached_property def calldata(self) -> bytes: """ - Return the calldata needed to call the beacon chain deposit contract and make the deposit. + Return the calldata needed to call the beacon chain deposit contract + and make the deposit. deposit( - bytes calldata pubkey, - bytes calldata withdrawal_credentials, - bytes calldata signature, - bytes32 deposit_data_root + bytes calldata pubkey, + bytes calldata withdrawal_credentials, + bytes calldata signature, + bytes32 deposit_data_root ) """ offset_length = 32 @@ -155,11 +150,11 @@ def log(self, *, include_abi_encoding: bool = True) -> bytes: Return the log data for the deposit event. event DepositEvent( - bytes pubkey, - bytes withdrawal_credentials, - bytes amount, - bytes signature, - bytes index + bytes pubkey, + bytes withdrawal_credentials, + bytes amount, + bytes signature, + bytes index ); """ data = bytearray(576) @@ -199,17 +194,11 @@ class DepositInteractionBase: """Base class for all types of deposit transactions we want to test.""" sender_balance: int = 32_000_000_000_000_000_000 * 100 - """ - Balance of the account that sends the transaction. - """ + """Balance of the account that sends the transaction.""" sender_account: EOA | None = None - """ - Account that sends the transaction. - """ + """Account that sends the transaction.""" requests: List[DepositRequest] - """ - Deposit request to be included in the block. - """ + """Deposit request to be included in the block.""" def transactions(self) -> List[Transaction]: """Return a transaction for the deposit request.""" @@ -220,13 +209,19 @@ def update_pre(self, pre: Alloc): raise NotImplementedError def valid_requests(self, current_minimum_fee: int) -> List[DepositRequest]: - """Return the list of deposit requests that should be included in the block.""" + """ + Return the list of deposit requests that should be included in the + block. + """ raise NotImplementedError @dataclass(kw_only=True) class DepositTransaction(DepositInteractionBase): - """Class used to describe a deposit originated from an externally owned account.""" + """ + Class used to describe a deposit originated from an externally owned + account. + """ def transactions(self) -> List[Transaction]: """Return a transaction for the deposit request.""" @@ -248,7 +243,10 @@ def update_pre(self, pre: Alloc): self.sender_account = pre.fund_eoa(self.sender_balance) def valid_requests(self, current_minimum_fee: int) -> List[DepositRequest]: - """Return the list of deposit requests that should be included in the block.""" + """ + Return the list of deposit requests that should be included in the + block. + """ return [ request for request in self.requests @@ -261,34 +259,23 @@ class DepositContract(DepositInteractionBase): """Class used to describe a deposit originated from a contract.""" tx_gas_limit: int = 1_000_000 - """ - Gas limit for the transaction. - """ + """Gas limit for the transaction.""" tx_value: int = 0 - """ - Value to send with the transaction. - """ + """Value to send with the transaction.""" contract_balance: int = 32_000_000_000_000_000_000 * 100 - """ - Balance of the contract that sends the deposit requests. - """ + """Balance of the contract that sends the deposit requests.""" contract_address: Address | None = None - """ - Address of the contract that sends the deposit requests. - """ + """Address of the contract that sends the deposit requests.""" entry_address: Address | None = None - """ - Address to send the transaction to. - """ + """Address to send the transaction to.""" call_type: Op = field(default_factory=lambda: Op.CALL) - """ - Type of call to be made to the deposit contract. - """ + """Type of call to be made to the deposit contract.""" call_depth: int = 2 """ - Frame depth of the beacon chain deposit contract when it executes the deposit requests. + Frame depth of the beacon chain deposit contract when it executes the + deposit requests. """ extra_code: Bytecode = field(default_factory=Bytecode) """ @@ -357,5 +344,8 @@ def update_pre(self, pre: Alloc): ) def valid_requests(self, current_minimum_fee: int) -> List[DepositRequest]: - """Return the list of deposit requests that should be included in the block.""" + """ + Return the list of deposit requests that should be included in the + block. + """ return [d for d in self.requests if d.valid and d.value >= current_minimum_fee] diff --git a/prague/eip6110_deposits/test_deposits.py b/prague/eip6110_deposits/test_deposits.py index 6e3d62fcc1..edf36f7510 100644 --- a/prague/eip6110_deposits/test_deposits.py +++ b/prague/eip6110_deposits/test_deposits.py @@ -1,7 +1,9 @@ """ -abstract: Tests [EIP-6110: Supply validator deposits on chain](https://eips.ethereum.org/EIPS/eip-6110) - Test [EIP-6110: Supply validator deposits on chain](https://eips.ethereum.org/EIPS/eip-6110). -""" # noqa: E501 +Tests validator deposit functionality. + +Tests the validator deposit functionality implementation from +[EIP-6110: Supply validator deposits on chain](https://eips.ethereum.org/EIPS/eip-6110). +""" from typing import List @@ -185,7 +187,8 @@ amount=32_000_000_000, signature=0x03, index=0x0, - # From traces, gas used by the first tx is 82,718 so reduce by one here + # From traces, gas used by the first tx is 82,718 + # so reduce by one here gas_limit=0x1431D, valid=False, ), @@ -218,7 +221,8 @@ amount=32_000_000_000, signature=0x03, index=0x0, - # From traces, gas used by the second tx is 68,594, reduce by one here + # From traces, gas used by the second tx is 68,594, + # reduce by one here gas_limit=0x10BF1, valid=False, ), @@ -838,8 +842,8 @@ valid=False, ) ], - # Send 32 ETH minus 1 wei to the contract, note `DepositRequest.amount` is in - # gwei + # Send 32 ETH minus 1 wei to the contract, note + # `DepositRequest.amount` is in gwei tx_value=32_000_000_000 * 10**9 - 1, contract_balance=0, ), @@ -1182,8 +1186,8 @@ def test_deposit_negative( blocks: List[Block], ): """ - Test producing a block with the incorrect deposits in the body of the block, - and/or Engine API payload. + Test producing a block with the incorrect deposits in the body of the + block, and/or Engine API payload. """ blockchain_test( pre=pre, diff --git a/prague/eip6110_deposits/test_modified_contract.py b/prague/eip6110_deposits/test_modified_contract.py index bbb1f4fba2..80f58a868d 100644 --- a/prague/eip6110_deposits/test_modified_contract.py +++ b/prague/eip6110_deposits/test_modified_contract.py @@ -1,4 +1,7 @@ -"""Test variants of the deposit contract which adheres the log-style as described in EIP-6110.""" +""" +Test variants of the deposit contract which adheres the log-style as described +in EIP-6110. +""" import pytest @@ -44,8 +47,9 @@ DEFAULT_DEPOSIT_REQUEST_LOG_DATA_DICT = { "pubkey_data": bytes(DEFAULT_DEPOSIT_REQUEST.pubkey), "withdrawal_credentials_data": bytes(DEFAULT_DEPOSIT_REQUEST.withdrawal_credentials), - # Note: after converting to bytes, it is converted to little-endian by `[::-1]` - # (This happens on-chain also, but this is done by the solidity contract) + # Note: after converting to bytes, it is converted to little-endian by + # `[::-1]` (This happens on-chain also, but this is done by the solidity + # contract) "amount_data": bytes.fromhex("0" + DEFAULT_DEPOSIT_REQUEST.amount.hex()[2:])[::-1], "signature_data": bytes(DEFAULT_DEPOSIT_REQUEST.signature), "index_data": bytes(DEFAULT_DEPOSIT_REQUEST.index), @@ -77,36 +81,43 @@ def test_extra_logs( pre: Alloc, include_deposit_event: bool, ): - """Test deposit contract emitting more log event types than the ones in mainnet.""" - # Supplant mainnet contract with a variant that emits a `Transfer`` log - # If `include_deposit_event` is `True``, it will also emit a `DepositEvent` log` + """ + Test deposit contract emitting more log event types than the ones in + mainnet. + """ + # Supplant mainnet contract with a variant that emits a `Transfer`` log If + # `include_deposit_event` is `True``, it will also emit a `DepositEvent` + # log` # ERC20 token transfer log (Sepolia) - # https://sepolia.etherscan.io/tx/0x2d71f3085a796a0539c9cc28acd9073a67cf862260a41475f000dd101279f94f - # JSON RPC: - # curl https://sepolia.infura.io/v3/APIKEY \ - # -X POST \ - # -H "Content-Type: application/json" \ - # -d '{"jsonrpc": "2.0", "method": "eth_getLogs", - # "params": [{"address": "0x7f02C3E3c98b133055B8B348B2Ac625669Ed295D", - # "blockHash": "0x8062a17fa791f5dbd59ea68891422e3299ca4e80885a89acf3fc706c8bceef53"}], + # https://sepolia.etherscan.io/tx/ + # 0x2d71f3085a796a0539c9cc28acd9073a67cf862260a41475f000dd101279f94f + # JSON RPC: curl https://sepolia.infura.io/v3/APIKEY \ -X POST \ -H + # "Content-Type: application/json" \ -d '{"jsonrpc": "2.0", "method": + # "eth_getLogs", "params": [{"address": + # "0x7f02C3E3c98b133055B8B348B2Ac625669Ed295D", "blockHash": + # "0x8062a17fa791f5dbd59ea68891422e3299ca4e80885a89acf3fc706c8bceef53"}], # "id": 1}' # {"jsonrpc":"2.0","id":1,"result": # [{"removed":false,"logIndex":"0x80","transactionIndex":"0x56", - # "transactionHash":"0x2d71f3085a796a0539c9cc28acd9073a67cf862260a41475f000dd101279f94f", - # "blockHash":"0x8062a17fa791f5dbd59ea68891422e3299ca4e80885a89acf3fc706c8bceef53", + # "transactionHash": + # "0x2d71f3085a796a0539c9cc28acd9073a67cf862260a41475f000dd101279f94f", + # "blockHash": + # "0x8062a17fa791f5dbd59ea68891422e3299ca4e80885a89acf3fc706c8bceef53", # "blockNumber":"0x794fb5", # "address":"0x7f02c3e3c98b133055b8b348b2ac625669ed295d", - # "data":"0x0000000000000000000000000000000000000000000000000000000000000001", - # "topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + # "data": + # "0x0000000000000000000000000000000000000000000000000000000000000001", + # "topics": + # ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", # "0x0000000000000000000000006885e36bfcb68cb383dfe90023a462c03bcb2ae5", # "0x00000000000000000000000080b5dc88c98e528bf9cb4b7f0f076ac41da24651"] bytecode = Op.LOG3( - # ERC-20 token transfer log - # ERC-20 token transfers are LOG3, since the topic, the sender, and receiver - # are all topics (the sender and receiver are `indexed` in the solidity event) + # ERC-20 token transfer log ERC-20 token transfers are LOG3, since the + # topic, the sender, and receiver are all topics (the sender and + # receiver are `indexed` in the solidity event) 0, 32, 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF, @@ -171,7 +182,9 @@ def test_extra_logs( def test_invalid_layout( blockchain_test: BlockchainTestFiller, pre: Alloc, log_argument: str, value: str ): - """Test deposit contract emitting logs with invalid layouts (sizes/offsets).""" + """ + Test deposit contract emitting logs with invalid layouts (sizes/offsets). + """ log_params = {**DEFAULT_DEPOSIT_REQUEST_LOG_DATA_DICT} log_params[log_argument] = 0 if value == "zero" else 2**256 - 1 # type: ignore @@ -225,7 +238,10 @@ def test_invalid_layout( ) @pytest.mark.exception_test def test_invalid_log_length(blockchain_test: BlockchainTestFiller, pre: Alloc, slice_bytes: bool): - """Test deposit contract emitting logs with invalid log length (one byte more or less).""" + """ + Test deposit contract emitting logs with invalid log length (one byte more + or less). + """ changed_log = DEFAULT_REQUEST_LOG[:-1] if slice_bytes else DEFAULT_REQUEST_LOG + b"\x00" bytecode = Om.MSTORE(changed_log) + Op.LOG1( diff --git a/prague/eip7002_el_triggerable_withdrawals/conftest.py b/prague/eip7002_el_triggerable_withdrawals/conftest.py index c134463011..ac66187db0 100644 --- a/prague/eip7002_el_triggerable_withdrawals/conftest.py +++ b/prague/eip7002_el_triggerable_withdrawals/conftest.py @@ -18,8 +18,8 @@ def update_pre( blocks_withdrawal_requests: List[List[WithdrawalRequestInteractionBase]], ): """ - Init state of the accounts. Every deposit transaction defines their own pre-state - requirements, and this fixture aggregates them all. + Init state of the accounts. Every deposit transaction defines their own + pre-state requirements, and this fixture aggregates them all. """ for requests in blocks_withdrawal_requests: for r in requests: @@ -31,7 +31,10 @@ def included_requests( update_pre: None, # Fixture is used for its side effects blocks_withdrawal_requests: List[List[WithdrawalRequestInteractionBase]], ) -> List[List[WithdrawalRequest]]: - """Return the list of withdrawal requests that should be included in each block.""" + """ + Return the list of withdrawal requests that should be included in each + block. + """ excess_withdrawal_requests = 0 carry_over_requests: List[WithdrawalRequest] = [] per_block_included_requests: List[List[WithdrawalRequest]] = [] @@ -110,8 +113,10 @@ def blocks( timestamp += 1 return blocks + [ + # Add an empty block at the end to verify that no more withdrawal + # requests are included Block( header_verify=Header(requests_hash=Requests()), timestamp=timestamp, ) - ] # Add an empty block at the end to verify that no more withdrawal requests are included + ] diff --git a/prague/eip7002_el_triggerable_withdrawals/helpers.py b/prague/eip7002_el_triggerable_withdrawals/helpers.py index 2a0f7216ad..d8fa578a6c 100644 --- a/prague/eip7002_el_triggerable_withdrawals/helpers.py +++ b/prague/eip7002_el_triggerable_withdrawals/helpers.py @@ -17,22 +17,17 @@ class WithdrawalRequest(WithdrawalRequestBase): fee: int = 0 """ - Fee to be paid to the system contract for the withdrawal request. - This is different from `amount` which is the amount of gwei to be withdrawn on the beacon - chain. + Fee to be paid to the system contract for the withdrawal request. This is + different from `amount` which is the amount of gwei to be withdrawn on the + beacon chain. + """ valid: bool = True - """ - Whether the withdrawal request is valid or not. - """ + """Whether the withdrawal request is valid or not.""" gas_limit: int = 1_000_000 - """ - Gas limit for the call. - """ + """Gas limit for the call.""" calldata_modifier: Callable[[bytes], bytes] = lambda x: x - """ - Calldata modifier function. - """ + """Calldata modifier function.""" interaction_contract_address: ClassVar[Address] = Address( Spec.WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS @@ -41,23 +36,26 @@ class WithdrawalRequest(WithdrawalRequestBase): @property def value(self) -> int: """ - Return the value of the call to the withdrawal request contract, equal to the fee - to be paid. + Return the value of the call to the withdrawal request contract, equal + to the fee to be paid. """ return self.fee @cached_property def calldata(self) -> bytes: """ - Return the calldata needed to call the withdrawal request contract and make the - withdrawal. + Return the calldata needed to call the withdrawal request contract and + make the withdrawal. """ return self.calldata_modifier( self.validator_pubkey + self.amount.to_bytes(8, byteorder="big") ) def with_source_address(self, source_address: Address) -> "WithdrawalRequest": - """Return a new instance of the withdrawal request with the source address set.""" + """ + Return a new instance of the withdrawal request with the source address + set. + """ return self.copy(source_address=source_address) @@ -66,17 +64,11 @@ class WithdrawalRequestInteractionBase: """Base class for all types of withdrawal transactions we want to test.""" sender_balance: int = 1_000_000_000_000_000_000 - """ - Balance of the account that sends the transaction. - """ + """Balance of the account that sends the transaction.""" sender_account: EOA | None = None - """ - Account that will send the transaction. - """ + """Account that will send the transaction.""" requests: List[WithdrawalRequest] - """ - Withdrawal request to be included in the block. - """ + """Withdrawal request to be included in the block.""" def transactions(self) -> List[Transaction]: """Return a transaction for the withdrawal request.""" @@ -87,13 +79,19 @@ def update_pre(self, pre: Alloc): raise NotImplementedError def valid_requests(self, current_minimum_fee: int) -> List[WithdrawalRequest]: - """Return the list of withdrawal requests that should be valid in the block.""" + """ + Return the list of withdrawal requests that should be valid in the + block. + """ raise NotImplementedError @dataclass(kw_only=True) class WithdrawalRequestTransaction(WithdrawalRequestInteractionBase): - """Class used to describe a withdrawal request originated from an externally owned account.""" + """ + Class used to describe a withdrawal request originated from an externally + owned account. + """ def transactions(self) -> List[Transaction]: """Return a transaction for the withdrawal request.""" @@ -129,9 +127,7 @@ class WithdrawalRequestContract(WithdrawalRequestInteractionBase): """Class used to describe a withdrawal originated from a contract.""" tx_gas_limit: int = 1_000_000 - """ - Gas limit for the transaction. - """ + """Gas limit for the transaction.""" contract_balance: int = 1_000_000_000_000_000_000 """ @@ -142,22 +138,14 @@ class WithdrawalRequestContract(WithdrawalRequestInteractionBase): Address of the contract that will make the call to the pre-deploy contract. """ entry_address: Address | None = None - """ - Address to send the transaction to. - """ + """Address to send the transaction to.""" call_type: Op = field(default_factory=lambda: Op.CALL) - """ - Type of call to be used to make the withdrawal request. - """ + """Type of call to be used to make the withdrawal request.""" call_depth: int = 2 - """ - Frame depth of the pre-deploy contract when it executes the call. - """ + """Frame depth of the pre-deploy contract when it executes the call.""" extra_code: Bytecode = field(default_factory=Bytecode) - """ - Extra code to be added to the contract code. - """ + """Extra code to be added to the contract code.""" @property def contract_code(self) -> Bytecode: @@ -243,12 +231,12 @@ def get_n_fee_increments(n: int) -> List[int]: def get_n_fee_increment_blocks(n: int) -> List[List[WithdrawalRequestContract]]: """ - Return N blocks that should be included in the test such that each subsequent block has an - increasing fee for the withdrawal requests. + Return N blocks that should be included in the test such that each + subsequent block has an increasing fee for the withdrawal requests. - This is done by calculating the number of withdrawals required to reach the next fee increment - and creating a block with that number of withdrawal requests plus the number of withdrawals - required to reach the target. + This is done by calculating the number of withdrawals required to reach the + next fee increment and creating a block with that number of withdrawal + requests plus the number of withdrawals required to reach the target. """ blocks = [] previous_excess = 0 diff --git a/prague/eip7002_el_triggerable_withdrawals/spec.py b/prague/eip7002_el_triggerable_withdrawals/spec.py index e30a15011b..30f9833872 100644 --- a/prague/eip7002_el_triggerable_withdrawals/spec.py +++ b/prague/eip7002_el_triggerable_withdrawals/spec.py @@ -1,7 +1,8 @@ """ Common procedures to test -[EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). -""" # noqa: E501 +[EIP-7002: Execution layer triggerable +withdrawals](https://eips.ethereum.org/EIPS/eip-7002). +""" from dataclasses import dataclass diff --git a/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py b/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py index 90f690180e..0d1aa8b517 100644 --- a/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py +++ b/prague/eip7002_el_triggerable_withdrawals/test_contract_deployment.py @@ -1,7 +1,6 @@ """ -abstract: Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). - Test system contract deployment for [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). -""" # noqa: E501 +Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). +""" from os.path import realpath from pathlib import Path diff --git a/prague/eip7002_el_triggerable_withdrawals/test_modified_withdrawal_contract.py b/prague/eip7002_el_triggerable_withdrawals/test_modified_withdrawal_contract.py index 7346a630ae..e47a564ede 100644 --- a/prague/eip7002_el_triggerable_withdrawals/test_modified_withdrawal_contract.py +++ b/prague/eip7002_el_triggerable_withdrawals/test_modified_withdrawal_contract.py @@ -1,8 +1,6 @@ """ -abstract: Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002) - Test execution layer triggered exits [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). - -""" # noqa: E501 +Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). +""" from typing import List @@ -91,7 +89,10 @@ def test_extra_withdrawals( pre: Alloc, requests_list: List[WithdrawalRequest], ): - """Test how clients were to behave when more than 16 withdrawals would be allowed per block.""" + """ + Test how clients were to behave when more than 16 withdrawals would be + allowed per block. + """ modified_code: Bytecode = Bytecode() memory_offset: int = 0 amount_of_requests: int = 0 @@ -116,7 +117,8 @@ def test_extra_withdrawals( balance=0, ) - # given a list of withdrawal requests construct a withdrawal request transaction + # given a list of withdrawal requests construct a withdrawal request + # transaction withdrawal_request_transaction = WithdrawalRequestTransaction(requests=requests_list) # prepare withdrawal senders withdrawal_request_transaction.update_pre(pre=pre) @@ -144,8 +146,8 @@ def test_extra_withdrawals( ) def test_system_contract_errors(): """ - Test system contract raising different errors when called by the system account at the - end of the block execution. + Test system contract raising different errors when called by the system + account at the end of the block execution. To see the list of generated tests, please refer to the `generate_system_contract_error_test` decorator definition. diff --git a/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests.py b/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests.py index d764ceccbc..0613eae236 100644 --- a/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests.py +++ b/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests.py @@ -1,8 +1,6 @@ """ -abstract: Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002) - Test execution layer triggered exits [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). - -""" # noqa: E501 +Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). +""" from typing import List @@ -816,8 +814,8 @@ def test_withdrawal_requests_negative( exception: BlockException, ): """ - Test blocks where the requests list and the actual withdrawal requests that happened in the - block's transactions do not match. + Test blocks where the requests list and the actual withdrawal requests that + happened in the block's transactions do not match. """ for d in requests: d.update_pre(pre) diff --git a/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests_during_fork.py b/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests_during_fork.py index e61cf87b7c..6f9948c038 100644 --- a/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests_during_fork.py +++ b/prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests_during_fork.py @@ -1,8 +1,6 @@ """ -abstract: Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002) - Test execution layer triggered exits [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). - -""" # noqa: E501 +Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002). +""" from os.path import realpath from pathlib import Path @@ -57,8 +55,9 @@ validator_pubkey=0x02, amount=0, fee=Spec.get_fee(10), - # First post-fork withdrawal request, will not be included - # because the inhibitor is cleared at the end of the block + # First post-fork withdrawal request, will not + # be included because the inhibitor is cleared + # at the end of the block valid=False, ) ], @@ -91,8 +90,12 @@ def test_withdrawal_requests_during_fork( blocks: List[Block], pre: Alloc, ): - """Test making a withdrawal request to the beacon chain at the time of the fork.""" - # We need to delete the deployed contract that comes by default in the pre state. + """ + Test making a withdrawal request to the beacon chain at the time of the + fork. + """ + # We need to delete the deployed contract that comes by default in the pre + # state. pre[Spec.WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS] = Account( balance=0, code=bytes(), diff --git a/prague/eip7251_consolidations/conftest.py b/prague/eip7251_consolidations/conftest.py index 3fd5b8be64..f116162ca4 100644 --- a/prague/eip7251_consolidations/conftest.py +++ b/prague/eip7251_consolidations/conftest.py @@ -18,8 +18,8 @@ def update_pre( blocks_consolidation_requests: List[List[ConsolidationRequestInteractionBase]], ): """ - Init state of the accounts. Every deposit transaction defines their own pre-state - requirements, and this fixture aggregates them all. + Init state of the accounts. Every deposit transaction defines their own + pre-state requirements, and this fixture aggregates them all. """ for requests in blocks_consolidation_requests: for r in requests: @@ -31,7 +31,10 @@ def included_requests( update_pre: None, # Fixture is used for its side effects blocks_consolidation_requests: List[List[ConsolidationRequestInteractionBase]], ) -> List[List[ConsolidationRequest]]: - """Return the list of consolidation requests that should be included in each block.""" + """ + Return the list of consolidation requests that should be included in each + block. + """ excess_consolidation_requests = 0 carry_over_requests: List[ConsolidationRequest] = [] per_block_included_requests: List[List[ConsolidationRequest]] = [] @@ -39,7 +42,8 @@ def included_requests( # Get fee for the current block current_minimum_fee = Spec.get_fee(excess_consolidation_requests) - # With the fee, get the valid consolidation requests for the current block + # With the fee, get the valid consolidation requests for the current + # block current_block_requests = [] for w in block_consolidation_requests: current_block_requests += w.valid_requests(current_minimum_fee) @@ -111,4 +115,5 @@ def blocks( header_verify=Header(requests_hash=Requests()), timestamp=timestamp, ) - ] # Add an empty block at the end to verify that no more consolidation requests are included + ] # Add an empty block at the end to verify that no more consolidation + # requests are included diff --git a/prague/eip7251_consolidations/helpers.py b/prague/eip7251_consolidations/helpers.py index 466afb8455..20795482db 100644 --- a/prague/eip7251_consolidations/helpers.py +++ b/prague/eip7251_consolidations/helpers.py @@ -16,21 +16,13 @@ class ConsolidationRequest(ConsolidationRequestBase): """Class used to describe a consolidation request in a test.""" fee: int = 0 - """ - Fee to be paid to the system contract for the consolidation request. - """ + """Fee to be paid to the system contract for the consolidation request.""" valid: bool = True - """ - Whether the consolidation request is valid or not. - """ + """Whether the consolidation request is valid or not.""" gas_limit: int = 1_000_000 - """ - Gas limit for the call. - """ + """Gas limit for the call.""" calldata_modifier: Callable[[bytes], bytes] = lambda x: x - """ - Calldata modifier function. - """ + """Calldata modifier function.""" interaction_contract_address: ClassVar[Address] = Address( Spec.CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS @@ -39,40 +31,39 @@ class ConsolidationRequest(ConsolidationRequestBase): @property def value(self) -> int: """ - Return the value of the call to the consolidation request contract, equal to the fee - to be paid. + Return the value of the call to the consolidation request contract, + equal to the fee to be paid. """ return self.fee @cached_property def calldata(self) -> bytes: """ - Return the calldata needed to call the consolidation request contract and make the - consolidation. + Return the calldata needed to call the consolidation request contract + and make the consolidation. """ return self.calldata_modifier(self.source_pubkey + self.target_pubkey) def with_source_address(self, source_address: Address) -> "ConsolidationRequest": - """Return a new instance of the consolidation request with the source address set.""" + """ + Return a new instance of the consolidation request with the source + address set. + """ return self.copy(source_address=source_address) @dataclass(kw_only=True) class ConsolidationRequestInteractionBase: - """Base class for all types of consolidation transactions we want to test.""" - - sender_balance: int = 1_000_000_000_000_000_000 """ - Balance of the account that sends the transaction. + Base class for all types of consolidation transactions we want to test. """ + + sender_balance: int = 1_000_000_000_000_000_000 + """Balance of the account that sends the transaction.""" sender_account: EOA | None = None - """ - Account that will send the transaction. - """ + """Account that will send the transaction.""" requests: List[ConsolidationRequest] - """ - Consolidation requests to be included in the block. - """ + """Consolidation requests to be included in the block.""" def transactions(self) -> List[Transaction]: """Return a transaction for the consolidation request.""" @@ -83,13 +74,19 @@ def update_pre(self, pre: Alloc): raise NotImplementedError def valid_requests(self, current_minimum_fee: int) -> List[ConsolidationRequest]: - """Return the list of consolidation requests that should be valid in the block.""" + """ + Return the list of consolidation requests that should be valid in the + block. + """ raise NotImplementedError @dataclass(kw_only=True) class ConsolidationRequestTransaction(ConsolidationRequestInteractionBase): - """Class to describe a consolidation request originated from an externally owned account.""" + """ + Class to describe a consolidation request originated from an externally + owned account. + """ def transactions(self) -> List[Transaction]: """Return a transaction for the consolidation request.""" @@ -125,9 +122,7 @@ class ConsolidationRequestContract(ConsolidationRequestInteractionBase): """Class used to describe a consolidation originated from a contract.""" tx_gas_limit: int = 10_000_000 - """ - Gas limit for the transaction. - """ + """Gas limit for the transaction.""" contract_balance: int = 1_000_000_000_000_000_000 """ @@ -138,22 +133,14 @@ class ConsolidationRequestContract(ConsolidationRequestInteractionBase): Address of the contract that will make the call to the pre-deploy contract. """ entry_address: Address | None = None - """ - Address to send the transaction to. - """ + """Address to send the transaction to.""" call_type: Op = field(default_factory=lambda: Op.CALL) - """ - Type of call to be used to make the consolidation request. - """ + """Type of call to be used to make the consolidation request.""" call_depth: int = 2 - """ - Frame depth of the pre-deploy contract when it executes the call. - """ + """Frame depth of the pre-deploy contract when it executes the call.""" extra_code: Bytecode = field(default_factory=Bytecode) - """ - Extra code to be added to the contract code. - """ + """Extra code to be added to the contract code.""" @property def contract_code(self) -> Bytecode: @@ -239,12 +226,13 @@ def get_n_fee_increments(n: int) -> List[int]: def get_n_fee_increment_blocks(n: int) -> List[List[ConsolidationRequestContract]]: """ - Return N blocks that should be included in the test such that each subsequent block has an - increasing fee for the consolidation requests. + Return N blocks that should be included in the test such that each + subsequent block has an increasing fee for the consolidation requests. - This is done by calculating the number of consolidations required to reach the next fee - increment and creating a block with that number of consolidation requests plus the number of - consolidations required to reach the target. + This is done by calculating the number of consolidations required to reach + the next fee increment and creating a block with that number of + consolidation requests plus the number of consolidations required to reach + the target. """ blocks = [] previous_excess = 0 diff --git a/prague/eip7251_consolidations/test_consolidations.py b/prague/eip7251_consolidations/test_consolidations.py index bd5f8d81e6..929ba8ba09 100644 --- a/prague/eip7251_consolidations/test_consolidations.py +++ b/prague/eip7251_consolidations/test_consolidations.py @@ -1,8 +1,6 @@ """ -abstract: Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251) - Test execution layer triggered consolidations [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251). - -""" # noqa: E501 +Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251). +""" from typing import List @@ -866,8 +864,8 @@ def test_consolidation_requests_negative( exception: BlockException, ): """ - Test blocks where the requests list and the actual consolidation requests that happened in the - block's transactions do not match. + Test blocks where the requests list and the actual consolidation requests + that happened in the block's transactions do not match. """ for d in requests: d.update_pre(pre) diff --git a/prague/eip7251_consolidations/test_consolidations_during_fork.py b/prague/eip7251_consolidations/test_consolidations_during_fork.py index 4731b3842f..36f948c102 100644 --- a/prague/eip7251_consolidations/test_consolidations_during_fork.py +++ b/prague/eip7251_consolidations/test_consolidations_during_fork.py @@ -1,8 +1,6 @@ """ -abstract: Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251) - Test execution layer triggered consolidations [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251). - -""" # noqa: E501 +Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251). +""" from os.path import realpath from pathlib import Path @@ -57,8 +55,9 @@ source_pubkey=0x03, target_pubkey=0x04, fee=Spec.get_fee(10), - # First post-fork consolidation request, will not be included - # because the inhibitor is cleared at the end of the block + # First post-fork consolidation request, will + # not be included because the inhibitor is + # cleared at the end of the block valid=False, ) ], @@ -91,8 +90,12 @@ def test_consolidation_requests_during_fork( blocks: List[Block], pre: Alloc, ): - """Test making a consolidation request to the beacon chain at the time of the fork.""" - # We need to delete the deployed contract that comes by default in the pre state. + """ + Test making a consolidation request to the beacon chain at the time of the + fork. + """ + # We need to delete the deployed contract that comes by default in the pre + # state. pre[Spec.CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS] = Account( balance=0, code=bytes(), diff --git a/prague/eip7251_consolidations/test_contract_deployment.py b/prague/eip7251_consolidations/test_contract_deployment.py index f0a66d2b96..0d195306ac 100644 --- a/prague/eip7251_consolidations/test_contract_deployment.py +++ b/prague/eip7251_consolidations/test_contract_deployment.py @@ -1,7 +1,6 @@ """ -abstract: Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251). - Test system contract deployment for [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251). -""" # noqa: E501 +Tests [EIP-7251: Increase the MAX_EFFECTIVE_BALANCE](https://eips.ethereum.org/EIPS/eip-7251). +""" from os.path import realpath from pathlib import Path diff --git a/prague/eip7251_consolidations/test_modified_consolidation_contract.py b/prague/eip7251_consolidations/test_modified_consolidation_contract.py index d29c1177e2..a3f33ac2ec 100644 --- a/prague/eip7251_consolidations/test_modified_consolidation_contract.py +++ b/prague/eip7251_consolidations/test_modified_consolidation_contract.py @@ -1,8 +1,6 @@ """ -abstract: Tests [EIP-7251: Execution layer triggerable consolidation](https://eips.ethereum.org/EIPS/eip-7251) - Test execution layer triggered exits [EIP-7251: Execution layer triggerable consolidation](https://eips.ethereum.org/EIPS/eip-7251). - -""" # noqa: E501 +Tests [EIP-7251: Execution layer triggerable consolidation](https://eips.ethereum.org/EIPS/eip-7251). +""" from typing import List @@ -91,7 +89,9 @@ def test_extra_consolidations( pre: Alloc, requests_list: List[ConsolidationRequest], ): - """Test how clients were to behave with more than 2 consolidations per block.""" + """ + Test how clients were to behave with more than 2 consolidations per block. + """ modified_code: Bytecode = Bytecode() memory_offset: int = 0 amount_of_requests: int = 0 @@ -116,7 +116,8 @@ def test_extra_consolidations( balance=0, ) - # given a list of consolidation requests construct a consolidation request transaction + # given a list of consolidation requests construct a consolidation request + # transaction consolidation_request_transaction = ConsolidationRequestTransaction(requests=requests_list) # prepare consolidation senders consolidation_request_transaction.update_pre(pre=pre) @@ -144,8 +145,8 @@ def test_extra_consolidations( ) def test_system_contract_errors(): """ - Test system contract raising different errors when called by the system account at the - end of the block execution. + Test system contract raising different errors when called by the system + account at the end of the block execution. To see the list of generated tests, please refer to the `generate_system_contract_error_test` decorator definition. diff --git a/prague/eip7623_increase_calldata_cost/__init__.py b/prague/eip7623_increase_calldata_cost/__init__.py index 951922c6f9..ef3f7c8099 100644 --- a/prague/eip7623_increase_calldata_cost/__init__.py +++ b/prague/eip7623_increase_calldata_cost/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623) - Tests for [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623). +Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623). """ diff --git a/prague/eip7623_increase_calldata_cost/conftest.py b/prague/eip7623_increase_calldata_cost/conftest.py index 5f0a4b50d0..a4f30d2911 100644 --- a/prague/eip7623_increase_calldata_cost/conftest.py +++ b/prague/eip7623_increase_calldata_cost/conftest.py @@ -48,8 +48,8 @@ def to( @pytest.fixture def protected() -> bool: """ - Return whether the transaction is protected or not. - Only valid for type-0 transactions. + Return whether the transaction is protected or not. Only valid for type-0 + transactions. """ return True @@ -62,7 +62,10 @@ def access_list() -> List[AccessList] | None: @pytest.fixture def authorization_refund() -> bool: - """Return whether the transaction has an existing authority in the authorization list.""" + """ + Return whether the transaction has an existing authority in the + authorization list. + """ return False @@ -75,9 +78,9 @@ def authorization_list( """ Authorization-list for the transaction. - This fixture needs to be parametrized indirectly in order to generate the authorizations with - valid signers using `pre` in this function, and the parametrized value should be a list of - addresses. + This fixture needs to be parametrized indirectly in order to generate the + authorizations with valid signers using `pre` in this function, and the + parametrized value should be a list of addresses. """ if not hasattr(request, "param"): return None @@ -127,20 +130,24 @@ def tx_data( intrinsic_gas_data_floor_minimum_delta: int, ) -> Bytes: """ - All tests in this file use data that is generated dynamically depending on the case and the - attributes of the transaction in order to reach the edge cases where the floor gas cost is - equal or barely greater than the intrinsic gas cost. + All tests in this file use data that is generated dynamically depending on + the case and the attributes of the transaction in order to reach the edge + cases where the floor gas cost is equal or barely greater than the + intrinsic gas cost. We have two different types of tests: - - FLOOR_GAS_COST_LESS_THAN_OR_EQUAL_TO_INTRINSIC_GAS: The floor gas cost is less than or equal - to the intrinsic gas cost, which means that the size of the tokens in the data are not - enough to trigger the floor gas cost. - - FLOOR_GAS_COST_GREATER_THAN_INTRINSIC_GAS: The floor gas cost is greater than the intrinsic - gas cost, which means that the size of the tokens in the data are enough to trigger the - floor gas cost. - - E.g. Given a transaction with a single access list and a single storage key, its intrinsic gas - cost (as of Prague fork) can be calculated as: + + - FLOOR_GAS_COST_LESS_THAN_OR_EQUAL_TO_INTRINSIC_GAS: The floor gas cost is + less than or equal to the intrinsic gas cost, which means that the size + of the tokens in the data are not enough to trigger the floor gas cost. + + - FLOOR_GAS_COST_GREATER_THAN_INTRINSIC_GAS: The floor gas cost is greater + than the intrinsic gas cost, which means that the size of the tokens in + the data are enough to trigger the floor gas cost. + + E.g. Given a transaction with a single access list and a single storage + key, its intrinsic gas cost (as of Prague fork) can be calculated as: + - 21,000 gas for the transaction - 2,400 gas for the access list - 1,900 gas for the storage key @@ -152,18 +159,19 @@ def tx_data( - 40 gas for each non-zero byte in the data - 10 gas for each zero byte in the data - Notice that the data included in the transaction affects both the intrinsic gas cost and the - floor data cost, but at different rates. + Notice that the data included in the transaction affects both the intrinsic + gas cost and the floor data cost, but at different rates. - The purpose of this function is to find the exact amount of data where the floor data gas - cost starts exceeding the intrinsic gas cost. + The purpose of this function is to find the exact amount of data where the + floor data gas cost starts exceeding the intrinsic gas cost. - After a binary search we find that adding 717 tokens of data (179 non-zero bytes + - 1 zero byte) triggers the floor gas cost. + After a binary search we find that adding 717 tokens of data (179 non-zero + bytes + 1 zero byte) triggers the floor gas cost. - Therefore, this function will return a Bytes object with 179 non-zero bytes and 1 zero byte - for `FLOOR_GAS_COST_GREATER_THAN_INTRINSIC_GAS` and a Bytes object with 179 non-zero bytes - and no zero bytes for `FLOOR_GAS_COST_LESS_THAN_OR_EQUAL_TO_INTRINSIC_GAS` + Therefore, this function will return a Bytes object with 179 non-zero bytes + and 1 zero byte for `FLOOR_GAS_COST_GREATER_THAN_INTRINSIC_GAS` and a Bytes + object with 179 non-zero bytes and no zero bytes for + `FLOOR_GAS_COST_LESS_THAN_OR_EQUAL_TO_INTRINSIC_GAS` """ def tokens_to_data(tokens: int) -> Bytes: @@ -188,11 +196,11 @@ def transaction_intrinsic_cost_calculator(tokens: int) -> int: def transaction_data_floor_cost_calculator(tokens: int) -> int: return fork_data_floor_cost_calculator(data=tokens_to_data(tokens)) - # Start with zero data and check the difference in the gas calculator between the - # intrinsic gas cost and the floor gas cost. + # Start with zero data and check the difference in the gas calculator + # between the intrinsic gas cost and the floor gas cost. if transaction_data_floor_cost_calculator(0) >= transaction_intrinsic_cost_calculator(0): - # Special case which is a transaction with no extra intrinsic gas costs other than the - # data cost, any data will trigger the floor gas cost. + # Special case which is a transaction with no extra intrinsic gas costs + # other than the data cost, any data will trigger the floor gas cost. if data_test_type == DataTestType.FLOOR_GAS_COST_LESS_THAN_OR_EQUAL_TO_INTRINSIC_GAS: return Bytes(b"") else: @@ -213,13 +221,15 @@ def tx_gas_delta() -> int: """ Gas delta to modify the gas amount included with the transaction. - If negative, the transaction will be invalid because the intrinsic gas cost is greater than the - gas limit. + If negative, the transaction will be invalid because the intrinsic gas cost + is greater than the gas limit. - This value operates regardless of whether the floor data gas cost is reached or not. + This value operates regardless of whether the floor data gas cost is + reached or not. - If the value is greater than zero, the transaction will also be valid and the test will check - that transaction processing does not consume more gas than it should. + If the value is greater than zero, the transaction will also be valid and + the test will check that transaction processing does not consume more gas + than it should. """ return 0 @@ -258,10 +268,11 @@ def tx_intrinsic_gas_cost_including_floor_data_cost( """ Transaction intrinsic gas cost. - The calculated value takes into account the normal intrinsic gas cost and the floor data gas - cost if it is greater than the intrinsic gas cost. + The calculated value takes into account the normal intrinsic gas cost and + the floor data gas cost if it is greater than the intrinsic gas cost. - In other words, this is the value that is required for the transaction to be valid. + In other words, this is the value that is required for the transaction to + be valid. """ intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() return intrinsic_gas_cost_calculator( @@ -290,7 +301,8 @@ def tx_gas_limit( """ Gas limit for the transaction. - The gas delta is added to the intrinsic gas cost to generate different test scenarios. + The gas delta is added to the intrinsic gas cost to generate different test + scenarios. """ return tx_intrinsic_gas_cost_including_floor_data_cost + tx_gas_delta diff --git a/prague/eip7623_increase_calldata_cost/helpers.py b/prague/eip7623_increase_calldata_cost/helpers.py index d4235976c3..fc4f94bd63 100644 --- a/prague/eip7623_increase_calldata_cost/helpers.py +++ b/prague/eip7623_increase_calldata_cost/helpers.py @@ -16,16 +16,18 @@ def find_floor_cost_threshold( intrinsic_gas_cost_calculator: Callable[[int], int], ) -> int: """ - Find the minimum amount of tokens that will trigger the floor gas cost, by using a binary - search and the intrinsic gas cost and floor data calculators. + Find the minimum amount of tokens that will trigger the floor gas cost, by + using a binary search and the intrinsic gas cost and floor data + calculators. """ - # Start with 1000 tokens and if the intrinsic gas cost is greater than the floor gas cost, - # multiply the number of tokens by 2 until it's not. + # Start with 1000 tokens and if the intrinsic gas cost is greater than the + # floor gas cost, multiply the number of tokens by 2 until it's not. tokens = 1000 while floor_data_gas_cost_calculator(tokens) < intrinsic_gas_cost_calculator(tokens): tokens *= 2 - # Binary search to find the minimum number of tokens that will trigger the floor gas cost. + # Binary search to find the minimum number of tokens that will trigger the + # floor gas cost. left = 0 right = tokens while left < right: @@ -39,7 +41,8 @@ def find_floor_cost_threshold( if floor_data_gas_cost_calculator(tokens) > intrinsic_gas_cost_calculator(tokens): tokens -= 1 - # Verify that increasing the tokens by one would always trigger the floor gas cost. + # Verify that increasing the tokens by one would always trigger the floor + # gas cost. assert ( floor_data_gas_cost_calculator(tokens) <= intrinsic_gas_cost_calculator(tokens) ) and floor_data_gas_cost_calculator(tokens + 1) > intrinsic_gas_cost_calculator(tokens + 1), ( diff --git a/prague/eip7623_increase_calldata_cost/test_execution_gas.py b/prague/eip7623_increase_calldata_cost/test_execution_gas.py index c0ef506023..53eb2957b5 100644 --- a/prague/eip7623_increase_calldata_cost/test_execution_gas.py +++ b/prague/eip7623_increase_calldata_cost/test_execution_gas.py @@ -1,7 +1,6 @@ """ -abstract: Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623) - Test execution gas consumption after [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623). -""" # noqa: E501 +Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623). +""" from typing import List @@ -41,7 +40,10 @@ class TestGasConsumption: @pytest.fixture def intrinsic_gas_data_floor_minimum_delta(self) -> int: - """Force a minimum delta in order to have some gas to execute the invalid opcode.""" + """ + Force a minimum delta in order to have some gas to execute the invalid + opcode. + """ return 50_000 @pytest.fixture @@ -49,7 +51,10 @@ def to( self, pre: Alloc, ) -> Address | None: - """Return a contract that consumes all gas when executed by calling an invalid opcode.""" + """ + Return a contract that consumes all gas when executed by calling an + invalid opcode. + """ return pre.deploy_contract(Op.INVALID) @pytest.mark.parametrize( @@ -78,7 +83,10 @@ def test_full_gas_consumption( pre: Alloc, tx: Transaction, ) -> None: - """Test executing a transaction that fully consumes its execution gas allocation.""" + """ + Test executing a transaction that fully consumes its execution gas + allocation. + """ tx.expected_receipt = TransactionReceipt(gas_used=tx.gas_limit) state_test( pre=pre, @@ -136,8 +144,8 @@ def to( @pytest.mark.parametrize( "tx_gas_delta", [ - # Test with exact gas and extra gas, to verify that the refund is correctly applied - # to the full consumed execution gas. + # Test with exact gas and extra gas, to verify that the refund is + # correctly applied to the full consumed execution gas. pytest.param(0, id="exact_gas"), ], ) @@ -148,7 +156,9 @@ def test_gas_consumption_below_data_floor( tx: Transaction, tx_floor_data_cost: int, ) -> None: - """Test executing a transaction that almost consumes the floor data cost.""" + """ + Test executing a transaction that almost consumes the floor data cost. + """ tx.expected_receipt = TransactionReceipt(gas_used=tx_floor_data_cost) state_test( pre=pre, diff --git a/prague/eip7623_increase_calldata_cost/test_refunds.py b/prague/eip7623_increase_calldata_cost/test_refunds.py index 10781bb9e0..94908fdf0d 100644 --- a/prague/eip7623_increase_calldata_cost/test_refunds.py +++ b/prague/eip7623_increase_calldata_cost/test_refunds.py @@ -1,7 +1,6 @@ """ -abstract: Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623) - Test applied refunds for [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623). -""" # noqa: E501 +Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623). +""" from enum import Enum, Flag, auto from typing import Dict, List @@ -35,18 +34,16 @@ class RefundTestType(Enum): EXECUTION_GAS_MINUS_REFUND_GREATER_THAN_DATA_FLOOR = 0 """ - The execution gas minus the refund is greater than the data floor, hence the execution gas cost - is charged. + The execution gas minus the refund is greater than the data floor, hence + the execution gas cost is charged. """ EXECUTION_GAS_MINUS_REFUND_LESS_THAN_DATA_FLOOR = 1 """ - The execution gas minus the refund is less than the data floor, hence the data floor cost is - charged. + The execution gas minus the refund is less than the data floor, hence the + data floor cost is charged. """ EXECUTION_GAS_MINUS_REFUND_EQUAL_TO_DATA_FLOOR = 2 - """ - The execution gas minus the refund is equal to the data floor. - """ + """The execution gas minus the refund is equal to the data floor.""" class RefundType(Flag): @@ -56,7 +53,10 @@ class RefundType(Flag): """The storage is cleared from a non-zero value.""" AUTHORIZATION_EXISTING_AUTHORITY = auto() - """The authorization list contains an authorization where the authority exists in the state.""" + """ + The authorization list contains an authorization where the authority exists + in the state. + """ @pytest.fixture @@ -67,7 +67,10 @@ def data_test_type() -> DataTestType: @pytest.fixture def authorization_list(pre: Alloc, refund_type: RefundType) -> List[AuthorizationTuple] | None: - """Modify fixture from conftest to automatically read the refund_type information.""" + """ + Modify fixture from conftest to automatically read the refund_type + information. + """ if RefundType.AUTHORIZATION_EXISTING_AUTHORITY not in refund_type: return None return [AuthorizationTuple(signer=pre.fund_eoa(1), address=Address(1))] @@ -75,7 +78,10 @@ def authorization_list(pre: Alloc, refund_type: RefundType) -> List[Authorizatio @pytest.fixture def ty(refund_type: RefundType) -> int: - """Modify fixture from conftest to automatically read the refund_type information.""" + """ + Modify fixture from conftest to automatically read the refund_type + information. + """ if RefundType.AUTHORIZATION_EXISTING_AUTHORITY in refund_type: return 4 return 2 @@ -125,8 +131,8 @@ def code_storage(refund_type: RefundType) -> Dict: @pytest.fixture def contract_creating_tx() -> bool: """ - Override fixture in order to avoid a circular fixture dependency since - none of these tests are contract creating transactions. + Override fixture in order to avoid a circular fixture dependency since none + of these tests are contract creating transactions. """ return False @@ -137,12 +143,14 @@ def intrinsic_gas_data_floor_minimum_delta() -> int: Induce a minimum delta between the transaction intrinsic gas cost and the floor data gas cost. - Since at least one of the cases requires some execution gas expenditure (SSTORE clearing), - we need to introduce an increment of the floor data cost above the transaction intrinsic gas - cost, otherwise the floor data cost would always be the below the execution gas cost even - after the refund is applied. + Since at least one of the cases requires some execution gas expenditure + (SSTORE clearing), we need to introduce an increment of the floor data cost + above the transaction intrinsic gas cost, otherwise the floor data cost + would always be the below the execution gas cost even after the refund is + applied. - This value has been set as of Prague and should be adjusted if the gas costs change. + This value has been set as of Prague and should be adjusted if the gas + costs change. """ return 250 @@ -160,10 +168,11 @@ def execution_gas_used( This gas amount is on top of the transaction intrinsic gas cost. - If this value were zero it would result in the refund being applied to the execution gas cost - and the resulting amount being always below the floor data cost, hence we need to find a - higher value in this function to ensure we get both scenarios where the refund drives - the execution cost below the floor data cost and above the floor data cost. + If this value were zero it would result in the refund being applied to the + execution gas cost and the resulting amount being always below the floor + data cost, hence we need to find a higher value in this function to ensure + we get both scenarios where the refund drives the execution cost below the + floor data cost and above the floor data cost. """ def execution_gas_cost(execution_gas: int) -> int: @@ -177,7 +186,8 @@ def execution_gas_cost(execution_gas: int) -> int: "test to fail. Try increasing the intrinsic_gas_data_floor_minimum_delta fixture." ) - # Dumb for-loop to find the execution gas cost that will result in the expected refund. + # Dumb for-loop to find the execution gas cost that will result in the + # expected refund. while execution_gas_cost(execution_gas) < tx_floor_data_cost: execution_gas += 1 if refund_test_type == RefundTestType.EXECUTION_GAS_MINUS_REFUND_EQUAL_TO_DATA_FLOOR: @@ -212,7 +222,8 @@ def to( """ Return a contract that consumes the expected execution gas. - At the moment we naively use JUMPDEST to consume the gas, which can yield very big contracts. + At the moment we naively use JUMPDEST to consume the gas, which can yield + very big contracts. Ideally, we can use memory expansion to consume gas. """ @@ -232,7 +243,8 @@ def tx_gas_limit( """ Gas limit for the transaction. - The gas delta is added to the intrinsic gas cost to generate different test scenarios. + The gas delta is added to the intrinsic gas cost to generate different test + scenarios. """ tx_gas_limit = tx_intrinsic_gas_cost_before_execution + execution_gas_used assert tx_gas_limit >= tx_intrinsic_gas_cost_including_floor_data_cost @@ -265,7 +277,10 @@ def test_gas_refunds_from_data_floor( refund: int, refund_test_type: RefundTestType, ) -> None: - """Test gas refunds deducted from the execution gas cost and not the data floor.""" + """ + Test gas refunds deducted from the execution gas cost and not the data + floor. + """ gas_used = tx_intrinsic_gas_cost_before_execution + execution_gas_used - refund if refund_test_type == RefundTestType.EXECUTION_GAS_MINUS_REFUND_LESS_THAN_DATA_FLOOR: assert gas_used < tx_floor_data_cost @@ -278,17 +293,17 @@ def test_gas_refunds_from_data_floor( if gas_used < tx_floor_data_cost: gas_used = tx_floor_data_cost # This is the actual test verification: - # - During test filling, the receipt returned by the transition tool (t8n) is verified against - # the expected receipt. - # - During test consumption, this is reflected in the balance difference and the state - # root. + # - During test filling, the receipt returned by the transition tool + # (t8n) is verified against the expected receipt. + # - During test consumption, this is reflected in the balance difference + # and the state root. tx.expected_receipt = TransactionReceipt(gas_used=gas_used) state_test( pre=pre, post={ tx.to: { - # Verify that the storage was cleared (for storage clear refund). - # See `code_storage` fixture for more details. + # Verify that the storage was cleared (for storage clear + # refund). See `code_storage` fixture for more details. "storage": {0: 0}, } }, diff --git a/prague/eip7623_increase_calldata_cost/test_transaction_validity.py b/prague/eip7623_increase_calldata_cost/test_transaction_validity.py index 27457fc328..dba9565f94 100644 --- a/prague/eip7623_increase_calldata_cost/test_transaction_validity.py +++ b/prague/eip7623_increase_calldata_cost/test_transaction_validity.py @@ -1,7 +1,6 @@ """ -abstract: Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623) - Test transaction validity on [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623). -""" # noqa: E501 +Test [EIP-7623: Increase calldata cost](https://eips.ethereum.org/EIPS/eip-7623). +""" import pytest @@ -33,8 +32,9 @@ pytest.mark.parametrize( "tx_gas_delta", [ - # Test the case where the included gas is greater than the intrinsic gas to verify that - # the data floor does not consume more gas than it should. + # Test the case where the included gas is greater than the + # intrinsic gas to verify that the data floor does not consume more + # gas than it should. pytest.param(1, id="extra_gas"), pytest.param(0, id="exact_gas"), pytest.param(-1, id="insufficient_gas", marks=pytest.mark.exception_test), @@ -81,7 +81,10 @@ def test_transaction_validity_type_0( pre: Alloc, tx: Transaction, ) -> None: - """Test transaction validity for transactions without access lists and contract creation.""" + """ + Test transaction validity for transactions without access lists and + contract creation. + """ state_test( pre=pre, post={}, @@ -143,7 +146,10 @@ def test_transaction_validity_type_1_type_2( pre: Alloc, tx: Transaction, ) -> None: - """Test transaction validity for transactions with access lists and contract creation.""" + """ + Test transaction validity for transactions with access lists and contract + creation. + """ state_test( pre=pre, post={}, @@ -188,9 +194,9 @@ def test_transaction_validity_type_1_type_2( ], ) @pytest.mark.parametrize( - # Blobs don't really have an effect because the blob gas does is not considered in the - # intrinsic gas calculation, but we still test it to make sure that the transaction is - # correctly processed. + # Blobs don't really have an effect because the blob gas does is not + # considered in the intrinsic gas calculation, but we still test it to make + # sure that the transaction is correctly processed. "blob_versioned_hashes", [ pytest.param( @@ -219,8 +225,8 @@ def test_transaction_validity_type_3( tx: Transaction, ) -> None: """ - Test transaction validity for transactions with access lists, blobs, - but no contract creation. + Test transaction validity for transactions with access lists, blobs, but no + contract creation. """ state_test( pre=pre, @@ -289,8 +295,8 @@ def test_transaction_validity_type_4( tx: Transaction, ) -> None: """ - Test transaction validity for transactions with access lists, authorization lists, but no - contract creation. + Test transaction validity for transactions with access lists, authorization + lists, but no contract creation. """ state_test( pre=pre, diff --git a/prague/eip7685_general_purpose_el_requests/conftest.py b/prague/eip7685_general_purpose_el_requests/conftest.py index 1d347199a7..03fa406f0d 100644 --- a/prague/eip7685_general_purpose_el_requests/conftest.py +++ b/prague/eip7685_general_purpose_el_requests/conftest.py @@ -29,7 +29,10 @@ def block_body_override_requests( request: pytest.FixtureRequest, ) -> List[DepositRequest | WithdrawalRequest | ConsolidationRequest] | None: - """List of requests that overwrite the requests in the header. None by default.""" + """ + List of requests that overwrite the requests in the header. None by + default. + """ if hasattr(request, "param"): return request.param return None @@ -38,9 +41,9 @@ def block_body_override_requests( @pytest.fixture def correct_requests_hash_in_header() -> bool: """ - Whether to include the correct requests hash in the header so the calculated - block hash is correct, even though the requests in the new payload parameters might - be wrong. + Whether to include the correct requests hash in the header so the + calculated block hash is correct, even though the requests in the new + payload parameters might be wrong. """ return False diff --git a/prague/eip7685_general_purpose_el_requests/spec.py b/prague/eip7685_general_purpose_el_requests/spec.py index 414e47d290..758fe93076 100644 --- a/prague/eip7685_general_purpose_el_requests/spec.py +++ b/prague/eip7685_general_purpose_el_requests/spec.py @@ -1,7 +1,8 @@ """ Common procedures to test -[EIP-7685: General purpose execution layer requests](https://eips.ethereum.org/EIPS/eip-7685). -""" # noqa: E501 +[EIP-7685: General purpose execution +layer requests](https://eips.ethereum.org/EIPS/eip-7685). +""" from dataclasses import dataclass diff --git a/prague/eip7685_general_purpose_el_requests/test_multi_type_requests.py b/prague/eip7685_general_purpose_el_requests/test_multi_type_requests.py index d11e62cffd..382b1cb404 100644 --- a/prague/eip7685_general_purpose_el_requests/test_multi_type_requests.py +++ b/prague/eip7685_general_purpose_el_requests/test_multi_type_requests.py @@ -1,8 +1,9 @@ """ -abstract: Tests [EIP-7685: General purpose execution layer requests](https://eips.ethereum.org/EIPS/eip-7685) - Cross testing for withdrawal and deposit request for [EIP-7685: General purpose execution layer requests](https://eips.ethereum.org/EIPS/eip-7685). +Tests EIP-7685 General purpose execution layer requests. -""" # noqa: E501 +Cross testing for withdrawal and deposit request for +[EIP-7685: General purpose execution layer requests](https://eips.ethereum.org/EIPS/eip-7685). +""" from itertools import permutations from typing import Callable, Dict, Generator, List, Tuple @@ -299,7 +300,8 @@ def get_contract_permutations(n: int = 3) -> Generator[ParameterSet, None, None] [ single_consolidation_from_contract(0), single_consolidation_from_contract(1), - # the following performs single_withdrawal_from_contract(0) to (16) + # the following performs single_withdrawal_from_contract(0) to + # (16) *[ single_withdrawal_from_contract(i) for i in range( @@ -307,10 +309,10 @@ def get_contract_permutations(n: int = 3) -> Generator[ParameterSet, None, None] 16, ) ], - # single_withdrawal_from_contract(16) not allowed cuz only - # 16 MAX WITHDRAWALS PER BLOCK (EIP-7002) - # - # the following performs single_deposit_from_contract(0) to (18) + # single_withdrawal_from_contract(16) not allowed cuz only 16 + # MAX WITHDRAWALS PER BLOCK (EIP-7002) + # the following performs single_deposit_from_contract(0) to + # (18) *[ single_deposit_from_contract(i) for i in range( @@ -354,8 +356,8 @@ def test_valid_multi_type_request_from_same_tx( fork: Fork, ): """ - Test making a deposit to the beacon chain deposit contract and a withdrawal in - the same tx. + Test making a deposit to the beacon chain deposit contract and a withdrawal + in the same tx. """ withdrawal_request_fee: int = 1 consolidation_request_fee: int = 1 @@ -440,8 +442,9 @@ def invalid_requests_block_combinations( """ Return a list of invalid request combinations for the given fork. - In the event of a new request type, the `all_request_types` dictionary should be updated - with the new request type and its corresponding request-generating transaction. + In the event of a new request type, the `all_request_types` dictionary + should be updated with the new request type and its corresponding + request-generating transaction. Returned parameters are: requests, block_body_override_requests, exception """ @@ -474,9 +477,10 @@ def func(fork: Fork) -> List[ParameterSet]: expected_exceptions: List[BlockException] = [BlockException.INVALID_REQUESTS] if correct_requests_hash_in_header: - # The client also might reject the block with an invalid-block-hash error because it - # might convert the requests in the new payload parameters to the requests hash in the - # header and compare it with the block hash. + # The client also might reject the block with an invalid-block-hash + # error because it might convert the requests in the new payload + # parameters to the requests hash in the header and compare it with + # the block hash. expected_exceptions.append(BlockException.INVALID_BLOCK_HASH) # - Empty requests list with invalid hash @@ -485,8 +489,10 @@ def func(fork: Fork) -> List[ParameterSet]: [], [ bytes([i]) for i in range(fork.max_request_type() + 1) - ], # Using empty requests, calculate the hash using an invalid calculation method: - # sha256(sha256(b"\0") ++ sha256(b"\1") ++ sha256(b"\2") ++ ...) + ], # Using empty requests, calculate the hash using an invalid + # calculation method: + # sha256(sha256(b"\0") ++ sha256(b"\1") ++ sha256(b"\2") ++ + # ...) expected_exceptions, id="no_requests_and_invalid_hash_calculation_method", ), @@ -494,7 +500,8 @@ def func(fork: Fork) -> List[ParameterSet]: [], [ bytes([]) for _ in range(fork.max_request_type() + 1) - ], # Using empty requests, calculate the hash using an invalid calculation method: + ], # Using empty requests, calculate the hash using an invalid + # calculation method: # sha256(sha256(b"") ++ sha256(b"") ++ sha256(b"") ++ ...) expected_exceptions, id="no_requests_and_invalid_hash_calculation_method_2", @@ -507,9 +514,8 @@ def func(fork: Fork) -> List[ParameterSet]: [ pytest.param( [eoa_request], - [ - block_request - ], # The request type byte missing because we need to use `Requests` + [block_request], # The request type byte missing because we need to + # use `Requests` expected_exceptions, id=f"single_{request_type}_missing_type_byte", ), @@ -636,10 +642,11 @@ def test_invalid_multi_type_requests( """ Negative testing for all request types in the same block. - In these tests, the requests hash in the header reflects what's received in the parameters - portion of the `engine_newPayloadVX` call, so the block hash calculation might pass if - a client copies the info received verbatim, but block validation must fail after - the block is executed (via RLP or Engine API). + In these tests, the requests hash in the header reflects what's received in + the parameters portion of the `engine_newPayloadVX` call, so the block hash + calculation might pass if a client copies the info received verbatim, but + block validation must fail after the block is executed (via RLP or Engine + API). """ blockchain_test( genesis_environment=Environment(), @@ -665,26 +672,26 @@ def test_invalid_multi_type_requests_engine( blocks: List[Block], ): """ - Negative testing for all request types in the same block with incorrect parameters - in the Engine API new payload parameters, but with the correct requests hash in the header - so the block hash is correct. - - In these tests, the requests hash in the header reflects what's actually in the executed block, - so the block might execute properly if the client ignores the requests in the new payload - parameters. - - Note that the only difference between the engine version produced by this test and - the ones produced by `test_invalid_multi_type_requests` is the - `blockHash` value in the new payloads, which is calculated using different request hashes - for each test, but since the request hash is not a value that is included in the payload, - it might not be immediately apparent. - - Also these tests would not fail if the block is imported via RLP (syncing from a peer), - so we only generate the BlockchainTestEngine for them. - - The client also might reject the block with an invalid-block-hash error because it might - convert the requests in the new payload parameters to the requests hash in the header - and compare it with the block hash. + Negative testing for all request types in the same block with incorrect + parameters in the Engine API new payload parameters, but with the correct + requests hash in the header so the block hash is correct. + + In these tests, the requests hash in the header reflects what's actually in + the executed block, so the block might execute properly if the client + ignores the requests in the new payload parameters. + + Note that the only difference between the engine version produced by this + test and the ones produced by `test_invalid_multi_type_requests` is the + `blockHash` value in the new payloads, which is calculated using different + request hashes for each test, but since the request hash is not a value + that is included in the payload, it might not be immediately apparent. + + Also these tests would not fail if the block is imported via RLP (syncing + from a peer), so we only generate the BlockchainTestEngine for them. + + The client also might reject the block with an invalid-block-hash error + because it might convert the requests in the new payload parameters to the + requests hash in the header and compare it with the block hash. """ blockchain_test( genesis_environment=Environment(), diff --git a/prague/eip7702_set_code_tx/helpers.py b/prague/eip7702_set_code_tx/helpers.py index 83bd4eb91b..8cc2194029 100644 --- a/prague/eip7702_set_code_tx/helpers.py +++ b/prague/eip7702_set_code_tx/helpers.py @@ -1,12 +1,15 @@ -"""Helper types, functions and classes for testing EIP-7702 Set Code Transaction.""" +""" +Helper types, functions and classes for testing EIP-7702 Set Code Transaction. +""" from enum import Enum, auto class AddressType(Enum): """ - Different types of addresses used to specify the type of authority that signs an authorization, - and the type of address to which the authority authorizes to set the code to. + Different types of addresses used to specify the type of authority that + signs an authorization, and the type of address to which the authority + authorizes to set the code to. """ EMPTY_ACCOUNT = auto() diff --git a/prague/eip7702_set_code_tx/test_gas.py b/prague/eip7702_set_code_tx/test_gas.py index af634fc29d..1b416b28fb 100644 --- a/prague/eip7702_set_code_tx/test_gas.py +++ b/prague/eip7702_set_code_tx/test_gas.py @@ -1,7 +1,9 @@ """ -abstract: Tests related to gas of set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702) - Tests related to gas of set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702). -""" # noqa: E501 +Tests related to gas of set-code transactions from EIP-7702. + +Tests related to gas of set-code transactions from +[EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702). +""" from dataclasses import dataclass from enum import Enum, auto @@ -43,7 +45,10 @@ class SignerType(Enum): - """Different cases of authorization lists for testing gas cost of set-code transactions.""" + """ + Different cases of authorization lists for testing gas cost of set-code + transactions. + """ SINGLE_SIGNER = auto() MULTIPLE_SIGNERS = auto() @@ -59,7 +64,10 @@ class AuthorizationInvalidityType(Enum): class AccessListType(Enum): - """Different cases of access lists for testing gas cost of set-code transactions.""" + """ + Different cases of access lists for testing gas cost of set-code + transactions. + """ EMPTY = auto() CONTAINS_AUTHORITY = auto() @@ -75,8 +83,8 @@ def contains_authority(self) -> bool: def contains_set_code_address(self) -> bool: """ - Return True if the access list contains the address to which the authority authorizes to - set the code to. + Return True if the access list contains the address to which the + authority authorizes to set the code to. """ return self in { AccessListType.CONTAINS_SET_CODE_ADDRESS, @@ -92,21 +100,21 @@ class AuthorityWithProperties: """Dataclass to hold the properties of the authority address.""" authority: EOA - """ - The address of the authority to be used in the transaction. - """ + """The address of the authority to be used in the transaction.""" address_type: AddressType - """ - The type of the address the authority was before the authorization. - """ + """The type of the address the authority was before the authorization.""" invalidity_type: AuthorizationInvalidityType | None """ - Whether the authorization will be invalid and if so, which type of invalidity it is. + Whether the authorization will be invalid and if so, which type of + invalidity it is. """ @property def empty(self) -> bool: - """Return True if the authority address is an empty account before the authorization.""" + """ + Return True if the authority address is an empty account before the + authorization. + """ return self.address_type == AddressType.EMPTY_ACCOUNT @@ -189,28 +197,29 @@ class AuthorizationWithProperties: """Dataclass to hold the properties of the authorization list.""" tuple: AuthorizationTuple - """ - The authorization tuple to be used in the transaction. - """ + """The authorization tuple to be used in the transaction.""" invalidity_type: AuthorizationInvalidityType | None """ - Whether the authorization is invalid and if so, which type of invalidity it is. + Whether the authorization is invalid and if so, which type of invalidity it + is. """ authority_type: AddressType - """ - The type of the address the authority was before the authorization. - """ + """The type of the address the authority was before the authorization.""" skip: bool """ - Whether the authorization should be skipped and therefore not included in the transaction. + Whether the authorization should be skipped and therefore not included in + the transaction. - Used for tests where the authorization was already in the state before the transaction was - created. + Used for tests where the authorization was already in the state before the + transaction was created. """ @property def empty(self) -> bool: - """Return True if the authority address is an empty account before the authorization.""" + """ + Return True if the authority address is an empty account before the + authorization. + """ return self.authority_type == AddressType.EMPTY_ACCOUNT @@ -227,14 +236,17 @@ def authorization_list_with_properties( self_sponsored: bool, re_authorize: bool, ) -> List[AuthorizationWithProperties]: - """Fixture to return the authorization-list-with-properties for the given case.""" + """ + Fixture to return the authorization-list-with-properties for the given + case. + """ authorization_list: List[AuthorizationWithProperties] = [] environment_chain_id = chain_config.chain_id match signer_type: case SignerType.SINGLE_SIGNER: authority_with_properties = next(authority_iterator) - # We have to take into account the cases where the nonce has already been increased - # before the authorization is processed. + # We have to take into account the cases where the nonce has + # already been increased before the authorization is processed. increased_nonce = ( self_sponsored or authority_with_properties.address_type == AddressType.EOA_WITH_SET_CODE @@ -360,7 +372,10 @@ def authorization_list( @pytest.fixture() def authorize_to_address(request: pytest.FixtureRequest, pre: Alloc) -> Address: - """Fixture to return the address to which the authority authorizes to set the code to.""" + """ + Fixture to return the address to which the authority authorizes to set the + code to. + """ match request.param: case AddressType.EMPTY_ACCOUNT: return pre.fund_eoa(0) @@ -421,14 +436,18 @@ def gas_test_parameter_args( include_pre_authorized: bool = True, execution_gas_allowance: bool = False, ): - """Return the parametrize decorator that can be used in all gas test functions.""" + """ + Return the parametrize decorator that can be used in all gas test + functions. + """ multiple_authorizations_count = 2 defaults = { "signer_type": SignerType.SINGLE_SIGNER, "authorization_invalidity_type": None, "authorizations_count": 1, - "invalid_authorization_index": -1, # All authorizations are equally invalid + "invalid_authorization_index": -1, # All authorizations are equally + # invalid "chain_id_type": ChainIDType.GENERIC, "authorize_to_address": AddressType.EMPTY_ACCOUNT, "access_list_case": AccessListType.EMPTY, @@ -694,7 +713,8 @@ def gas_test_parameter_args( ] if include_many: - # Fit as many authorizations as possible within the transaction gas limit. + # Fit as many authorizations as possible within the transaction gas + # limit. max_gas = 16_777_216 - 21_000 if execution_gas_allowance: # Leave some gas for the execution of the test code. @@ -743,7 +763,10 @@ def test_gas_cost( access_list: List[AccessList], sender: EOA, ): - """Test gas at the execution start of a set-code transaction in multiple scenarios.""" + """ + Test gas at the execution start of a set-code transaction in multiple + scenarios. + """ # Calculate the intrinsic gas cost of the authorizations, by default the # full empty account cost is charged for each authorization. intrinsic_gas = fork.transaction_intrinsic_cost_calculator()( @@ -768,9 +791,10 @@ def test_gas_cost( Spec.PER_EMPTY_ACCOUNT_COST - Spec.PER_AUTH_BASE_COST ) * discounted_authorizations - # We calculate the exact gas required to execute the test code. - # We add SSTORE opcodes in order to make sure that the refund is less than one fifth (EIP-3529) - # of the total gas used, so we can see the full discount being reflected in most of the tests. + # We calculate the exact gas required to execute the test code. We add + # SSTORE opcodes in order to make sure that the refund is less than one + # fifth (EIP-3529) of the total gas used, so we can see the full discount + # being reflected in most of the tests. gas_costs = fork.gas_costs() gas_opcode_cost = gas_costs.G_BASE sstore_opcode_count = 10 @@ -781,8 +805,8 @@ def test_gas_cost( execution_gas = gas_opcode_cost + push_opcode_cost + sstore_opcode_cost + cold_storage_cost - # The first opcode that executes in the code is the GAS opcode, which costs 2 gas, so we - # subtract that from the expected gas measure. + # The first opcode that executes in the code is the GAS opcode, which costs + # 2 gas, so we subtract that from the expected gas measure. expected_gas_measure = execution_gas - gas_opcode_cost test_code_storage = Storage() @@ -801,7 +825,8 @@ def test_gas_cost( max_discount = tx_gas_limit // 5 if discount_gas > max_discount: - # Only one test hits this condition, but it's ok to also test this case. + # Only one test hits this condition, but it's ok to also test this + # case. discount_gas = max_discount gas_used = tx_gas_limit - discount_gas @@ -841,8 +866,12 @@ def test_account_warming( sender: EOA, check_delegated_account_first: bool, ): - """Test warming of the authority and authorized accounts for set-code transactions.""" - # Overhead cost is the single push operation required for the address to check. + """ + Test warming of the authority and authorized accounts for set-code + transactions. + """ + # Overhead cost is the single push operation required for the address to + # check. overhead_cost = 3 * len(Op.CALL.kwargs) # type: ignore cold_account_cost = 2600 @@ -850,8 +879,8 @@ def test_account_warming( access_list_addresses = {access_list.address for access_list in access_list} - # Dictionary to keep track of the addresses to check for warming, and the expected cost of - # accessing such account. + # Dictionary to keep track of the addresses to check for warming, and the + # expected cost of accessing such account. addresses_to_check: Dict[Address, int] = {} for authorization_with_properties in authorization_list_with_properties: @@ -861,9 +890,9 @@ def test_account_warming( authority_contains_delegation_after_authorization = ( authorization_with_properties.invalidity_type is None - # If the authority already contained a delegation prior to the transaction, - # even if the authorization is invalid, there will be a delegation when we - # check the address. + # If the authority already contained a delegation prior to the + # transaction, even if the authorization is invalid, there will be + # a delegation when we check the address. or authorization_with_properties.authority_type == AddressType.EOA_WITH_SET_CODE ) @@ -896,8 +925,9 @@ def test_account_warming( ) if authority_contains_delegation_after_authorization: - # The double charge for accessing the delegated account, only if the - # account ends up with a delegation in its code. + # The double charge for accessing the delegated account, + # only if the account ends up with a delegation in its + # code. access_cost += warm_account_cost addresses_to_check[authority] = access_cost @@ -920,8 +950,8 @@ def test_account_warming( access_cost = warm_account_cost if ( - # We can only charge the delegated account access cost if the authorization - # went through + # We can only charge the delegated account access cost if + # the authorization went through authority_contains_delegation_after_authorization ): if ( @@ -999,8 +1029,8 @@ def test_intrinsic_gas_cost( valid: bool, ): """ - Test sending a transaction with the exact intrinsic gas required and also insufficient - gas. + Test sending a transaction with the exact intrinsic gas required and also + insufficient gas. """ # Calculate the intrinsic gas cost of the authorizations, by default the # full empty account cost is charged for each authorization. @@ -1097,7 +1127,9 @@ def test_call_to_pre_authorized_oog( fork: Fork, call_opcode: Op, ): - """Test additional cost of delegation contract access in call instructions.""" + """ + Test additional cost of delegation contract access in call instructions. + """ # Delegation contract. It should never be reached by a call. delegation_code = Op.SSTORE(0, 1) delegation = pre.deploy_contract(delegation_code) diff --git a/prague/eip7702_set_code_tx/test_invalid_tx.py b/prague/eip7702_set_code_tx/test_invalid_tx.py index 75067b08a9..4855a73823 100644 --- a/prague/eip7702_set_code_tx/test_invalid_tx.py +++ b/prague/eip7702_set_code_tx/test_invalid_tx.py @@ -1,7 +1,9 @@ """ -abstract: Tests invalid set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702) - Tests invalid set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702). -""" # noqa: E501 +Tests invalid set-code transactions from EIP-7702. + +Tests invalid set-code transactions from +[EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702). +""" from enum import Enum, auto from typing import List, Type @@ -102,7 +104,10 @@ def test_invalid_auth_signature( s: int, delegate_address: Address, ): - """Test sending a transaction where one of the signature elements is out of range.""" + """ + Test sending a transaction where one of the signature elements is out of + range. + """ tx = Transaction( gas_limit=100_000, to=0, @@ -150,8 +155,8 @@ def test_invalid_tx_invalid_auth_chain_id( delegate_address: Address, ): """ - Test sending a transaction where the chain id field of an authorization overflows the - maximum value. + Test sending a transaction where the chain id field of an authorization + overflows the maximum value. """ authorization = AuthorizationTuple( address=delegate_address, @@ -193,8 +198,8 @@ def test_invalid_tx_invalid_auth_chain_id_encoding( auth_chain_id: int, ): """ - Test sending a transaction where the chain id field of an authorization has an incorrect - encoding. + Test sending a transaction where the chain id field of an authorization has + an incorrect encoding. """ class ModifiedAuthorizationTuple(AuthorizationTuple): @@ -243,8 +248,8 @@ def test_invalid_tx_invalid_nonce( delegate_address: Address, ): """ - Test sending a transaction where the nonce field of an authorization overflows the maximum - value. + Test sending a transaction where the nonce field of an authorization + overflows the maximum value. """ auth_signer = pre.fund_eoa() @@ -291,8 +296,8 @@ def test_invalid_tx_invalid_nonce_as_list( delegate_address: Address, ): """ - Test sending a transaction where the nonce field of an authorization overflows the maximum - value. + Test sending a transaction where the nonce field of an authorization + overflows the maximum value. """ auth_signer = pre.fund_eoa() @@ -333,8 +338,8 @@ def test_invalid_tx_invalid_nonce_encoding( delegate_address: Address, ): """ - Test sending a transaction where the chain id field of an authorization has an incorrect - encoding. + Test sending a transaction where the chain id field of an authorization has + an incorrect encoding. """ class ModifiedAuthorizationTuple(AuthorizationTuple): @@ -391,8 +396,8 @@ def test_invalid_tx_invalid_address( address_type: Type[FixedSizeBytes], ): """ - Test sending a transaction where the address field of an authorization is incorrectly - serialized. + Test sending a transaction where the address field of an authorization is + incorrectly serialized. """ auth_signer = pre.fund_eoa() @@ -435,8 +440,8 @@ def test_invalid_tx_invalid_authorization_tuple_extra_element( extra_element_value: int, ): """ - Test sending a transaction where the authorization tuple field of the type-4 transaction - is serialized to contain an extra element. + Test sending a transaction where the authorization tuple field of the + type-4 transaction is serialized to contain an extra element. """ auth_signer = pre.fund_eoa() @@ -444,7 +449,9 @@ class ExtraElementAuthorizationTuple(AuthorizationTuple): extra_element: HexNumber # type: ignore def get_rlp_fields(self) -> List[str]: - """Append the extra field to the list of fields to be encoded in RLP.""" + """ + Append the extra field to the list of fields to be encoded in RLP. + """ rlp_fields = super().get_rlp_fields()[:] rlp_fields.append("extra_element") return rlp_fields @@ -496,8 +503,8 @@ def test_invalid_tx_invalid_authorization_tuple_missing_element( missing_index: int, ): """ - Test sending a transaction where the authorization tuple field of the type-4 transaction - is serialized to miss one element. + Test sending a transaction where the authorization tuple field of the + type-4 transaction is serialized to miss one element. """ auth_signer = pre.fund_eoa() @@ -505,7 +512,9 @@ class MissingElementAuthorizationTuple(AuthorizationTuple): missing_element_index: int def get_rlp_fields(self) -> List[str]: - """Remove the field that is specified by the missing element index.""" + """ + Remove the field that is specified by the missing element index. + """ rlp_fields = super().get_rlp_fields()[:] rlp_fields.pop(self.missing_element_index) return rlp_fields @@ -545,8 +554,9 @@ def test_invalid_tx_invalid_authorization_tuple_encoded_as_bytes( delegate_address: Address, ): """ - Test sending a transaction where the authorization tuple field of the type-4 transaction - is encoded in the outer element as bytes instead of a list of elements. + Test sending a transaction where the authorization tuple field of the + type-4 transaction is encoded in the outer element as bytes instead of a + list of elements. """ class ModifiedTransaction(Transaction): @@ -595,8 +605,8 @@ def test_invalid_tx_invalid_rlp_encoding( invalid_rlp_mode: InvalidRLPMode, ): """ - Test sending a transaction type-4 where the RLP encoding of the transaction is - invalid. + Test sending a transaction type-4 where the RLP encoding of the transaction + is invalid. """ auth_signer = pre.fund_eoa() diff --git a/prague/eip7702_set_code_tx/test_set_code_txs.py b/prague/eip7702_set_code_tx/test_set_code_txs.py index 090fea22fb..c401488bd4 100644 --- a/prague/eip7702_set_code_tx/test_set_code_txs.py +++ b/prague/eip7702_set_code_tx/test_set_code_txs.py @@ -1,7 +1,9 @@ """ -abstract: Tests use of set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702) - Tests use of set-code transactions from [EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702). -""" # noqa: E501 +Tests use of set-code transactions from EIP-7702. + +Tests use of set-code transactions from +[EIP-7702: Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702). +""" from enum import StrEnum from hashlib import sha256 @@ -88,11 +90,11 @@ def test_self_sponsored_set_code( """ Test the executing a self-sponsored set-code transaction. - The transaction is sent to the sender, and the sender is the signer of the only authorization - tuple in the authorization list. + The transaction is sent to the sender, and the sender is the signer of the + only authorization tuple in the authorization list. - The authorization tuple has a nonce of 1 because the self-sponsored transaction increases the - nonce of the sender from zero to one first. + The authorization tuple has a nonce of 1 because the self-sponsored + transaction increases the nonce of the sender from zero to one first. The expected nonce at the end of the transaction is 2. """ @@ -268,7 +270,10 @@ def test_set_code_to_sstore_then_sload( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test the executing a simple SSTORE then SLOAD in two separate set-code transactions.""" + """ + Test the executing a simple SSTORE then SLOAD in two separate set-code + transactions. + """ auth_signer = pre.fund_eoa(auth_account_start_balance) sender = pre.fund_eoa() @@ -346,8 +351,8 @@ def test_set_code_to_tstore_reentry( evm_code_type: EVMCodeType, ): """ - Test the executing a simple TSTORE in a set-code transaction, which also performs a - re-entry to TLOAD the value. + Test the executing a simple TSTORE in a set-code transaction, which also + performs a re-entry to TLOAD the value. """ auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -403,9 +408,10 @@ def test_set_code_to_tstore_available_at_correct_address( call_eoa_first: bool, ): """ - Test TLOADing from slot 2 and then SSTORE this in slot 1, then TSTORE 3 in slot 2. - This is done both from the EOA which is delegated to account A, and then A is called. - The storage should stay empty on both the EOA and the delegated account. + Test TLOADing from slot 2 and then SSTORE this in slot 1, then TSTORE 3 in + slot 2. This is done both from the EOA which is delegated to account A, and + then A is called. The storage should stay empty on both the EOA and the + delegated account. """ auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -522,7 +528,9 @@ def test_set_code_to_contract_creator( create_opcode: Op, evm_code_type: EVMCodeType, ): - """Test the executing a contract-creating opcode in a set-code transaction.""" + """ + Test the executing a contract-creating opcode in a set-code transaction. + """ storage = Storage() auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -677,8 +685,8 @@ def test_set_code_max_depth_call_stack( fork: Fork, ): """ - Test re-entry to delegated account until the max call stack depth possible in a - transaction is reached. + Test re-entry to delegated account until the max call stack depth possible + in a transaction is reached. """ storage = Storage() auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -867,7 +875,10 @@ def test_tx_into_self_delegating_set_code( state_test: StateTestFiller, pre: Alloc, ): - """Test a transaction that has entry-point into a set-code account that delegates to itself.""" + """ + Test a transaction that has entry-point into a set-code account that + delegates to itself. + """ auth_signer = pre.fund_eoa(auth_account_start_balance) tx = Transaction( @@ -902,8 +913,8 @@ def test_tx_into_chain_delegating_set_code( pre: Alloc, ): """ - Test a transaction that has entry-point into a set-code account that delegates to another - set-code account. + Test a transaction that has entry-point into a set-code account that + delegates to another set-code account. """ auth_signer_1 = pre.fund_eoa(auth_account_start_balance) auth_signer_2 = pre.fund_eoa(auth_account_start_balance) @@ -994,7 +1005,10 @@ def test_call_into_chain_delegating_set_code( pre: Alloc, call_opcode: Op, ): - """Test call into a set-code account that delegates to another set-code account.""" + """ + Test call into a set-code account that delegates to another set-code + account. + """ auth_signer_1 = pre.fund_eoa(auth_account_start_balance) auth_signer_2 = pre.fund_eoa(auth_account_start_balance) @@ -1310,8 +1324,8 @@ def test_set_code_address_and_authority_warm_state_call_types( ): """ Test set to code address and authority warm status after a call to - authority address, or vice-versa, using all available call opcodes - without using `GAS` opcode (unavailable in EOF). + authority address, or vice-versa, using all available call opcodes without + using `GAS` opcode (unavailable in EOF). """ auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -1376,7 +1390,10 @@ def test_ext_code_on_self_delegating_set_code( pre: Alloc, balance: int, ): - """Test different ext*code operations on a set-code address that delegates to itself.""" + """ + Test different ext*code operations on a set-code address that delegates to + itself. + """ auth_signer = pre.fund_eoa(balance) slot = count(1) @@ -1438,8 +1455,8 @@ def test_ext_code_on_chain_delegating_set_code( pre: Alloc, ): """ - Test different ext*code operations on a set-code address that references another delegated - address. + Test different ext*code operations on a set-code address that references + another delegated address. """ auth_signer_1_balance = 1 auth_signer_2_balance = 0 @@ -1601,8 +1618,9 @@ def test_set_code_to_account_deployed_in_same_tx( evm_code_type: EVMCodeType, ): """ - Test setting the code of an account to an address that is deployed in the same transaction, - and test calling the set-code address and the deployed contract. + Test setting the code of an account to an address that is deployed in the + same transaction, and test calling the set-code address and the deployed + contract. """ auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -1720,9 +1738,9 @@ def test_set_code_to_self_destructing_account_deployed_in_same_tx( balance: int, ): """ - Test setting the code of an account to an account that contains the SELFDESTRUCT opcode and - was deployed in the same transaction, and test calling the set-code address and the deployed - in both sequence orders. + Test setting the code of an account to an account that contains the + SELFDESTRUCT opcode and was deployed in the same transaction, and test + calling the set-code address and the deployed in both sequence orders. """ auth_signer = pre.fund_eoa(balance) if external_sendall_recipient: @@ -1818,8 +1836,8 @@ def test_set_code_multiple_first_valid_authorization_tuples_same_signer( pre: Alloc, ): """ - Test setting the code of an account with multiple authorization tuples - from the same signer. + Test setting the code of an account with multiple authorization tuples from + the same signer. """ auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -1866,8 +1884,9 @@ def test_set_code_multiple_valid_authorization_tuples_same_signer_increasing_non pre: Alloc, ): """ - Test setting the code of an account with multiple authorization tuples from the same signer - and each authorization tuple has an increasing nonce, therefore the last tuple is executed. + Test setting the code of an account with multiple authorization tuples from + the same signer and each authorization tuple has an increasing nonce, + therefore the last tuple is executed. """ auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -1914,9 +1933,10 @@ def test_set_code_multiple_valid_authorization_tuples_same_signer_increasing_non pre: Alloc, ): """ - Test setting the code of an account with multiple authorization tuples from the same signer - and each authorization tuple has an increasing nonce, therefore the last tuple is executed, - and the transaction is self-sponsored. + Test setting the code of an account with multiple authorization tuples from + the same signer and each authorization tuple has an increasing nonce, + therefore the last tuple is executed, and the transaction is + self-sponsored. """ auth_signer = pre.fund_eoa() @@ -1962,8 +1982,8 @@ def test_set_code_multiple_valid_authorization_tuples_first_invalid_same_signer( pre: Alloc, ): """ - Test setting the code of an account with multiple authorization tuples from the same signer - but the first tuple is invalid. + Test setting the code of an account with multiple authorization tuples from + the same signer but the first tuple is invalid. """ auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -2010,8 +2030,8 @@ def test_set_code_all_invalid_authorization_tuples( pre: Alloc, ): """ - Test setting the code of an account with multiple authorization tuples from the same signer - and all of them are invalid. + Test setting the code of an account with multiple authorization tuples from + the same signer and all of them are invalid. """ auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -2050,7 +2070,10 @@ def test_set_code_using_chain_specific_id( pre: Alloc, chain_config: ChainConfig, ): - """Test sending a transaction to set the code of an account using a chain-specific ID.""" + """ + Test sending a transaction to set the code of an account using a + chain-specific ID. + """ auth_signer = pre.fund_eoa(auth_account_start_balance) success_slot = 1 @@ -2113,7 +2136,10 @@ def test_set_code_using_valid_synthetic_signatures( r: int, s: int, ): - """Test sending a transaction to set the code of an account using synthetic signatures.""" + """ + Test sending a transaction to set the code of an account using synthetic + signatures. + """ success_slot = 1 set_code = Op.SSTORE(success_slot, 1) + Op.STOP @@ -2162,8 +2188,10 @@ def test_set_code_using_valid_synthetic_signatures( pytest.param(2, 1, 1, id="v=2"), pytest.param(27, 1, 1, id="v=27"), # Type-0 transaction valid value pytest.param(28, 1, 1, id="v=28"), # Type-0 transaction valid value - pytest.param(35, 1, 1, id="v=35"), # Type-0 replay-protected transaction valid value - pytest.param(36, 1, 1, id="v=36"), # Type-0 replay-protected transaction valid value + pytest.param(35, 1, 1, id="v=35"), # Type-0 replay-protected + # transaction valid value + pytest.param(36, 1, 1, id="v=36"), # Type-0 replay-protected + # transaction valid value pytest.param(2**8 - 1, 1, 1, id="v=2**8-1"), # R pytest.param(1, 0, 1, id="r=0"), @@ -2194,8 +2222,9 @@ def test_valid_tx_invalid_auth_signature( s: int, ): """ - Test sending a transaction to set the code of an account using synthetic signatures, - the transaction is valid but the authorization should not go through. + Test sending a transaction to set the code of an account using synthetic + signatures, the transaction is valid but the authorization should not go + through. """ success_slot = 1 @@ -2237,8 +2266,9 @@ def test_signature_s_out_of_range( chain_config: ChainConfig, ): """ - Test sending a transaction with an authorization tuple where the signature s value is out of - range by modifying its value to be `SECP256K1N - S` and flipping the v value. + Test sending a transaction with an authorization tuple where the signature + s value is out of range by modifying its value to be `SECP256K1N - S` and + flipping the v value. """ auth_signer = pre.fund_eoa(0) @@ -2309,8 +2339,8 @@ def test_valid_tx_invalid_chain_id( invalid_chain_id_case: InvalidChainID, ): """ - Test sending a transaction where the chain id field does not match - the current chain's id. + Test sending a transaction where the chain id field does not match the + current chain's id. """ auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -2405,11 +2435,11 @@ def test_nonce_validity( authorization_nonce: int, ): """ - Test sending a transaction where the nonce field of an authorization almost overflows the - maximum value. + Test sending a transaction where the nonce field of an authorization almost + overflows the maximum value. - Also test calling the account of the authorization signer in order to verify that the account - is not warm. + Also test calling the account of the authorization signer in order to + verify that the account is not warm. """ auth_signer = pre.fund_eoa(auth_account_start_balance, nonce=account_nonce) @@ -2470,8 +2500,8 @@ def test_nonce_overflow_after_first_authorization( pre: Alloc, ): """ - Test sending a transaction with two authorization where the first one bumps the nonce - to 2**64-1 and the second would result in overflow. + Test sending a transaction with two authorization where the first one bumps + the nonce to 2**64-1 and the second would result in overflow. """ nonce = 2**64 - 2 auth_signer = pre.fund_eoa(auth_account_start_balance, nonce=nonce) @@ -2547,7 +2577,10 @@ def test_set_code_to_log( pre: Alloc, log_opcode: Op, ): - """Test setting the code of an account to a contract that performs the log operation.""" + """ + Test setting the code of an account to a contract that performs the log + operation. + """ sender = pre.fund_eoa() log_kwargs = {} @@ -2604,8 +2637,8 @@ def test_set_code_to_precompile( call_opcode: Op, ): """ - Test setting the code of an account to a pre-compile address and executing all call - opcodes. + Test setting the code of an account to a pre-compile address and executing + all call opcodes. """ auth_signer = pre.fund_eoa(auth_account_start_balance) @@ -2663,8 +2696,8 @@ def test_set_code_to_precompile_not_enough_gas_for_precompile_execution( precompile: int, ): """ - Test set code to precompile and making direct call in same transaction with intrinsic gas - only, no extra gas for precompile execution. + Test set code to precompile and making direct call in same transaction with + intrinsic gas only, no extra gas for precompile execution. """ auth_signer = pre.fund_eoa(amount=1) auth = AuthorizationTuple(address=Address(precompile), nonce=0, signer=auth_signer) @@ -2738,10 +2771,12 @@ def test_set_code_to_system_contract( call_value = 0 - # Setup the initial storage of the account to mimic the system contract if required + # Setup the initial storage of the account to mimic the system contract if + # required match system_contract: case Address(0x00000000219AB540356CBB839CBE05303D7705FA): # EIP-6110 - # Deposit contract needs specific storage values, so we set them on the account + # Deposit contract needs specific storage values, so we set them on + # the account auth_signer = pre.fund_eoa( auth_account_start_balance, storage=deposit_contract_initial_storage() ) @@ -2788,8 +2823,8 @@ def test_set_code_to_system_contract( caller_payload = consolidation_request.calldata call_value = consolidation_request.value case Address(0x0000F90827F1C53A10CB7A02335B175320002935): # EIP-2935 - # This payload is used to identify the number of blocks to be subtracted from the - # latest block number + # This payload is used to identify the number of blocks to be + # subtracted from the latest block number caller_payload = Hash(1) caller_code_storage[call_return_data_size_slot] = 32 case _: @@ -2798,8 +2833,8 @@ def test_set_code_to_system_contract( # Setup the code to call the system contract match system_contract: case Address(0x0000F90827F1C53A10CB7A02335B175320002935): # EIP-2935 - # Do a trick here to get the block number of the penultimate block to ensure it is - # saved in the history contract + # Do a trick here to get the block number of the penultimate block + # to ensure it is saved in the history contract check_block_number = Op.SUB(Op.NUMBER, Op.CALLDATALOAD(0)) call_system_contract_code = Op.MSTORE(0, check_block_number) + Op.SSTORE( call_return_code_slot, @@ -2844,7 +2879,8 @@ def test_set_code_to_system_contract( blocks=[ Block( txs=txs, - requests_hash=Requests(), # Verify nothing slipped into the requests trie + requests_hash=Requests(), # Verify nothing slipped into the + # requests trie ) ], post={ @@ -2885,7 +2921,10 @@ def test_eoa_tx_after_set_code( evm_code_type: EVMCodeType, same_block: bool, ): - """Test sending a transaction from an EOA after code has been set to the account.""" + """ + Test sending a transaction from an EOA after code has been set to the + account. + """ auth_signer = pre.fund_eoa() set_code = Op.SSTORE(1, Op.ADD(Op.SLOAD(1), 1)) + Op.STOP @@ -3145,12 +3184,14 @@ def test_delegation_clearing( self_sponsored: bool, ): """ - Test clearing the delegation of an account under a variety of circumstances. - - - pre_set_delegation_code: The code to set on the account before clearing delegation, or None - if the account should not have any code set. - - self_sponsored: Whether the delegation clearing transaction is self-sponsored. - + Test clearing the delegation of an account under a variety of + circumstances. + + - pre_set_delegation_code: The code to set on the account before clearing + delegation, or None if the account should not + have any code set. + - self_sponsored: Whether the delegation clearing transaction is + self-sponsored. """ # noqa: D417 pre_set_delegation_address: Address | None = None if pre_set_delegation_code is not None: @@ -3238,10 +3279,11 @@ def test_delegation_clearing_tx_to( """ Tests directly calling the account which delegation is being cleared. - - pre_set_delegation_code: The code to set on the account before clearing delegation, or None - if the account should not have any code set. - - self_sponsored: Whether the delegation clearing transaction is self-sponsored. - + - pre_set_delegation_code: The code to set on the account before clearing + delegation, or None if the account should not + have any code set. + - self_sponsored: Whether the delegation clearing transaction is + self-sponsored. """ # noqa: D417 pre_set_delegation_address: Address | None = None if pre_set_delegation_code is not None: @@ -3295,11 +3337,11 @@ def test_delegation_clearing_and_set( pre_set_delegation_code: Bytecode | None, ): """ - Tests clearing and setting the delegation again in the same authorization list. - - - pre_set_delegation_code: The code to set on the account before clearing delegation, or None - if the account should not have any code set. + Tests clearing and setting the delegation again in the same authorization + list. + - pre_set_delegation_code: The code to set on the account before clearing + delegation, or None if the account should not have any code set. """ # noqa: D417 pre_set_delegation_address: Address | None = None if pre_set_delegation_code is not None: @@ -3361,7 +3403,10 @@ def test_delegation_clearing_failing_tx( pre: Alloc, entry_code: Bytecode, ): - """Test clearing the delegation of an account in a transaction that fails, OOGs or reverts.""" # noqa: D417 + """ + Test clearing the delegation of an account in a transaction that fails, + OOGs or reverts. + """ # noqa: D417 pre_set_delegation_code = Op.RETURN(0, 1) pre_set_delegation_address = pre.deploy_contract(pre_set_delegation_code) @@ -3459,8 +3504,10 @@ def test_creating_delegation_designation_contract( initcode_is_delegation_designation: bool, ): """ - Tx -> create -> pointer bytecode - Attempt to deploy contract with magic bytes result in no contract being created. + Tx -> create -> pointer bytecode. + + Attempt to deploy contract with magic bytes result in no + contract being created. """ env = Environment() @@ -3522,14 +3569,16 @@ def test_many_delegations( signer_balance: int, ): """ - Perform as many delegations as possible in a transaction using the entire block gas limit. + Perform as many delegations as possible in a transaction using the entire + block gas limit. Every delegation comes from a different signer. - The account of can be empty or not depending on the `signer_balance` parameter. + The account of can be empty or not depending on the `signer_balance` + parameter. - The transaction is expected to succeed and the state after the transaction is expected to have - the code of the entry contract set to 1. + The transaction is expected to succeed and the state after the transaction + is expected to have the code of the entry contract set to 1. """ env = Environment() tx_gas_limit_cap = fork.transaction_gas_limit_cap() @@ -3587,8 +3636,8 @@ def test_invalid_transaction_after_authorization( pre: Alloc, ): """ - Test an invalid block due to a transaction reusing the same nonce as an authorization - included in a prior transaction. + Test an invalid block due to a transaction reusing the same nonce as an + authorization included in a prior transaction. """ auth_signer = pre.fund_eoa() recipient = pre.fund_eoa(amount=0) @@ -3636,8 +3685,8 @@ def test_authorization_reusing_nonce( pre: Alloc, ): """ - Test an authorization reusing the same nonce as a prior transaction included in the same - block. + Test an authorization reusing the same nonce as a prior transaction + included in the same block. """ auth_signer = pre.fund_eoa() sender = pre.fund_eoa() @@ -3694,12 +3743,12 @@ def test_set_code_from_account_with_non_delegating_code( self_sponsored: bool, ): """ - Test that a transaction is correctly rejected, - if the sender account has a non-delegating code set. + Test that a transaction is correctly rejected, if the sender account has a + non-delegating code set. - The auth transaction is sent from sender which has contract code (not delegating) - But at the same time it has auth tuple that will point this sender account - To be eoa, delegation, contract .. etc + The auth transaction is sent from sender which has contract code (not + delegating) But at the same time it has auth tuple that will point this + sender account To be eoa, delegation, contract .. etc """ sender = pre.fund_eoa(nonce=1) random_address = pre.fund_eoa(0) @@ -3719,7 +3768,8 @@ def test_set_code_from_account_with_non_delegating_code( raise ValueError(f"Unsupported set code type: {set_code_type}") callee_address = pre.deploy_contract(Op.SSTORE(0, 1) + Op.STOP) - # Set the sender account to have some code, that is specifically not a delegation. + # Set the sender account to have some code, that is specifically not a + # delegation. sender_account = pre[sender] assert sender_account is not None sender_account.code = Bytes(Op.STOP) @@ -3781,7 +3831,9 @@ def test_set_code_transaction_fee_validations( max_priority_fee_per_gas: int, expected_error: TransactionException, ): - """Test that a transaction with an insufficient max fee per gas is rejected.""" + """ + Test that a transaction with an insufficient max fee per gas is rejected. + """ set_to_code = pre.deploy_contract(Op.STOP) auth_signer = pre.fund_eoa(amount=0) tx = Transaction( diff --git a/prague/eip7702_set_code_tx/test_set_code_txs_2.py b/prague/eip7702_set_code_tx/test_set_code_txs_2.py index e6a622246e..ef4208b76d 100644 --- a/prague/eip7702_set_code_tx/test_set_code_txs_2.py +++ b/prague/eip7702_set_code_tx/test_set_code_txs_2.py @@ -1,4 +1,6 @@ -"""A state test for [EIP-7702 SetCodeTX](https://eips.ethereum.org/EIPS/eip-7702).""" +""" +A state test for [EIP-7702 SetCodeTX](https://eips.ethereum.org/EIPS/eip-7702). +""" from enum import Enum, IntEnum @@ -40,8 +42,9 @@ def test_pointer_contract_pointer_loop(state_test: StateTestFiller, pre: Alloc): """ Tx -> call -> pointer A -> contract A -> pointer B -> contract loop C. - Call pointer that goes more level of depth to call a contract loop - Loop is created only if pointers are set with auth tuples + Call pointer that goes more level of depth to call a contract loop. + + Loop is created only if pointers are set with auth tuples. """ env = Environment() @@ -137,8 +140,10 @@ def test_pointer_to_pointer(state_test: StateTestFiller, pre: Alloc): @pytest.mark.valid_from("Prague") def test_pointer_normal(blockchain_test: BlockchainTestFiller, pre: Alloc): """ - Tx -> call -> pointer A -> contract - Other normal tx can interact with previously assigned pointers. + Tx -> call -> pointer A -> contract. + + Other normal tx can interact with + previously assigned pointers. """ env = Environment() @@ -197,8 +202,10 @@ def test_pointer_normal(blockchain_test: BlockchainTestFiller, pre: Alloc): @pytest.mark.valid_from("Prague") def test_pointer_measurements(blockchain_test: BlockchainTestFiller, pre: Alloc): """ - Check extcode* operations on pointer before and after pointer is set - Check context opcode results when called under pointer call + Check extcode* operations on pointer before and after pointer is set. + + Check context opcode results when called under pointer call. + Opcodes have context of an original pointer account (balance, storage). """ env = Environment() @@ -208,7 +215,8 @@ def test_pointer_measurements(blockchain_test: BlockchainTestFiller, pre: Alloc) storage_normal: Storage = Storage() storage_pointer: Storage = Storage() - storage_pointer_code: Storage = Storage() # this storage will be applied to pointer address + storage_pointer_code: Storage = Storage() # this storage will be applied + # to pointer address pointer_code = pre.deploy_contract( balance=200, code=Op.SSTORE(storage_pointer_code.store_next(pointer, "address"), Op.ADDRESS()) @@ -327,9 +335,10 @@ def test_call_to_precompile_in_pointer_context( state_test: StateTestFiller, pre: Alloc, precompile: int ): """ - Tx -> call -> pointer A -> precompile contract - Make sure that gas consumed when calling precompiles in normal call are the same - As from inside the pointer context call. + Tx -> call -> pointer A -> precompile contract. + + Make sure that gas consumed when calling precompiles in normal call + are the same As from inside the pointer context call. """ env = Environment() @@ -400,11 +409,13 @@ def test_pointer_to_precompile(state_test: StateTestFiller, pre: Alloc, precompi """ Tx -> call -> pointer A -> precompile contract. - In case a delegation designator points to a precompile address, retrieved code is considered - empty and CALL, CALLCODE, STATICCALL, DELEGATECALL instructions targeting this account will - execute empty code, i.e. succeed with no execution given enough gas. + In case a delegation designator points to a precompile address, retrieved + code is considered empty and CALL, CALLCODE, STATICCALL, DELEGATECALL + instructions targeting this account will execute empty code, i.e. succeed + with no execution given enough gas. - So call to a pointer that points to a precompile is like call to an empty account + So call to a pointer that points to a precompile is like call to an empty + account """ env = Environment() @@ -440,7 +451,8 @@ def test_pointer_to_precompile(state_test: StateTestFiller, pre: Alloc, precompi ret_offset=1000, ret_size=32, ) - # pointer call to a precompile with 0 gas always return 1 as if calling empty address + # pointer call to a precompile with 0 gas always return 1 as if calling + # empty address + Op.SSTORE(storage.store_next(1, "pointer_call_result"), Op.MLOAD(1000)) ) @@ -727,9 +739,9 @@ def test_pointer_call_followed_by_direct_call( ): """ If we first call by pointer then direct call, will the call/sload be hot - The direct call will warm because pointer access marks it warm - But the sload is still cold because - storage marked hot from pointer's account in a pointer call. + The direct call will warm because pointer access marks it warm But the + sload is still cold because storage marked hot from pointer's account in a + pointer call. """ env = Environment() @@ -747,8 +759,10 @@ def test_pointer_call_followed_by_direct_call( ) direct_call_gas = ( gas_costs.G_STORAGE_SET - + gas_costs.G_WARM_ACCOUNT_ACCESS # since previous pointer call, contract is now warm - + gas_costs.G_COLD_SLOAD # but storage is cold, because it's contract's direct + + gas_costs.G_WARM_ACCOUNT_ACCESS # since previous pointer call, + # contract is now warm + + gas_costs.G_COLD_SLOAD # but storage is cold, because it's + # contract's direct + opcodes_price ) @@ -803,7 +817,8 @@ def test_pointer_call_followed_by_direct_call( @pytest.mark.valid_from("Prague") def test_pointer_to_static(state_test: StateTestFiller, pre: Alloc): """ - Tx -> call -> pointer A -> static -> static violation + Tx -> call -> pointer A -> static -> static violation. + Verify that static context is active when called under pointer. """ env = Environment() @@ -849,7 +864,8 @@ def test_pointer_to_static(state_test: StateTestFiller, pre: Alloc): @pytest.mark.valid_from("Prague") def test_static_to_pointer(state_test: StateTestFiller, pre: Alloc): """ - Tx -> staticcall -> pointer A -> static violation + Tx -> staticcall -> pointer A -> static violation. + Verify that static context is active when make sub call to pointer. """ env = Environment() @@ -895,7 +911,8 @@ def test_static_to_pointer(state_test: StateTestFiller, pre: Alloc): @pytest.mark.valid_from("EOFv1") def test_pointer_to_eof(state_test: StateTestFiller, pre: Alloc): """ - Tx -> call -> pointer A -> EOF + Tx -> call -> pointer A -> EOF. + Pointer to eof contract works. """ env = Environment() @@ -1013,7 +1030,9 @@ def test_contract_storage_to_pointer_with_storage( state_test: StateTestFiller, pre: Alloc, call_type: Op ): """ - Tx call -> contract with storage -> pointer A with storage -> storage/tstorage modify + Tx call -> contract with storage -> pointer A with storage -> + storage/tstorage modify. + Check storage/tstorage modifications when interacting with pointers. """ env = Environment() @@ -1056,18 +1075,21 @@ def test_contract_storage_to_pointer_with_storage( code=Op.TSTORE(third_slot, 1) + call_type(address=pointer_b, gas=500_000) + Op.SSTORE(third_slot, Op.TLOAD(third_slot)) - # Verify tstorage in contract after interacting with pointer, it must be 0 + # Verify tstorage in contract after interacting with pointer, it must + # be 0 + Op.MSTORE(0, 1) + Op.CALL(address=contract_b, gas=500_000, args_offset=0, args_size=32), storage={ storage_a.store_next( - # caller storage is modified when calling pointer with delegate or callcode + # caller storage is modified when calling pointer with delegate + # or callcode 6 if call_type in [Op.DELEGATECALL, Op.CALLCODE] else 5, "first_slot", ): 5, storage_a.store_next(2, "second_slot"): 2, storage_a.store_next( - # TSTORE is modified when calling pointer with delegate or callcode + # TSTORE is modified when calling pointer with delegate or + # callcode 2 if call_type in [Op.DELEGATECALL, Op.CALLCODE] else 1, "third_slot", ): 3, @@ -1113,8 +1135,10 @@ class ReentryAction(IntEnum): @pytest.mark.valid_from("Prague") def test_pointer_reentry(state_test: StateTestFiller, pre: Alloc): """ - Check operations when reenter the pointer again - TODO: feel free to extend the code checks under given scenarios in switch case. + Check operations when reenter the pointer again. + + TODO: feel free to extend the code checks under given scenarios in + switch case. """ env = Environment() arg_contract = 0 @@ -1152,7 +1176,8 @@ def test_pointer_reentry(state_test: StateTestFiller, pre: Alloc): + Op.STOP(), ), Case( - # This code is executed under pointer -> proxy -> pointer context + # This code is executed under pointer -> proxy -> pointer + # context condition=Op.EQ(Op.MLOAD(arg_action), ReentryAction.MEASURE_VALUES), action=Op.SSTORE(storage_pointer_b.store_next(sender, "origin"), Op.ORIGIN()) + Op.SSTORE(storage_pointer_b.store_next(pointer_b, "address"), Op.ADDRESS()) @@ -1172,7 +1197,8 @@ def test_pointer_reentry(state_test: StateTestFiller, pre: Alloc): Case( # This code is executed under # pointer -> proxy -> pointer -> contract - # so pointer calling the code of it's dest after reentry to itself + # so pointer calling the code of it's dest + # after reentry to itself condition=Op.EQ(Op.MLOAD(arg_action), ReentryAction.MEASURE_VALUES_CONTRACT), action=Op.SSTORE(storage_b.store_next(sender, "origin"), Op.ORIGIN()) + Op.SSTORE(slot_reentry_address, Op.ADDRESS()) @@ -1216,9 +1242,11 @@ def test_pointer_reentry(state_test: StateTestFiller, pre: Alloc): @pytest.mark.valid_from("Prague") def test_eoa_init_as_pointer(state_test: StateTestFiller, pre: Alloc): """ - It was agreed before that senders don't have code - And there were issues with tests sending transactions from account's with code - With EIP7702 it is again possible, let's check the test runners are ok. + It was agreed before that senders don't have code. + + And there were issues with tests sending transactions from account's + with code With EIP7702 it is again possible, + let's check the test runners are ok. """ env = Environment() storage = Storage() @@ -1249,13 +1277,17 @@ def test_call_pointer_to_created_from_create_after_oog_call_again( """ Set pointer to account that we are about to create. - Pointer is set to create address that is yet not in the state - During the call, address is created. pointer is called from init code to do nothing + Pointer is set to create address that is yet not in the state. + + During the call, address is created. pointer is called from init code + to do nothing. + Then after account is created it is called again to run created code - Then revert / no revert + Then revert / no revert. - Call pointer again from the upper level to ensure it does not call reverted code + Call pointer again from the upper level to ensure it does not call reverted + code. """ env = Environment() @@ -1544,10 +1576,12 @@ def test_pointer_resets_an_empty_code_account_with_storage( pre: Alloc, ): """ - So in Block1 we create a sender with empty code, but non empty storage using pointers - In Block2 we create account that perform suicide, then we check that when calling - a pointer, that points to newly created account and runs suicide, - is not deleted as well as its storage. + So in Block1 we create a sender with empty code, but non empty storage + using pointers. + + In Block2 we create account that perform suicide, then we + check that when calling a pointer, that points to newly created account and + runs suicide, is not deleted as well as its storage. This one is a little messy. """ @@ -1624,7 +1658,9 @@ def test_pointer_resets_an_empty_code_account_with_storage( # Block 2 # Sender with storage and pointer code calling selfdestruct on itself - # But it points to a newly created account, check that pointer storage is not deleted + # + # But it points to a newly created account, check that pointer + # storage is not deleted suicide_dest = pre.fund_eoa(amount=0) deploy_code = Op.SSTORE(5, 5) + Op.SELFDESTRUCT(suicide_dest) sender_storage[5] = 5 @@ -1637,7 +1673,8 @@ def test_pointer_resets_an_empty_code_account_with_storage( + Op.SSTORE(1, Op.CREATE(0, 0, Op.CALLDATASIZE())) + Op.CALL(address=sender) # run suicide from pointer + Op.CALL(address=Op.SLOAD(1)) # run suicide directly - + Op.CALL(address=another_pointer) # run suicide from pointer that is not sender + + Op.CALL(address=another_pointer) # run suicide from pointer that is + # not sender ) newly_created_address = compute_create_address(address=contract_create, nonce=1) @@ -1679,9 +1716,13 @@ def test_pointer_resets_an_empty_code_account_with_storage( post=post, blocks=[ # post = { - # pointer: Account(nonce=2, balance=0, storage=pointer_storage, code=bytes()), - # sender: Account(storage=pointer_storage, code=bytes()), - # } + # pointer: Account(nonce=2, + # balance=0, + # storage=pointer_storage, + # code=bytes() + # ), + # sender: Account(storage=pointer_storage, code=bytes()) + # } Block( txs=[ tx_set_pointer_storage, @@ -1710,7 +1751,8 @@ def test_set_code_type_tx_pre_fork( Reject blocks with set code type transactions before the Prague fork. This test was based on: - tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_self_sponsored_set_code + tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_self_sponsored_set_ + code """ storage = Storage() sender = pre.fund_eoa() @@ -1763,9 +1805,9 @@ def test_delegation_replacement_call_previous_contract( fork: Fork, ): """ - Test setting the code of an EOA that already has - delegation, calling the previous delegated contract. - Previous contract shouldn't be warm when doing the CALL. + Test setting the code of an EOA that already has delegation, calling the + previous delegated contract. Previous contract shouldn't be warm when doing + the CALL. """ pre_set_delegation_code = Op.STOP pre_set_delegation_address = pre.deploy_contract(pre_set_delegation_code) diff --git a/shanghai/eip3651_warm_coinbase/__init__.py b/shanghai/eip3651_warm_coinbase/__init__.py index f24c6b66a5..66363cc4b3 100644 --- a/shanghai/eip3651_warm_coinbase/__init__.py +++ b/shanghai/eip3651_warm_coinbase/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651) - Tests for [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651). +Tests for [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651). """ diff --git a/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py b/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py index b49b8569fd..7f535043ba 100644 --- a/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py +++ b/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py @@ -1,9 +1,8 @@ """ -abstract: Tests [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651) - Tests for [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651). +Tests [EIP-3651: Warm COINBASE](https://eips.ethereum.org/EIPS/eip-3651). -note: Tests ported from: - - [ethereum/tests/pull/1082](https://github.com/ethereum/tests/pull/1082). +Tests ported from: +[ethereum/tests/pull/1082](https://github.com/ethereum/tests/pull/1082). """ import pytest diff --git a/shanghai/eip3855_push0/__init__.py b/shanghai/eip3855_push0/__init__.py index a8372e6ccf..986e36b549 100644 --- a/shanghai/eip3855_push0/__init__.py +++ b/shanghai/eip3855_push0/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Tests [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855) - Tests for [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855). +Tests [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855). """ diff --git a/shanghai/eip3855_push0/test_push0.py b/shanghai/eip3855_push0/test_push0.py index c490d0d8fa..aa3e471f46 100644 --- a/shanghai/eip3855_push0/test_push0.py +++ b/shanghai/eip3855_push0/test_push0.py @@ -1,9 +1,8 @@ """ -abstract: Tests [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855) - Tests for [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855). +Tests [EIP-3855: PUSH0 Instruction](https://eips.ethereum.org/EIPS/eip-3855). -note: Tests ported from: - - [ethereum/tests/pull/1033](https://github.com/ethereum/tests/pull/1033). +Tests ported from: +[ethereum/tests/pull/1033](https://github.com/ethereum/tests/pull/1033). """ import pytest @@ -92,16 +91,21 @@ def test_push0_contracts( class TestPush0CallContext: """ - Tests the PUSH0 operation during various call contexts including: - - CALL - - CALLCODE - - DELEGATECALL + Test the PUSH0 operation in various contract call contexts. + + Test PUSH0 in the following contract call contexts: + + - CALL, + - CALLCODE, + - DELEGATECALL, - STATICCALL. """ @pytest.fixture def push0_contract_callee(self, pre: Alloc) -> Address: - """Deploys a PUSH0 contract callee to the pre alloc returning its address.""" + """ + Deploys a PUSH0 contract callee to the pre alloc returning its address. + """ push0_contract = pre.deploy_contract(Op.MSTORE8(Op.PUSH0, 0xFF) + Op.RETURN(Op.PUSH0, 1)) return push0_contract @@ -110,8 +114,9 @@ def push0_contract_caller( self, pre: Alloc, call_opcode: Op, push0_contract_callee: Address ) -> Address: """ - Deploy contract responsible for calling the callee PUSH0 contract - returning its address. + Deploy the contract that calls the callee PUSH0 contract into `pre`. + + This fixture returns its address. """ call_code = ( Op.SSTORE(0, call_opcode(gas=100_000, address=push0_contract_callee)) diff --git a/shanghai/eip3860_initcode/__init__.py b/shanghai/eip3860_initcode/__init__.py index 62ee051a08..0d50d930d9 100644 --- a/shanghai/eip3860_initcode/__init__.py +++ b/shanghai/eip3860_initcode/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Test [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860) - Tests for [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860). +Test [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860). """ diff --git a/shanghai/eip3860_initcode/spec.py b/shanghai/eip3860_initcode/spec.py index 65dad3fcea..67ccec1e53 100644 --- a/shanghai/eip3860_initcode/spec.py +++ b/shanghai/eip3860_initcode/spec.py @@ -17,7 +17,9 @@ class ReferenceSpec: @dataclass(frozen=True) class Spec: """ - Parameters from the EIP-3860 specifications as defined at + Define parameters from the EIP-3860 specifications. + + These are the parameters defined at https://eips.ethereum.org/EIPS/eip-3860#parameters. """ diff --git a/shanghai/eip3860_initcode/test_initcode.py b/shanghai/eip3860_initcode/test_initcode.py index 1b52b29b03..8f31bb2f20 100644 --- a/shanghai/eip3860_initcode/test_initcode.py +++ b/shanghai/eip3860_initcode/test_initcode.py @@ -1,10 +1,9 @@ """ -abstract: Test [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860) - Tests for [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860). +Test [EIP-3860: Limit and meter initcode](https://eips.ethereum.org/EIPS/eip-3860). -note: Tests ported from: - - [ethereum/tests/pull/990](https://github.com/ethereum/tests/pull/990) - - [ethereum/tests/pull/1012](https://github.com/ethereum/tests/pull/990) +Tests ported from: +- [ethereum/tests/pull/990](https://github.com/ethereum/tests/pull/990) +- [ethereum/tests/pull/1012](https://github.com/ethereum/tests/pull/990) """ from typing import List @@ -39,9 +38,7 @@ pytestmark = pytest.mark.valid_from("Shanghai") -""" -Initcode templates used throughout the tests -""" +"""Initcode templates used throughout the tests""" INITCODE_ONES_MAX_LIMIT = Initcode( deploy_code=INITCODE_RESULTING_DEPLOYED_CODE, initcode_length=Spec.MAX_INITCODE_SIZE, @@ -112,9 +109,7 @@ SINGLE_BYTE_INITCODE.deployment_gas = 0 SINGLE_BYTE_INITCODE.execution_gas = 0 -""" -Test cases using a contract creating transaction -""" +"""Test cases using a contract creating transaction""" @pytest.mark.xdist_group(name="bigmem") @@ -137,8 +132,7 @@ def test_contract_creating_tx( initcode: Initcode, ): """ - Tests creating a contract using a transaction with an initcode that is - on/over the max allowed limit. + Test creating a contract with initcode that is on/over the allowed limit. """ create_contract_address = compute_create_address( address=sender, @@ -209,15 +203,18 @@ def valid_gas_test_case(initcode: Initcode, gas_test_case: str) -> bool: ) class TestContractCreationGasUsage: """ - Tests the following cases that verify the gas cost behavior of a - contract creating transaction. - - 1. Test with exact intrinsic gas minus one, contract create fails - and tx is invalid. - 2. Test with exact intrinsic gas, contract create fails, - but tx is valid. - 3. Test with exact execution gas minus one, contract create fails, - but tx is valid. + Test the gas cost behavior of a contract creating transaction. + + The following scenarios are tested: + + 1. Test with exact intrinsic gas minus one, contract create fails and tx is + invalid. + + 2. Test with exact intrinsic gas, contract create fails, but tx is valid. + + 3. Test with exact execution gas minus one, contract create fails, but tx + is valid. + 4. Test with exact execution gas, contract create succeeds. Initcode must be within a valid EIP-3860 length. @@ -226,8 +223,10 @@ class TestContractCreationGasUsage: @pytest.fixture def tx_access_list(self) -> List[AccessList]: """ - On EIP-7623, we need to use an access list to raise the intrinsic gas cost to - be above the floor data cost. + Return an access list to raise the intrinsic gas cost. + + Upon EIP-7623 activation, we need to use an access list to raise the + intrinsic gas cost to be above the floor data cost. """ return [AccessList(address=Address(i), storage_keys=[]) for i in range(1, 478)] @@ -235,7 +234,9 @@ def tx_access_list(self) -> List[AccessList]: def exact_intrinsic_gas( self, fork: Fork, initcode: Initcode, tx_access_list: List[AccessList] ) -> int: - """Calculate the intrinsic tx gas cost.""" + """ + Calculate the intrinsic tx gas cost. + """ tx_intrinsic_gas_cost_calculator = fork.transaction_intrinsic_cost_calculator() assert tx_intrinsic_gas_cost_calculator( calldata=initcode, @@ -255,12 +256,16 @@ def exact_intrinsic_gas( @pytest.fixture def exact_execution_gas(self, exact_intrinsic_gas: int, initcode: Initcode) -> int: - """Calculate total execution gas cost.""" + """ + Calculate total execution gas cost. + """ return exact_intrinsic_gas + initcode.deployment_gas + initcode.execution_gas @pytest.fixture def tx_error(self, gas_test_case: str) -> TransactionException | None: """ + Return the transaction exception, or None, as expected. + Check that the transaction is invalid if too little intrinsic gas is specified, otherwise the tx is valid and succeeds. """ @@ -280,7 +285,9 @@ def tx( exact_execution_gas: int, ) -> Transaction: """ - Implement the gas_test_case by setting the gas_limit of the tx + Return a tx with `gas_limit` corresponding to the `gas_test_case`. + + Implement the gas_test_case by setting the `gas_limit` of the tx appropriately and test whether the tx succeeds or fails with appropriate error. """ @@ -318,8 +325,7 @@ def post( exact_execution_gas: int, ) -> Alloc: """ - Test that contract creation fails unless enough execution gas is - provided. + Test contract creation fails unless enough execution gas is provided. """ create_contract_address = compute_create_address( address=sender, @@ -341,7 +347,9 @@ def test_gas_usage( post: Alloc, tx: Transaction, ): - """Test transaction and contract creation behavior for different gas limits.""" + """ + Test transaction and contract creation using different gas limits. + """ state_test( env=env, pre=pre, @@ -369,18 +377,24 @@ def test_gas_usage( @pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2], ids=get_create_id) class TestCreateInitcode: """ - Test contract creation via the CREATE/CREATE2 opcodes that have an initcode - that is on/over the max allowed limit. + Test contract creation with valid and invalid initcode lengths. + + Test contract creation via CREATE/CREATE2, parametrized by initcode that is + on/over the max allowed limit. """ @pytest.fixture def create2_salt(self) -> int: - """Salt value used for CREATE2 contract creation.""" + """ + Salt value used for CREATE2 contract creation. + """ return 0xDEADBEEF @pytest.fixture def creator_code(self, opcode: Op, create2_salt: int) -> Bytecode: - """Generate code for the creator contract which performs the CREATE/CREATE2 operation.""" + """ + Generate code for the creator contract which calls CREATE/CREATE2. + """ return ( Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + Op.GAS @@ -415,7 +429,9 @@ def created_contract_address( # noqa: D103 initcode: Initcode, creator_contract_address: Address, ) -> Address: - """Calculate address of the contract created by the creator contract.""" + """ + Calculate address of the contract created by the creator contract. + """ return compute_create_address( address=creator_contract_address, nonce=1, @@ -426,7 +442,9 @@ def created_contract_address( # noqa: D103 @pytest.fixture def caller_code(self, creator_contract_address: Address) -> Bytecode: - """Generate code for the caller contract that calls the creator contract.""" + """ + Generate code for the caller contract that calls the creator contract. + """ return Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + Op.SSTORE( Op.CALL(5000000, creator_contract_address, 0, 0, Op.CALLDATASIZE, 0, 0), 1 ) @@ -499,8 +517,10 @@ def test_create_opcode_initcode( create2_word_cost: int, ): """ - Test contract creation via the CREATE/CREATE2 opcodes that have an - initcode that is on/over the max allowed limit. + Test contract creation with valid and invalid initcode lengths. + + Test contract creation via CREATE/CREATE2, parametrized by initcode + that is on/over the max allowed limit. """ if len(initcode) > Spec.MAX_INITCODE_SIZE: # Call returns 0 as out of gas s[0]==1 diff --git a/shanghai/eip3860_initcode/test_with_eof.py b/shanghai/eip3860_initcode/test_with_eof.py index 433ba31d9f..f3b7318518 100644 --- a/shanghai/eip3860_initcode/test_with_eof.py +++ b/shanghai/eip3860_initcode/test_with_eof.py @@ -1,4 +1,6 @@ -"""Tests interaction between edge case size CREATE / CREATE2 and EOF, including EIP-3860 limits.""" +""" +Test CREATE / CREATE2 and EOF interaction for EIP-3860 initcode limits. +""" import itertools @@ -54,9 +56,12 @@ def test_legacy_create_edge_code_size( init_code: Bytecode, ): """ - Verifies that legacy initcode/deploycode having 0 or max size continues to work in the fork - where EOF is enabled. Handling of EOF magic prefix and version interferes with the handling - of legacy creation, so a specific test was proposed to test behavior doesn't change. + Test legacy initcode and deployed code edge cases with EOF enabled. + + Verify that legacy initcode/deploycode having 0 or max size continues to + work in the fork where EOF is enabled. Handling of EOF magic prefix and + version interferes with the handling of legacy creation, so a specific test + was proposed to test behavior doesn't change. """ env = Environment() diff --git a/shanghai/eip4895_withdrawals/__init__.py b/shanghai/eip4895_withdrawals/__init__.py index bb4a893dcb..c10cd7154b 100644 --- a/shanghai/eip4895_withdrawals/__init__.py +++ b/shanghai/eip4895_withdrawals/__init__.py @@ -1,5 +1,3 @@ """ -abstract: Tests [EIP-4895: Beacon chain withdrawals](https://eips.ethereum.org/EIPS/eip-4895) - Test cases for [EIP-4895: Beacon chain push withdrawals as - operations](https://eips.ethereum.org/EIPS/eip-4895). +Tests [EIP-4895: Beacon chain withdrawals](https://eips.ethereum.org/EIPS/eip-4895). """ diff --git a/shanghai/eip4895_withdrawals/test_withdrawals.py b/shanghai/eip4895_withdrawals/test_withdrawals.py index 44bbbeb902..df2124df95 100644 --- a/shanghai/eip4895_withdrawals/test_withdrawals.py +++ b/shanghai/eip4895_withdrawals/test_withdrawals.py @@ -1,7 +1,5 @@ """ -abstract: Tests [EIP-4895: Beacon chain withdrawals](https://eips.ethereum.org/EIPS/eip-4895) - Test cases for [EIP-4895: Beacon chain push withdrawals as - operations](https://eips.ethereum.org/EIPS/eip-4895). +Tests for [EIP-4895: Beacon chain withdrawals](https://eips.ethereum.org/EIPS/eip-4895). """ from enum import Enum, unique @@ -50,11 +48,11 @@ class TestUseValueInTx: """ Test that the value from a withdrawal can be used in a transaction. - 1. `tx_in_withdrawals_block`: Test that the withdrawal value can not be used by a transaction - in the same block as the withdrawal. + 1. `tx_in_withdrawals_block`: Test that the withdrawal value can not be + used by a transaction in the same block as the withdrawal. - 2. `tx_after_withdrawals_block`: Test that the withdrawal value can be used by a transaction - in the subsequent block. + 2. `tx_after_withdrawals_block`: Test that the withdrawal value can be used + by a transaction in the subsequent block. """ @pytest.fixture @@ -189,8 +187,7 @@ def test_use_value_in_contract( def test_balance_within_block(blockchain_test: BlockchainTestFiller, pre: Alloc): """ - Test Withdrawal balance increase within the same block, - inside contract call. + Test withdrawal balance increase within the same block in a contract call. """ save_balance_on_block_number = Op.SSTORE( Op.NUMBER, @@ -304,8 +301,7 @@ def test_multiple_withdrawals_same_address( blocks: List[Block], ): """ - Test Withdrawals can be done to the same address multiple times in - the same block. + Test withdrawals to the same address multiple times in the same block. """ # Expected post is the same for both test cases. post = {} @@ -323,8 +319,7 @@ def test_many_withdrawals( pre: Alloc, ): """ - Test Withdrawals with a count of N withdrawals in a single block where - N is a high number not expected to be seen in mainnet. + Test an unexpected high number of withdrawals in a single block. """ n = 400 withdrawals = [] @@ -362,8 +357,9 @@ def test_self_destructing_account( ): """ Test withdrawals can be done to self-destructed accounts. - Account `0x100` self-destructs and sends all its balance to `0x200`. - Then, a withdrawal is received at `0x100` with 99 wei. + + Account `0x100` self-destructs and sends all its balance to `0x200`. Then, + a withdrawal is received at `0x100` with 99 wei. """ self_destruct_code = Op.SELFDESTRUCT(Op.CALLDATALOAD(0)) sender = pre.fund_eoa() @@ -419,7 +415,7 @@ def test_newly_created_contract( include_value_in_tx: bool, request, ): - """Test Withdrawing to a newly created contract.""" + """Test withdrawing to a newly created contract.""" sender = pre.fund_eoa() initcode = Op.RETURN(0, 1) tx = Transaction( @@ -463,7 +459,7 @@ def test_no_evm_execution( blockchain_test: BlockchainTestFiller, pre: Alloc, ): - """Test Withdrawals don't trigger EVM execution.""" + """Test withdrawals don't trigger EVM execution.""" sender = pre.fund_eoa() contracts = [pre.deploy_contract(Op.SSTORE(Op.NUMBER, 1)) for _ in range(4)] blocks = [ @@ -554,16 +550,19 @@ def test_zero_amount( test_case: ZeroAmountTestCases, ): """ - Test withdrawals with zero amount for the following cases, all withdrawals - are included in one block. + Test withdrawal scenarios with a zero amount in a single block. + + All the withdrawals in the following scenarios are included in one block. 1. Two withdrawals of zero amount to two different addresses; one to an - untouched account, one to an account with a balance. + untouched account, one to an account with a balance. + 2. As 1., but with an additional withdrawal with positive value. + 3. As 2., but with an additional withdrawal containing the maximum value possible. - 4. As 3., but with order of withdrawals in the block reversed. + 4. As 3., but with order of withdrawals in the block reversed. """ empty_accounts = [pre.fund_eoa(0) for _ in range(3)] zero_balance_contract = pre.deploy_contract(Op.STOP) @@ -657,8 +656,9 @@ def test_large_amount( pre: Alloc, ): """ - Test Withdrawals that have a large gwei amount, so that (gwei * 1e9) - could overflow uint64 but not uint256. + Test withdrawals that have a large gwei amount. + + Test such that that (gwei * 1e9) could overflow uint64 but not uint256. """ withdrawals: List[Withdrawal] = [] amounts: List[int] = [ diff --git a/unscheduled/__init__.py b/unscheduled/__init__.py index c0bc59e8d5..f4907906a2 100644 --- a/unscheduled/__init__.py +++ b/unscheduled/__init__.py @@ -1 +1,4 @@ -"""Test cases for unscheduled EVM functionality. A temporary home for features that are not yet CFI'd for inclusion in the next hardfork.""" # noqa: E501 +""" +Test cases for unscheduled EVM functionality. A temporary home for features +that are not yet CFI'd for inclusion in the next hardfork. +""" diff --git a/unscheduled/eip7692_eof_v1/__init__.py b/unscheduled/eip7692_eof_v1/__init__.py index 39b893bb4a..47bb9a0684 100644 --- a/unscheduled/eip7692_eof_v1/__init__.py +++ b/unscheduled/eip7692_eof_v1/__init__.py @@ -1,6 +1,6 @@ """ -abstract: Test cases for [EIP-7692: EVM Object Format (EOFv1) Meta](https://eips.ethereum.org/EIPS/eip-7692) - Test cases for the EIPs included in [EIP-7692 EOFv1 Meta](https://eips.ethereum.org/EIPS/eip-7692). +Test cases for [EIP-7692: EVM Object Format (EOFv1) Meta](https://eips.ethereum.org/EIPS/eip-7692). + Test cases for the EIPs included in EIP-7692 EOFv1 Meta. * [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663). * [EIP-3540: EOF - EVM Object Format v1](https://eips.ethereum.org/EIPS/eip-3540). @@ -16,7 +16,7 @@ ## Devnet Specifications -- [ethpandaops/eof-devnet-0](https://notes.ethereum.org/@ethpandaops/eof-devnet-0). -""" # noqa: E501 + - [ethpandaops/eof-devnet-0](https://notes.ethereum.org/@ethpandaops/eof-devnet-0). +""" EOF_FORK_NAME = "EOFv1" diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/__init__.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/__init__.py index de9eb0a8f9..3d69914537 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/__init__.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/__init__.py @@ -1,5 +1,10 @@ """ -abstract: Test cases for [EIP-3540: EOF - EVM Object Format v1](https://eips.ethereum.org/EIPS/eip-3540) - EIP-3540 introduces a structured format for EVM bytecode, with separate sections for code and data. - Opcodes introduced: None (defines a new bytecode structure but no new opcodes). -""" # noqa: E501 +EOF - EVM Object Format v1 tests. + +Test cases for +[EIP-3540: EOF - EVM Object Format v1](https://eips.ethereum.org/EIPS/eip-3540). + +EIP-3540 introduces a structured format for EVM bytecode, with separate +sections for code and data. Opcodes introduced: None (defines a new +bytecode structure but no new opcodes). +""" diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py index c7310bcaf0..314c699838 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_all_opcodes_in_container.py @@ -1,4 +1,7 @@ -"""EOF Container: check how every opcode behaves in the middle of the valid eof container code.""" +""" +EOF Container: check how every opcode behaves in the middle of the valid eof +container code. +""" import itertools from typing import Any, Dict, Generator, List, Tuple @@ -22,7 +25,8 @@ all_opcodes = set(Op) undefined_opcodes = set(UndefinedOpcodes) -# Invalid Opcodes will produce EOFException.UNDEFINED_INSTRUCTION when used in EOFContainer +# Invalid Opcodes will produce EOFException.UNDEFINED_INSTRUCTION when used in +# EOFContainer invalid_eof_opcodes = { Op.CODESIZE, Op.SELFDESTRUCT, @@ -44,7 +48,8 @@ valid_eof_opcodes = all_opcodes - invalid_eof_opcodes -# Halting the execution opcodes can be placed without STOP instruction at the end +# Halting the execution opcodes can be placed without STOP instruction at the +# end halting_opcodes = { Op.STOP, Op.RETURNCODE, @@ -53,7 +58,8 @@ Op.INVALID, } -# Opcodes that end the code section and can be placed without STOP instruction at the end +# Opcodes that end the code section and can be placed without STOP instruction +# at the end section_terminating_opcodes = { Op.RETF, Op.JUMPF, @@ -62,7 +68,8 @@ data_portion_opcodes = {op for op in all_opcodes if op.has_data_portion()} -# NOTE: `sorted` is used to ensure that the tests are collected in a deterministic order. +# NOTE: `sorted` is used to ensure that the tests are collected in a +# deterministic order. @pytest.mark.parametrize( @@ -74,8 +81,7 @@ def test_all_opcodes_in_container( opcode: Opcode, ): """ - Test all opcodes inside valid container - 257 because 0x5B is duplicated. + Test all opcodes inside valid container 257 because 0x5B is duplicated. """ data_portion = 1 if opcode == Op.CALLF else 0 opcode_with_data_portion = opcode[data_portion] if opcode.has_data_portion() else opcode @@ -134,7 +140,10 @@ def test_invalid_opcodes_after_stop( opcode: Opcode, terminating_opcode: Opcode, ): - """Test that an invalid opcode placed after STOP (terminating instruction) invalidates EOF.""" + """ + Test that an invalid opcode placed after STOP (terminating instruction) + invalidates EOF. + """ terminating_code = Bytecode(terminating_opcode) match terminating_opcode: # Enhance the code for complex opcodes. case Op.RETURNCODE: @@ -180,8 +189,9 @@ def test_all_invalid_terminating_opcodes( ): """Test all opcodes that are invalid as the last opcode in a container.""" if opcode.has_data_portion(): - # Add the appropriate data portion to the opcode by using the get_item method. - # On the CALLF opcode we need to reference the second code section, hence the [1] index. + # Add the appropriate data portion to the opcode by using the get_item + # method. On the CALLF opcode we need to reference the second code + # section, hence the [1] index. opcode = opcode[0] if opcode != Op.CALLF else opcode[1] bytecode = (Op.PUSH0 * opcode.min_stack_height) + opcode @@ -322,11 +332,13 @@ def test_all_unreachable_terminating_opcodes_before_stop( @pytest.mark.parametrize( "exception", # We test two types of exceptions here: - # 1. Invalid max stack height, where we modify the `max_stack_height` field of the code section - # to the maximum stack height allowed by the EIP-3540, so the code still has to be checked - # for stack overflow. - # 2. Max stack height above limit, where we don't modify the `max_stack_height` field of the - # code section, so the actual code doesn't have to be verified for the stack overflow. + # 1. Invalid max stack height, where we modify the `max_stack_height` + # field of the code section to the maximum stack height allowed by + # the EIP-3540, so the code still has to be checked for stack overflow. + # + # 2. Max stack height above limit, where we don't modify the + # `max_stack_height` field of the code section, so the actual + # code doesn't have to be verified for the stack overflow. [EOFException.INVALID_MAX_STACK_INCREASE, EOFException.MAX_STACK_INCREASE_ABOVE_LIMIT], ) def test_all_opcodes_stack_overflow( @@ -334,7 +346,9 @@ def test_all_opcodes_stack_overflow( opcode: Opcode, exception: EOFException, ): - """Test stack overflow on all opcodes that push more items than they pop.""" + """ + Test stack overflow on all opcodes that push more items than they pop. + """ opcode = opcode[0] if opcode.has_data_portion() else opcode assert opcode.pushed_stack_items - opcode.popped_stack_items == 1 @@ -347,7 +361,8 @@ def test_all_opcodes_stack_overflow( kwargs: Dict[str, Any] = {"code": bytecode} if exception == EOFException.INVALID_MAX_STACK_INCREASE: - # Lie about the max stack height to make the code be checked for stack overflow. + # Lie about the max stack height to make the code be checked for stack + # overflow. kwargs["max_stack_height"] = MAX_STACK_INCREASE_LIMIT sections = [Section.Code(**kwargs)] @@ -367,13 +382,17 @@ def valid_opcode_combinations( truncate_all_options: List[bool], opcodes: List[Opcode], ) -> Generator[Tuple[bool, bool, Opcode], None, None]: - """Create valid parameter combinations for test_truncated_data_portion_opcodes().""" + """ + Create valid parameter combinations for + test_truncated_data_portion_opcodes(). + """ for opcode, truncate_all, compute_max_stack_height in itertools.product( opcodes, truncate_all_options, compute_max_stack_height_options ): opcode_with_data_portion: bytes = bytes(opcode[1]) - # Skip invalid or redundant combinations to avoid using pytest.skip in the test + # Skip invalid or redundant combinations to avoid using pytest.skip in + # the test if len(opcode_with_data_portion) == 2 and truncate_all: continue if ( @@ -401,7 +420,8 @@ def test_truncated_data_portion_opcodes( """ opcode_with_data_portion: bytes = bytes(opcode[1]) - # Compose instruction bytes with empty imm bytes (truncate_all) or 1 byte shorter imm bytes. + # Compose instruction bytes with empty imm bytes (truncate_all) or 1 byte + # shorter imm bytes. opcode_bytes = opcode_with_data_portion[0:1] if truncate_all else opcode_with_data_portion[:-1] if opcode.min_stack_height > 0: diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py index 1cc141fc03..5dfbccb173 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_size.py @@ -27,7 +27,8 @@ def test_max_size( over_limit: int, ): """Verify EOF container valid at maximum size, invalid above.""" - # Expand the minimal EOF code by more noop code, reaching the desired target container size. + # Expand the minimal EOF code by more noop code, reaching the desired + # target container size. code = Container( sections=[ Section.Code( @@ -52,7 +53,10 @@ def test_above_max_size_raw( eof_test: EOFTestFiller, size: int, ): - """Verify EOF container invalid above maximum size, regardless of header contents.""" + """ + Verify EOF container invalid above maximum size, regardless of header + contents. + """ code = Op.INVALID * size eof_test( container=Container(raw_bytes=code), @@ -101,7 +105,10 @@ def test_section_after_end_of_container( eof_test: EOFTestFiller, code: Container, ): - """Verify EOF container is invalid if any of sections declares above container size.""" + """ + Verify EOF container is invalid if any of sections declares above container + size. + """ eof_test( container=code, expect_exception=EOFException.INVALID_SECTION_BODIES_SIZE, diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py index 7e0875da28..b06ab65fbe 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_container_validation.py @@ -406,13 +406,15 @@ def test_valid_containers( validity_error=EOFException.MISSING_CODE_HEADER, ), Container( - # EOF code containing multiple type headers, second one matches code length + # EOF code containing multiple type headers, second one matches + # code length name="multiple_type_headers_2", raw_bytes="ef0001010004010001ff00000000800000fe", validity_error=EOFException.MISSING_CODE_HEADER, ), Container( - # EOF code containing multiple type headers followed by 2 code sections + # EOF code containing multiple type headers followed by 2 code + # sections name="multiple_type_headers_3", sections=[ Section(kind=SectionKind.TYPE, data="00800000"), @@ -486,8 +488,8 @@ def test_valid_containers( ], ), # The basic `no_section_terminator` cases just remove the terminator - # and the `00` for zeroth section inputs looks like one. Error is because - # the sections are wrongly sized. + # and the `00` for zeroth section inputs looks like one. Error is + # because the sections are wrongly sized. Container( name="no_section_terminator", header_terminator=bytes(), @@ -521,9 +523,9 @@ def test_valid_containers( EOFException.INVALID_FIRST_SECTION_TYPE, ], ), - # The following cases just remove the terminator - # and the `00` for zeroth section inputs looks like one. Section bodies - # are as the size prescribes here, so the error is about the inputs of zeroth section. + # The following cases just remove the terminator and the `00` for + # zeroth section inputs looks like one. Section bodies are as the size + # prescribes here, so the error is about the inputs of zeroth section. Container( name="no_section_terminator_section_bodies_ok_1", header_terminator=bytes(), @@ -536,8 +538,8 @@ def test_valid_containers( sections=[Section.Code(code=Op.JUMPDEST * 2 + Op.STOP, custom_size=2)], validity_error=EOFException.INVALID_FIRST_SECTION_TYPE, ), - # Here the terminator is missing but made to look like a different section - # or arbitrary byte + # Here the terminator is missing but made to look like a different + # section or arbitrary byte Container( name="no_section_terminator_nonzero", header_terminator=b"01", @@ -625,7 +627,8 @@ def test_valid_containers( Container( name="empty_code_section", sections=[Section.Code(code="0x")], - # TODO the exception must be about code section EOFException.INVALID_CODE_SECTION, + # TODO the exception must be about code section + # EOFException.INVALID_CODE_SECTION, validity_error=EOFException.ZERO_SECTION_SIZE, ), Container( @@ -634,7 +637,8 @@ def test_valid_containers( Section.Code(code="0x"), Section.Data(data="0xDEADBEEF"), ], - # TODO the exception must be about code section EOFException.INVALID_CODE_SECTION, + # TODO the exception must be about code section + # EOFException.INVALID_CODE_SECTION, validity_error=EOFException.ZERO_SECTION_SIZE, ), Container( @@ -684,7 +688,8 @@ def test_valid_containers( Container( name="data_section_without_code_section", sections=[Section.Data(data="0xDEADBEEF")], - # TODO the actual exception should be EOFException.MISSING_CODE_HEADER + # TODO the actual exception should be + # EOFException.MISSING_CODE_HEADER validity_error=[EOFException.ZERO_SECTION_SIZE, EOFException.UNEXPECTED_HEADER_KIND], ), Container( @@ -1059,7 +1064,8 @@ def test_valid_containers( Section.Code(code=Op.POP + Op.RETF, code_inputs=1), Section.Code(Op.STOP), ], - # TODO the actual exception should be EOFException.INVALID_TYPE_BODY, + # TODO the actual exception should be + # EOFException.INVALID_TYPE_BODY, validity_error=EOFException.INVALID_FIRST_SECTION_TYPE, ), Container( @@ -1068,7 +1074,8 @@ def test_valid_containers( Section.Code(code=Op.PUSH0, code_outputs=1), Section.Code(Op.STOP), ], - # TODO the actual exception should be EOFException.INVALID_TYPE_BODY, + # TODO the actual exception should be + # EOFException.INVALID_TYPE_BODY, validity_error=EOFException.INVALID_FIRST_SECTION_TYPE, ), Container( @@ -1158,7 +1165,8 @@ def test_valid_containers( max_stack_height=1024, ), ], - # TODO auto types section generation probably failed, the exception must be about code + # TODO auto types section generation probably failed, the exception + # must be about code validity_error=EOFException.MAX_STACK_INCREASE_ABOVE_LIMIT, ), ], diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py index 3970dd5fd7..5263afbedc 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_eof_example.py @@ -23,13 +23,16 @@ def test_eof_example(eof_test: EOFTestFiller): # TYPES section is constructed automatically based on CODE # CODE section Section.Code( - code=Op.CALLF[1](Op.PUSH0) + Op.STOP, # bytecode to be deployed in the body + code=Op.CALLF[1](Op.PUSH0) + Op.STOP, # bytecode to be + # deployed in the body # Code: call section 1 with a single zero as input, then stop. - max_stack_increase=1, # define code header (in body) stack size + max_stack_increase=1, # define code header (in body) stack + # size ), # There can be multiple code sections Section.Code( - # Remove input and call section 2 with no inputs, then remove output and return + # Remove input and call section 2 with no inputs, then remove + # output and return code=Op.POP + Op.CALLF[2]() + Op.POP + Op.RETF, code_inputs=1, code_outputs=0, @@ -64,45 +67,56 @@ def test_eof_example(eof_test: EOFTestFiller): def test_eof_example_custom_fields(eof_test: EOFTestFiller): """Example of python EOF container class tuning.""" - # if you need to overwrite certain structure bytes, you can use customization - # this is useful for unit testing the eof structure format, you can reorganize sections - # and overwrite the header bytes for testing purposes - # most of the combinations are covered by the unit tests + # if you need to overwrite certain structure bytes, you can use + # customization. this is useful for unit testing the eof structure format, + # you can reorganize sections and overwrite the header bytes for testing + # purposes. most of the combinations are covered by the unit tests # This features are subject for development and will change in the future eof_code = Container( name="valid_container_example_2", - magic=b"\xef\x00", # magic can be overwritten for test purposes, (default is 0xEF00) - version=b"\x01", # version can be overwritten for testing purposes (default is 0x01) - header_terminator=b"\x00", # terminator byte can be overwritten (default is 0x00) - extra=b"", # extra bytes to be trailed after the container body bytes (default is None) + magic=b"\xef\x00", # magic can be overwritten for test purposes, + # (default is 0xEF00) + version=b"\x01", # version can be overwritten for testing purposes + # (default is 0x01) + header_terminator=b"\x00", # terminator byte can be overwritten + # (default is 0x00) + extra=b"", # extra bytes to be trailed after the container body bytes + # (default is None) sections=[ # TYPES section is constructed automatically based on CODE # CODE section Section.Code( - code=Op.PUSH1(2) - + Op.STOP, # this is the actual bytecode to be deployed in the body + code=Op.PUSH1(2) + Op.STOP, # this is the actual bytecode to be deployed in the + # body max_stack_height=1, # define code header (in body) stack size ), # DATA section Section.Data( data="0xef", - # custom_size overrides the size bytes, so you can put only 1 byte into data - # but still make the header size of 2 to produce invalid section + # custom_size overrides the size bytes, so you can put only 1 + # byte into data but still make the header size of 2 to produce + # invalid section + # # if custom_size != len(data), the section will be invalid custom_size=1, ), ], # auto generate types section based on provided code sections - # AutoSection.ONLY_BODY - means the section will be generated only for the body bytes - # AutoSection.ONLY_BODY - means the section will be generated only for the header bytes + # AutoSection.ONLY_BODY - means the section will be generated only for + # the body bytes + # + # AutoSection.ONLY_BODY - means the section will be generated only for + # the header bytes auto_type_section=AutoSection.AUTO, # auto generate default data section (0x empty), by default is True auto_data_section=True, # auto sort section by order 01 02 03 04 - # AutoSection.ONLY_BODY - means the sorting will be done only for the body bytes - # AutoSection.ONLY_BODY - means the section will be done only for the header bytes + # AutoSection.ONLY_BODY - means the sorting will be done only for the + # body bytes + # AutoSection.ONLY_BODY - means the section will be done only for the + # header bytes auto_sort_sections=AutoSection.AUTO, ) diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_opcodes_in_legacy.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_opcodes_in_legacy.py index 0dfabd0445..3916f8570f 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_opcodes_in_legacy.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_opcodes_in_legacy.py @@ -48,7 +48,8 @@ pytest.param(Op.DATASIZE, id="DATASIZE"), pytest.param(Op.DATACOPY(0, 0, 32), id="DATACOPY"), pytest.param(Op.EOFCREATE[0](0, 0, 0, 0), id="EOFCREATE"), - # pytest.param(Op.TXCREATE(0, 0, 0, 0, 0), id="TXCREATE"), not EOF-only anymore + # pytest.param(Op.TXCREATE(0, 0, 0, 0, 0), id="TXCREATE"), not EOF-only + # anymore pytest.param(Op.RETURNCODE[0], id="RETURNCODE"), ] @@ -67,7 +68,8 @@ def test_opcodes_in_legacy(state_test: StateTestFiller, pre: Alloc, code: Opcode ) post = { - # assert the canary is not over-written. If it was written then the EOF opcode was valid + # assert the canary is not over-written. If it was written then the EOF + # opcode was valid address_test_contract: Account(storage={slot_code_executed: value_non_execution_canary}), } @@ -209,7 +211,8 @@ def test_opcodes_in_eof_calling_legacy( ) post = { - # assert the canary is not over-written. If it was written then the EOF opcode was valid + # assert the canary is not over-written. If it was written then the EOF + # opcode was valid address_test_contract: Account(storage={slot_code_executed: value_non_execution_canary}), address_entry_contract: Account( storage={ diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_header_body_mismatch.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_header_body_mismatch.py index 4292914e63..d1b11bea5c 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_header_body_mismatch.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_header_body_mismatch.py @@ -18,10 +18,14 @@ @pytest.mark.parametrize( **extend_with_defaults( defaults={ - "skip_header_listing": False, # second section is mentioned in code header array - "skip_body_listing": False, # second section code is in container's body - "skip_types_body_listing": False, # code input bytes not listed in container's body - "skip_types_header_listing": False, # code input bytes size not added to types section size # noqa: E501 + # second section is mentioned in code header array + "skip_header_listing": False, + # second section code is in container's body + "skip_body_listing": False, + # code input bytes not listed in container's body + "skip_types_body_listing": False, + # code input bytes size not added to types section size + "skip_types_header_listing": False, "expected_code": "", "expected_exception": None, }, @@ -30,7 +34,8 @@ { "skip_header_listing": True, "skip_body_listing": True, - "expected_code": "ef00010100080200010003ff00040000800001000000003050000bad60A7", # noqa: E501 + "expected_code": "ef00010100080200010003ff0004000080000" + "1000000003050000bad60A7", "expected_exception": [ EOFException.INVALID_TYPE_SECTION_SIZE, EOFException.INVALID_SECTION_BODIES_SIZE, @@ -42,7 +47,8 @@ { "skip_header_listing": True, "skip_body_listing": False, - "expected_code": "ef00010100080200010003ff00040000800001000000003050003050000bad60A7", # noqa: E501 + "expected_code": "ef00010100080200010003ff0004000080000" + "1000000003050003050000bad60A7", "expected_exception": [ EOFException.INVALID_TYPE_SECTION_SIZE, EOFException.INVALID_SECTION_BODIES_SIZE, @@ -54,7 +60,8 @@ { "skip_header_listing": False, "skip_body_listing": True, - "expected_code": "ef000101000802000200030003ff00040000800001000000003050000bad60A7", # noqa: E501 + "expected_code": "ef000101000802000200030003ff000400008" + "00001000000003050000bad60A7", "expected_exception": [ EOFException.UNREACHABLE_CODE_SECTIONS, EOFException.TOPLEVEL_CONTAINER_TRUNCATED, @@ -66,7 +73,8 @@ { "skip_header_listing": False, "skip_body_listing": False, - "expected_code": "ef000101000802000200030003ff00040000800001000000003050003050000bad60A7", # noqa: E501 + "expected_code": "ef000101000802000200030003ff000400008" + "00001000000003050003050000bad60A7", "expected_exception": EOFException.UNREACHABLE_CODE_SECTIONS, }, id="layout_ok_code_bad", @@ -125,7 +133,8 @@ def test_code_section_header_body_mismatch( skip_body_listing=skip_body_listing, # whether to not print its input bytes in containers body skip_types_body_listing=skip_types_body_listing, - # whether to not calculate its input bytes size in types section's header + # whether to not calculate its input bytes size in types + # section's header skip_types_header_listing=skip_types_header_listing, ), Section.Data("0x0bad60A7"), diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py index 8e5f7c6da0..aae8c4af0b 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_order.py @@ -36,7 +36,9 @@ class CasePosition(Enum): def get_expected_code_exception( section_kind, section_test, test_position ) -> tuple[str, EOFExceptionInstanceOrList | None]: - """Verification vectors with code and exception based on test combinations.""" + """ + Verification vectors with code and exception based on test combinations. + """ match (section_kind, section_test, test_position): case (SectionKind.TYPE, SectionTest.MISSING, CasePosition.HEADER): return ( @@ -64,7 +66,8 @@ def get_expected_code_exception( case (SectionKind.TYPE, SectionTest.WRONG_ORDER, CasePosition.BODY): return ( "ef00010100040200010003ff00010030500000800001ef", - # TODO why invalid first section type? it should say that the body incorrect + # TODO why invalid first section type? it should say that the + # body incorrect EOFException.INVALID_FIRST_SECTION_TYPE, ) case (SectionKind.TYPE, SectionTest.WRONG_ORDER, CasePosition.BODY_AND_HEADER): @@ -80,8 +83,8 @@ def get_expected_code_exception( case (SectionKind.CODE, SectionTest.MISSING, CasePosition.BODY): return ( "ef00010100040200010003ff00010000800001ef", - # TODO should be an exception of empty code bytes, because it can understand that - # last byte is data section byte + # TODO should be an exception of empty code bytes, because it + # can understand that last byte is data section byte [EOFException.INVALID_SECTION_BODIES_SIZE, EOFException.UNEXPECTED_HEADER_KIND], ) case (SectionKind.CODE, SectionTest.MISSING, CasePosition.BODY_AND_HEADER): @@ -230,17 +233,17 @@ def test_container_section_order( test_position: CasePosition, ): """ - Test containers section being out of order in the header and/or body. - This extends and follows the convention of the test_section_order() - for the optional container section. + Test containers section being out of order in the header and/or body. This + extends and follows the convention of the test_section_order() for the + optional container section. """ if container_position == 2: pytest.skip("Skip valid container section position") section_code = Section.Code( code=Op.EOFCREATE[0](0, 0, 0, 0) - # TODO: Migrated tests had the following infinite loop, so it is kept here - # to equalize code coverage. + # TODO: Migrated tests had the following infinite loop, so it is kept + # here to equalize code coverage. + Op.RJUMP[0] + Op.STOP() ) @@ -270,7 +273,8 @@ def get_expected_exception(): return EOFException.INVALID_FIRST_SECTION_TYPE case 1, CasePosition.BODY: # Messes up with the code section return EOFException.UNDEFINED_INSTRUCTION - case 3, CasePosition.BODY: # Data section messes up with the container section + case 3, CasePosition.BODY: # Data section messes up with the + # container section return EOFException.INVALID_MAGIC case 0, CasePosition.HEADER | CasePosition.BODY_AND_HEADER: return EOFException.MISSING_TYPE_HEADER diff --git a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py index 6fecfe1799..f5ea074b85 100644 --- a/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py +++ b/unscheduled/eip7692_eof_v1/eip3540_eof_v1/test_section_size.py @@ -120,7 +120,9 @@ def test_section_size( section_kind: SectionKind, exception: EOFExceptionInstanceOrList, ): - """Test custom_size is auto, more or less than the actual size of the section.""" + """ + Test custom_size is auto, more or less than the actual size of the section. + """ eof_code = Container() if section_size != SectionSize.NORMAL and section_kind == SectionKind.TYPE: @@ -183,8 +185,8 @@ def test_section_size( @pytest.mark.parametrize( "truncation_len, exception", [ - # The original container is not valid by itself because its 2-byte code section - # starts with the terminating instruction: INVALID. + # The original container is not valid by itself because its 2-byte code + # section starts with the terminating instruction: INVALID. pytest.param(0, EOFException.UNREACHABLE_INSTRUCTIONS), pytest.param(1, EOFException.INVALID_SECTION_BODIES_SIZE, id="EOF1_truncated_section_2"), pytest.param(3, EOFException.INVALID_SECTION_BODIES_SIZE, id="EOF1_truncated_section_1"), @@ -198,7 +200,8 @@ def test_truncated_container_without_data( ): """ Test takes a semi-valid container and removes some bytes from its tail. - Migrated from EOFTests/efValidation/EOF1_truncated_section_.json (cases without data section). + Migrated from EOFTests/efValidation/EOF1_truncated_section_.json (cases + without data section). """ container = Container(sections=[Section.Code(Op.INVALID + Op.INVALID)]) bytecode = bytes(container) @@ -222,8 +225,9 @@ def test_truncated_container_with_data( exception: EOFException, ): """ - Test takes a valid container with data and removes some bytes from its tail. - Migrated from EOFTests/efValidation/EOF1_truncated_section_.json (cases with data section). + Test takes a valid container with data and removes some bytes from its + tail. Migrated from EOFTests/efValidation/EOF1_truncated_section_.json + (cases with data section). """ data = b"\xaa\xbb" container = Container( diff --git a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/__init__.py b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/__init__.py index 4eef21b71a..f08cf8e60e 100644 --- a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/__init__.py +++ b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/__init__.py @@ -1,5 +1,7 @@ """ -abstract: Test cases for [EIP-4200: EOF - Static relative jumps](https://eips.ethereum.org/EIPS/eip-4200) - EIP-4200 replaces dynamic jump instructions with relative jump offsets for improved control flow predictability. - Opcodes introduced: `RJUMP` (`0xE0`), `RJUMPI` (`0xE1`), `RJUMPV` (`0xE2`). -""" # noqa: E501 +Test cases for [EIP-4200: EOF - Static relative jumps](https://eips.ethereum.org/EIPS/eip-4200). + +EIP-4200 replaces dynamic jump instructions with relative jump offsets for +improved control flow predictability. Opcodes introduced: `RJUMP` (`0xE0`), +`RJUMPI` (`0xE1`), `RJUMPV` (`0xE2`). +""" diff --git a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py index 0a2e407cc5..490bea5297 100644 --- a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py +++ b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjump.py @@ -39,7 +39,9 @@ def test_rjump_negative( def test_rjump_positive_negative( eof_state_test: EOFStateTestFiller, ): - """EOF1V4200_0001 (Valid) EOF code containing RJUMP (Positive, Negative).""" + """ + EOF1V4200_0001 (Valid) EOF code containing RJUMP (Positive, Negative). + """ eof_state_test( container=Container.Code( Op.PUSH0 @@ -68,7 +70,10 @@ def test_rjump_zero( def test_rjump_maxes( eof_state_test: EOFStateTestFiller, ): - """EOF1V4200_0003 EOF with RJUMP containing the max positive and negative offset (32767).""" + """ + EOF1V4200_0003 EOF with RJUMP containing the max positive and negative + offset (32767). + """ eof_state_test( container=Container.Code( Op.PUSH0 @@ -87,8 +92,8 @@ def test_rjump_max_bytecode_size( eof_test: EOFTestFiller, ): """ - EOF1V4200_0003 EOF with RJUMP containing the maximum offset that does not exceed the maximum - bytecode size. + EOF1V4200_0003 EOF with RJUMP containing the maximum offset that does not + exceed the maximum bytecode size. """ noop_count = MAX_BYTECODE_SIZE - 27 code = ( @@ -128,8 +133,8 @@ def test_rjump_into_header( offset: int, ): """ - EOF1I4200_0003 (Invalid) EOF code containing RJUMP with target outside code bounds - (Jumping into header). + EOF1I4200_0003 (Invalid) EOF code containing RJUMP with target outside code + bounds (Jumping into header). """ eof_test( container=Container.Code(Op.RJUMP[offset]), @@ -141,8 +146,8 @@ def test_rjump_before_header( eof_test: EOFTestFiller, ): """ - EOF1I4200_0004 (Invalid) EOF code containing RJUMP with target outside code bounds - (Jumping before code begin). + EOF1I4200_0004 (Invalid) EOF code containing RJUMP with target outside code + bounds (Jumping before code begin). """ eof_test( container=Container.Code(Op.RJUMP[-23]), @@ -154,8 +159,8 @@ def test_rjump_into_data( eof_test: EOFTestFiller, ): """ - EOF1I4200_0005 (Invalid) EOF code containing RJUMP with target outside code bounds - (Jumping into data section). + EOF1I4200_0005 (Invalid) EOF code containing RJUMP with target outside code + bounds (Jumping into data section). """ eof_test( container=Container( @@ -171,7 +176,10 @@ def test_rjump_into_data( def test_rjump_outside_other_section_before( eof_test: EOFTestFiller, ): - """EOF code containing RJUMP with target outside code bounds (prior code section).""" + """ + EOF code containing RJUMP with target outside code bounds (prior code + section). + """ eof_test( container=Container( sections=[ @@ -186,7 +194,10 @@ def test_rjump_outside_other_section_before( def test_rjump_outside_other_section_after( eof_test: EOFTestFiller, ): - """EOF code containing RJUMP with target outside code bounds (Subsequent code section).""" + """ + EOF code containing RJUMP with target outside code bounds (Subsequent code + section). + """ eof_test( container=Container( sections=[ @@ -203,8 +214,8 @@ def test_rjump_after_container( eof_test: EOFTestFiller, ): """ - EOF1I4200_0006 (Invalid) EOF code containing RJUMP with target outside code bounds - (Jumping after code end). + EOF1I4200_0006 (Invalid) EOF code containing RJUMP with target outside code + bounds (Jumping after code end). """ eof_test( container=Container.Code(Op.RJUMP[2]), @@ -216,8 +227,8 @@ def test_rjump_to_code_end( eof_test: EOFTestFiller, ): """ - EOF1I4200_0007 (Invalid) EOF code containing RJUMP with target outside code bounds - (Jumping to code end). + EOF1I4200_0007 (Invalid) EOF code containing RJUMP with target outside code + bounds (Jumping to code end). """ eof_test( container=Container.Code(Op.RJUMP[1] + Op.STOP), @@ -230,7 +241,10 @@ def test_rjump_into_self_data_portion( eof_test: EOFTestFiller, offset: int, ): - """EOF1I4200_0008 (Invalid) EOF code containing RJUMP with target self RJUMP immediate.""" + """ + EOF1I4200_0008 (Invalid) EOF code containing RJUMP with target self RJUMP + immediate. + """ eof_test( container=Container.Code(Op.RJUMP[-offset] + Op.STOP), expect_exception=EOFException.INVALID_RJUMP_DESTINATION, @@ -241,8 +255,8 @@ def test_rjump_into_self_remaining_code( eof_test: EOFTestFiller, ): """ - EOF1I4200_0008 (Invalid) EOF code containing RJUMP with target self RJUMP but remaining - unreachable code. + EOF1I4200_0008 (Invalid) EOF code containing RJUMP with target self RJUMP + but remaining unreachable code. """ eof_test( container=Container.Code(Op.RJUMP[-len(Op.RJUMP[0])] + Op.STOP), @@ -269,7 +283,10 @@ def test_rjump_into_self( def test_rjump_into_self_pre_code( eof_test: EOFTestFiller, ): - """EOF code containing RJUMP with target self RJUMP with non-zero stack before RJUMP.""" + """ + EOF code containing RJUMP with target self RJUMP with non-zero stack before + RJUMP. + """ eof_test( container=Container.Code(Op.PUSH1[0] + Op.RJUMP[-len(Op.RJUMP[0])]), ) @@ -455,8 +472,8 @@ def test_rjump_valid_forward( container: Container, ): """ - Validate a valid code section containing at least one forward RJUMP. - These tests exercise the stack height validation. + Validate a valid code section containing at least one forward RJUMP. These + tests exercise the stack height validation. """ eof_test(container=container) @@ -551,8 +568,8 @@ def test_rjump_valid_backward( container: Container, ): """ - Validate a valid code section containing at least one backward RJUMP. - These tests exercise the stack height validation. + Validate a valid code section containing at least one backward RJUMP. These + tests exercise the stack height validation. """ eof_test(container=container) @@ -560,7 +577,10 @@ def test_rjump_valid_backward( def test_rjump_into_stack_height_diff( eof_test: EOFTestFiller, ): - """EOF code containing RJUMP with target instruction that causes stack height difference.""" + """ + EOF code containing RJUMP with target instruction that causes stack height + difference. + """ eof_test( container=Container.Code(Op.PUSH1[0] + Op.RJUMP[-(len(Op.RJUMP[0]) + len(Op.PUSH1[0]))]), expect_exception=EOFException.STACK_HEIGHT_MISMATCH, @@ -570,7 +590,10 @@ def test_rjump_into_stack_height_diff( def test_rjump_into_stack_height_diff_2( eof_test: EOFTestFiller, ): - """EOF code containing RJUMP with target instruction that cause stack height difference.""" + """ + EOF code containing RJUMP with target instruction that cause stack height + difference. + """ eof_test( container=Container.Code( Op.PUSH1[0] + Op.POP + Op.RJUMP[-(len(Op.RJUMP[0]) + len(Op.POP))] @@ -757,8 +780,8 @@ def test_rjump_backward_invalid_max_stack_height( container: Container, ): """ - Validate a code section containing at least one backward RJUMP - invalid because of the incorrect max stack height. + Validate a code section containing at least one backward RJUMP invalid + because of the incorrect max stack height. """ eof_test(container=container, expect_exception=EOFException.STACK_HEIGHT_MISMATCH) @@ -766,7 +789,10 @@ def test_rjump_backward_invalid_max_stack_height( def test_rjump_into_stack_underflow( eof_test: EOFTestFiller, ): - """EOF code containing RJUMP with target instruction that cause stack underflow.""" + """ + EOF code containing RJUMP with target instruction that cause stack + underflow. + """ eof_test( container=Container.Code( Op.ORIGIN @@ -783,7 +809,10 @@ def test_rjump_into_stack_underflow( def test_rjump_into_rjump( eof_test: EOFTestFiller, ): - """EOF1I4200_0009 (Invalid) EOF code containing RJUMP with target other RJUMP immediate.""" + """ + EOF1I4200_0009 (Invalid) EOF code containing RJUMP with target other RJUMP + immediate. + """ eof_test( container=Container.Code(Op.RJUMP[1] + Op.RJUMP[0]), expect_exception=EOFException.INVALID_RJUMP_DESTINATION, @@ -793,7 +822,10 @@ def test_rjump_into_rjump( def test_rjump_into_rjumpi( eof_test: EOFTestFiller, ): - """EOF1I4200_0010 (Invalid) EOF code containing RJUMP with target RJUMPI immediate.""" + """ + EOF1I4200_0010 (Invalid) EOF code containing RJUMP with target RJUMPI + immediate. + """ eof_test( container=Container.Code(Op.RJUMP[5] + Op.STOP + Op.PUSH1[1] + Op.RJUMPI[-6] + Op.STOP), expect_exception=EOFException.INVALID_RJUMP_DESTINATION, @@ -802,7 +834,10 @@ def test_rjump_into_rjumpi( @pytest.mark.parametrize("jump", [JumpDirection.FORWARD, JumpDirection.BACKWARD]) def test_rjump_into_push_1(eof_test: EOFTestFiller, jump: JumpDirection): - """EOF1I4200_0011 (Invalid) EOF code containing RJUMP with target PUSH1 immediate.""" + """ + EOF1I4200_0011 (Invalid) EOF code containing RJUMP with target PUSH1 + immediate. + """ code = ( Op.PUSH1[1] + Op.RJUMP[-4] if jump == JumpDirection.BACKWARD else Op.RJUMP[1] + Op.PUSH1[1] ) + Op.STOP @@ -860,7 +895,10 @@ def test_rjump_into_push_n( jump: JumpDirection, data_portion_end: bool, ): - """EOF1I4200_0011 (Invalid) EOF code containing RJUMP with target PUSH2+ immediate.""" + """ + EOF1I4200_0011 (Invalid) EOF code containing RJUMP with target PUSH2+ + immediate. + """ data_portion_length = int.from_bytes(opcode, byteorder="big") - 0x5F if jump == JumpDirection.FORWARD: offset = data_portion_length if data_portion_end else 1 @@ -885,7 +923,10 @@ def test_rjump_into_rjumpv( target_rjumpv_table_size: int, data_portion_end: bool, ): - """EOF1I4200_0012 (Invalid) EOF code containing RJUMP with target RJUMPV immediate.""" + """ + EOF1I4200_0012 (Invalid) EOF code containing RJUMP with target RJUMPV + immediate. + """ invalid_destination = 4 + (2 * target_rjumpv_table_size) if data_portion_end else 4 target_jump_table = [0 for _ in range(target_rjumpv_table_size)] eof_test( @@ -909,7 +950,10 @@ def test_rjump_into_callf( eof_test: EOFTestFiller, data_portion_end: bool, ): - """EOF1I4200_0013 (Invalid) EOF code containing RJUMP with target CALLF immediate.""" + """ + EOF1I4200_0013 (Invalid) EOF code containing RJUMP with target CALLF + immediate. + """ invalid_destination = 2 if data_portion_end else 1 eof_test( container=Container( diff --git a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py index 3fa0e7f3f6..dd1647eb95 100644 --- a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py +++ b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpi.py @@ -129,7 +129,9 @@ def test_rjumpi_condition_zero( pre: Alloc, calldata: bytes, ): - """Test RJUMPI contract switching based on external input (condition zero).""" + """ + Test RJUMPI contract switching based on external input (condition zero). + """ env = Environment() sender = pre.fund_eoa(10**18) contract_address = pre.deploy_contract( @@ -221,7 +223,10 @@ def test_rjumpi_zero( def test_rjumpi_max_forward( eof_state_test: EOFStateTestFiller, ): - """EOF1V4200_0007 (Valid) EOF with RJUMPI containing the maximum offset (32767).""" + """ + EOF1V4200_0007 (Valid) EOF with RJUMPI containing the maximum offset + (32767). + """ eof_state_test( container=Container( sections=[ @@ -730,8 +735,8 @@ def test_rjumpi_valid_forward( container: Container, ): """ - Validate a valid code section containing at least one forward RJUMPI. - These tests exercise the stack height validation. + Validate a valid code section containing at least one forward RJUMPI. These + tests exercise the stack height validation. """ eof_test(container=container) @@ -909,8 +914,8 @@ def test_rjumpi_max_bytecode_size( eof_test: EOFTestFiller, ): """ - EOF1V4200_0003 EOF with RJUMPI containing the maximum offset that does not exceed the maximum - bytecode size. + EOF1V4200_0003 EOF with RJUMPI containing the maximum offset that does not + exceed the maximum bytecode size. """ noop_count = MAX_BYTECODE_SIZE - 24 code = Op.RJUMPI[len(Op.NOOP) * noop_count](Op.ORIGIN) + (Op.NOOP * noop_count) + Op.STOP @@ -957,8 +962,8 @@ def test_rjumpi_into_header( offset: int, ): """ - EOF1I4200_0016 (Invalid) EOF code containing RJUMPI with target outside code bounds - (Jumping into header). + EOF1I4200_0016 (Invalid) EOF code containing RJUMPI with target outside + code bounds (Jumping into header). """ eof_test( container=Container( @@ -976,8 +981,8 @@ def test_rjumpi_jump_before_header( eof_test: EOFTestFiller, ): """ - EOF1I4200_0017 (Invalid) EOF code containing RJUMPI with target outside code bounds - (Jumping to before code begin). + EOF1I4200_0017 (Invalid) EOF code containing RJUMPI with target outside + code bounds (Jumping to before code begin). """ eof_test( container=Container( @@ -995,8 +1000,8 @@ def test_rjumpi_into_data( eof_test: EOFTestFiller, ): """ - EOF1I4200_0018 (Invalid) EOF code containing RJUMPI with target outside code bounds - (Jumping into data section). + EOF1I4200_0018 (Invalid) EOF code containing RJUMPI with target outside + code bounds (Jumping into data section). """ eof_test( container=Container( @@ -1015,8 +1020,8 @@ def test_rjumpi_after_container( eof_test: EOFTestFiller, ): """ - EOF1I4200_0019 (Invalid) EOF code containing RJUMPI with target outside code bounds - (Jumping to after code end). + EOF1I4200_0019 (Invalid) EOF code containing RJUMPI with target outside + code bounds (Jumping to after code end). """ eof_test( container=Container( @@ -1034,8 +1039,8 @@ def test_rjumpi_to_code_end( eof_test: EOFTestFiller, ): """ - EOF1I4200_0020 (Invalid) EOF code containing RJUMPI with target outside code bounds - (Jumping to code end). + EOF1I4200_0020 (Invalid) EOF code containing RJUMPI with target outside + code bounds (Jumping to code end). """ eof_test( container=Container( @@ -1055,8 +1060,8 @@ def test_rjumpi_into_self_data_portion( offset: int, ): """ - EOF1I4200_0021 (Invalid) EOF code containing RJUMPI with target same RJUMPI immediate - (with offset). + EOF1I4200_0021 (Invalid) EOF code containing RJUMPI with target same RJUMPI + immediate (with offset). """ eof_test( container=Container( @@ -1076,8 +1081,8 @@ def test_rjumpi_into_self( stack_height_spread: int, ): """ - EOF code containing RJUMPI targeting itself (-3). - This can never be valid because this is backward jump and RJUMPI consumes one stack item. + EOF code containing RJUMPI targeting itself (-3). This can never be valid + because this is backward jump and RJUMPI consumes one stack item. """ # Create variadic stack height by the parametrized spread. stack_spread_code = Bytecode() @@ -1099,7 +1104,10 @@ def test_rjumpi_into_self( def test_rjumpi_into_stack_height_diff( eof_test: EOFTestFiller, ): - """EOF code containing RJUMPI with target instruction that causes stack height difference.""" + """ + EOF code containing RJUMPI with target instruction that causes stack height + difference. + """ eof_test( container=Container( sections=[ @@ -1118,7 +1126,10 @@ def test_rjumpi_into_stack_height_diff( def test_rjumpi_into_stack_underflow( eof_test: EOFTestFiller, ): - """EOF code containing RJUMPI with target instruction that cause stack underflow.""" + """ + EOF code containing RJUMPI with target instruction that cause stack + underflow. + """ eof_test( container=Container( sections=[ @@ -1134,7 +1145,10 @@ def test_rjumpi_into_stack_underflow( def test_rjumpi_skips_stack_underflow( eof_test: EOFTestFiller, ): - """EOF code containing RJUMPI where the default path produces a stack underflow.""" + """ + EOF code containing RJUMPI where the default path produces a stack + underflow. + """ eof_test( container=Container( sections=[ @@ -1148,7 +1162,10 @@ def test_rjumpi_skips_stack_underflow( def test_rjumpi_into_rjump( eof_test: EOFTestFiller, ): - """EOF1I4200_0023 (Invalid) EOF code containing RJUMPI with target RJUMP immediate.""" + """ + EOF1I4200_0023 (Invalid) EOF code containing RJUMPI with target RJUMP + immediate. + """ eof_test( container=Container( sections=[ @@ -1164,7 +1181,10 @@ def test_rjumpi_into_rjump( def test_rjumpi_into_rjumpi( eof_test: EOFTestFiller, ): - """EOF1I4200_0022 (Invalid) EOF code containing RJUMPI with target other RJUMPI immediate.""" + """ + EOF1I4200_0022 (Invalid) EOF code containing RJUMPI with target other + RJUMPI immediate. + """ eof_test( container=Container( sections=[ @@ -1187,7 +1207,10 @@ def test_rjumpi_into_push_1( eof_test: EOFTestFiller, jump: JumpDirection, ): - """EOF1I4200_0024 (Invalid) EOF code containing RJUMPI with target PUSH1 immediate.""" + """ + EOF1I4200_0024 (Invalid) EOF code containing RJUMPI with target PUSH1 + immediate. + """ code = ( Op.PUSH1[1] + Op.RJUMPI[-4] if jump == JumpDirection.BACKWARD @@ -1251,7 +1274,10 @@ def test_rjumpi_into_push_n( jump: JumpDirection, data_portion_end: bool, ): - """EOF1I4200_0024 (Invalid) EOF code containing RJUMPI with target PUSH2+ immediate.""" + """ + EOF1I4200_0024 (Invalid) EOF code containing RJUMPI with target PUSH2+ + immediate. + """ data_portion_length = int.from_bytes(opcode, byteorder="big") - 0x5F if jump == JumpDirection.FORWARD: offset = data_portion_length if data_portion_end else 1 @@ -1280,7 +1306,10 @@ def test_rjumpi_into_rjumpv( target_rjumpv_table_size: int, data_portion_end: bool, ): - """EOF1I4200_0025 (Invalid) EOF code containing RJUMPI with target RJUMPV immediate.""" + """ + EOF1I4200_0025 (Invalid) EOF code containing RJUMPI with target RJUMPV + immediate. + """ invalid_destination = 4 + (2 * target_rjumpv_table_size) if data_portion_end else 4 target_jump_table = [0 for _ in range(target_rjumpv_table_size)] eof_test( @@ -1309,7 +1338,10 @@ def test_rjumpi_into_callf( eof_test: EOFTestFiller, data_portion_end: bool, ): - """EOF1I4200_0026 (Invalid) EOF code containing RJUMPI with target CALLF immediate.""" + """ + EOF1I4200_0026 (Invalid) EOF code containing RJUMPI with target CALLF + immediate. + """ invalid_destination = 2 if data_portion_end else 1 eof_test( container=Container( @@ -1474,8 +1506,8 @@ def test_rjumpi_stack_validation( ): """ Check that you can get to the same opcode with two different stack heights - Spec now allows this: - 4.b in https://github.com/ipsilon/eof/blob/main/spec/eof.md#stack-validation. + Spec now allows this: 4.b in + https://github.com/ipsilon/eof/blob/main/spec/eof.md#stack-validation. """ container = Container.Code(code=Op.RJUMPI[1](1) + Op.ADDRESS + Op.NOOP + Op.STOP) eof_test( @@ -1490,7 +1522,8 @@ def test_rjumpi_at_the_end( """ Test invalid RJUMPI as the end of a code section. https://github.com/ipsilon/eof/blob/main/spec/eof.md#stack-validation 4.i: - This implies that the last instruction must be a terminating instruction or RJUMP. + This implies that the last instruction must be a terminating instruction or + RJUMP. """ eof_test( container=Container( @@ -1611,8 +1644,8 @@ def test_double_rjumpi_stack_height_mismatch( eof_test: EOFTestFiller, ): """ - Test stack height check of the backward RJUMP - targeted by two RJUMPIs with the non-uniform stack height range. + Test stack height check of the backward RJUMP targeted by two RJUMPIs with + the non-uniform stack height range. """ eof_test( container=Container( @@ -1635,8 +1668,8 @@ def test_double_rjumpi_invalid_max_stack_height( eof_test: EOFTestFiller, ): """ - Test max stack height of the final block - targeted by two RJUMPIs with the non-uniform stack height range. + Test max stack height of the final block targeted by two RJUMPIs with the + non-uniform stack height range. """ eof_test( container=Container( @@ -1848,7 +1881,7 @@ def test_rjumpi_backward_invalid_max_stack_height( container: Container, ): """ - Validate a code section containing at least one backward RJUMPI - invalid because of the incorrect max stack height. + Validate a code section containing at least one backward RJUMPI invalid + because of the incorrect max stack height. """ eof_test(container=container, expect_exception=EOFException.STACK_HEIGHT_MISMATCH) diff --git a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py index 7fe59d8ffa..6d32799aae 100644 --- a/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py +++ b/unscheduled/eip7692_eof_v1/eip4200_relative_jumps/test_rjumpv.py @@ -200,7 +200,10 @@ def test_rjumpv_full_table( eof_state_test: EOFStateTestFiller, target: int, ): - """EOF1V4200_0012/13/14/15 (Valid) EOF with RJUMPV table size 256 (target parameterized).""" + """ + EOF1V4200_0012/13/14/15 (Valid) EOF with RJUMPV table size 256 (target + parameterized). + """ eof_state_test( container=Container( sections=[ @@ -220,7 +223,10 @@ def test_rjumpv_full_table( def test_rjumpv_max_forwards( eof_state_test: EOFStateTestFiller, ): - """EOF1V4200_0016 (Valid) EOF with RJUMPV containing the maximum offset (32767).""" + """ + EOF1V4200_0016 (Valid) EOF with RJUMPV containing the maximum offset + (32767). + """ eof_state_test( container=Container( sections=[ @@ -240,7 +246,10 @@ def test_rjumpv_max_forwards( def test_rjumpv_truncated_empty( eof_test: EOFTestFiller, ): - """EOF1I4200_0027 (Invalid) EOF code containing RJUMPV with max_index 0 but no immediates.""" + """ + EOF1I4200_0027 (Invalid) EOF code containing RJUMPV with max_index 0 but no + immediates. + """ eof_test( container=Container( sections=[ @@ -290,8 +299,8 @@ def test_rjumpv_into_header( invalid_index: int, ): """ - EOF1I4200_0031 (Invalid) EOF code containing RJUMPV with target outside code bounds - (Jumping into header). + EOF1I4200_0031 (Invalid) EOF code containing RJUMPV with target outside + code bounds (Jumping into header). """ invalid_destination = -5 - (2 * table_size) jump_table = [0 for _ in range(table_size)] @@ -324,8 +333,8 @@ def test_rjumpv_before_container( offset: int, ): """ - EOF1I4200_0032 (Invalid) EOF code containing RJUMPV with target outside code bounds - (Jumping to before code begin). + EOF1I4200_0032 (Invalid) EOF code containing RJUMPV with target outside + code bounds (Jumping to before code begin). """ invalid_destination = offset - (2 * table_size) jump_table = [0 for _ in range(table_size)] @@ -356,8 +365,8 @@ def test_rjumpv_into_data( invalid_index: int, ): """ - EOF1I4200_0033 (Invalid) EOF code containing RJUMPV with target outside code bounds - (Jumping into data section). + EOF1I4200_0033 (Invalid) EOF code containing RJUMPV with target outside + code bounds (Jumping into data section). """ invalid_destination = 2 jump_table = [0 for _ in range(table_size)] @@ -389,8 +398,8 @@ def test_rjumpv_after_container( invalid_index: int, ): """ - EOF1I4200_0034 (Invalid) EOF code containing RJUMPV with target outside code bounds - (Jumping to after code end). + EOF1I4200_0034 (Invalid) EOF code containing RJUMPV with target outside + code bounds (Jumping to after code end). """ invalid_destination = 2 jump_table = [0 for _ in range(table_size)] @@ -421,8 +430,8 @@ def test_rjumpv_at_end( invalid_index: int, ): """ - EOF1I4200_0035 (Invalid) EOF code containing RJUMPV with target outside code bounds - (Jumping to code end). + EOF1I4200_0035 (Invalid) EOF code containing RJUMPV with target outside + code bounds (Jumping to code end). """ invalid_destination = 1 jump_table = [0 for _ in range(table_size)] @@ -458,7 +467,10 @@ def test_rjumpv_into_self_data_portion( invalid_index: int, data_portion_end: bool, ): - """EOF1I4200_0036 (Invalid) EOF code containing RJUMPV with target same RJUMPV immediate.""" + """ + EOF1I4200_0036 (Invalid) EOF code containing RJUMPV with target same RJUMPV + immediate. + """ invalid_destination = -1 if data_portion_end else -(2 * table_size) - 1 jump_table = [0 for _ in range(table_size)] jump_table[invalid_index] = invalid_destination @@ -490,8 +502,8 @@ def test_rjumpv_into_self( stack_height_spread: int, ): """ - EOF code containing RJUMPV targeting itself. - This can never be valid because this is backward jump and RJUMPV consumes one stack item. + EOF code containing RJUMPV targeting itself. This can never be valid + because this is backward jump and RJUMPV consumes one stack item. """ # Create variadic stack height by the parametrized spread. stack_spread_code = Bytecode() @@ -527,7 +539,10 @@ def test_rjumpv_into_stack_height_diff( table_size: int, invalid_index: int, ): - """EOF code containing RJUMPV with target instruction that causes stack height difference.""" + """ + EOF code containing RJUMPV with target instruction that causes stack height + difference. + """ jump_table = [0 for _ in range(table_size)] jump_table[invalid_index] = -(len(Op.RJUMPV[jump_table]) + len(Op.PUSH1[0]) + len(Op.PUSH1[0])) @@ -556,7 +571,10 @@ def test_rjumpv_into_stack_underflow( table_size: int, invalid_index: int, ): - """EOF code containing RJUMPV with target instruction that cause stack underflow.""" + """ + EOF code containing RJUMPV with target instruction that cause stack + underflow. + """ jump_table = [0 for _ in range(table_size)] jump_table[invalid_index] = 1 eof_test( @@ -580,7 +598,10 @@ def test_rjumpv_skips_stack_underflow( eof_test: EOFTestFiller, table_size: int, ): - """EOF code containing RJUMPV where the default path produces a stack underflow.""" + """ + EOF code containing RJUMPV where the default path produces a stack + underflow. + """ jump_table = [1 for _ in range(table_size)] eof_test( container=Container( @@ -611,7 +632,10 @@ def test_rjumpv_into_rjump( invalid_index: int, data_portion_end: bool, ): - """EOF1I4200_0037 (Invalid) EOF code containing RJUMPV with target RJUMP immediate.""" + """ + EOF1I4200_0037 (Invalid) EOF code containing RJUMPV with target RJUMP + immediate. + """ invalid_destination = 3 if data_portion_end else 2 jump_table = [0 for _ in range(table_size)] jump_table[invalid_index] = invalid_destination @@ -651,7 +675,10 @@ def test_rjumpv_into_rjumpi( invalid_index: int, data_portion_end: bool, ): - """EOF1I4200_0038 (Invalid) EOF code containing RJUMPV with target RJUMPI immediate.""" + """ + EOF1I4200_0038 (Invalid) EOF code containing RJUMPV with target RJUMPI + immediate. + """ invalid_destination = 5 if data_portion_end else 4 jump_table = [0 for _ in range(table_size)] jump_table[invalid_index] = invalid_destination @@ -692,7 +719,10 @@ def test_rjumpv_into_push_1( table_size: int, invalid_index: int, ): - """EOF1I4200_0039 (Invalid) EOF code containing RJUMPV with target PUSH1 immediate.""" + """ + EOF1I4200_0039 (Invalid) EOF code containing RJUMPV with target PUSH1 + immediate. + """ if jump == JumpDirection.FORWARD: invalid_destination = 2 jump_table = [0 for _ in range(table_size)] @@ -777,7 +807,10 @@ def test_rjumpv_into_push_n( invalid_index: int, data_portion_end: bool, ): - """EOF1I4200_0039 (Invalid) EOF code containing RJUMPV with target PUSHN immediate.""" + """ + EOF1I4200_0039 (Invalid) EOF code containing RJUMPV with target PUSHN + immediate. + """ data_portion_length = int.from_bytes(opcode, byteorder="big") - 0x5F if jump == JumpDirection.FORWARD: invalid_destination = data_portion_length + 1 if data_portion_end else 2 @@ -830,7 +863,10 @@ def test_rjumpv_into_rjumpv( invalid_index: int, data_portion_end: bool, ): - """EOF1I4200_0040 (Invalid) EOF code containing RJUMPV with target other RJUMPV immediate.""" + """ + EOF1I4200_0040 (Invalid) EOF code containing RJUMPV with target other + RJUMPV immediate. + """ invalid_destination = 4 + (2 * target_table_size) if data_portion_end else 4 source_jump_table = [0 for _ in range(source_table_size)] source_jump_table[invalid_index] = invalid_destination @@ -871,7 +907,10 @@ def test_rjumpv_into_callf( invalid_index: int, data_portion_end: bool, ): - """EOF1I4200_0041 (Invalid) EOF code containing RJUMPV with target CALLF immediate.""" + """ + EOF1I4200_0041 (Invalid) EOF code containing RJUMPV with target CALLF + immediate. + """ invalid_destination = 2 if data_portion_end else 1 jump_table = [0 for _ in range(table_size)] jump_table[invalid_index] = invalid_destination @@ -1104,7 +1143,8 @@ def test_rjumpv_at_the_end( ): """ https://github.com/ipsilon/eof/blob/main/spec/eof.md#stack-validation 4.i: - This implies that the last instruction may be a terminating instruction or RJUMPV. + This implies that the last instruction may be a terminating instruction or + RJUMPV. """ eof_test( container=Container( @@ -1546,8 +1586,8 @@ def test_rjumpv_valid_forward( container: Container, ): """ - Validate a valid code section containing at least one forward RJUMPV. - These tests exercise the stack height validation. + Validate a valid code section containing at least one forward RJUMPV. These + tests exercise the stack height validation. """ eof_test(container=container) @@ -1849,7 +1889,7 @@ def test_rjumpv_backward_invalid_max_stack_height( container: Container, ): """ - Validate a code section containing at least one backward RJUMPV - invalid because of the incorrect max stack height. + Validate a code section containing at least one backward RJUMPV invalid + because of the incorrect max stack height. """ eof_test(container=container, expect_exception=EOFException.STACK_HEIGHT_MISMATCH) diff --git a/unscheduled/eip7692_eof_v1/eip4750_functions/__init__.py b/unscheduled/eip7692_eof_v1/eip4750_functions/__init__.py index 20c62ac752..3889e56081 100644 --- a/unscheduled/eip7692_eof_v1/eip4750_functions/__init__.py +++ b/unscheduled/eip7692_eof_v1/eip4750_functions/__init__.py @@ -1,5 +1,7 @@ """ -abstract: Test cases for [EIP-4750: EOF - Functions](https://eips.ethereum.org/EIPS/eip-4750) - EIP-4750 formalizes functions in the EVM object format, introducing callable units of code. - Opcodes introduced: `CALLF` (`0xE3`), `RETF` (`0xE4`). -""" # noqa: E501 +Test cases for [EIP-4750: EOF - Functions](https://eips.ethereum.org/EIPS/eip-4750). + +EIP-4750 formalizes functions in the EVM object format, introducing +callable units of code. Opcodes introduced: `CALLF` (`0xE3`), `RETF` +(`0xE4`). +""" diff --git a/unscheduled/eip7692_eof_v1/eip4750_functions/test_callf_execution.py b/unscheduled/eip7692_eof_v1/eip4750_functions/test_callf_execution.py index 30adfa59c2..b0b1d2a0f5 100644 --- a/unscheduled/eip7692_eof_v1/eip4750_functions/test_callf_execution.py +++ b/unscheduled/eip7692_eof_v1/eip4750_functions/test_callf_execution.py @@ -73,7 +73,9 @@ def test_callf_factorial(eof_state_test: EOFStateTestFiller, n, result): ((0, 1), (1, 1), (13, 233), (27, 196418)), ) def test_callf_fibonacci(eof_state_test: EOFStateTestFiller, n, result): - """Test fibonacci sequence implementation with recursive CALLF instructions.""" + """ + Test fibonacci sequence implementation with recursive CALLF instructions. + """ eof_state_test( container=Container( sections=[ @@ -454,11 +456,14 @@ def test_callf_sneaky_stack_overflow( pre: Alloc, ): """ - CALLF where a normal execution would not overflow, but EIP-4750 CALLF rule #3 triggers. + CALLF where a normal execution would not overflow, but EIP-4750 CALLF rule + #3 triggers. Code Section 0 - Mostly fills the stack - Code Section 1 - jumper to 2, so container verification passes (we want a runtime failure) - Code Section 2 - Could require too much stack, but doesn't as it JUMPFs to 3 + Code Section 1 - jumper to 2, so container verification passes (we want a + runtime failure) + Code Section 2 - Could require too much stack, but doesn't as it JUMPFs + to 3 Code Section 3 - Writes canary values The intent is to catch implementations of CALLF that don't enforce rule #3 @@ -552,17 +557,18 @@ def test_callf_max_stack( pre: Alloc, ): """ - CALLF where a normal execution would not overflow, but EIP-4750 CALLF rule #4 triggers. + CALLF where a normal execution would not overflow, but EIP-4750 CALLF rule + #4 triggers. - Code Section 0 - calls #1 with the configured height, but we load some operands so the - return stack does not overflow - Code Section 1 - expands stack, calls #2, THEN recursively calls itself until input is zero, - and returns. + Code Section 0 - calls #1 with the configured height, but we load some + operands so the return stack does not overflow + Code Section 1 - expands stack, calls #2, THEN recursively calls itself + until input is zero, and returns. Code Section 2 - Just returns, zero inputs, zero outputs - This will catch CALLF execution rule #3: always fail if the operand stack is full. Not - checking rule 3 results in a call to section 2 and not overfilling the stack (as it is just - RETF). + This will catch CALLF execution rule #3: always fail if the operand stack + is full. Not checking rule 3 results in a call to section 2 and not + overfilling the stack (as it is just RETF). """ env = Environment() sender = pre.fund_eoa() diff --git a/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py b/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py index c705d19758..e1df510d68 100644 --- a/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py +++ b/unscheduled/eip7692_eof_v1/eip4750_functions/test_code_validation.py @@ -379,7 +379,10 @@ def test_eof_validity( eof_test: EOFTestFiller, container: Container, ): - """Test EOF container validation for features around EIP-4750 / Functions / Code Sections.""" + """ + Test EOF container validation for features around EIP-4750 / Functions / + Code Sections. + """ eof_test(container=container) @@ -475,7 +478,9 @@ def test_invalid_code_section_index( eof_test: EOFTestFiller, container: Container, ): - """Test cases for CALLF instructions with invalid target code section index.""" + """ + Test cases for CALLF instructions with invalid target code section index. + """ eof_test(container=container, expect_exception=EOFException.INVALID_CODE_SECTION_INDEX) @@ -637,8 +642,8 @@ def test_unreachable_code_sections( container: Container, ): """ - Test cases for EOF unreachable code sections - (i.e. code sections not reachable from the code section 0). + Test cases for EOF unreachable code sections (i.e. code sections not + reachable from the code section 0). """ eof_test(container=container, expect_exception=EOFException.UNREACHABLE_CODE_SECTIONS) @@ -646,9 +651,10 @@ def test_unreachable_code_sections( @pytest.mark.parametrize("callee_outputs", [1, 2, MAX_CODE_OUTPUTS]) def test_callf_stack_height_limit_exceeded(eof_test, callee_outputs): """ - Test for invalid EOF code containing CALLF instruction exceeding the stack height limit. - The code reaches the maximum runtime stack height (1024) - which is above the EOF limit for the stack height in the type section (1023). + Test for invalid EOF code containing CALLF instruction exceeding the stack + height limit. The code reaches the maximum runtime stack height (1024) + which is above the EOF limit for the stack height in the type section + (1023). """ callf_stack_height = MAX_RUNTIME_STACK_HEIGHT - callee_outputs container = Container( @@ -669,7 +675,9 @@ def test_callf_stack_height_limit_exceeded(eof_test, callee_outputs): @pytest.mark.parametrize("stack_height", [512, 513, 1023]) def test_callf_stack_overflow(eof_test: EOFTestFiller, stack_height: int): - """Test CALLF instruction recursively calling itself causing stack overflow.""" + """ + Test CALLF instruction recursively calling itself causing stack overflow. + """ container = Container( sections=[ Section.Code(code=Op.CALLF[1] + Op.STOP), @@ -689,7 +697,10 @@ def test_callf_stack_overflow(eof_test: EOFTestFiller, stack_height: int): @pytest.mark.parametrize("stack_height", [1, 2]) def test_callf_stack_overflow_after_callf(eof_test: EOFTestFiller, stack_height: int): - """Test CALLF instruction calling next function causing stack overflow at validation time.""" + """ + Test CALLF instruction calling next function causing stack overflow at + validation time. + """ container = Container( sections=[ Section.Code(code=Op.CALLF[1] + Op.STOP), @@ -823,7 +834,10 @@ def test_callf_stack_overflow_variable_stack_4(eof_test: EOFTestFiller): @pytest.mark.parametrize("stack_height", [2, 3]) def test_callf_validate_outputs(eof_test: EOFTestFiller, stack_height: int): - """Test CALLF instruction when calling a function returning more outputs than expected.""" + """ + Test CALLF instruction when calling a function returning more outputs than + expected. + """ container = Container( sections=[ Section.Code(code=Op.CALLF[1] + Op.STOP, max_stack_height=1), @@ -1074,10 +1088,11 @@ def test_callf_with_inputs_stack_overflow_variable_stack( ) def test_callf_stack_overflow_by_outputs(eof_test, callee_outputs, max_stack_height): """ - Test for invalid EOF code containing CALLF instruction exceeding the runtime stack height limit - by calling a function with at least one output. The computed stack height of the code section 0 - is always above the maximum allowed in the EOF type section. Therefore, the test declares - an invalid max_stack_height. + Test for invalid EOF code containing CALLF instruction exceeding the + runtime stack height limit by calling a function with at least one output. + The computed stack height of the code section 0 is always above the maximum + allowed in the EOF type section. Therefore, the test declares an invalid + max_stack_height. """ callf_stack_height = (MAX_RUNTIME_STACK_HEIGHT + 1) - callee_outputs container = Container( @@ -1102,10 +1117,10 @@ def test_callf_stack_overflow_by_outputs(eof_test, callee_outputs, max_stack_hei ) def test_callf_stack_overflow_by_height(eof_test, callee_stack_height): """ - Test for invalid EOF code containing CALLF instruction exceeding the runtime stack height limit - by calling a function with 2+ maximum stack height. - The callee with the maximum stack height of 1 is valid because runtime limit (1024) - is 1 bigger than the EOF limit (1023). + Test for invalid EOF code containing CALLF instruction exceeding the + runtime stack height limit by calling a function with 2+ maximum stack + height. The callee with the maximum stack height of 1 is valid because + runtime limit (1024) is 1 bigger than the EOF limit (1023). """ container = Container( sections=[ @@ -1234,8 +1249,8 @@ def test_returning_section_aborts( eof_test: EOFTestFiller, ): """ - Test EOF container validation where in the same code section we have returning - and nonreturning terminating instructions. + Test EOF container validation where in the same code section we have + returning and nonreturning terminating instructions. """ container = Container( name="returning_section_aborts", diff --git a/unscheduled/eip7692_eof_v1/eip5450_stack/__init__.py b/unscheduled/eip7692_eof_v1/eip5450_stack/__init__.py index fb5897d4ed..3935e40789 100644 --- a/unscheduled/eip7692_eof_v1/eip5450_stack/__init__.py +++ b/unscheduled/eip7692_eof_v1/eip5450_stack/__init__.py @@ -1,5 +1,8 @@ """ -abstract: Test cases for [EIP-5450: EOF - Stack Validation](https://eips.ethereum.org/EIPS/eip-5450) - EIP-5450 defines stack validation requirements to ensure consistent behavior during execution. - Opcodes introduced: None (specifies validation rules for stack usage). -""" # noqa: E501 +Tests for +[EIP-5450: EOF - Stack Validation](https://eips.ethereum.org/EIPS/eip-5450). + +EIP-5450 defines stack validation requirements to ensure consistent +behavior during execution. Opcodes introduced: None (specifies validation +rules for stack usage). +""" diff --git a/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py b/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py index ed58e09c06..f85edd1f12 100644 --- a/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py +++ b/unscheduled/eip7692_eof_v1/eip5450_stack/test_code_validation.py @@ -1,4 +1,7 @@ -"""Code validation of CALLF, JUMPF, RETF opcodes in conjunction with static relative jumps.""" +""" +Code validation of CALLF, JUMPF, RETF opcodes in conjunction with static +relative jumps. +""" import itertools from enum import Enum, auto, unique @@ -51,7 +54,9 @@ def __str__(self) -> str: @unique class RjumpSpot(Enum): - """Possible spots in the code section layout where the RJUMP* is injected.""" + """ + Possible spots in the code section layout where the RJUMP* is injected. + """ BEGINNING = auto() BEFORE_TERMINATION = auto() @@ -65,14 +70,16 @@ def rjump_code_with( rjump_kind: RjumpKind | None, code_so_far_len: int, next_code: Bytecode ) -> Tuple[Bytecode, bool, bool, bool]: """ - Unless `rjump_kind` is None generates a code snippet with an RJUMP* instruction. - For some kinds `code_so_far_len` must be code length in bytes preceding the snippet. - For some kinds `next_code_len` must be code length in bytes of some code which follows. + Unless `rjump_kind` is None generates a code snippet with an RJUMP* + instruction. For some kinds `code_so_far_len` must be code length in bytes + preceding the snippet. For some kinds `next_code_len` must be code length + in bytes of some code which follows. - It is expected that the snippet and the jump target are valid, but the resulting code - or its stack balance might not. + It is expected that the snippet and the jump target are valid, but the + resulting code or its stack balance might not. - Also returns some traits of the snippet: `is_backwards`, `pops` and `pushes` + Also returns some traits of the snippet: `is_backwards`, `pops` and + `pushes` """ body = Bytecode() @@ -124,8 +131,9 @@ def rjump_code_with( raise TypeError("unknown rjumps value" + str(rjump_kind)) if jumps_over_next: - # This is against intuition, but if the code we're jumping over pushes, the path - # which misses it will be short of stack items, as if the RJUMP* popped and vice versa. + # This is against intuition, but if the code we're jumping over pushes, + # the path which misses it will be short of stack items, as if the + # RJUMP* popped and vice versa. if next_code.pushed_stack_items > next_code.popped_stack_items: pops = True elif next_code.popped_stack_items > next_code.pushed_stack_items: @@ -136,10 +144,11 @@ def rjump_code_with( def call_code_with(inputs, outputs, call: Bytecode) -> Bytecode: """ - Generate code snippet with the `call` bytecode provided and its respective input/output - management. + Generate code snippet with the `call` bytecode provided and its respective + input/output management. - `inputs` and `outputs` are understood as those of the code section we're generating for. + `inputs` and `outputs` are understood as those of the code section we're + generating for. """ body = Bytecode() @@ -168,8 +177,8 @@ def section_code_with( """ Generate code section with RJUMP* and CALLF/RETF instructions. - Also returns some traits of the section: `has_invalid_back_jump`, `rjump_snippet_pops`, - `rjump_snippet_pushes`, `rjump_falls_off_code` + Also returns some traits of the section: `has_invalid_back_jump`, + `rjump_snippet_pops`, `rjump_snippet_pushes`, `rjump_falls_off_code` """ code = Bytecode() code.pushed_stack_items, code.max_stack_height = (inputs, inputs) @@ -214,7 +223,8 @@ def section_code_with( RjumpKind.RJUMPI_OVER_NEXT_NESTED, RjumpKind.RJUMPV_EMPTY_AND_OVER_NEXT, ]: - # Jump over termination or jump over body, but there is nothing after the body. + # Jump over termination or jump over body, but there is nothing + # after the body. rjump_falls_off_code = True code += termination @@ -260,10 +270,12 @@ def test_rjumps_callf_retf( """ Test EOF container validation for EIP-4200 vs EIP-4750 interactions. - Each test's code consists of `num_sections` code sections, which call into one another - and then return. Code may include RJUMP* snippets of `rjump_kind` in various `rjump_spots`. + Each test's code consists of `num_sections` code sections, which call into + one another and then return. Code may include RJUMP* snippets of + `rjump_kind` in various `rjump_spots`. """ - # Zeroth section has always 0 inputs and 0 outputs, so is excluded from param + # Zeroth section has always 0 inputs and 0 outputs, so is excluded from + # param inputs = (0,) + inputs outputs = (0,) + outputs @@ -316,7 +328,8 @@ def test_rjumps_callf_retf( container_has_invalid_back_jump = True if rjump_snippet_pops: container_has_rjump_pops = True - # Pushes to the stack never affect the zeroth section, because it `STOP`s and not `RETF`s. + # Pushes to the stack never affect the zeroth section, because it + # `STOP`s and not `RETF`s. if rjump_snippet_pushes and section_idx != 0: container_has_rjump_pushes = True if rjump_falls_off_code: @@ -371,10 +384,11 @@ def test_rjumps_jumpf_nonreturning( rjump_spot: RjumpSpot, ): """ - Test EOF container validation for EIP-4200 vs EIP-6206 interactions on non-returning - functions. + Test EOF container validation for EIP-4200 vs EIP-6206 interactions on + non-returning functions. """ - # Zeroth section has always 0 inputs and 0 outputs, so is excluded from param + # Zeroth section has always 0 inputs and 0 outputs, so is excluded from + # param inputs = (0,) + inputs sections = [] @@ -394,8 +408,9 @@ def test_rjumps_jumpf_nonreturning( call = None termination = Op.STOP - # `section_has_invalid_back_jump` - never happens: we excluded RJUMP from the end - # `rjump_snippet_pushes` - never happens: we never RETF where too large stack would fail + # `section_has_invalid_back_jump` - never happens: we excluded RJUMP + # from the end `rjump_snippet_pushes` - never happens: we never RETF + # where too large stack would fail ( code, _section_has_invalid_back_jump, @@ -463,8 +478,8 @@ def test_all_opcodes_stack_underflow( eof_test: EOFTestFiller, op: Op, stack_height: int, spread: int ): """ - Test EOF validation failing due to stack overflow - caused by the specific instruction `op`. + Test EOF validation failing due to stack overflow caused by the specific + instruction `op`. """ code = Bytecode() @@ -579,7 +594,9 @@ def test_all_opcodes_stack_underflow( ids=lambda x: x.name, ) def test_stack_underflow_examples(eof_test, container): - """Test EOF validation failing due to stack underflow at basic instructions.""" + """ + Test EOF validation failing due to stack underflow at basic instructions. + """ eof_test(container=container, expect_exception=EOFException.STACK_UNDERFLOW) diff --git a/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py b/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py index d72f12eb14..5c9fa2fa5b 100644 --- a/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py +++ b/unscheduled/eip7692_eof_v1/eip5450_stack/test_execution.py @@ -27,12 +27,13 @@ def test_execution_at_max_stack_height( eof_state_test: EOFStateTestFiller, code_inputs: int, call_op: Op ): """ - Test execution at the maximum runtime operand stack height (1024). - EOF doesn't allow to increase the stack height of a single code section more than 1023. - The effect of the maximum runtime stack height is achieved by using non-zero number - of the code section inputs and increasing the runtime stack to the limit accordingly. - The test pushes consecutive numbers starting from 0 (including inputs). - At the maximum stack height SSTORE is used so it should store 1022 at key 1023. + Test execution at the maximum runtime operand stack height (1024). EOF + doesn't allow to increase the stack height of a single code section more + than 1023. The effect of the maximum runtime stack height is achieved by + using non-zero number of the code section inputs and increasing the runtime + stack to the limit accordingly. The test pushes consecutive numbers + starting from 0 (including inputs). At the maximum stack height SSTORE is + used so it should store 1022 at key 1023. """ max_stack_increase = MAX_RUNTIME_STACK_HEIGHT - code_inputs container = Container( diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/__init__.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/__init__.py index b2391ecb03..dcd27c79cd 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/__init__.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/__init__.py @@ -1,5 +1,7 @@ """ -abstract: Test cases for [EIP-6206: EOF - JUMPF and non-returning functions](https://eips.ethereum.org/EIPS/eip-6206) - EIP-6206 adds a conditional forward jump instruction and support for functions without return values. - Opcodes introduced: `JUMPF` (`0xE5`). -""" # noqa: E501 +Test cases for [EIP-6206: EOF - JUMPF and non-returning functions](https:// +eips.ethereum.org/EIPS/eip-6206). + +EIP-6206 adds a conditional forward jump instruction and support for +functions without return values. Opcodes introduced: `JUMPF` (`0xE5`). +""" diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py index c8c21022b9..b26d7702de 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_execution.py @@ -299,7 +299,10 @@ def test_jumpf_way_too_large( def test_jumpf_to_nonexistent_section( eof_state_test: EOFStateTestFiller, ): - """Tests JUMPF jumping to valid section number but where the section does not exist.""" + """ + Tests JUMPF jumping to valid section number but where the section does not + exist. + """ eof_state_test( container=Container( sections=[ @@ -358,7 +361,9 @@ def test_jumpf_stack_size_1024( def test_jumpf_with_inputs_stack_size_1024( eof_state_test: EOFStateTestFiller, ): - """Test stack reaching 1024 items in target function of JUMPF with inputs.""" + """ + Test stack reaching 1024 items in target function of JUMPF with inputs. + """ eof_state_test( container=Container( sections=[ @@ -381,7 +386,10 @@ def test_jumpf_with_inputs_stack_size_1024( def test_jumpf_stack_size_1024_at_push( eof_state_test: EOFStateTestFiller, ): - """Test stack reaching 1024 items in JUMPF target function at PUSH0 instruction.""" + """ + Test stack reaching 1024 items in JUMPF target function at PUSH0 + instruction. + """ eof_state_test( container=Container( sections=[ @@ -430,13 +438,18 @@ def test_jumpf_stack_overflow( eof_state_test: EOFStateTestFiller, ): """ - Test rule #2 in execution semantics, where we make sure we have enough stack to guarantee - safe execution (the "reserved stack rule") max possible stack will not exceed 1024. But some - executions may not overflow the stack, so we need to ensure the rule is checked. + Test rule #2 in execution semantics, where we make sure we have enough + stack to guarantee safe execution (the "reserved stack rule") max possible + stack will not exceed 1024. But some executions may not overflow the stack, + so we need to ensure the rule is checked. `no_overflow` - the stack does not overflow at JUMPF call, executes to end - `rule_overflow` - reserved stack rule triggers, but execution would not overflow if allowed - `execution_overflow` - execution would overflow (but still blocked by reserved stack rule) + + `rule_overflow` - reserved stack rule triggers, but execution would not + overflow if allowed + + `execution_overflow` - execution would overflow (but still blocked by + reserved stack rule) """ eof_state_test( container=Container( @@ -482,7 +495,10 @@ def test_jumpf_stack_overflow( def test_jumpf_with_inputs_stack_size_1024_at_push( eof_state_test: EOFStateTestFiller, ): - """Test stack reaching 1024 items in JUMPF target function with inputs at PUSH0 instruction.""" + """ + Test stack reaching 1024 items in JUMPF target function with inputs at + PUSH0 instruction. + """ eof_state_test( container=Container( sections=[ @@ -520,7 +536,9 @@ def test_jumpf_with_inputs_stack_size_1024_at_push( def test_jumpf_with_inputs_stack_overflow( eof_state_test: EOFStateTestFiller, ): - """Test stack overflowing 1024 items in JUMPF target function with inputs.""" + """ + Test stack overflowing 1024 items in JUMPF target function with inputs. + """ eof_state_test( container=Container( sections=[ diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py index 0831a8c9c2..f54946a307 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_stack.py @@ -33,8 +33,8 @@ def test_jumpf_stack_non_returning_rules( stack_height: int, ): """ - Tests for JUMPF validation stack rules. Non-returning section cases. - Valid cases are executed. + Tests for JUMPF validation stack rules. Non-returning section cases. Valid + cases are executed. """ container = Container( name="stack-non-retuning_h-%d_ti-%d" % (stack_height, target_inputs), @@ -90,8 +90,8 @@ def test_jumpf_stack_returning_rules( stack_diff: int, ): """ - Tests for JUMPF validation stack rules. Returning section cases. - Valid cases are executed. + Tests for JUMPF validation stack rules. Returning section cases. Valid + cases are executed. """ if target_outputs > source_outputs: # These create invalid containers without JUMPF validation, Don't test. @@ -297,7 +297,10 @@ def test_jumpf_self_variadic_stack_overflow(eof_test: EOFTestFiller): def test_jumpf_variadic_stack_overflow( eof_test: EOFTestFiller, stack_height: int, callee_stack_height: int ): - """Test JUMPF stack validation causing stack overflow with variable stack height.""" + """ + Test JUMPF stack validation causing stack overflow with variable stack + height. + """ container = Container( sections=[ Section.Code( @@ -346,7 +349,10 @@ def test_jumpf_with_inputs_stack_overflow( def test_jumpf_with_inputs_stack_overflow_variable_stack( eof_test: EOFTestFiller, stack_height: int, callee_stack_increase: int ): - """Test JUMPF with variable stack depending on RJUMPI calling function with inputs.""" + """ + Test JUMPF with variable stack depending on RJUMPI calling function with + inputs. + """ container = Container( sections=[ Section.Code( diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py index dcfd397430..886a39e758 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_target.py @@ -32,8 +32,8 @@ def test_jumpf_target_rules( target_outputs: int, ): """ - Validate the target section rules of JUMPF, and execute valid cases. - We are not testing stack so a lot of the logic is to get correct stack values. + Validate the target section rules of JUMPF, and execute valid cases. We are + not testing stack so a lot of the logic is to get correct stack values. """ source_non_returning = source_outputs == NON_RETURNING_SECTION source_height = 0 if source_non_returning else source_outputs @@ -43,10 +43,11 @@ def test_jumpf_target_rules( target_height = 0 if target_non_returning else target_outputs target_section_index = 2 - # Because we are testing the target and not the stack height validation we need to do some work - # to make sure the stack passes validation. + # Because we are testing the target and not the stack height validation we + # need to do some work to make sure the stack passes validation. - # `source_extra_push` is how many more pushes we need to match our stack commitments + # `source_extra_push` is how many more pushes we need to match our stack + # commitments source_extra_push = max(0, source_height - target_height) source_section = Section.Code( code=Op.PUSH0 * (source_height) @@ -60,8 +61,9 @@ def test_jumpf_target_rules( max_stack_height=source_height + max(1, source_extra_push), ) - # `delta` is how many stack items the target output is from the input height, and tracks the - # number of pushes or (if negative) pops the target needs to do to match output commitments + # `delta` is how many stack items the target output is from the input + # height, and tracks the number of pushes or (if negative) pops the target + # needs to do to match output commitments delta = 0 if target_non_returning or source_non_returning else target_outputs - source_height target_section = Section.Code( code=((Op.PUSH0 * delta) if delta >= 0 else (Op.POP * -delta)) @@ -116,7 +118,7 @@ def test_jumpf_multi_target_rules( eof_state_test: EOFStateTestFiller, ): """ - NOT IMPLEMENTED: - Test a section that contains multiple JUMPF to different targets with different outputs. + NOT IMPLEMENTED: Test a section that contains multiple JUMPF to different + targets with different outputs. """ pass diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py index 67a057df89..4fe3100e93 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_jumpf_validation.py @@ -111,7 +111,9 @@ def test_invalid_code_section_index( eof_test: EOFTestFiller, container: Container, ): - """Test cases for JUMPF instructions with invalid target code section index.""" + """ + Test cases for JUMPF instructions with invalid target code section index. + """ eof_test(container=container, expect_exception=EOFException.INVALID_CODE_SECTION_INDEX) @@ -119,8 +121,8 @@ def test_returning_section_aborts_jumpf( eof_test: EOFTestFiller, ): """ - Test EOF container validation where in the same code section we have returning - and nonreturning terminating instructions. + Test EOF container validation where in the same code section we have + returning and nonreturning terminating instructions. """ container = Container( sections=[ @@ -141,7 +143,10 @@ def test_returning_section_aborts_jumpf( @pytest.mark.parametrize("stack_height", [512, 513, 1023]) def test_jumpf_self_stack_overflow(eof_test: EOFTestFiller, stack_height: int): - """Test JUMPF instruction jumping to itself causing validation time stack overflow.""" + """ + Test JUMPF instruction jumping to itself causing validation time stack + overflow. + """ container = Container( sections=[ Section.Code( @@ -162,7 +167,10 @@ def test_jumpf_self_stack_overflow(eof_test: EOFTestFiller, stack_height: int): def test_jumpf_other_stack_overflow( eof_test: EOFTestFiller, stack_height: int, stack_height_other: int ): - """Test JUMPF instruction jumping to other section causing validation time stack overflow.""" + """ + Test JUMPF instruction jumping to other section causing validation time + stack overflow. + """ container = Container( sections=[ Section.Code( @@ -202,7 +210,10 @@ def test_jumpf_to_non_returning(eof_test: EOFTestFiller, stack_height: int, code @pytest.mark.parametrize("code_inputs", [0, 1, 3, 5]) def test_jumpf_to_non_returning_variable_stack(eof_test: EOFTestFiller, code_inputs: int): - """Test JUMPF jumping to a non-returning function with stack depending on RJUMPI.""" + """ + Test JUMPF jumping to a non-returning function with stack depending on + RJUMPI. + """ container = Container( sections=[ Section.Code( @@ -266,7 +277,10 @@ def test_jumpf_to_returning_variable_stack_1( code_outputs: int, stack_increase: int, ): - """Test JUMPF with variable stack jumping to a returning function increasing the stack.""" + """ + Test JUMPF with variable stack jumping to a returning function increasing + the stack. + """ exception = None if code_inputs >= 3 or code_outputs + 1 < 3: # 3 = Section 1's max stack exception = EOFException.STACK_UNDERFLOW @@ -305,7 +319,10 @@ def test_jumpf_to_returning_variable_stack_2( code_outputs: int, stack_decrease: int, ): - """Test JUMPF with variable stack jumping to a returning function decreasing the stack.""" + """ + Test JUMPF with variable stack jumping to a returning function decreasing + the stack. + """ exceptions = [] if code_inputs >= 3 or code_outputs + 1 < 3: # 3 = Section 1's max stack exceptions.append(EOFException.STACK_UNDERFLOW) @@ -336,7 +353,10 @@ def test_jumpf_to_returning_variable_stack_2( def test_jumpf_to_returning_variable_stack_3(eof_test: EOFTestFiller): - """Test JUMPF with variable stack jumping to a returning function increasing the stack.""" + """ + Test JUMPF with variable stack jumping to a returning function increasing + the stack. + """ container = Container( sections=[ Section.Code(code=Op.CALLF[1] + Op.STOP, max_stack_height=2), diff --git a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py index c5bc912994..d40bdb0eb7 100644 --- a/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py +++ b/unscheduled/eip7692_eof_v1/eip6206_jumpf/test_nonreturning_validation.py @@ -31,7 +31,9 @@ [0, 1, 0x7F, 0x81, 0xFF], ) def test_first_section_returning(eof_test: EOFTestFiller, code: Bytecode, outputs: int): - """Test EOF validation failing because the first section is not non-returning.""" + """ + Test EOF validation failing because the first section is not non-returning. + """ eof_test( container=Container( sections=[Section.Code(code, code_outputs=outputs)], @@ -62,7 +64,10 @@ def test_first_section_returning(eof_test: EOFTestFiller, code: Bytecode, output def test_first_section_with_inputs( eof_test: EOFTestFiller, code: Bytecode, inputs: int, outputs: int ): - """Test EOF validation failing because the first section has non-zero number of inputs.""" + """ + Test EOF validation failing because the first section has non-zero number + of inputs. + """ eof_test( container=Container( sections=[ @@ -94,7 +99,10 @@ def test_first_section_with_inputs( ], ) def test_returning_section_not_returning(eof_test: EOFTestFiller, code_section: Section): - """Test EOF validation failing due to returning section with no RETF or JUMPF-to-returning.""" + """ + Test EOF validation failing due to returning section with no RETF or + JUMPF-to-returning. + """ eof_test( container=Container( sections=[ @@ -118,8 +126,8 @@ def test_returning_section_not_returning(eof_test: EOFTestFiller, code_section: ) def test_returning_section_returncode(eof_test: EOFTestFiller, code_section: Section): """ - Test EOF validation failing because a returning section has no RETF or JUMPF-to-returning - - RETURNCODE version. + Test EOF validation failing because a returning section has no RETF or + JUMPF-to-returning - RETURNCODE version. """ eof_test( container=Container( @@ -148,7 +156,10 @@ def test_returning_section_returncode(eof_test: EOFTestFiller, code_section: Sec @first @code_prefix def test_retf_in_nonreturning(eof_test: EOFTestFiller, first: bool, code_prefix: Bytecode): - """Test EOF validation failing due to non-returning section with the RETF instruction.""" + """ + Test EOF validation failing due to non-returning section with the RETF + instruction. + """ sections = [Section.Code(code_prefix + Op.RETF, code_outputs=NON_RETURNING_SECTION)] if not first: # Prefix sections with additional valid JUMPF to invalid section sections = [Section.Code(Op.JUMPF[1])] + sections @@ -162,7 +173,10 @@ def test_retf_in_nonreturning(eof_test: EOFTestFiller, first: bool, code_prefix: @first @code_prefix def test_jumpf_in_nonreturning(eof_test: EOFTestFiller, first: bool, code_prefix: Bytecode): - """Test EOF validation failing due to non-returning section with the JUMPF instruction.""" + """ + Test EOF validation failing due to non-returning section with the JUMPF + instruction. + """ invalid_section = Section.Code( code_prefix + Op.JUMPF[1 if first else 2], code_outputs=NON_RETURNING_SECTION, diff --git a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/__init__.py b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/__init__.py index d75f39a597..01a78b4734 100644 --- a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/__init__.py +++ b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/__init__.py @@ -1,8 +1,10 @@ """ -abstract: Test cases for [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663) - EIP-663 defines new stack manipulation instructions that allow accessing the stack at higher depths. - Opcodes introduced: `DUPN` (`0xE6`), `SWAPN` (`0xE7`), `EXCHANGEN` (`0xE8`). -""" # noqa: E501 +Test cases for EIP-663 SWAPN, DUPN and EXCHANGE instructions + [EIP-663](https://eips.ethereum.org/EIPS/eip-663) defines new stack + manipulation instructions that allow accessing the stack at higher depths. + Opcodes introduced: `DUPN` (`0xE6`), `SWAPN` (`0xE7`), `EXCHANGEN` + (`0xE8`). +""" REFERENCE_SPEC_GIT_PATH = "EIPS/eip-663.md" REFERENCE_SPEC_VERSION = "b658bb87fe039d29e9475d5cfaebca9b92e0fca2" diff --git a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py index 4285d6c8e0..a68cae5681 100644 --- a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py +++ b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_dupn.py @@ -1,7 +1,8 @@ """ -abstract: Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663) - Tests for the DUPN instruction. -""" # noqa: E501 +DUPN instruction tests + Tests for DUPN instruction in + [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663). +""" import pytest diff --git a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py index 74e40d83f1..583c10d89b 100644 --- a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py +++ b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_exchange.py @@ -1,7 +1,6 @@ """ -abstract: Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663) - Tests for the EXCHANGE instruction. -""" # noqa: E501 +Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663). +""" import pytest diff --git a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py index dedbd76771..b0d14af35d 100644 --- a/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py +++ b/unscheduled/eip7692_eof_v1/eip663_dupn_swapn_exchange/test_swapn.py @@ -1,7 +1,4 @@ -""" -abstract: Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663) - Tests for the SWAPN instruction. -""" # noqa: E501 +"""Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663).""" import pytest diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/__init__.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/__init__.py index 63bedd7fd2..672c24a740 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/__init__.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/__init__.py @@ -1,8 +1,11 @@ """ -abstract: Test cases for [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069) - EIP-7069 proposes modifications to `CALL` instructions to align with the structured EOF format. - Opcodes introduced: `EXTCALL` (`0xF8`), `EXTDELEGATECALL` (`0xF9`), `EXTSTATICCALL` (`0xFB`), `RETURNDATALOAD` (`0xF7`). -""" # noqa: E501 +Test cases for EIP-7069 Revamped CALL instructions + [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069) + proposes modifications to `CALL` instructions to align with the + structured EOF format. Opcodes introduced: `EXTCALL` (`0xF8`), + `EXTDELEGATECALL` (`0xF9`), `EXTSTATICCALL` (`0xFB`), `RETURNDATALOAD` + (`0xF7`). +""" REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7069.md" REFERENCE_SPEC_VERSION = "1795943aeacc86131d5ab6bb3d65824b3b1d4cad" diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py index feee36e6b2..a2180dca07 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py @@ -65,7 +65,10 @@ def test_address_space_extension( target_opcode: Op, target_account_type: str, ): - """Test contacts with possibly extended address and fail if address is too large.""" + """ + Test contacts with possibly extended address and fail if address is too + large. + """ env = Environment() ase_address = len(target_address) > 20 @@ -167,11 +170,12 @@ def test_address_space_extension( caller_storage[slot_target_returndata] = stripped_address case Op.CALLCODE | Op.DELEGATECALL: caller_storage[slot_target_call_status] = LEGACY_CALL_SUCCESS - # CALLCODE and DELEGATECALL call will call the stripped address - # but will change the sender to self + # CALLCODE and DELEGATECALL call will call the stripped + # address but will change the sender to self caller_storage[slot_target_returndata] = address_caller case Op.EXTCALL | Op.EXTSTATICCALL: - # EXTCALL and EXTSTATICCALL will fault if calling an ASE address + # EXTCALL and EXTSTATICCALL will fault if calling an ASE + # address if ase_address: caller_storage[slot_target_call_status] = value_exceptional_abort_canary caller_storage[slot_target_returndata] = value_exceptional_abort_canary diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py index 2bc3f36e83..99faf72283 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calldata.py @@ -1,7 +1,8 @@ """ -abstract: Tests [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069) - Tests for the RETURNDATALOAD instruction. -""" # noqa: E501 +Call data tests for EXT*CALL instructions + Tests for call data handling in + [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069). +""" import pytest @@ -61,8 +62,8 @@ def test_extcalls_inputdata( """ Tests call data into EXTCALL including multiple offset conditions. - Caller pushes data into memory, then calls the target. Target writes 64 bytes of call data - to storage and a success byte. + Caller pushes data into memory, then calls the target. Target writes 64 + bytes of call data to storage and a success byte. """ env = Environment() @@ -148,8 +149,8 @@ def test_extdelegatecall_inputdata( """ Tests call data into EXTDELEGATECALL including multiple offset conditions. - Caller pushes data into memory, then calls the target. Target writes 64 bytes of call data - to storage and a success byte. + Caller pushes data into memory, then calls the target. Target writes 64 + bytes of call data to storage and a success byte. """ env = Environment() @@ -232,8 +233,8 @@ def test_extstaticcall_inputdata( """ Tests call data into EXTSTATICCALL including multiple offset conditions. - Caller pushes data into memory, then calls the target. Target writes 64 bytes of call data - to storage and a success byte. + Caller pushes data into memory, then calls the target. Target writes 64 + bytes of call data to storage and a success byte. """ env = Environment() @@ -312,8 +313,8 @@ def test_calldata_remains_after_subcall( """ Tests call data remains after a call to another contract. - Caller pushes data into memory, then calls the target. Target calls 3rd contract. 3rd contract - returns. Target writes calldata to storage. + Caller pushes data into memory, then calls the target. Target calls 3rd + contract. 3rd contract returns. Target writes calldata to storage. """ env = Environment() @@ -494,18 +495,21 @@ def test_extcalls_input_offset( """ Tests call data into EXT*CALL including multiple offset conditions. - Returner returns a success value, which caller stores. If memory expansion cost is less than - 2 billion gas call succeeds. Else whole transaction aborts, leaving canaries in memory. + Returner returns a success value, which caller stores. If memory expansion + cost is less than 2 billion gas call succeeds. Else whole transaction + aborts, leaving canaries in memory. - The name id of `*-mem-cost` refers to the bit-length of the result of the calculated memory - expansion cost. Their length choice is designed to cause problems on shorter bit-length - representations with native integers. + The name id of `*-mem-cost` refers to the bit-length of the result of the + calculated memory expansion cost. Their length choice is designed to cause + problems on shorter bit-length representations with native integers. - The `offset_field` param indicates what part of the input data arguments are being tested, - either the offset of the data in memory or the size of the data in memory. + The `offset_field` param indicates what part of the input data arguments + are being tested, either the offset of the data in memory or the size of + the data in memory. - The `test_arg` param is the value passed into the field being tested (offset or size), - intending to trigger integer size bugs for that particular field. + The `test_arg` param is the value passed into the field being tested + (offset or size), intending to trigger integer size bugs for that + particular field. """ env = Environment(gas_limit=1_000_000_000) diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py index a6e6f0a393..55c2c67ba8 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py @@ -365,8 +365,8 @@ def test_eof_calls_eof_mstore( identity = Address(0x04) -# `blake2f`` is chosen for the test because it fails unless args_size == 213, which is what we are -# interested in. +# `blake2f`` is chosen for the test because it fails unless args_size == 213, +# which is what we are interested in. blake2f = Address(0x09) # `p256verify` / RIP-7212 has been in and out of prague and osaka. # Hence we need to test explicitly @@ -843,7 +843,9 @@ def test_eof_calls_static_flag_with_value( sender: EOA, opcode: Op, ): - """Test EOF contracts calls handle static flag and sending value correctly.""" + """ + Test EOF contracts calls handle static flag and sending value correctly. + """ env = Environment() noop_callee_address = pre.deploy_contract(Container.Code(Op.STOP)) @@ -922,13 +924,16 @@ def test_eof_calls_min_callee_gas( reverts: bool, ): """ - Test EOF contracts calls do light failure when retained/callee gas is not enough. + Test EOF contracts calls do light failure when retained/callee gas is not + enough. - Premise of the test is that there exists a range of `gas_limit` values, which are enough - for all instructions to execute, but call's returned value is 1, meaning not enough for gas - allowances (MIN_RETAINED_GAS and MIN_CALLEE_GAS) - ones marked with `reverts==False`. + Premise of the test is that there exists a range of `gas_limit` values, + which are enough for all instructions to execute, but call's returned value + is 1, meaning not enough for gas allowances (MIN_RETAINED_GAS and + MIN_CALLEE_GAS) - ones marked with `reverts==False`. - Once we provide both allowances, the RJUMPI condition is no longer met and `reverts==True`. + Once we provide both allowances, the RJUMPI condition is no longer met and + `reverts==True`. """ env = Environment() @@ -939,7 +944,8 @@ def test_eof_calls_min_callee_gas( Container.Code( Op.SSTORE(slot_code_worked, value_code_worked) + Op.EQ(opcode(address=noop_callee_address, value=value), EXTCALL_REVERT) - # If the return code isn't 1, it means gas was enough to cover the allowances. + # If the return code isn't 1, it means gas was enough to cover the + # allowances. + Op.RJUMPI[len(revert_block)] + revert_block + Op.STOP @@ -947,7 +953,8 @@ def test_eof_calls_min_callee_gas( balance=value, ) - # `no_oog_gas` is minimum amount of gas_limit which makes the transaction not go oog. + # `no_oog_gas` is minimum amount of gas_limit which makes the transaction + # not go oog. push_operations = 3 + len(opcode.kwargs) # type: ignore no_oog_gas = ( 21_000 @@ -994,7 +1001,10 @@ def test_eof_calls_with_value( balance: int, value: int, ): - """Test EOF contracts calls handle value calls with and without enough balance.""" + """ + Test EOF contracts calls handle value calls with and without enough + balance. + """ env = Environment() noop_callee_address = pre.deploy_contract(Container.Code(Op.STOP)) @@ -1047,24 +1057,30 @@ def test_eof_calls_msg_depth( ): """ Test EOF contracts calls handle msg depth limit correctly (1024). - NOTE: due to block gas limit and the 63/64th rule this limit is unlikely to be hit - on mainnet. + + Note: + due to block gas limit and the 63/64th rule this limit is unlikely + to be hit on mainnet. + """ - # Not a precise gas_limit formula, but enough to exclude risk of gas causing the failure. + # Not a precise gas_limit formula, but enough to exclude risk of gas + # causing the failure. gas_limit = int(200000 * (64 / 63) ** 1024) env = Environment(gas_limit=gas_limit) # Flow of the test: - # `callee_code` is recursively calling itself, passing msg depth as calldata - # (kept with the `MSTORE(0, ADD(...))`). When maximum msg depth is reached - # the call fails and starts returning. The deep-most frame returns: + # `callee_code` is recursively calling itself, passing msg depth as + # calldata (kept with the `MSTORE(0, ADD(...))`). When maximum msg depth is + # reached the call fails and starts returning. The deep-most frame returns: # - current reached msg depth (expected to be the maximum 1024), with the # `MSTORE(32, ADD(...))` - # - the respective return code of the EXT*CALL (expected to be 1 - light failure), with the - # `MSTORE(64, NOOP)`. Note the `NOOP` is just to appease the `Op.MSTORE` call, the return - # code value is actually coming from the `Op.DUP1` - # When unwinding the msg call stack, the intermediate frames return whatever the deeper callee - # returned with the `RETURNDATACOPY` instruction. + # - the respective return code of the EXT*CALL (expected to be 1 - light + # failure), with the `MSTORE(64, NOOP)`. Note the `NOOP` is just to + # appease the `Op.MSTORE` call, the return code value is actually + # coming from the `Op.DUP1` + # When unwinding the msg call stack, the intermediate frames return + # whatever the deeper callee returned with the `RETURNDATACOPY` + # instruction. # Memory offsets layout: # - 0 - input - msg depth @@ -1084,8 +1100,10 @@ def test_eof_calls_msg_depth( # duplicate return code for the `returndatacopy_block` below + Op.DUP1 # if return code was: - # - 1, we're in the deep-most frame, `deep_most_result_block` returns the actual result - # - 0, we're in an intermediate frame, `returndatacopy_block` only passes on the result + # - 1, we're in the deep-most frame, `deep_most_result_block` returns + # the actual result + # - 0, we're in an intermediate frame, `returndatacopy_block` only + # passes on the result + Op.RJUMPI[rjump_offset] + returndatacopy_block + deep_most_result_block @@ -1139,8 +1157,8 @@ def test_extdelegate_call_targets( call_from_initcode: bool, ): """ - Test EOF contracts extdelegatecalling various targets, especially resolved via 7702 - delegation. + Test EOF contracts extdelegatecalling various targets, especially resolved + via 7702 delegation. """ env = Environment() diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py index e7b6ffa923..638adc05c5 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_gas.py @@ -1,7 +1,8 @@ """ -abstract: Tests [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069) - Tests gas consumption. -""" # noqa: E501 +Gas consumption tests for EXT*CALL instructions + Tests for gas consumption in + [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069). +""" import pytest @@ -32,9 +33,9 @@ def state_env() -> Environment: """ Prepare the environment for all state test cases. - Main difference is that the excess blob gas is not increased by the target, as - there is no genesis block -> block 1 transition, and therefore the excess blob gas - is not decreased by the target. + Main difference is that the excess blob gas is not increased by the target, + as there is no genesis block -> block 1 transition, and therefore the + excess blob gas is not decreased by the target. """ return Environment() @@ -124,7 +125,10 @@ def test_ext_calls_gas( new_account: bool, mem_expansion_bytes: int, ): - """Tests variations of EXT*CALL gas, both warm and cold, without and with mem expansions.""" + """ + Tests variations of EXT*CALL gas, both warm and cold, without and with mem + expansions. + """ address_target = ( pre.fund_eoa(0) if new_account else pre.deploy_contract(Container.Code(Op.STOP)) ) @@ -154,11 +158,12 @@ def test_transfer_gas_is_cleared( value: int, ): """ - Test that EXT*CALL call doesn't charge for value transfer, even if the outer call - transferred value. + Test that EXT*CALL call doesn't charge for value transfer, even if the + outer call transferred value. - NOTE: This is particularly possible for EXTDELEGATECALL, which carries over the value sent - in the outer call, however, we extend the test to all 3 EXT*CALL opcodes for good measure. + NOTE: This is particularly possible for EXTDELEGATECALL, which carries over + the value sent in the outer call, however, we extend the test to all 3 + EXT*CALL opcodes for good measure. """ noop_callee_address = pre.deploy_contract(Container.Code(Op.STOP)) @@ -176,8 +181,8 @@ def test_transfer_gas_is_cleared( subject_code=Op.EXTCALL, subject_balance=5 * value, tear_down_code=Op.STOP, - # NOTE: CALL_WITH_VALUE_GAS is charged only once on the outer EXTCALL, while the base - # call gas - twice. + # NOTE: CALL_WITH_VALUE_GAS is charged only once on the outer EXTCALL, + # while the base call gas - twice. cold_gas=2 * COLD_ACCOUNT_ACCESS_GAS + (CALL_WITH_VALUE_GAS if value > 0 else 0) + push_gas, @@ -196,8 +201,8 @@ def test_late_account_create( opcode: Op, ): """ - Test EXTCALL to a non-existent account after another EXT*CALL has called it and not - created it. + Test EXTCALL to a non-existent account after another EXT*CALL has called it + and not created it. """ empty_address = Address(0xDECAFC0DE) diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndatacopy_memory_expansion.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndatacopy_memory_expansion.py index f5b6112c0b..7b99727594 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndatacopy_memory_expansion.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndatacopy_memory_expansion.py @@ -52,7 +52,10 @@ def subcall_exact_cost( dest: int, length: int, ) -> int: - """Return exact cost of the subcall, based on the initial memory and the length of the copy.""" + """ + Return exact cost of the subcall, based on the initial memory and the + length of the copy. + """ cost_memory_bytes = fork.memory_expansion_gas_calculator() returndatacopy_cost = 3 @@ -78,8 +81,9 @@ def bytecode_storage( memory_expansion_address: Address, ) -> Tuple[Bytecode, Storage.StorageDictType]: """ - Prepare bytecode and storage for the test, based on the expected result of the subcall - (whether it succeeds or fails depending on the length of the memory expansion). + Prepare bytecode and storage for the test, based on the expected result of + the subcall (whether it succeeds or fails depending on the length of the + memory expansion). """ bytecode = Bytecode() storage = {} @@ -213,7 +217,10 @@ def test_returndatacopy_memory_expansion( post: Mapping[str, Account], tx: Transaction, ): - """Perform RETURNDATACOPY operations that expand the memory, and verify the gas it costs.""" + """ + Perform RETURNDATACOPY operations that expand the memory, and verify the + gas it costs. + """ state_test( env=env, pre=pre, @@ -266,8 +273,8 @@ def test_returndatacopy_huge_memory_expansion( tx: Transaction, ): """ - Perform RETURNDATACOPY operations that expand the memory by huge amounts, and verify that it - correctly runs out of gas. + Perform RETURNDATACOPY operations that expand the memory by huge amounts, + and verify that it correctly runs out of gas. """ state_test( env=env, diff --git a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py index 53400fd80f..8c75d1af34 100644 --- a/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py +++ b/unscheduled/eip7692_eof_v1/eip7069_extcall/test_returndataload.py @@ -1,7 +1,8 @@ """ -abstract: Tests [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069) - Tests for the RETURNDATALOAD instruction. -""" # noqa: E501 +RETURNDATALOAD instruction tests + Tests for RETURNDATALOAD instruction in + [EIP-7069: Revamped CALL instructions](https://eips.ethereum.org/EIPS/eip-7069). +""" from typing import cast @@ -82,14 +83,16 @@ def test_returndatacopy_handling( size: int, ): """ - Tests ReturnDataLoad including multiple offset conditions and differing legacy vs. eof - boundary conditions. + Tests ReturnDataLoad including multiple offset conditions and differing + legacy vs. eof boundary conditions. entrypoint creates a "0xff" test area of memory, delegate calls to caller. - Caller is either EOF or legacy, as per parameter. Calls returner and copies the return data - based on offset and size params. Cases are expected to trigger boundary violations. + Caller is either EOF or legacy, as per parameter. Calls returner and + copies the return data based on offset and size params. Cases are expected + to trigger boundary violations. - Entrypoint copies the test area to storage slots, and the expected result is asserted. + Entrypoint copies the test area to storage slots, and the expected result + is asserted. """ env = Environment() @@ -215,9 +218,10 @@ def test_returndataload_handling( offset: int, ): """ - Much simpler than returndatacopy, no memory or boosted call. Returner is called - and results are stored in storage slot, which is asserted for expected values. - The parameters offset and return data are configured to test boundary conditions. + Much simpler than returndatacopy, no memory or boosted call. Returner is + called and results are stored in storage slot, which is asserted for + expected values. The parameters offset and return data are configured to + test boundary conditions. """ env = Environment() @@ -283,16 +287,17 @@ def test_returndatacopy_oob( opcode: Op, ): """ - Extends the RETURNDATACOPY test for correct out-of-bounds behavior, by checking if the - caller frame's context being EOF or legacy doesn't impact the execution logic of the - RETURNDATACOPY instance under test. + Extends the RETURNDATACOPY test for correct out-of-bounds behavior, by + checking if the caller frame's context being EOF or legacy doesn't impact + the execution logic of the RETURNDATACOPY instance under test. """ env = Environment() sender = pre.fund_eoa() - # Both callee codes below make an OOB (out-of-bounds) RETURNDATACOPY of one byte, - # which they then attempt to return (Legacy should exceptionally halt on RETURNDATACOPY). + # Both callee codes below make an OOB (out-of-bounds) RETURNDATACOPY of one + # byte, which they then attempt to return (Legacy should exceptionally halt + # on RETURNDATACOPY). address_callee_eof = pre.deploy_contract( code=Container( sections=[ diff --git a/unscheduled/eip7692_eof_v1/eip7480_data_section/__init__.py b/unscheduled/eip7692_eof_v1/eip7480_data_section/__init__.py index 845a31a74a..ee7f967e8f 100644 --- a/unscheduled/eip7692_eof_v1/eip7480_data_section/__init__.py +++ b/unscheduled/eip7692_eof_v1/eip7480_data_section/__init__.py @@ -1,5 +1,9 @@ """ -abstract: Test cases for [EIP-7480: EOF - Data section access instructions](https://eips.ethereum.org/EIPS/eip-7480) - EIP-7480 specifies instructions for accessing data stored in the dedicated data section of the EOF format. - Opcodes introduced: `DATALOAD` (`0xD0`), `DATALOADN` (`0xD1`), `DATASIZE` (`0xD2`), `DATACOPY` (`0xD3`). -""" # noqa: E501 +Test cases for EOF Data section access instructions for EIP-7480. + +EIP-7480 specifies instructions for accessing data stored in the dedicated +data section of the EOF format. Full specification: [EIP-7480: EOF - Data +section access instructions](https://eips.ethereum.org/EIPS/eip-7480). +Opcodes introduced: `DATALOAD` (`0xD0`), `DATALOADN` (`0xD1`), `DATASIZE` +(`0xD2`), `DATACOPY` (`0xD3`). +""" diff --git a/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py b/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py index 234ea530a7..2770011f6c 100644 --- a/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py +++ b/unscheduled/eip7692_eof_v1/eip7480_data_section/test_data_opcodes.py @@ -36,7 +36,10 @@ def test_dataloadn(eof_state_test: EOFStateTestFiller, index: int, suffix_len: i def create_data_test(offset: int, datasize: int): - """Generate data load operators test cases based on load offset and data section size.""" + """ + Generate data load operators test cases based on load offset and data + section size. + """ data = b"".join(i.to_bytes(length=2, byteorder="big") for i in range(1, datasize // 2 + 1)) assert len(data) == datasize overhang = min(32, offset + 32 - datasize) diff --git a/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py b/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py index 4c4e58d7bb..90c2ec6756 100644 --- a/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py +++ b/unscheduled/eip7692_eof_v1/eip7480_data_section/test_datacopy_memory_expansion.py @@ -52,7 +52,10 @@ def subcall_exact_cost( dest: int, length: int, ) -> int: - """Return exact cost of the subcall, based on the initial memory and the length of the copy.""" + """ + Return exact cost of the subcall, based on the initial memory and the + length of the copy. + """ cost_memory_bytes = fork.memory_expansion_gas_calculator() datacopy_cost = 3 @@ -78,8 +81,9 @@ def bytecode_storage( memory_expansion_address: Address, ) -> Tuple[Bytecode, Storage.StorageDictType]: """ - Prepare bytecode and storage for the test, based on the expected result of the subcall - (whether it succeeds or fails depending on the length of the memory expansion). + Prepare bytecode and storage for the test, based on the expected result of + the subcall (whether it succeeds or fails depending on the length of the + memory expansion). """ bytecode = Bytecode() storage = {} @@ -223,7 +227,10 @@ def test_datacopy_memory_expansion( post: Mapping[str, Account], tx: Transaction, ): - """Perform DATACOPY operations that expand the memory, and verify the gas it costs to do so.""" + """ + Perform DATACOPY operations that expand the memory, and verify the gas it + costs to do so. + """ state_test( env=env, pre=pre, @@ -286,8 +293,8 @@ def test_datacopy_huge_memory_expansion( tx: Transaction, ): """ - Perform DATACOPY operations that expand the memory by huge amounts, and verify that it - correctly runs out of gas. + Perform DATACOPY operations that expand the memory by huge amounts, and + verify that it correctly runs out of gas. """ state_test( env=env, diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/__init__.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/__init__.py index 886cfd7db2..4156e92a7a 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/__init__.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/__init__.py @@ -1,19 +1,26 @@ """ -abstract: Test cases for [EIP-7620: EOF Contract Creation](https://eips.ethereum.org/EIPS/eip-7620) - EIP-7620 replaces `CREATE` and `CREATE2` with `EOFCREATE` for deploying contracts in the EOF format. - Opcodes introduced: `EOFCREATE` (`0xEC`), `RETURNCODE` (`0xEE`). +Test cases for EOF Contract Creation for EIP-7620. +EIP-7620 replaces `CREATE` and `CREATE2` with `EOFCREATE` for deploying +contracts in the EOF format. -EOFCREATE, RETURNCODE, and container tests +Full specification: +[EIP-7620: EOF Contract Creation](https://eips.ethereum.org/EIPS/eip-7620). -evmone tests not ported +Opcodes introduced: `EOFCREATE` (`0xEC`), `RETURNCODE` (`0xEE`). -- create_tx_with_eof_initcode - This calls it invalid, it is now the way to add EOF contacts to state -- eofcreate_extcall_returncode - per the new initcode mode tests you cannot have RETURNCODE - in a deployed contract -- eofcreate_dataloadn_referring_to_auxdata - covered by - tests.unscheduled.eip7480_data_section.test_data_opcodes.test_data_section_succeed -- eofcreate_initcontainer_return - RETURN is banned in initcode containers -- eofcreate_initcontainer_stop - STOP is banned in initcode containers +EOFCREATE, RETURNCODE, and container tests. + +evmone tests not ported: +- create_tx_with_eof_initcode: This calls it invalid, it is now the way to + add EOF contacts to state +- eofcreate_extcall_returncode: Per the new initcode + mode tests you cannot have RETURNCODE in a + deployed contract +- eofcreate_dataloadn_referring_to_auxdata: covered by + tests.unscheduled.eip7480_data_section. + test_data_opcodes.test_data_section_succeed +- eofcreate_initcontainer_return: RETURN is banned in initcode containers +- eofcreate_initcontainer_stop: STOP is banned in initcode containers - All TXCREATE tests. -""" # noqa: E501 +""" diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py index 3f4780368a..e8a6846adb 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate.py @@ -76,7 +76,10 @@ def test_eofcreate_then_dataload( state_test: StateTestFiller, pre: Alloc, ): - """Verifies that a contract returned with auxdata does not overwrite the parent data.""" + """ + Verifies that a contract returned with auxdata does not overwrite the + parent data. + """ env = Environment() sender = pre.fund_eoa() small_auxdata_container = Container( @@ -124,7 +127,9 @@ def test_eofcreate_then_call( state_test: StateTestFiller, pre: Alloc, ): - """Verifies a simple EOFCREATE case, and then calls the deployed contract.""" + """ + Verifies a simple EOFCREATE case, and then calls the deployed contract. + """ env = Environment() callable_contract = Container( sections=[ @@ -314,7 +319,9 @@ def test_eofcreate_in_initcode( state_test: StateTestFiller, pre: Alloc, ): - """Verifies an EOFCREATE occurring within initcode creates that contract.""" + """ + Verifies an EOFCREATE occurring within initcode creates that contract. + """ nested_initcode_subcontainer = Container( sections=[ Section.Code( @@ -368,7 +375,10 @@ def test_eofcreate_in_initcode_reverts( state_test: StateTestFiller, pre: Alloc, ): - """Verifies an EOFCREATE occurring in an initcode is rolled back when the initcode reverts.""" + """ + Verifies an EOFCREATE occurring in an initcode is rolled back when the + initcode reverts. + """ nested_initcode_subcontainer = Container( sections=[ Section.Code( @@ -422,7 +432,10 @@ def test_return_data_cleared( state_test: StateTestFiller, pre: Alloc, ): - """Verifies the return data is not reused from a extcall but is cleared upon eofcreate.""" + """ + Verifies the return data is not reused from a extcall but is cleared upon + eofcreate. + """ env = Environment() value_return_canary = 0x4158675309 value_return_canary_size = 5 @@ -518,8 +531,10 @@ def test_address_collision( contract_address: Account( storage={ slot_create_address: salt_zero_address, - slot_create_address_2: EOFCREATE_FAILURE, # had an in-transaction collision - slot_create_address_3: EOFCREATE_FAILURE, # had a pre-existing collision + # had an in-transaction collision + slot_create_address_2: EOFCREATE_FAILURE, + # had a pre-existing collision + slot_create_address_3: EOFCREATE_FAILURE, slot_code_worked: value_code_worked, } ) @@ -540,7 +555,10 @@ def test_eofcreate_revert_eof_returndata( state_test: StateTestFiller, pre: Alloc, ): - """Verifies the return data is not being deployed, even if happens to be valid EOF.""" + """ + Verifies the return data is not being deployed, even if happens to be valid + EOF. + """ env = Environment() code_reverts_with_calldata = Container( name="Initcode Subcontainer reverting with its calldata", @@ -638,7 +656,9 @@ def test_eofcreate_truncated_container( data_len: int, data_section_size: int, ): - """EOFCREATE instruction targeting a container with truncated data section.""" + """ + EOFCREATE instruction targeting a container with truncated data section. + """ assert data_len < data_section_size eof_test( container=Container( @@ -716,7 +736,8 @@ def test_eofcreate_context( elif expected_result == "selfbalance": expected_bytes = eofcreate_value elif expected_result == "factorybalance": - # Factory receives value from sender and passes on eofcreate_value as endowment. + # Factory receives value from sender and passes on eofcreate_value as + # endowment. expected_bytes = value - eofcreate_value else: raise TypeError("Unexpected expected_result", expected_result) @@ -747,7 +768,10 @@ def test_eofcreate_memory_context( state_test: StateTestFiller, pre: Alloc, ): - """Verifies an EOFCREATE frame enjoys a separate EVM memory from its caller frame.""" + """ + Verifies an EOFCREATE frame enjoys a separate EVM memory from its caller + frame. + """ env = Environment() destination_storage = Storage() contract_storage = Storage() diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py index 68f50eec3e..1b3872b5c0 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_eofcreate_failures.py @@ -142,8 +142,8 @@ def test_initcode_aborts( """ -Size of the factory portion of test_eofcreate_deploy_sizes, but as the runtime code is dynamic, we -have to use a pre-calculated size +Size of the factory portion of test_eofcreate_deploy_sizes, but as the runtime +code is dynamic, we have to use a pre-calculated size """ factory_size = 78 @@ -172,7 +172,10 @@ def test_eofcreate_deploy_sizes( pre: Alloc, target_deploy_size: int, ): - """Verifies a mix of runtime contract sizes mixing success and multiple size failure modes.""" + """ + Verifies a mix of runtime contract sizes mixing success and multiple size + failure modes. + """ env = Environment() runtime_container = Container( @@ -215,9 +218,9 @@ def test_eofcreate_deploy_sizes( sender = pre.fund_eoa() contract_address = pre.deploy_contract(code=factory_container) - # Storage in 0 should have the address, - # Storage 1 is a canary of 1 to make sure it tried to execute, which also covers cases of - # data+code being greater than initcode_size_max, which is allowed. + # Storage in 0 should have the address, Storage 1 is a canary of 1 to make + # sure it tried to execute, which also covers cases of data+code being + # greater than initcode_size_max, which is allowed. success = target_deploy_size <= MAX_BYTECODE_SIZE post = { contract_address: Account( @@ -260,8 +263,8 @@ def test_eofcreate_deploy_sizes_tx( target_deploy_size: int, ): """ - Verifies a mix of runtime contract sizes mixing success and multiple size failure modes - where the initcontainer is included in a transaction. + Verifies a mix of runtime contract sizes mixing success and multiple size + failure modes where the initcontainer is included in a transaction. """ raise NotImplementedError("Not implemented") @@ -278,7 +281,9 @@ def test_eofcreate_deploy_sizes_tx( ], ) def test_auxdata_size_failures(state_test: StateTestFiller, pre: Alloc, auxdata_size: int): - """Exercises a number of auxdata size violations, and one maxcode success.""" + """ + Exercises a number of auxdata size violations, and one maxcode success. + """ env = Environment() auxdata_bytes = b"a" * auxdata_size @@ -309,8 +314,11 @@ def test_auxdata_size_failures(state_test: StateTestFiller, pre: Alloc, auxdata_ deployed_container_size = len(smallest_runtime_subcontainer) + auxdata_size - # Storage in 0 will have address in first test, 0 in all other cases indicating failure - # Storage 1 in 1 is a canary to see if EOFCREATE opcode halted + # Storage in 0 will have address in first test, 0 in all other cases + # indicating failure + # + # Storage 1 in 1 is a canary to see if EOFCREATE opcode + # halted success = deployed_container_size <= MAX_BYTECODE_SIZE post = { contract_address: Account( @@ -351,8 +359,8 @@ def test_eofcreate_insufficient_stipend( value: int, ): """ - Exercises an EOFCREATE that fails because the calling account does not have enough ether to - pay the stipend. + Exercises an EOFCREATE that fails because the calling account does not have + enough ether to pay the stipend. """ env = Environment() initcode_container = Container( @@ -370,7 +378,9 @@ def test_eofcreate_insufficient_stipend( code=initcode_container, balance=value - 1, ) - # create will fail but not trigger a halt, so canary at storage 1 should be set + # create will fail but not trigger a halt, so canary at storage 1 should be + # set + # # also validate target created contract fails post = { contract_address: Account( @@ -395,7 +405,10 @@ def test_insufficient_initcode_gas( state_test: StateTestFiller, pre: Alloc, ): - """Exercises an EOFCREATE when there is not enough gas for the initcode charge.""" + """ + Exercises an EOFCREATE when there is not enough gas for the initcode + charge. + """ env = Environment() initcode_data = b"a" * 0x5000 @@ -455,7 +468,10 @@ def test_insufficient_gas_memory_expansion( state_test: StateTestFiller, pre: Alloc, ): - """Exercises EOFCREATE when the memory for auxdata has not been expanded but is requested.""" + """ + Exercises EOFCREATE when the memory for auxdata has not been expanded but + is requested. + """ env = Environment() auxdata_size = 0x5000 @@ -513,7 +529,10 @@ def test_insufficient_returncode_auxdata_gas( state_test: StateTestFiller, pre: Alloc, ): - """Exercises a RETURNCODE when there is not enough gas for the initcode charge.""" + """ + Exercises a RETURNCODE when there is not enough gas for the initcode + charge. + """ env = Environment() auxdata_size = 0x5000 @@ -583,7 +602,8 @@ def test_insufficient_returncode_auxdata_gas( Op.EXTSTATICCALL, ], ) -@pytest.mark.parametrize("endowment", [0, 1]) # included to verify static flag check comes first +@pytest.mark.parametrize("endowment", [0, 1]) # included to verify static flag +# check comes first @pytest.mark.parametrize( "initcode", [smallest_initcode_subcontainer, aborting_container], @@ -664,14 +684,18 @@ def test_eof_eofcreate_msg_depth( ): """ Test EOFCREATE handles msg depth limit correctly (1024). - NOTE: due to block gas limit and the 63/64th rule this limit is unlikely to be hit - on mainnet. - NOTE: See `tests/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py::test_eof_calls_msg_depth` - for more explanations and comments. Most notable deviation from that test is that here - calls and `EOFCREATE`s alternate in order to reach the max depth. `who_fails` decides - whether the failing depth 1024 will be on a call or on an `EOFCREATE` to happen. - """ # noqa: E501 - # Not a precise gas_limit formula, but enough to exclude risk of gas causing the failure. + + NOTE: due to block gas limit and the 63/64th rule this limit is + unlikely to be hit on mainnet. + NOTE: See `tests/unscheduled/eip7692_eof_v1/eip7069_extcall/ + test_calls.py::test_eof_calls_msg_depth` for more explanations and + comments. Most notable deviation from that test is that here calls + and `EOFCREATE`s alternate in order to reach the max depth. + `who_fails` decides whether the failing depth 1024 will be on a call + or on an `EOFCREATE` to happen. + """ + # Not a precise gas_limit formula, but enough to exclude risk of gas + # causing the failure. gas_limit = int(20000000 * (64 / 63) ** 1024) env = Environment(gas_limit=gas_limit) sender = pre.fund_eoa() @@ -730,8 +754,9 @@ def test_eof_eofcreate_msg_depth( ) ) - # Only bumps the msg call depth "register" and forwards to the `calling_contract_address`. - # If it is used it makes the "failing" depth of 1024 to happen on EOFCREATE, instead of CALL. + # Only bumps the msg call depth "register" and forwards to the + # `calling_contract_address`. If it is used it makes the "failing" depth of + # 1024 to happen on EOFCREATE, instead of CALL. passthrough_address = pre.deploy_contract( Container.Code( Op.MSTORE(0, 1) + Op.EXTCALL(address=calling_contract_address, args_size=32) + Op.STOP @@ -768,12 +793,15 @@ def test_reentrant_eofcreate( state_test: StateTestFiller, pre: Alloc, ): - """Verifies a reentrant EOFCREATE case, where EIP-161 prevents conflict via nonce bump.""" + """ + Verifies a reentrant EOFCREATE case, where EIP-161 prevents conflict via + nonce bump. + """ env = Environment() # Calls into the factory contract with 1 as input. reenter_code = Op.MSTORE(0, 1) + Op.EXTCALL(address=Op.CALLDATALOAD(32), args_size=32) - # Initcode: if given 0 as 1st word of input will call into the factory again. - # 2nd word of input is the address of the factory. + # Initcode: if given 0 as 1st word of input will call into the factory + # again. 2nd word of input is the address of the factory. initcontainer = Container( sections=[ Section.Code( @@ -786,15 +814,19 @@ def test_reentrant_eofcreate( Section.Container(smallest_runtime_subcontainer), ] ) - # Factory: Passes on its input into the initcode. It's 0 first time, 1 the second time. - # Saves the result of deployment in slot 0 first time, 1 the second time. + # Factory: + # Passes on its input into the initcode. + # It's 0 first time, 1 the second time. + # Saves the result of deployment in slot 0 first time, 1 the + # second time. contract_address = pre.deploy_contract( code=Container( sections=[ Section.Code( Op.CALLDATACOPY(0, 0, 32) + Op.MSTORE(32, Op.ADDRESS) - # 1st word - copied from input (reenter flag), 2nd word - `this.address`. + # 1st word - copied from input (reenter flag) + # 2nd word - `this.address` + Op.SSTORE(Op.CALLDATALOAD(0), Op.EOFCREATE[0](input_size=64)) + Op.STOP, ), @@ -803,13 +835,18 @@ def test_reentrant_eofcreate( ), storage={0: 0xB17D, 1: 0xB17D}, # a canary to be overwritten ) - # Flow is: reenter flag 0 -> factory -> reenter flag 0 -> initcode -> reenter -> - # reenter flag 1 -> factory -> reenter flag 1 -> (!) initcode -> stop, - # if the EIP-161 nonce bump is not implemented. If it is, it fails before second - # inicode marked (!). + # Flow is: + # reenter flag 0 -> factory -> reenter flag 0 -> initcode -> + # reenter -> reenter flag 1 -> factory -> reenter flag 1 -> (!) initcode + # -> stop + # if the EIP-161 nonce bump is not implemented. + # + # If it is, it fails before second inicode marked (!). + # # Storage in 0 should have the address from the outer EOFCREATE. - # Storage in 1 should have 0 from the inner EOFCREATE. - # For the created contract storage in `slot_counter` should be 1 as initcode executes only once + # Storage in 1 should have 0 from the inner EOFCREATE. For the created + # contract storage in `slot_counter` should be 1 as initcode + # executes only once. post = { contract_address: Account( storage={ diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py index f7cb2519a1..c3019da962 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_gas.py @@ -130,8 +130,9 @@ def test_eofcreate_gas( for a in salt_addresses: pre.fund_address(a, 1) - # Using `TLOAD` / `TSTORE` to work around warm/cold gas differences. We need a counter to pick - # a distinct salt on each `EOFCREATE` and avoid running into address conflicts. + # Using `TLOAD` / `TSTORE` to work around warm/cold gas differences. We + # need a counter to pick a distinct salt on each `EOFCREATE` and avoid + # running into address conflicts. code_increment_counter = ( Op.TLOAD(slot_counter) + Op.DUP1 + Op.TSTORE(slot_counter, Op.PUSH1(1) + Op.ADD) ) diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py index 390b1ce089..d6ab9c2a09 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_legacy_eof_creates.py @@ -56,7 +56,10 @@ def test_cross_version_creates_fail_light( legacy_create_opcode: Opcodes, initcode: Bytes | Container, ): - """Verifies that CREATE and CREATE2 cannot run EOF initcodes and fail early on attempt.""" + """ + Verifies that CREATE and CREATE2 cannot run EOF initcodes and fail early on + attempt. + """ env = Environment() sender = pre.fund_eoa() @@ -66,7 +69,8 @@ def test_cross_version_creates_fail_light( contract_address = pre.deploy_contract( code=Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + Op.SSTORE(slot_create_address, legacy_create_opcode(size=Op.CALLDATASIZE)) - # Approximates whether code until here consumed the 63/64th gas given to subcall + # Approximates whether code until here consumed the 63/64th gas given + # to subcall + Op.SSTORE(slot_all_subcall_gas_gone, Op.LT(Op.GAS, tx_gas_limit // 64)) + Op.SSTORE(slot_code_worked, value_code_worked) + Op.STOP @@ -126,8 +130,8 @@ def test_cross_version_creates_fail_hard( initcode: Bytes, ): """ - Verifies that CREATE and CREATE2 fail hard on attempt to run initcode starting with `EF` but - not `EF00`. + Verifies that CREATE and CREATE2 fail hard on attempt to run initcode + starting with `EF` but not `EF00`. """ env = Environment() @@ -138,7 +142,8 @@ def test_cross_version_creates_fail_hard( contract_address = pre.deploy_contract( code=Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + Op.SSTORE(slot_create_address, legacy_create_opcode(size=Op.CALLDATASIZE)) - # Approximates whether code until here consumed the 63/64th gas given to subcall + # Approximates whether code until here consumed the 63/64th gas given + # to subcall + Op.SSTORE(slot_all_subcall_gas_gone, Op.LT(Op.GAS, tx_gas_limit // 64)) + Op.SSTORE(slot_code_worked, value_code_worked) + Op.STOP diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py index 67748507e6..15eed022ae 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_memory.py @@ -62,18 +62,20 @@ def test_eofcreate_memory( """ Tests auxdata sizes in EOFCREATE including multiple offset conditions. - EOFCREATE either succeeds or fails based on memory access cost, resulting in new address - or zero in the create address slot. + EOFCREATE either succeeds or fails based on memory access cost, resulting + in new address or zero in the create address slot. - The name id of `*-mem-cost` refers to the bit-length of the result of the calculated memory - expansion cost. Their length choice is designed to cause problems on shorter bit-length - representations with native integers. + The name id of `*-mem-cost` refers to the bit-length of the result of the + calculated memory expansion cost. Their length choice is designed to cause + problems on shorter bit-length representations with native integers. - The `offset_field` param indicates what part of the input data arguments are being tested, - either the offset of the data in memory or the size of the data in memory. + The `offset_field` param indicates what part of the input data arguments + are being tested, either the offset of the data in memory or the size of + the data in memory. - The `test_arg` param is the value passed into the field being tested (offset or size), - intending to trigger integer size bugs for that particular field. + The `test_arg` param is the value passed into the field being tested + (offset or size), intending to trigger integer size bugs for that + particular field. """ env = Environment(gas_limit=2_000_000_000) diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py index 3b50714dec..e945768371 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_returncode.py @@ -203,18 +203,21 @@ def test_returncode_memory_expansion( success: bool, ): """ - Attempts an EOFCREATE with a possibly too-large auxdata. Create either fails due to gas - or contract too large, resulting in address or zero on failure in the create address slot. + Attempts an EOFCREATE with a possibly too-large auxdata. Create either + fails due to gas or contract too large, resulting in address or zero on + failure in the create address slot. - The name id of `*-mem-cost` refers to the bit-length of the result of the calculated memory - expansion cost. Their length choice is designed to cause problems on shorter bit-length - representations with native integers. + The name id of `*-mem-cost` refers to the bit-length of the result of the + calculated memory expansion cost. Their length choice is designed to cause + problems on shorter bit-length representations with native integers. - The `offset_field` param indicates what part of the input data arguments are being tested, - either the offset of the data in memory or the size of the data in memory. + The `offset_field` param indicates what part of the input data arguments + are being tested, either the offset of the data in memory or the size of + the data in memory. - The `test_arg` param is the value passed into the field being tested (offset or size), - intending to trigger integer size bugs for that particular field. + The `test_arg` param is the value passed into the field being tested + (offset or size), intending to trigger integer size bugs for that + particular field. """ env = Environment(gas_limit=2_000_000_000) sender = pre.fund_eoa(10**27) diff --git a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py index 045e3dbbd3..8c796feb75 100644 --- a/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py +++ b/unscheduled/eip7692_eof_v1/eip7620_eof_create/test_subcontainer_validation.py @@ -264,7 +264,10 @@ def test_container_combos_deeply_nested_valid( code_section: Section, first_sub_container: Container, ): - """Test valid subcontainer reference / opcode combos on a deep container nesting level.""" + """ + Test valid subcontainer reference / opcode combos on a deep container + nesting level. + """ valid_container = Container( sections=[ code_section, @@ -314,7 +317,10 @@ def test_container_combos_deeply_nested_invalid( code_section: Section, first_sub_container: Container, ): - """Test invalid subcontainer reference / opcode combos on a deep container nesting level.""" + """ + Test invalid subcontainer reference / opcode combos on a deep container + nesting level. + """ invalid_container = Container( sections=[ code_section, @@ -380,7 +386,10 @@ def test_container_combos_non_first_code_sections_valid( first_sub_container: Container, container_kind: ContainerKind, ): - """Test valid subcontainer reference / opcode combos in a non-first code section.""" + """ + Test valid subcontainer reference / opcode combos in a non-first code + section. + """ eof_test( container=Container( sections=[Section.Code(Op.JUMPF[i]) for i in range(1, 1024)] @@ -419,7 +428,10 @@ def test_container_combos_non_first_code_sections_invalid( first_sub_container: Container, container_kind: ContainerKind, ): - """Test invalid subcontainer reference / opcode combos in a non-first code section.""" + """ + Test invalid subcontainer reference / opcode combos in a non-first code + section. + """ eof_test( container=Container( sections=[Section.Code(Op.JUMPF[i]) for i in range(1, 1024)] @@ -431,7 +443,9 @@ def test_container_combos_non_first_code_sections_invalid( def test_container_both_kinds_same_sub(eof_test: EOFTestFiller): - """Test subcontainer conflicts (both EOFCREATE and RETURNCODE Reference).""" + """ + Test subcontainer conflicts (both EOFCREATE and RETURNCODE Reference). + """ eof_test( container=Container( sections=[ @@ -460,8 +474,8 @@ def test_container_ambiguous_kind( eof_test: EOFTestFiller, container_idx: int, sub_container: Section ): """ - Test ambiguous container kind: - a single subcontainer reference by both EOFCREATE and RETURNCODE. + Test ambiguous container kind: a single subcontainer reference by both + EOFCREATE and RETURNCODE. """ sections = [ Section.Code( @@ -504,7 +518,10 @@ def test_container_both_kinds_different_sub(eof_test: EOFTestFiller): def test_container_multiple_eofcreate_references(eof_test: EOFTestFiller): - """Test multiple references to the same subcontainer from an EOFCREATE operation.""" + """ + Test multiple references to the same subcontainer from an EOFCREATE + operation. + """ eof_test( container=Container( sections=[ @@ -518,7 +535,10 @@ def test_container_multiple_eofcreate_references(eof_test: EOFTestFiller): def test_container_multiple_returncode_references(eof_test: EOFTestFiller): - """Test multiple references to the same subcontainer from a RETURNCONTACT operation.""" + """ + Test multiple references to the same subcontainer from a RETURNCONTACT + operation. + """ eof_test( container=Container( sections=[ @@ -611,7 +631,8 @@ def test_deep_container( """ Test a very deeply nested container. - This test skips generating a state test because the initcode size is too large. + This test skips generating a state test because the initcode size is too + large. """ container = deepest_container last_container = deepest_container @@ -785,7 +806,8 @@ def test_wide_container(eof_test: EOFTestFiller, width: int, exception: EOFExcep ef0001010004020001000603000100000014ff000200008000016000e0000000ef000101000402000100 01ff00000000800000fe""", # Originally this test was "valid" but against the current spec - # it contains two errors: data section truncated and orphan subcontainer. + # it contains two errors: data section truncated and orphan + # subcontainer. validity_error=EOFException.TOPLEVEL_CONTAINER_TRUNCATED, ), id="orphan_subcontainer_0_and_truncated_data", @@ -812,7 +834,8 @@ def test_wide_container(eof_test: EOFTestFiller, width: int, exception: EOFExcep Section.Code(Op.EOFCREATE[0](0, 0, 0, 0) + Op.STOP), Section.Container("aabbccddeeff"), ], - # The original test has been modified to reference the subcontainer by EOFCREATE. + # The original test has been modified to reference the + # subcontainer by EOFCREATE. validity_error=EOFException.INVALID_MAGIC, ), id="subcontainer_0_with_invalid_prefix", @@ -896,7 +919,10 @@ def test_migrated_eofcreate(eof_test: EOFTestFiller, container: Container): def test_dangling_initcode_subcontainer_bytes( eof_test: EOFTestFiller, ): - """Initcode mode EOF Subcontainer test with subcontainer containing dangling bytes.""" + """ + Initcode mode EOF Subcontainer test with subcontainer containing dangling + bytes. + """ eof_test( container=Container( sections=[ @@ -916,7 +942,10 @@ def test_dangling_initcode_subcontainer_bytes( def test_dangling_runtime_subcontainer_bytes( eof_test: EOFTestFiller, ): - """Runtime mode EOF Subcontainer test with subcontainer containing dangling bytes.""" + """ + Runtime mode EOF Subcontainer test with subcontainer containing dangling + bytes. + """ eof_test( container=Container( sections=[ diff --git a/unscheduled/eip7692_eof_v1/eip7873_tx_create/__init__.py b/unscheduled/eip7692_eof_v1/eip7873_tx_create/__init__.py index b893e42d5a..ddd4426793 100644 --- a/unscheduled/eip7692_eof_v1/eip7873_tx_create/__init__.py +++ b/unscheduled/eip7692_eof_v1/eip7873_tx_create/__init__.py @@ -1,4 +1,3 @@ """ -abstract: Test cases for -[EIP-7873: TXCREATE and InitcodeTransaction](https://eips.ethereum.org/EIPS/eip-7873). -""" # noqa: E501 +Test cases for [EIP-7873: TXCREATE and InitcodeTransaction](https://eips.ethereum.org/EIPS/eip-7873). +""" diff --git a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py index 7d21916f29..842fd90e8e 100644 --- a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py +++ b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_creation_tx.py @@ -99,9 +99,9 @@ def test_legacy_create_tx_prefix_initcode( initcode: Bytes, ): """ - Test that a legacy contract creation tx behaves as it did before EIP-7873 for - initcode stating with `EF`. - The transaction should be valid but fail on executing of the first byte `EF`. + Test that a legacy contract creation tx behaves as it did before EIP-7873 + for initcode stating with `EF`. The transaction should be valid but fail on + executing of the first byte `EF`. """ env = Environment() sender = pre.fund_eoa() diff --git a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py index 4d3b571f23..049cca1406 100644 --- a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py +++ b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate.py @@ -67,7 +67,10 @@ def test_txcreate_then_dataload( state_test: StateTestFiller, pre: Alloc, ): - """Verifies that a contract returned with auxdata does not overwrite the parent data.""" + """ + Verifies that a contract returned with auxdata does not overwrite the + parent data. + """ env = Environment() sender = pre.fund_eoa() small_auxdata_container = Container( @@ -110,7 +113,9 @@ def test_txcreate_then_dataload( @pytest.mark.with_all_evm_code_types def test_txcreate_then_call(state_test: StateTestFiller, pre: Alloc, evm_code_type: EVMCodeType): - """Verifies a simple TXCREATE case, and then calls the deployed contract.""" + """ + Verifies a simple TXCREATE case, and then calls the deployed contract. + """ env = Environment() callable_contract = Container( sections=[ @@ -294,8 +299,8 @@ def test_txcreate_in_initcode( """ Verifies an TXCREATE occurring within initcode creates that contract. - Via the `outer_create_reverts` also verifies a TXCREATE occurring in an initcode is rolled back - when the initcode reverts. + Via the `outer_create_reverts` also verifies a TXCREATE occurring in an + initcode is rolled back when the initcode reverts. """ smallest_initcode_subcontainer_hash = smallest_initcode_subcontainer.hash inner_create_bytecode = ( @@ -303,8 +308,8 @@ def test_txcreate_in_initcode( if inner_create_opcode == Op.TXCREATE else Op.EOFCREATE[1](0, 0, 0, 0) ) - # The terminating code of the inner initcontainer, the RJUMPI is a trick to not need to deal - # with the subcontainer indices + # The terminating code of the inner initcontainer, the RJUMPI is a trick to + # not need to deal with the subcontainer indices revert_code = Op.REVERT(0, 0) terminating_code = ( Op.RJUMPI[len(revert_code)](0) + revert_code + Op.RETURNCODE[0](0, 0) @@ -385,7 +390,10 @@ def test_return_data_cleared( pre: Alloc, evm_code_type: EVMCodeType, ): - """Verifies the return data is not reused from a extcall but is cleared upon TXCREATE.""" + """ + Verifies the return data is not reused from a extcall but is cleared upon + TXCREATE. + """ env = Environment() value_return_canary = 0x4158675309 value_return_canary_size = 5 @@ -472,8 +480,10 @@ def test_address_collision( contract_address: Account( storage={ slot_create_address: salt_zero_address, - slot_create_address_2: TXCREATE_FAILURE, # had an in-transaction collision - slot_create_address_3: TXCREATE_FAILURE, # had a pre-existing collision + # had an in-transaction collision + slot_create_address_2: TXCREATE_FAILURE, + # had a pre-existing collision + slot_create_address_3: TXCREATE_FAILURE, slot_code_worked: value_code_worked, } ) @@ -494,7 +504,10 @@ def test_txcreate_revert_eof_returndata( state_test: StateTestFiller, pre: Alloc, ): - """Verifies the return data is not being deployed, even if happens to be valid EOF.""" + """ + Verifies the return data is not being deployed, even if happens to be valid + EOF. + """ env = Environment() code_reverts_with_calldata = Container( name="Initcode Subcontainer reverting with its calldata", @@ -602,7 +615,8 @@ def test_txcreate_context( elif expected_result == "selfbalance": expected_bytes = txcreate_value elif expected_result == "factorybalance": - # Factory receives value from sender and passes on eofcreate_value as endowment. + # Factory receives value from sender and passes on eofcreate_value as + # endowment. expected_bytes = value - txcreate_value else: raise TypeError("Unexpected expected_result", expected_result) @@ -634,7 +648,10 @@ def test_txcreate_memory_context( state_test: StateTestFiller, pre: Alloc, ): - """Verifies an TXCREATE frame enjoys a separate EVM memory from its caller frame.""" + """ + Verifies an TXCREATE frame enjoys a separate EVM memory from its caller + frame. + """ env = Environment() destination_storage = Storage() contract_storage = Storage() @@ -680,7 +697,10 @@ def test_short_data_subcontainer( state_test: StateTestFiller, pre: Alloc, ): - """Deploy a subcontainer where the data is "short" and filled by deployment code.""" + """ + Deploy a subcontainer where the data is "short" and filled by deployment + code. + """ env = Environment() sender = pre.fund_eoa() diff --git a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py index d44588aaed..2fd8170545 100644 --- a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py +++ b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_failures.py @@ -177,8 +177,8 @@ def test_initcode_aborts( """ -Size of the initcode portion of test_txcreate_deploy_sizes, but as the runtime code is dynamic, we -have to use a pre-calculated size +Size of the initcode portion of test_txcreate_deploy_sizes, but as the runtime +code is dynamic, we have to use a pre-calculated size """ initcode_size = 32 @@ -199,7 +199,11 @@ def test_txcreate_deploy_sizes( pre: Alloc, target_deploy_size: int, ): - """Verifies a mix of runtime contract sizes mixing success and multiple size failure modes.""" + """ + Verify a mix of runtime contract sizes. + + This mixes success and multiple size failure modes. + """ env = Environment() runtime_container = Container( @@ -237,9 +241,9 @@ def test_txcreate_deploy_sizes( + Op.SSTORE(slot_code_worked, value_code_worked) + Op.STOP ) - # Storage in 0 should have the address, - # Storage 1 is a canary of 1 to make sure it tried to execute, which also covers cases of - # data+code being greater than initcode_size_max, which is allowed. + # Storage in 0 should have the address, Storage 1 is a canary of 1 to make + # sure it tried to execute, which also covers cases of data+code being + # greater than initcode_size_max, which is allowed. success = target_deploy_size <= MAX_BYTECODE_SIZE post = { contract_address: Account( @@ -277,7 +281,9 @@ def test_txcreate_deploy_sizes( ], ) def test_auxdata_size_failures(state_test: StateTestFiller, pre: Alloc, auxdata_size: int): - """Exercises a number of auxdata size violations, and one maxcode success.""" + """ + Exercises a number of auxdata size violations, and one maxcode success. + """ env = Environment() auxdata_bytes = b"a" * auxdata_size @@ -305,7 +311,9 @@ def test_auxdata_size_failures(state_test: StateTestFiller, pre: Alloc, auxdata_ deployed_container_size = len(smallest_runtime_subcontainer) + auxdata_size - # Storage in 0 will have address in first test, 0 in all other cases indicating failure + # Storage in 0 will have address in first test, 0 in all other cases + # indicating failure + # # Storage 1 in 1 is a canary to see if TXCREATE opcode halted success = deployed_container_size <= MAX_BYTECODE_SIZE post = { @@ -347,8 +355,8 @@ def test_txcreate_insufficient_stipend( value: int, ): """ - Exercises an TXCREATE that fails because the calling account does not have enough ether to - pay the stipend. + Exercises an TXCREATE that fails because the calling account does not have + enough ether to pay the stipend. """ env = Environment() sender = pre.fund_eoa(10**11) @@ -362,7 +370,9 @@ def test_txcreate_insufficient_stipend( + Op.STOP, balance=value - 1, ) - # create will fail but not trigger a halt, so canary at storage 1 should be set + # create will fail but not trigger a halt, so canary at storage 1 + # should be set + # # also validate target created contract fails post = { contract_address: Account( @@ -384,7 +394,9 @@ def test_txcreate_insufficient_stipend( @pytest.mark.with_all_evm_code_types def test_insufficient_initcode_gas(state_test: StateTestFiller, pre: Alloc, fork: Fork): - """Exercises an TXCREATE when there is not enough gas for the constant charge.""" + """ + Exercises an TXCREATE when there is not enough gas for the constant charge. + """ env = Environment() initcode_container = Container( @@ -440,7 +452,10 @@ def test_insufficient_gas_memory_expansion( pre: Alloc, fork: Fork, ): - """Exercises TXCREATE when the memory for auxdata has not been expanded but is requested.""" + """ + Exercises TXCREATE when the memory for auxdata has not been expanded but is + requested. + """ env = Environment() auxdata_size = 0x5000 @@ -493,7 +508,10 @@ def test_insufficient_returncode_auxdata_gas( pre: Alloc, fork: Fork, ): - """Exercises a RETURNCODE when there is not enough gas for the initcode charge.""" + """ + Exercises a RETURNCODE when there is not enough gas for the initcode + charge. + """ env = Environment() auxdata_size = 0x5000 @@ -517,8 +535,8 @@ def test_insufficient_returncode_auxdata_gas( slot_code_worked: value_canary_to_be_overwritten, }, ) - # 63/64ths is not enough to cover RETURNCODE memory expansion. Unfortunately the 1/64th left - # won't realistically accommodate a SSTORE + # 63/64ths is not enough to cover RETURNCODE memory expansion. + # Unfortunately the 1/64th left won't realistically accommodate a SSTORE auxdata_size_words = (auxdata_size + 31) // 32 gas_limit = ( 32_000 @@ -555,7 +573,8 @@ def test_insufficient_returncode_auxdata_gas( Op.EXTSTATICCALL, ], ) -@pytest.mark.parametrize("endowment", [0, 1]) # included to verify static flag check comes first +@pytest.mark.parametrize("endowment", [0, 1]) # included to verify static flag +# check comes first @pytest.mark.parametrize( "initcode", [smallest_initcode_subcontainer, aborting_container], @@ -582,7 +601,8 @@ def test_static_flag_txcreate( ) calling_address = pre.deploy_contract( calling_code, - # Need to override the global value from the `with_all_evm_code_types` marker. + # Need to override the global value from the `with_all_evm_code_types` + # marker. evm_code_type=EVMCodeType.EOF_V1 if opcode == Op.EXTSTATICCALL else EVMCodeType.LEGACY, ) @@ -626,14 +646,17 @@ def test_eof_txcreate_msg_depth( ): """ Test TXCREATE handles msg depth limit correctly (1024). - NOTE: due to block gas limit and the 63/64th rule this limit is unlikely to be hit - on mainnet. - NOTE: See `tests/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py::test_eof_calls_msg_depth` - for more explanations and comments. Most notable deviation from that test is that here - calls and `TXCREATE`s alternate in order to reach the max depth. `who_fails` decides - whether the failing depth 1024 will be on a call or on an `TXCREATE` to happen. - """ # noqa: E501 - # Not a precise gas_limit formula, but enough to exclude risk of gas causing the failure. + NOTE: due to block gas limit and the 63/64th rule this limit is + unlikely to be hit on mainnet. + NOTE: See + `tests/unscheduled/eip7692_eof_v1/eip7069_extcall/test_calls.py:: + test_eof_calls_msg_depth` for more explanations and comments. + Most notable deviation from that test is that here calls and `TXCREATE`s + alternate in order to reach the max depth. `who_fails` decides whether + the failing depth 1024 will be on a call or on an `TXCREATE` to happen. + """ + # Not a precise gas_limit formula, but enough to exclude risk of gas + # causing the failure. gas_limit = int(20000000 * (64 / 63) ** 1024) env = Environment(gas_limit=gas_limit) @@ -694,8 +717,9 @@ def test_eof_txcreate_msg_depth( ) ) - # Only bumps the msg call depth "register" and forwards to the `calling_contract_address`. - # If it is used it makes the "failing" depth of 1024 to happen on TXCREATE, instead of CALL. + # Only bumps the msg call depth "register" and forwards to the + # `calling_contract_address`. If it is used it makes the "failing" depth of + # 1024 to happen on TXCREATE, instead of CALL. passthrough_address = pre.deploy_contract( Container.Code( Op.MSTORE(0, 1) + Op.EXTCALL(address=calling_contract_address, args_size=32) + Op.STOP @@ -734,12 +758,15 @@ def test_reentrant_txcreate( state_test: StateTestFiller, pre: Alloc, ): - """Verifies a reentrant TXCREATE case, where EIP-161 prevents conflict via nonce bump.""" + """ + Verifies a reentrant TXCREATE case, where EIP-161 prevents conflict via + nonce bump. + """ env = Environment() # Calls into the factory contract with 1 as input. reenter_code = Op.MSTORE(0, 1) + Op.EXTCALL(address=Op.CALLDATALOAD(32), args_size=32) - # Initcode: if given 0 as 1st word of input will call into the factory again. - # 2nd word of input is the address of the factory. + # Initcode: if given 0 as 1st word of input will call into the factory + # again. 2nd word of input is the address of the factory. initcontainer = Container( sections=[ Section.Code( @@ -753,12 +780,15 @@ def test_reentrant_txcreate( ] ) initcode_hash = initcontainer.hash - # Factory: Passes on its input into the initcode. It's 0 first time, 1 the second time. - # Saves the result of deployment in slot 0 first time, 1 the second time. + # Factory: + # Passes on its input into the initcode. + # It's 0 first time, 1 the second time. + # Saves the result of deployment in slot 0 first time, 1 the second time. contract_address = pre.deploy_contract( code=Op.CALLDATACOPY(0, 0, 32) + Op.MSTORE(32, Op.ADDRESS) - # 1st word - copied from input (reenter flag), 2nd word - `this.address`. + # 1st word - copied from input (reenter flag) + # 2nd word - `this.address` + Op.SSTORE( Op.CALLDATALOAD(0), Op.TXCREATE(tx_initcode_hash=initcode_hash, input_size=64), @@ -766,13 +796,15 @@ def test_reentrant_txcreate( + Op.STOP, storage={0: 0xB17D, 1: 0xB17D}, # a canary to be overwritten ) - # Flow is: reenter flag 0 -> factory -> reenter flag 0 -> initcode -> reenter -> - # reenter flag 1 -> factory -> reenter flag 1 -> (!) initcode -> stop, - # if the EIP-161 nonce bump is not implemented. If it is, it fails before second - # inicode marked (!). + # Flow is: reenter flag 0 -> factory -> reenter flag 0 -> initcode + # -> reenter -> reenter flag 1 -> factory -> reenter flag 1 + # -> (!) initcode -> stop, + # if the EIP-161 nonce bump is not implemented. If it is, it fails before + # second initcode marked (!). # Storage in 0 should have the address from the outer TXCREATE. # Storage in 1 should have 0 from the inner TXCREATE. - # For the created contract storage in `slot_counter` should be 1 as initcode executes only once + # For the created contract storage in `slot_counter` should be 1 as + # initcode executes only once post = { contract_address: Account( storage={ @@ -814,7 +846,10 @@ def test_invalid_container_deployment( pre: Alloc, reason: str, ): - """Verify contract is not deployed when an invalid container deployment is attempted.""" + """ + Verify contract is not deployed when an invalid container deployment is + attempted. + """ env = Environment() sender = pre.fund_eoa() diff --git a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py index 3dd9dc8965..1fca0845e6 100644 --- a/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py +++ b/unscheduled/eip7692_eof_v1/eip7873_tx_create/test_txcreate_validates.py @@ -88,8 +88,10 @@ def __str__(self) -> str: class Factory(Enum): """ - Kinds of systems leading up to a call to TXCREATE. DIRECT just puts the TXCREATE in the - code it generates, while *CALL ones call into another account which does the TXCREATE. + Kinds of systems leading up to a call to TXCREATE. + + DIRECT just puts the TXCREATE in the code it generates, while *CALL ones + call into another account which does the TXCREATE. """ DIRECT = auto() @@ -107,9 +109,10 @@ def creation_snippet( input_size: int, ) -> Tuple[Bytecode, Address | None]: """ - Return snippet to cause TXCREATE to be called along with an address which - will end up in the `compute_eofcreate_address`, or None if that would be the snippet - itself. + Return snippet to cause TXCREATE to be called along with an address. + + This will end up in the `compute_eofcreate_address` or None if that + would be the snippet itself. """ if evm_code_type not in [EVMCodeType.LEGACY, EVMCodeType.EOF_V1]: raise Exception(f"Test needs to be updated for {evm_code_type}") @@ -119,7 +122,8 @@ def creation_snippet( ) # Snippet which returns the TXCREATE result to caller callee_txcreate_code = Op.MSTORE(0, txcreate_code) + Op.RETURN(0, 32) - # Snippet which recovers the TXCREATE result from returndata (wipes memory afterwards) + # Snippet which recovers the TXCREATE result from returndata (wipes + # memory afterwards) returndataload_code = ( Op.RETURNDATALOAD if evm_code_type == EVMCodeType.EOF_V1 @@ -175,8 +179,7 @@ def test_txcreate_validates( access_list_a: bool, ): """ - Verifies proper validation of initcode on TXCREATE in various circumstances of the - opcode. + Verifies proper validation of initcode on TXCREATE in various scenarios. """ env = Environment() snippet_a, factory_address_a = factory_a.creation_snippet( diff --git a/unscheduled/eip7692_eof_v1/gas_test.py b/unscheduled/eip7692_eof_v1/gas_test.py index b2520dcbc8..eaeeb1fd83 100644 --- a/unscheduled/eip7692_eof_v1/gas_test.py +++ b/unscheduled/eip7692_eof_v1/gas_test.py @@ -43,9 +43,9 @@ def gas_test( """ Create State Test to check the gas cost of a sequence of EOF code. - `setup_code` and `tear_down_code` are called multiple times during the test, and MUST NOT have - any side-effects which persist across message calls, and in particular, any effects on the gas - usage of `subject_code`. + `setup_code` and `tear_down_code` are called multiple times during the + test, and MUST NOT have any side-effects which persist across message + calls, and in particular, any effects on the gas usage of `subject_code`. """ if cold_gas <= 0: raise ValueError(f"Target gas allocations (cold_gas) must be > 0, got {cold_gas}") @@ -68,7 +68,8 @@ def gas_test( balance=subject_balance, address=subject_address, ) - # 2 times GAS, POP, CALL, 6 times PUSH1 - instructions charged for at every gas run + # 2 times GAS, POP, CALL, 6 times PUSH1 - instructions charged for at every + # gas run gas_single_gas_run = 2 * 2 + 2 + WARM_ACCOUNT_ACCESS_GAS + 6 * 3 address_legacy_harness = pre.deploy_contract( code=( @@ -109,11 +110,15 @@ def gas_test( + (Op.DUP2 + Op.SWAP1 + Op.SUB + Op.PUSH2(slot_cold_gas) + Op.SSTORE) + ( ( - # do an oog gas run, unless skipped with `out_of_gas_testing=False`: - # - DUP7 is the gas of the baseline gas run, after other CALL args were pushed + # do an oog gas run, unless skipped with + # `out_of_gas_testing=False`: + # + # - DUP7 is the gas of the baseline gas run, after other + # CALL args were pushed # - subtract the gas charged by the harness # - add warm gas charged by the subject - # - subtract `oog_difference` to cause OOG exception (1 by default) + # - subtract `oog_difference` to cause OOG exception + # (1 by default) Op.SSTORE( slot_oog_call_result, Op.CALL( @@ -121,7 +126,8 @@ def gas_test( address=address_subject, ), ) - # sanity gas run: not subtracting 1 to see if enough gas makes the call succeed + # sanity gas run: not subtracting 1 to see if enough gas + # makes the call succeed + Op.SSTORE( slot_sanity_call_result, Op.CALL( @@ -135,7 +141,8 @@ def gas_test( else Op.STOP ) ), - evm_code_type=EVMCodeType.LEGACY, # Needs to be legacy to use GAS opcode + evm_code_type=EVMCodeType.LEGACY, # Needs to be legacy to use GAS + # opcode ) post = { From 5545577f8ba6e7d460b7fb9dd0856a24e36569c2 Mon Sep 17 00:00:00 2001 From: spencer Date: Fri, 26 Sep 2025 12:03:21 +0100 Subject: [PATCH 034/102] chore(cli): update reth gas limit exception mapper Update regex pattern to match new Reth error message format: - Old: "transaction 0x[hash] gas limit X exceeds maximum Y" - New: "transaction gas limit (X) is greater than the cap (Y)" --- ethereum_clis/clis/reth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum_clis/clis/reth.py b/ethereum_clis/clis/reth.py index 4a3c0bcdca..ad6d986967 100644 --- a/ethereum_clis/clis/reth.py +++ b/ethereum_clis/clis/reth.py @@ -58,7 +58,7 @@ class RethExceptionMapper(ExceptionMapper): r"transaction gas limit \w+ is more than blocks available gas \w+" ), TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM: ( - r"transaction 0x[a-fA-F0-9]+ gas limit \d+ exceeds maximum \d+" + r"transaction gas limit.*is greater than the cap" ), BlockException.SYSTEM_CONTRACT_CALL_FAILED: r"failed to apply .* requests contract call", BlockException.INCORRECT_BLOB_GAS_USED: ( From db15a065b498576e51a2c8b60001cf67de0124b3 Mon Sep 17 00:00:00 2001 From: spencer Date: Fri, 26 Sep 2025 12:28:43 +0100 Subject: [PATCH 035/102] chore(tests): workaround for EIP-6110 deposit log checks (#2177) * chore(tests): workaround for EIP-6110 deposit log checks. * chore(tests): future-proof comments for line-length 79 --------- Co-authored-by: danceratopz --- .../test_modified_contract.py | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/prague/eip6110_deposits/test_modified_contract.py b/prague/eip6110_deposits/test_modified_contract.py index 80f58a868d..0d5132e232 100644 --- a/prague/eip6110_deposits/test_modified_contract.py +++ b/prague/eip6110_deposits/test_modified_contract.py @@ -213,7 +213,29 @@ def test_invalid_layout( blockchain_test( pre=pre, blocks=[ - Block(txs=[tx], exception=BlockException.INVALID_DEPOSIT_EVENT_LAYOUT), + Block( + txs=[tx], + exception=[ + BlockException.INVALID_DEPOSIT_EVENT_LAYOUT, + BlockException.INVALID_REQUESTS, + # INVALID_REQUESTS is an alternative workaround for + # Geth/Reth only. + # + # Geth/Reth do not validate the sizes or offsets of the + # deposit contract logs. + # + # Although this is out of spec, it is understood that this + # will not cause an issue so long as the mainnet/testnet + # deposit contracts don't change. + # + # This offsets are checked second and the sizes are checked + # third within the `is_valid_deposit_event_data` function: + # https://eips.ethereum.org/EIPS/eip-6110#block-validity + # + # EELS definition for `is_valid_deposit_event_data`: + # https://github.com/ethereum/execution-specs/blob/5ddb904fa7ba27daeff423e78466744c51e8cb6a/src/ethereum/forks/prague/requests.py#L51 + ], + ), ], post={}, ) @@ -267,7 +289,29 @@ def test_invalid_log_length(blockchain_test: BlockchainTestFiller, pre: Alloc, s blockchain_test( pre=pre, blocks=[ - Block(txs=[tx], exception=BlockException.INVALID_DEPOSIT_EVENT_LAYOUT), + Block( + txs=[tx], + exception=[ + BlockException.INVALID_DEPOSIT_EVENT_LAYOUT, + BlockException.INVALID_REQUESTS, + # INVALID_REQUESTS is an alternative workaround for + # Geth/Reth only. + # + # Geth/Reth do not validate the sizes or offsets of the + # deposit contract logs. + # + # Although this is out of spec, it is understood that this + # will not cause an issue so long as the mainnet/testnet + # deposit contracts don't change. + # + # This offsets are checked second and the sizes are checked + # third within the `is_valid_deposit_event_data` function: + # https://eips.ethereum.org/EIPS/eip-6110#block-validity + # + # EELS definition for `is_valid_deposit_event_data`: + # https://github.com/ethereum/execution-specs/blob/5ddb904fa7ba27daeff423e78466744c51e8cb6a/src/ethereum/forks/prague/requests.py#L51 + ], + ), ], post={}, ) From 49582081e80d4afb782d7945b717345473da12b9 Mon Sep 17 00:00:00 2001 From: danceratopz Date: Fri, 26 Sep 2025 13:58:11 +0200 Subject: [PATCH 036/102] feat(deps,rpc): add retry logic to fix flaky connection issues in hive (#2205) * chore(deps): add `tenacity` for retry logic * feat(rpc): add rpc request retries with exp backoff * docs: add retry logic via tenacity to coding standards * docs: add changelog --- ethereum_test_rpc/rpc.py | 44 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/ethereum_test_rpc/rpc.py b/ethereum_test_rpc/rpc.py index a09055ba12..e654340c28 100644 --- a/ethereum_test_rpc/rpc.py +++ b/ethereum_test_rpc/rpc.py @@ -2,6 +2,7 @@ JSON-RPC methods and helper functions for EEST consume based hive simulators. """ +import logging import time from itertools import count from pprint import pprint @@ -10,6 +11,13 @@ import requests from jwt import encode from pydantic import ValidationError +from tenacity import ( + before_sleep_log, + retry, + retry_if_exception_type, + stop_after_attempt, + wait_exponential, +) from ethereum_test_base_types import Address, Bytes, Hash, to_json from ethereum_test_types import Transaction @@ -88,6 +96,34 @@ def __init_subclass__(cls, namespace: str | None = None) -> None: namespace = namespace.lower() cls.namespace = namespace + @retry( + retry=retry_if_exception_type((requests.ConnectionError, ConnectionRefusedError)), + stop=stop_after_attempt(5), + wait=wait_exponential(multiplier=0.5, min=0.5, max=4.0), + before_sleep=before_sleep_log(logger, logging.WARNING), + reraise=True, + ) + def _make_request( + self, + url: str, + json_payload: dict, + headers: dict, + timeout: int | None, + ) -> requests.Response: + """ + Make HTTP POST request with retry logic for connection errors only. + + This method only retries network-level connection failures + (ConnectionError, ConnectionRefusedError). HTTP status errors (4xx/5xx) + are handled by the caller using response.raise_for_status() WITHOUT + retries because: + - 4xx errors are client errors (permanent failures, no point retrying) + - 5xx errors are server errors that typically indicate + application-level issues rather than transient network problems + """ + logger.debug(f"Making HTTP request to {url}, timeout={timeout}") + return requests.post(url, json=json_payload, headers=headers, timeout=timeout) + def post_request( self, *, @@ -123,8 +159,12 @@ def post_request( } headers = base_header | extra_headers - logger.debug(f"Sending RPC request, timeout is set to {timeout}...") - response = requests.post(self.url, json=payload, headers=headers, timeout=timeout) + logger.debug( + f"Sending RPC request to {self.url}, method={self.namespace}_{method}, " + f"timeout={timeout}..." + ) + + response = self._make_request(self.url, payload, headers, timeout) response.raise_for_status() response_json = response.json() From 779c6c679fe51e3fdbb104c91d24404d8cd00477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 26 Sep 2025 14:14:30 +0200 Subject: [PATCH 037/102] feat(tests): add test cases for P256 input hash special values (#2203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure a valid P256 signature is correctly verified in the full range of hash values: `0–2**256-1`. Add also tests with invalid signature but with valid inputs (r and s in range, Q on curve). --- osaka/eip7951_p256verify_precompiles/spec.py | 3 + .../test_p256verify.py | 68 +++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/osaka/eip7951_p256verify_precompiles/spec.py b/osaka/eip7951_p256verify_precompiles/spec.py index eacb89633b..d4cb594e03 100644 --- a/osaka/eip7951_p256verify_precompiles/spec.py +++ b/osaka/eip7951_p256verify_precompiles/spec.py @@ -99,6 +99,9 @@ class Spec: B = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B ## Curve Coefficient N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 ## Subgroup Order + Gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296 ## Generator Point X + Gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5 ## Generator Point Y + # Other constants SUCCESS_RETURN_VALUE = b"\x01".rjust(32, b"\x00") INVALID_RETURN_VALUE = b"" diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index e908fe2310..da71616ab3 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -89,6 +89,50 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t state_test(env=Environment(), pre=pre, post=post, tx=tx) +@pytest.mark.parametrize( + "input_data", + [ + pytest.param( + H(0) + R(Spec.Gx) + S(Spec.Gx) + X(Spec.Gx) + Y(Spec.Gy), + id="hash_0", + ), + pytest.param( + H(Spec.N - 1) + R(Spec.Gx) + S(Spec.Gx - 1) + X(Spec.Gx) + Y(Spec.Gy), + id="hash_N_minus_1", + ), + pytest.param( + H(Spec.N) + R(Spec.Gx) + S(Spec.Gx) + X(Spec.Gx) + Y(Spec.Gy), + id="hash_N", + ), + pytest.param( + H(Spec.P - 1) + + R(Spec.Gx) + + S(Spec.Gx + Spec.P - 1 - Spec.N) + + X(Spec.Gx) + + Y(Spec.Gy), + id="hash_P_minus_1", + ), + pytest.param( + H(Spec.P) + R(Spec.Gx) + S(Spec.Gx + Spec.P - Spec.N) + X(Spec.Gx) + Y(Spec.Gy), + id="hash_P", + ), + pytest.param( + H(2**256 - 1) + + R(Spec.Gx) + + S(Spec.Gx + 2**256 - 1 - Spec.N) + + X(Spec.Gx) + + Y(Spec.Gy), + id="hash_max", + ), + ], +) +@pytest.mark.parametrize("expected_output", [Spec.SUCCESS_RETURN_VALUE], ids=[""]) +@pytest.mark.parametrize("precompile_address", [Spec.P256VERIFY], ids=[""]) +def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transaction): + """Positive tests for the P256VERIFY precompile.""" + state_test(env=Environment(), pre=pre, post=post, tx=tx) + + @pytest.mark.parametrize( "input_data", [ @@ -105,6 +149,30 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t H(0) + R(0) + S(0) + X(0) + Y(0), id="input_all_zeros", ), + pytest.param( + H(0) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0, + id="hash_0", + ), + pytest.param( + H(Spec.N - 1) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0, + id="hash_N_minus_1", + ), + pytest.param( + H(Spec.N) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0, + id="hash_N", + ), + pytest.param( + H(Spec.P - 1) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0, + id="hash_P_minus_1", + ), + pytest.param( + H(Spec.P) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0, + id="hash_P", + ), + pytest.param( + H(2**256 - 1) + Spec.R0 + Spec.S0 + Spec.X0 + Spec.Y0, + id="hash_max", + ), pytest.param( Spec.H0 + R(0) + Spec.S0 + Spec.X0 + Spec.Y0, id="r_eq_to_zero", From f222c0a604eaa5faead61c9e7545e77517cf6b83 Mon Sep 17 00:00:00 2001 From: spencer Date: Mon, 29 Sep 2025 07:03:02 +0100 Subject: [PATCH 038/102] chore(cli): update nethermind's `NONCE_IS_MAX` message in exception mapper (#2211) --- ethereum_clis/clis/nethermind.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum_clis/clis/nethermind.py b/ethereum_clis/clis/nethermind.py index 85d6ea4484..68c075fbd7 100644 --- a/ethereum_clis/clis/nethermind.py +++ b/ethereum_clis/clis/nethermind.py @@ -343,7 +343,7 @@ class NethermindExceptionMapper(ExceptionMapper): "InvalidMaxPriorityFeePerGas: Cannot be higher than maxFeePerGas" ), TransactionException.GAS_ALLOWANCE_EXCEEDED: "Block gas limit exceeded", - TransactionException.NONCE_IS_MAX: "nonce overflow", + TransactionException.NONCE_IS_MAX: "NonceTooHigh", TransactionException.INITCODE_SIZE_EXCEEDED: "max initcode size exceeded", TransactionException.NONCE_MISMATCH_TOO_LOW: "wrong transaction nonce", TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS: ( From 20409f199f5c360df4263a171508478cb472b98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 29 Sep 2025 20:16:28 +0200 Subject: [PATCH 039/102] feat(tests): add test case for P256 where `Q.x` is zero (#2221) The P256 curve has two points with `x` coordinate being `0` (and none points with `y` being `0`). Add two positive test cases where the points with `0` x-coordinate are public keys. --- .../test_p256verify.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index da71616ab3..11661249ce 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -124,6 +124,22 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t + Y(Spec.Gy), id="hash_max", ), + pytest.param( + H(0xC3D3BE9EB3577F217AE0AB360529A30B18ADC751AEC886328593D7D6FE042809) + + R(0x3A4E97B44CBF88B90E6205A45BA957E520F63F3C6072B53C244653278A1819D8) + + S(0x6A184AA037688A5EBD25081FD2C0B10BB64FA558B671BD81955CA86E09D9D722) + + X(0) + + Y(0x66485C780E2F83D72433BD5D84A06BB6541C2AF31DAE871728BF856A174F93F4), + id="x_0_y_positive", + ), + pytest.param( + H(0xF98A88895CB0866C5BAD58CF03000DDF9D21CB9407892FF54D637E6A046AFBB3) + + R(0x81DC074973D3222F3930981AD98D022517C91063FFB83CFD620E29B86DC30A8F) + + S(0x365E4CD085617A265765062A2D9954ED86309DFA33CF5AE1464FE119419FC34A) + + X(0) + + Y(0x99B7A386F1D07C29DBCC42A27B5F9449ABE3D50DE25178E8D7407A95E8B06C0B), + id="x_0_y_negative", + ), ], ) @pytest.mark.parametrize("expected_output", [Spec.SUCCESS_RETURN_VALUE], ids=[""]) From 5defdbbad7db661e983293817c9b1d00d166db0b Mon Sep 17 00:00:00 2001 From: raxhvl <10168946+raxhvl@users.noreply.github.com> Date: Mon, 29 Sep 2025 20:27:44 +0200 Subject: [PATCH 040/102] =?UTF-8?q?=E2=9C=A8=20feat(tests):=20EIP-7928=20S?= =?UTF-8?q?ELFDESTRUCT=20tests=20(#2159)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat(tests): EIP-7928 SELFDESTRUCT tests * feat: point to latest commit in BALs specs (resolver) * feat: Validate t8n BAL does not have duplicate entries for the same tx_index * 📄 docs: Changelog entry * chore: avoid extra fields in BAL classes, related to #2197 * Add tests for EIP-7928 around precompiles (doc) * fix(tests): Fix expectations for self-destruct tests --------- Co-authored-by: raxhvl Co-authored-by: fselmo Co-authored-by: Toni Wahrstätter <51536394+nerolation@users.noreply.github.com> --- .../test_block_access_lists.py | 140 ++++++++++++++++++ .../test_cases.md | 8 +- 2 files changed, 147 insertions(+), 1 deletion(-) diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py index 128f8276f8..1f53ca1b21 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py @@ -1,12 +1,16 @@ """Tests for EIP-7928 using the consistent data class pattern.""" +from typing import Dict + import pytest +from ethereum_test_base_types import Address from ethereum_test_tools import ( Account, Alloc, Block, BlockchainTestFiller, + Initcode, Storage, Transaction, compute_create_address, @@ -284,3 +288,139 @@ def test_bal_code_changes( ), }, ) + + +@pytest.mark.valid_from("Amsterdam") +@pytest.mark.parametrize("self_destruct_in_same_tx", [True, False], ids=["same_tx", "new_tx"]) +@pytest.mark.parametrize("pre_funded", [True, False], ids=["pre_funded", "not_pre_funded"]) +def test_bal_self_destruct( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + self_destruct_in_same_tx: bool, + pre_funded: bool, +): + """Ensure BAL captures balance changes caused by `SELFDESTRUCT`.""" + alice = pre.fund_eoa() + bob = pre.fund_eoa(amount=0) + + selfdestruct_code = ( + Op.SLOAD(0x01) # Read from storage slot 0x01 + + Op.SSTORE(0x02, 0x42) # Write to storage slot 0x02 + + Op.SELFDESTRUCT(bob) + ) + # A pre existing self-destruct contract with initial storage + kaboom = pre.deploy_contract(code=selfdestruct_code, storage={0x01: 0x123}) + + # A template for self-destruct contract + self_destruct_init_code = Initcode(deploy_code=selfdestruct_code) + template = pre.deploy_contract(code=self_destruct_init_code) + + transfer_amount = expected_recipient_balance = 100 + pre_fund_amount = 10 + + if self_destruct_in_same_tx: + # The goal is to create a self-destructing contract in the same + # transaction to trigger deletion of code as per EIP-6780. + # The factory contract below creates a new self-destructing + # contract and calls it in this transaction. + + bytecode_size = len(self_destruct_init_code) + factory_bytecode = ( + # Clone template memory + Op.EXTCODECOPY(template, 0, 0, bytecode_size) + # Fund 100 wei and deploy the clone + + Op.CREATE(transfer_amount, 0, bytecode_size) + # Call the clone, which self-destructs + + Op.CALL(100_000, Op.DUP6, 0, 0, 0, 0, 0) + + Op.STOP + ) + + factory = pre.deploy_contract(code=factory_bytecode) + kaboom_same_tx = compute_create_address(address=factory, nonce=1) + + # Determine which account will be self-destructed + self_destructed_account = kaboom_same_tx if self_destruct_in_same_tx else kaboom + + if pre_funded: + expected_recipient_balance += pre_fund_amount + pre.fund_address(address=self_destructed_account, amount=pre_fund_amount) + + tx = Transaction( + sender=alice, + to=factory if self_destruct_in_same_tx else kaboom, + value=transfer_amount, + gas_limit=1_000_000, + gas_price=0xA, + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + bob: BalAccountExpectation( + balance_changes=[ + BalBalanceChange(tx_index=1, post_balance=expected_recipient_balance) + ] + ), + self_destructed_account: BalAccountExpectation( + balance_changes=[BalBalanceChange(tx_index=1, post_balance=0)] + if pre_funded + else [], + # Accessed slots for same-tx are recorded as reads (0x02) + storage_reads=[0x01, 0x02] if self_destruct_in_same_tx else [0x01], + # Storage changes are recorded for non-same-tx + # self-destructs + storage_changes=[ + BalStorageSlot( + slot=0x02, slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)] + ) + ] + if not self_destruct_in_same_tx + else [], + code_changes=[], # should not be present + nonce_changes=[], # should not be present + ), + } + ), + ) + + post: Dict[Address, Account] = { + alice: Account(nonce=1), + bob: Account(balance=expected_recipient_balance), + } + + # If the account was self-destructed in the same transaction, + # we expect the account to non-existent and its balance to be 0. + if self_destruct_in_same_tx: + post.update( + { + factory: Account( + nonce=2, # incremented after CREATE + balance=0, # spent on CREATE + code=factory_bytecode, + ), + kaboom_same_tx: Account.NONEXISTENT, # type: ignore + # The pre-existing contract remains unaffected + kaboom: Account(balance=0, code=selfdestruct_code, storage={0x01: 0x123}), + } + ) + else: + post.update( + { + # This contract was self-destructed in a separate tx. + # From EIP 6780: `SELFDESTRUCT` does not delete any data + # (including storage keys, code, or the account itself). + kaboom: Account( + balance=0, code=selfdestruct_code, storage={0x01: 0x123, 0x2: 0x42} + ), + } + ) + + blockchain_test( + pre=pre, + blocks=[block], + post=post, + ) diff --git a/amsterdam/eip7928_block_level_access_lists/test_cases.md b/amsterdam/eip7928_block_level_access_lists/test_cases.md index 3c371be939..d5b3d2c11d 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_cases.md +++ b/amsterdam/eip7928_block_level_access_lists/test_cases.md @@ -7,12 +7,18 @@ | `test_bal_storage_writes` | Ensure BAL captures storage writes | Alice calls contract that writes to storage slot `0x01` | BAL MUST include storage changes with correct slot and value | ✅ Completed | | `test_bal_storage_reads` | Ensure BAL captures storage reads | Alice calls contract that reads from storage slot `0x01` | BAL MUST include storage access for the read operation | ✅ Completed | | `test_bal_code_changes` | Ensure BAL captures changes to account code | Alice deploys factory contract that creates new contract | BAL MUST include code changes for newly deployed contract | ✅ Completed | -| `test_bal_2930_slot_listed_but_untouched` | Ensure 2930 access list alone doesn’t appear in BAL | Include `(KV, S=0x01)` in tx’s EIP-2930 access list; tx executes code that does **no** `SLOAD`/`SSTORE` to `S` (e.g., pure arithmetic/log). | BAL **MUST NOT** contain any entry for `(KV, S)` — neither reads nor writes — because the slot wasn’t touched. | 🟡 Planned | +| `test_bal_self_destruct` | Ensure BAL captures storage access and balance changes caused by `SELFDESTRUCT` | Parameterized test: Alice interacts with a contract (either existing or created same-tx) that reads from storage slot 0x01, writes to storage slot 0x02, then executes `SELFDESTRUCT` with Bob as recipient. Contract may be pre-funded with 10 wei | BAL MUST include Alice's nonce change (increment) and Bob's balance change (100 or 110 depending on pre-funding). For the self-destructing contract: storage_reads=[0x01], empty storage_changes=[], and if pre-funded, balance_changes with post_balance=0; if not pre-funded, no balance change recorded. MUST NOT have code_changes or nonce_changes entries | ✅ Completed | +| `test_bal_2930_slot_listed_but_untouched` | Ensure 2930 access list alone doesn't appear in BAL | Include `(KV, S=0x01)` in tx's EIP-2930 access list; tx executes code that does **no** `SLOAD`/`SSTORE` to `S` (e.g., pure arithmetic/log). | BAL **MUST NOT** contain any entry for `(KV, S)` — neither reads nor writes — because the slot wasn't touched. | 🟡 Planned | | `test_bal_2930_slot_listed_and_modified` | Ensure BAL records writes only because the slot is touched | Same access list as above, but tx executes `SSTORE` to `S`. | BAL **MUST** include `storage_changes` for `(KV, S)` (and no separate read record for that slot if implementation deduplicates). Presence in the access list is irrelevant; inclusion is due to the actual write. | 🟡 Planned | | `test_bal_7702_delegated_create` | BAL tracks EIP-7702 delegation indicator write and contract creation | Alice sends a type-4 (7702) tx authorizing herself to delegate to `Deployer` code which executes `CREATE` | BAL MUST include for **Alice**: `code_changes` (delegation indicator), `nonce_changes` (increment from 7702 processing), and `balance_changes` (post-gas). For **Child**: `code_changes` (runtime bytecode) and `nonce_changes = 1`. | 🟡 Planned | | `test_bal_self_transfer` | BAL handles self-transfers correctly | Alice sends `1 ETH` to **Alice** | BAL MUST include **one** entry for Alice with `balance_changes` reflecting **gas only** (value cancels out) and a nonce change; Coinbase balance updated for fees; no separate recipient row. | 🟡 Planned | | `test_bal_system_contracts_2935_4788` | BAL includes pre-exec system writes for parent hash & beacon root | Build a block with `N` normal txs; 2935 & 4788 active | BAL MUST include `HISTORY_STORAGE_ADDRESS` (EIP-2935) and `BEACON_ROOTS_ADDRESS` (EIP-4788) with `storage_changes` to ring-buffer slots; each write uses `tx_index = N` (system op). | 🟡 Planned | | `test_bal_system_dequeue_withdrawals_eip7002` | BAL tracks post-exec system dequeues for withdrawals | Pre-populate EIP-7002 withdrawal requests; produce a block where dequeues occur | BAL MUST include the 7002 system contract with `storage_changes` (queue head/tail slots 0–3) using `tx_index = len(txs)` and balance changes for withdrawal recipients. | 🟡 Planned | | `test_bal_system_dequeue_consolidations_eip7251` | BAL tracks post-exec system dequeues for consolidations | Pre-populate EIP-7251 consolidation requests; produce a block where dequeues occur | BAL MUST include the 7251 system contract with `storage_changes` (queue slots 0–3) using `tx_index = len(txs)`. | 🟡 Planned | +| `test_bal_create2_to_A_read_then_selfdestruct` | BAL records balance change for A and storage access (no persistent change) | Tx0: Alice sends ETH to address **A**. Tx1: Deployer `CREATE2` a contract **at A**; contract does `SLOAD(B)` and immediately `SELFDESTRUCT(beneficiary=X)` in the same tx. | BAL **MUST** include **A** with `balance_changes` (funding in Tx0 and transfer on selfdestruct in Tx1). BAL **MUST** include storage key **B** as an accessed `StorageKey`, and **MUST NOT** include **B** under `storage_changes` (no persistence due to same-tx create+destruct). | 🟡 Planned | +| `test_bal_create2_to_A_write_then_selfdestruct` | BAL records balance change for A and storage access even if a write occurred (no persistent change) | Tx0: Alice sends ETH to **A**. Tx1: Deployer `CREATE2` contract **at A**; contract does `SSTORE(B, v)` (optionally `SLOAD(B)`), then `SELFDESTRUCT(beneficiary=Y)` in the same tx. | BAL **MUST** include **A** with `balance_changes` (Tx0 fund; Tx1 outflow to `Y`). BAL **MUST** include **B** as `StorageKey` accessed, and **MUST NOT** include **B** under `storage_changes` (ephemeral write discarded because the contract was created and destroyed in the same tx). | 🟡 Planned | +| `test_bal_precompile_funded_then_called` | BAL records precompile with balance change (fund) and access (call) | **Tx0**: Alice sends `1 ETH` to `ecrecover` (0x01). **Tx1**: Alice (or Bob) calls `ecrecover` with valid input and `0 ETH`. | BAL **MUST** include address `0x01` with `balance_changes` (from Tx0). No `storage_changes` or `code_changes`. | 🟡 Planned | +| `test_bal_precompile_call_only` | BAL records precompile when called with no balance change | Alice calls `ecrecover` (0x01) with a valid input, sending **0 ETH**. | BAL **MUST** include address `0x01` in access list, with **no** `balance_changes`, `storage_changes`, or `code_changes`. | 🟡 Planned | + > ℹ️ Scope describes whether a test spans a single transaction (`tx`) or entire block (`blk`). From 6db86ad27dedd92621edf100e8eb63efefdc887a Mon Sep 17 00:00:00 2001 From: raxhvl <10168946+raxhvl@users.noreply.github.com> Date: Mon, 29 Sep 2025 20:27:44 +0200 Subject: [PATCH 041/102] =?UTF-8?q?=E2=9C=A8=20feat(tests):=20EIP-7928=20S?= =?UTF-8?q?ELFDESTRUCT=20tests=20(#2159)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat(tests): EIP-7928 SELFDESTRUCT tests * feat: point to latest commit in BALs specs (resolver) * feat: Validate t8n BAL does not have duplicate entries for the same tx_index * 📄 docs: Changelog entry * chore: avoid extra fields in BAL classes, related to #2197 * Add tests for EIP-7928 around precompiles (doc) * fix(tests): Fix expectations for self-destruct tests --------- Co-authored-by: raxhvl Co-authored-by: fselmo Co-authored-by: Toni Wahrstätter <51536394+nerolation@users.noreply.github.com> --- .../account_absent_values.py | 2 + .../block_access_list/account_changes.py | 12 +++ .../block_access_list/expectations.py | 74 ++++++++++++------ .../tests/test_block_access_lists.py | 77 +++++++++++++++++++ pytest_plugins/eels_resolutions.json | 2 +- 5 files changed, 141 insertions(+), 26 deletions(-) diff --git a/ethereum_test_types/block_access_list/account_absent_values.py b/ethereum_test_types/block_access_list/account_absent_values.py index c0fea606a9..d2109477cb 100644 --- a/ethereum_test_types/block_access_list/account_absent_values.py +++ b/ethereum_test_types/block_access_list/account_absent_values.py @@ -74,6 +74,8 @@ class BalAccountAbsentValues(CamelModel): """ + model_config = CamelModel.model_config | {"extra": "forbid"} + nonce_changes: List[BalNonceChange] = Field( default_factory=list, description="List of nonce changes that should NOT exist in the BAL. " diff --git a/ethereum_test_types/block_access_list/account_changes.py b/ethereum_test_types/block_access_list/account_changes.py index 5edb0b9fc5..b5a9632c8a 100644 --- a/ethereum_test_types/block_access_list/account_changes.py +++ b/ethereum_test_types/block_access_list/account_changes.py @@ -22,6 +22,8 @@ class BalNonceChange(CamelModel, RLPSerializable): """Represents a nonce change in the block access list.""" + model_config = CamelModel.model_config | {"extra": "forbid"} + tx_index: HexNumber = Field( HexNumber(1), description="Transaction index where the change occurred", @@ -34,6 +36,8 @@ class BalNonceChange(CamelModel, RLPSerializable): class BalBalanceChange(CamelModel, RLPSerializable): """Represents a balance change in the block access list.""" + model_config = CamelModel.model_config | {"extra": "forbid"} + tx_index: HexNumber = Field( HexNumber(1), description="Transaction index where the change occurred", @@ -46,6 +50,8 @@ class BalBalanceChange(CamelModel, RLPSerializable): class BalCodeChange(CamelModel, RLPSerializable): """Represents a code change in the block access list.""" + model_config = CamelModel.model_config | {"extra": "forbid"} + tx_index: HexNumber = Field( HexNumber(1), description="Transaction index where the change occurred", @@ -58,6 +64,8 @@ class BalCodeChange(CamelModel, RLPSerializable): class BalStorageChange(CamelModel, RLPSerializable): """Represents a change to a specific storage slot.""" + model_config = CamelModel.model_config | {"extra": "forbid"} + tx_index: HexNumber = Field( HexNumber(1), description="Transaction index where the change occurred", @@ -70,6 +78,8 @@ class BalStorageChange(CamelModel, RLPSerializable): class BalStorageSlot(CamelModel, RLPSerializable): """Represents all changes to a specific storage slot.""" + model_config = CamelModel.model_config | {"extra": "forbid"} + slot: StorageKey = Field(..., description="Storage slot key") slot_changes: List[BalStorageChange] = Field( default_factory=list, description="List of changes to this slot" @@ -81,6 +91,8 @@ class BalStorageSlot(CamelModel, RLPSerializable): class BalAccountChange(CamelModel, RLPSerializable): """Represents all changes to a specific account in a block.""" + model_config = CamelModel.model_config | {"extra": "forbid"} + address: Address = Field(..., description="Account address") nonce_changes: List[BalNonceChange] = Field( default_factory=list, description="List of nonce changes" diff --git a/ethereum_test_types/block_access_list/expectations.py b/ethereum_test_types/block_access_list/expectations.py index 8bcdeba538..5a69d45e7d 100644 --- a/ethereum_test_types/block_access_list/expectations.py +++ b/ethereum_test_types/block_access_list/expectations.py @@ -32,6 +32,8 @@ class BalAccountExpectation(CamelModel): used for expectations. """ + model_config = CamelModel.model_config | {"extra": "forbid"} + nonce_changes: List[BalNonceChange] = Field( default_factory=list, description="List of expected nonce changes" ) @@ -199,21 +201,33 @@ def _validate_bal_ordering(bal: "BlockAccessList") -> None: f"{bal.root[i - 1].address} >= {bal.root[i].address}" ) - # Check transaction index ordering within accounts + # Check transaction index ordering and uniqueness within accounts for account in bal.root: - change_lists: List[BlockAccessListChangeLists] = [ - account.nonce_changes, - account.balance_changes, - account.code_changes, + changes_to_check: List[tuple[str, BlockAccessListChangeLists]] = [ + ("nonce_changes", account.nonce_changes), + ("balance_changes", account.balance_changes), + ("code_changes", account.code_changes), ] - for change_list in change_lists: - for i in range(1, len(change_list)): - if change_list[i - 1].tx_index >= change_list[i].tx_index: - raise BlockAccessListValidationError( - f"Transaction indices not in ascending order in account " - f"{account.address}: {change_list[i - 1].tx_index} >= " - f"{change_list[i].tx_index}" - ) + + for field_name, change_list in changes_to_check: + if not change_list: + continue + + tx_indices = [c.tx_index for c in change_list] + + # Check both ordering and duplicates + if tx_indices != sorted(tx_indices): + raise BlockAccessListValidationError( + f"Transaction indices not in ascending order in {field_name} of account " + f"{account.address}. Got: {tx_indices}, Expected: {sorted(tx_indices)}" + ) + + if len(tx_indices) != len(set(tx_indices)): + duplicates = sorted({idx for idx in tx_indices if tx_indices.count(idx) > 1}) + raise BlockAccessListValidationError( + f"Duplicate transaction indices in {field_name} of account " + f"{account.address}. Duplicates: {duplicates}" + ) # Check storage slot ordering for i in range(1, len(account.storage_changes)): @@ -224,19 +238,29 @@ def _validate_bal_ordering(bal: "BlockAccessList") -> None: f"{account.storage_changes[i].slot}" ) - # Check transaction index ordering within storage slots + # Check transaction index ordering and uniqueness within storage + # slots for storage_slot in account.storage_changes: - for i in range(1, len(storage_slot.slot_changes)): - if ( - storage_slot.slot_changes[i - 1].tx_index - >= storage_slot.slot_changes[i].tx_index - ): - raise BlockAccessListValidationError( - f"Transaction indices not in ascending order in storage slot " - f"{storage_slot.slot} of account {account.address}: " - f"{storage_slot.slot_changes[i - 1].tx_index} >= " - f"{storage_slot.slot_changes[i].tx_index}" - ) + if not storage_slot.slot_changes: + continue + + tx_indices = [c.tx_index for c in storage_slot.slot_changes] + + # Check both ordering and duplicates + if tx_indices != sorted(tx_indices): + raise BlockAccessListValidationError( + f"Transaction indices not in ascending order in storage slot " + f"{storage_slot.slot} of account {account.address}. " + f"Got: {tx_indices}, Expected: {sorted(tx_indices)}" + ) + + if len(tx_indices) != len(set(tx_indices)): + duplicates = sorted({idx for idx in tx_indices if tx_indices.count(idx) > 1}) + raise BlockAccessListValidationError( + f"Duplicate transaction indices in storage slot " + f"{storage_slot.slot} of account {account.address}. " + f"Duplicates: {duplicates}" + ) # Check storage reads ordering for i in range(1, len(account.storage_reads)): diff --git a/ethereum_test_types/tests/test_block_access_lists.py b/ethereum_test_types/tests/test_block_access_lists.py index 0665081072..20ad08b497 100644 --- a/ethereum_test_types/tests/test_block_access_lists.py +++ b/ethereum_test_types/tests/test_block_access_lists.py @@ -335,6 +335,83 @@ def test_actual_bal_tx_indices_ordering(field_name): expectation.verify_against(actual_bal) +@pytest.mark.parametrize( + "field_name", + ["nonce_changes", "balance_changes", "code_changes"], +) +def test_actual_bal_duplicate_tx_indices(field_name): + """ + Test that actual BAL must not have duplicate tx indices in change lists. + """ + addr = Address(0xA) + + # Duplicate tx_index=1 + changes = [] + if field_name == "nonce_changes": + changes = [ + BalNonceChange(tx_index=1, post_nonce=1), + BalNonceChange(tx_index=1, post_nonce=2), # duplicate tx_index + BalNonceChange(tx_index=2, post_nonce=3), + ] + elif field_name == "balance_changes": + changes = [ + BalBalanceChange(tx_index=1, post_balance=100), + BalBalanceChange(tx_index=1, post_balance=200), # duplicate tx_index + BalBalanceChange(tx_index=2, post_balance=300), + ] + elif field_name == "code_changes": + changes = [ + BalCodeChange(tx_index=1, new_code=b"code1"), + BalCodeChange(tx_index=1, new_code=b""), # duplicate tx_index + BalCodeChange(tx_index=2, new_code=b"code2"), + ] + + actual_bal = BlockAccessList([BalAccountChange(address=addr, **{field_name: changes})]) + + expectation = BlockAccessListExpectation(account_expectations={}) + + with pytest.raises( + BlockAccessListValidationError, + match=f"Duplicate transaction indices in {field_name}.*Duplicates: \\[1\\]", + ): + expectation.verify_against(actual_bal) + + +def test_actual_bal_storage_duplicate_tx_indices(): + """ + Test that storage changes must not have duplicate tx indices within same + slot. + """ + addr = Address(0xA) + + # Create storage changes with duplicate tx_index within the same slot + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=addr, + storage_changes=[ + BalStorageSlot( + slot=0x01, + slot_changes=[ + BalStorageChange(tx_index=1, post_value=0x100), + BalStorageChange(tx_index=1, post_value=0x200), # duplicate tx_index + BalStorageChange(tx_index=2, post_value=0x300), + ], + ) + ], + ) + ] + ) + + expectation = BlockAccessListExpectation(account_expectations={}) + + with pytest.raises( + BlockAccessListValidationError, + match="Duplicate transaction indices in storage slot.*Duplicates: \\[1\\]", + ): + expectation.verify_against(actual_bal) + + def test_expected_addresses_auto_sorted(): """ Test that expected addresses are automatically sorted before comparison. diff --git a/pytest_plugins/eels_resolutions.json b/pytest_plugins/eels_resolutions.json index 2b1a9c5f9d..f7b1dd9908 100644 --- a/pytest_plugins/eels_resolutions.json +++ b/pytest_plugins/eels_resolutions.json @@ -55,6 +55,6 @@ "Amsterdam": { "git_url": "https://github.com/fselmo/execution-specs.git", "branch": "feat/amsterdam-fork-and-block-access-lists", - "commit": "39e0b59613be4100d2efc86702ff594c54e5bd81" + "commit": "6abe0ecb792265211d93bc3fea2f932e5d2cfa90" } } From b144c51f6fa4626f7235eb527d655d40ed71316d Mon Sep 17 00:00:00 2001 From: raxhvl <10168946+raxhvl@users.noreply.github.com> Date: Mon, 29 Sep 2025 23:04:09 +0200 Subject: [PATCH 042/102] =?UTF-8?q?=E2=9C=A8=20feat(tests):=20EIP-7928=20a?= =?UTF-8?q?ccount=20access=20test=20cases=20(#2182)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat(tests): test_bal_account_access_target * ✨ feat(tests): test_bal_call_with_value_transfer * ✨ feat(tests): test_bal_callcode_with_value_transfer * 🧹 chore: Global fork marker * ✨ feat(tests): test_bal_delegated_storage_writes * ✨ feat(tests): test_bal_delegated_storage_reads * ✨ feat(test): test_bal_block_rewards * refactor: rebase and fix conflicts --------- Co-authored-by: raxhvl Co-authored-by: fselmo --- .../test_block_access_lists.py | 319 +++++++++++++++++- .../test_cases.md | 7 + 2 files changed, 320 insertions(+), 6 deletions(-) diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py index 1f53ca1b21..b5e9e54214 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py @@ -31,8 +31,9 @@ REFERENCE_SPEC_GIT_PATH = ref_spec_7928.git_path REFERENCE_SPEC_VERSION = ref_spec_7928.version +pytestmark = pytest.mark.valid_from("Amsterdam") + -@pytest.mark.valid_from("Amsterdam") def test_bal_nonce_changes( pre: Alloc, blockchain_test: BlockchainTestFiller, @@ -68,7 +69,6 @@ def test_bal_nonce_changes( ) -@pytest.mark.valid_from("Amsterdam") def test_bal_balance_changes( pre: Alloc, blockchain_test: BlockchainTestFiller, @@ -128,7 +128,6 @@ def test_bal_balance_changes( ) -@pytest.mark.valid_from("Amsterdam") def test_bal_storage_writes( pre: Alloc, blockchain_test: BlockchainTestFiller, @@ -174,7 +173,6 @@ def test_bal_storage_writes( ) -@pytest.mark.valid_from("Amsterdam") def test_bal_storage_reads( pre: Alloc, blockchain_test: BlockchainTestFiller, @@ -213,7 +211,6 @@ def test_bal_storage_reads( ) -@pytest.mark.valid_from("Amsterdam") def test_bal_code_changes( pre: Alloc, blockchain_test: BlockchainTestFiller, @@ -290,7 +287,6 @@ def test_bal_code_changes( ) -@pytest.mark.valid_from("Amsterdam") @pytest.mark.parametrize("self_destruct_in_same_tx", [True, False], ids=["same_tx", "new_tx"]) @pytest.mark.parametrize("pre_funded", [True, False], ids=["pre_funded", "not_pre_funded"]) def test_bal_self_destruct( @@ -424,3 +420,314 @@ def test_bal_self_destruct( blocks=[block], post=post, ) + + +@pytest.mark.parametrize( + "account_access_opcode", + [ + pytest.param(lambda target_addr: Op.BALANCE(target_addr), id="balance"), + pytest.param(lambda target_addr: Op.EXTCODESIZE(target_addr), id="extcodesize"), + pytest.param(lambda target_addr: Op.EXTCODECOPY(target_addr, 0, 0, 32), id="extcodecopy"), + pytest.param(lambda target_addr: Op.EXTCODEHASH(target_addr), id="extcodehash"), + pytest.param(lambda target_addr: Op.CALL(0, target_addr, 50, 0, 0, 0, 0), id="call"), + pytest.param( + lambda target_addr: Op.CALLCODE(0, target_addr, 0, 0, 0, 0, 0), id="callcode" + ), + pytest.param( + lambda target_addr: Op.DELEGATECALL(0, target_addr, 0, 0, 0, 0), id="delegatecall" + ), + pytest.param( + lambda target_addr: Op.STATICCALL(0, target_addr, 0, 0, 0, 0), id="staticcall" + ), + ], +) +def test_bal_account_access_target( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + account_access_opcode, +): + """Ensure BAL captures target address of account access opcodes.""" + alice = pre.fund_eoa() + target_contract = pre.deploy_contract(code=Op.STOP) + + oracle_contract = pre.deploy_contract( + balance=100, + code=account_access_opcode(target_contract), + ) + + tx = Transaction(sender=alice, to=oracle_contract, gas_limit=5_000_000, gas_price=0xA) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)] + ), + target_contract: BalAccountExpectation(), + oracle_contract: BalAccountExpectation(), + } + ), + ) + + blockchain_test(pre=pre, blocks=[block], post={}) + + +def test_bal_call_with_value_transfer( + pre: Alloc, + blockchain_test: BlockchainTestFiller, +): + """ + Ensure BAL captures balance changes from CALL opcode with + value transfer. + """ + alice = pre.fund_eoa() + bob = pre.fund_eoa(amount=0) + + # Oracle contract that uses CALL to transfer 100 wei to Bob + oracle_code = Op.CALL(0, bob, 100, 0, 0, 0, 0) + oracle_contract = pre.deploy_contract(code=oracle_code, balance=200) + + tx = Transaction(sender=alice, to=oracle_contract, gas_limit=1_000_000, gas_price=0xA) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + oracle_contract: BalAccountExpectation( + balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)], + ), + bob: BalAccountExpectation( + balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)], + ), + } + ), + ) + + blockchain_test(pre=pre, blocks=[block], post={}) + + +def test_bal_callcode_with_value_transfer( + pre: Alloc, + blockchain_test: BlockchainTestFiller, +): + """ + Ensure BAL captures balance changes from CALLCODE opcode with + value transfer. + """ + alice = pre.fund_eoa() + bob = pre.fund_eoa(amount=0) + + # TargetContract sends 100 wei to bob + target_code = Op.CALL(0, bob, 100, 0, 0, 0, 0) + target_contract = pre.deploy_contract(code=target_code) + + # Oracle contract that uses CALLCODE to execute TargetContract's code + oracle_code = Op.CALLCODE(50_000, target_contract, 100, 0, 0, 0, 0) + oracle_contract = pre.deploy_contract(code=oracle_code, balance=200) + + tx = Transaction(sender=alice, to=oracle_contract, gas_limit=1_000_000, gas_price=0xA) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + oracle_contract: BalAccountExpectation( + balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)], + ), + bob: BalAccountExpectation( + balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)], + ), + target_contract: BalAccountExpectation(), + } + ), + ) + + blockchain_test(pre=pre, blocks=[block], post={}) + + +@pytest.mark.parametrize( + "delegated_opcode", + [ + pytest.param( + lambda target_addr: Op.DELEGATECALL(50000, target_addr, 0, 0, 0, 0), id="delegatecall" + ), + pytest.param( + lambda target_addr: Op.CALLCODE(50000, target_addr, 0, 0, 0, 0, 0), id="callcode" + ), + ], +) +def test_bal_delegated_storage_writes( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + delegated_opcode, +): + """ + Ensure BAL captures delegated storage writes via + DELEGATECALL and CALLCODE. + """ + alice = pre.fund_eoa() + + # TargetContract that writes 0x42 to slot 0x01 + target_code = Op.SSTORE(0x01, 0x42) + target_contract = pre.deploy_contract(code=target_code) + + # Oracle contract that uses delegated opcode to execute + # TargetContract's code + oracle_code = delegated_opcode(target_contract) + oracle_contract = pre.deploy_contract(code=oracle_code) + + tx = Transaction( + sender=alice, + to=oracle_contract, + gas_limit=1_000_000, + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + oracle_contract: BalAccountExpectation( + storage_changes=[ + BalStorageSlot( + slot=0x01, + slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)], + ) + ], + ), + target_contract: BalAccountExpectation(), + } + ), + ) + + blockchain_test(pre=pre, blocks=[block], post={}) + + +@pytest.mark.parametrize( + "delegated_opcode", + [ + pytest.param( + lambda target_addr: Op.DELEGATECALL(50000, target_addr, 0, 0, 0, 0), id="delegatecall" + ), + pytest.param( + lambda target_addr: Op.CALLCODE(50000, target_addr, 0, 0, 0, 0, 0), id="callcode" + ), + ], +) +def test_bal_delegated_storage_reads( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + delegated_opcode, +): + """ + Ensure BAL captures delegated storage reads via + DELEGATECALL and CALLCODE. + """ + alice = pre.fund_eoa() + + # TargetContract that reads from slot 0x01 + target_code = Op.SLOAD(0x01) + Op.STOP + target_contract = pre.deploy_contract(code=target_code) + + # Oracle contract with storage slot 0x01 = 0x42, + # uses delegated opcode to execute TargetContract's code + oracle_code = delegated_opcode(target_contract) + oracle_contract = pre.deploy_contract(code=oracle_code, storage={0x01: 0x42}) + + tx = Transaction( + sender=alice, + to=oracle_contract, + gas_limit=1_000_000, + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + oracle_contract: BalAccountExpectation( + storage_reads=[0x01], + ), + target_contract: BalAccountExpectation(), + } + ), + ) + + blockchain_test(pre=pre, blocks=[block], post={}) + + +def test_bal_block_rewards( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork, +): + """Ensure BAL captures fee recipient balance changes from block rewards.""" + alice_initial_balance = 1_000_000 + alice = pre.fund_eoa(amount=alice_initial_balance) + bob = pre.fund_eoa(amount=0) + charlie = pre.fund_eoa(amount=0) # fee recipient + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_calculator( + calldata=b"", + contract_creation=False, + access_list=[], + ) + tx_gas_limit = intrinsic_gas_cost + 1000 # add a small buffer + gas_price = 0xA + base_fee_per_gas = 0x2 # Set base fee for EIP-1559 + + tx = Transaction( + sender=alice, + to=bob, + value=100, + gas_limit=tx_gas_limit, + gas_price=gas_price, + ) + + # EIP-1559 fee calculation: + # - Total gas cost + total_gas_cost = intrinsic_gas_cost * gas_price + # - Tip portion + tip_to_charlie = intrinsic_gas_cost * (gas_price - base_fee_per_gas) + + alice_final_balance = alice_initial_balance - 100 - total_gas_cost + + block = Block( + txs=[tx], + fee_recipient=charlie, # Set Charlie as the fee recipient + base_fee_per_gas=base_fee_per_gas, # Set base fee for EIP-1559 + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + balance_changes=[ + BalBalanceChange(tx_index=1, post_balance=alice_final_balance) + ], + ), + bob: BalAccountExpectation( + balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)], + ), + charlie: BalAccountExpectation( + balance_changes=[BalBalanceChange(tx_index=1, post_balance=tip_to_charlie)], + ), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={}, + ) diff --git a/amsterdam/eip7928_block_level_access_lists/test_cases.md b/amsterdam/eip7928_block_level_access_lists/test_cases.md index d5b3d2c11d..a627b34cfa 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_cases.md +++ b/amsterdam/eip7928_block_level_access_lists/test_cases.md @@ -9,6 +9,13 @@ | `test_bal_code_changes` | Ensure BAL captures changes to account code | Alice deploys factory contract that creates new contract | BAL MUST include code changes for newly deployed contract | ✅ Completed | | `test_bal_self_destruct` | Ensure BAL captures storage access and balance changes caused by `SELFDESTRUCT` | Parameterized test: Alice interacts with a contract (either existing or created same-tx) that reads from storage slot 0x01, writes to storage slot 0x02, then executes `SELFDESTRUCT` with Bob as recipient. Contract may be pre-funded with 10 wei | BAL MUST include Alice's nonce change (increment) and Bob's balance change (100 or 110 depending on pre-funding). For the self-destructing contract: storage_reads=[0x01], empty storage_changes=[], and if pre-funded, balance_changes with post_balance=0; if not pre-funded, no balance change recorded. MUST NOT have code_changes or nonce_changes entries | ✅ Completed | | `test_bal_2930_slot_listed_but_untouched` | Ensure 2930 access list alone doesn't appear in BAL | Include `(KV, S=0x01)` in tx's EIP-2930 access list; tx executes code that does **no** `SLOAD`/`SSTORE` to `S` (e.g., pure arithmetic/log). | BAL **MUST NOT** contain any entry for `(KV, S)` — neither reads nor writes — because the slot wasn't touched. | 🟡 Planned | +| `test_bal_account_access_target` | Ensure BAL captures target addresses of account access opcodes | Alice calls `Oracle` contract which uses account access opcodes (`BALANCE`, `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH`, `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`) on `TargetContract`. | BAL MUST include Alice, `Oracle`, and `TargetContract` with empty changes for `TargetContract` and nonce changes for Alice. | ✅ Completed | +| `test_bal_call_with_value_transfer` | Ensure BAL captures balance changes from `CALL` opcode with value transfer | Alice calls `Oracle` contract (200 wei balance) which uses `CALL` opcode to transfer 100 wei to Bob (0 wei balance). | BAL MUST include Alice (nonce changes), Oracle (balance change to 100 wei), and Bob (balance change to 100 wei). | ✅ Completed | +| `test_bal_callcode_with_value_transfer` | Ensure BAL captures balance changes from `CALLCODE` opcode with value transfer | Alice calls `Oracle` contract (200 wei balance) which uses `CALLCODE` opcode to execute `TargetContract`'s code with 100 wei value transfer to Bob (0 wei balance). | BAL MUST include Alice (nonce changes), `Oracle` (balance change to 100 wei), Bob (balance change to 100 wei), and `TargetContract` (empty changes). | ✅ Completed | +| `test_bal_delegated_storage_writes` | Ensure BAL captures delegated storage writes via `DELEGATECALL` and `CALLCODE` | Alice calls `Oracle` contract which uses `DELEGATECALL`/`CALLCODE` to `TargetContract` that writes `0x42` to slot `0x01`. | BAL MUST include Alice (nonce changes), `Oracle` (storage changes for slot `0x01` = `0x42`), and `TargetContract` (empty changes). | ✅ Completed | +| `test_bal_delegated_storage_reads` | Ensure BAL captures delegated storage reads via `DELEGATECALL` and `CALLCODE` | Alice calls `Oracle` contract (with slot `0x01` = `0x42`) which uses `DELEGATECALL`/`CALLCODE` to `TargetContract` that reads from slot `0x01`. | BAL MUST include Alice (nonce changes), `Oracle` (storage reads for slot `0x01`), and `TargetContract` (empty changes). | ✅ Completed | +| `test_bal_block_rewards` | BAL tracks fee recipient balance changes from block rewards | Alice sends 100 wei to Bob with Charlie as fee recipient | BAL MUST include fee recipient Charlie with `balance_changes` reflecting transaction fees collected from the block. | ✅ Completed | +| `test_bal_2930_slot_listed_but_untouched` | Ensure 2930 access list alone doesn’t appear in BAL | Include `(KV, S=0x01)` in tx’s EIP-2930 access list; tx executes code that does **no** `SLOAD`/`SSTORE` to `S` (e.g., pure arithmetic/log). | BAL **MUST NOT** contain any entry for `(KV, S)` — neither reads nor writes — because the slot wasn’t touched. | 🟡 Planned | | `test_bal_2930_slot_listed_and_modified` | Ensure BAL records writes only because the slot is touched | Same access list as above, but tx executes `SSTORE` to `S`. | BAL **MUST** include `storage_changes` for `(KV, S)` (and no separate read record for that slot if implementation deduplicates). Presence in the access list is irrelevant; inclusion is due to the actual write. | 🟡 Planned | | `test_bal_7702_delegated_create` | BAL tracks EIP-7702 delegation indicator write and contract creation | Alice sends a type-4 (7702) tx authorizing herself to delegate to `Deployer` code which executes `CREATE` | BAL MUST include for **Alice**: `code_changes` (delegation indicator), `nonce_changes` (increment from 7702 processing), and `balance_changes` (post-gas). For **Child**: `code_changes` (runtime bytecode) and `nonce_changes = 1`. | 🟡 Planned | | `test_bal_self_transfer` | BAL handles self-transfers correctly | Alice sends `1 ETH` to **Alice** | BAL MUST include **one** entry for Alice with `balance_changes` reflecting **gas only** (value cancels out) and a nonce change; Coinbase balance updated for fees; no separate recipient row. | 🟡 Planned | From 63401ee52c8eca2a30a34f79508a975a3e722e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2025 13:58:05 +0200 Subject: [PATCH 043/102] feat(tests): add test cases for P256 input s special values (#2215) Add test cases for the `p256verify` precompile with `s` edge values: `1`, `N-1` and `(2**256-1)%N`. For the last value also include an invalid signature because not covered by other test cases. --- .../test_p256verify.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index 11661249ce..bb44bae7eb 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -124,6 +124,22 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t + Y(Spec.Gy), id="hash_max", ), + pytest.param( + H(Spec.N + 1 - Spec.Gx) + R(Spec.Gx) + S(1) + X(Spec.Gx) + Y(Spec.Gy), + id="s_1", + ), + pytest.param( + H(Spec.N - 1 - Spec.Gx) + R(Spec.Gx) + S(Spec.N - 1) + X(Spec.Gx) + Y(Spec.Gy), + id="s_N_minus_1", + ), + pytest.param( + H(((2**256 - 1) % Spec.N) - Spec.Gx + Spec.N) + + R(Spec.Gx) + + S((2**256 - 1) % Spec.N) + + X(Spec.Gx) + + Y(Spec.Gy), + id="s_max_mod_N", + ), pytest.param( H(0xC3D3BE9EB3577F217AE0AB360529A30B18ADC751AEC886328593D7D6FE042809) + R(0x3A4E97B44CBF88B90E6205A45BA957E520F63F3C6072B53C244653278A1819D8) @@ -205,6 +221,10 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact Spec.H0 + Spec.R0 + S(Spec.N) + Spec.X0 + Spec.Y0, id="s_eq_to_n", ), + pytest.param( + Spec.H0 + R(Spec.Gx) + S((2**256 - 1) % Spec.N) + X(Spec.Gx) + Y(Spec.Gy), + id="s_max_mod_N", + ), pytest.param( Spec.H0 + Spec.R0 + Spec.S0 + X(Spec.P) + Spec.Y0, id="x_eq_to_p", From 8def6e3775f358edd1cbb0460aac5a23f7f86fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2025 14:04:17 +0200 Subject: [PATCH 044/102] feat(tests): add test cases for P256 with zero h, r, s (#2216) Add better test inputs for the `p256verify` precompile where at least `r` or `s` is `0 mod N`. There test cases represent invalid inputs but in some category of incorrect implementations have chance to be positively verified. --- .../test_p256verify.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index bb44bae7eb..5da6e6215c 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -221,6 +221,44 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact Spec.H0 + Spec.R0 + S(Spec.N) + Spec.X0 + Spec.Y0, id="s_eq_to_n", ), + # If checks for r, s, and point-at-infinity are missing, the s=0 zeros + # both u1 and u2, so the computed R is the point at infinity, + # and the signature may be considered valid in such implementation. + pytest.param( + Spec.H0 + R(0) + S(0) + X(Spec.Gx) + Y(Spec.Gy), + id="r_0_s_0", + ), + pytest.param( + Spec.H0 + R(0) + S(Spec.N) + X(Spec.Gx) + Y(Spec.Gy), + id="r_0_s_N", + ), + pytest.param( + Spec.H0 + R(Spec.N) + S(0) + X(Spec.Gx) + Y(Spec.Gy), + id="r_N_s_0", + ), + pytest.param( + Spec.H0 + R(Spec.N) + S(Spec.N) + X(Spec.Gx) + Y(Spec.Gy), + id="r_N_s_N", + ), + # If checks for r and point-at-infinity are missing, the h=0 and r=0 + # zero both u1 and u2, so the computed R is the point at infinity, + # and the signature may be considered valid in such implementation. + pytest.param( + H(0) + R(0) + Spec.S0 + X(Spec.Gx) + Y(Spec.Gy), + id="hash_0_r_0", + ), + pytest.param( + H(0) + R(Spec.N) + Spec.S0 + X(Spec.Gx) + Y(Spec.Gy), + id="hash_0_r_N", + ), + pytest.param( + H(Spec.N) + R(0) + Spec.S0 + X(Spec.Gx) + Y(Spec.Gy), + id="hash_N_r_0", + ), + pytest.param( + H(Spec.N) + R(Spec.N) + Spec.S0 + X(Spec.Gx) + Y(Spec.Gy), + id="hash_N_r_N", + ), pytest.param( Spec.H0 + R(Spec.Gx) + S((2**256 - 1) % Spec.N) + X(Spec.Gx) + Y(Spec.Gy), id="s_max_mod_N", From 8f0f7ba38cc40fbbbdd716c65720caf1400eb9e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2025 14:09:45 +0200 Subject: [PATCH 045/102] feat(tests): add test case with invalid P256 with x1 above N (#2217) Add new test case with invalid P256 signature with `x1 >= N`. These input values are hard to find because requires very small `r`. Produce the test case by modifying an existing valid signature with `x1 >= N`. --- osaka/eip7951_p256verify_precompiles/spec.py | 9 +++++++++ .../test_p256verify.py | 20 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/osaka/eip7951_p256verify_precompiles/spec.py b/osaka/eip7951_p256verify_precompiles/spec.py index d4cb594e03..277897f0ca 100644 --- a/osaka/eip7951_p256verify_precompiles/spec.py +++ b/osaka/eip7951_p256verify_precompiles/spec.py @@ -115,6 +115,15 @@ class Spec: X0 = X(0x2927B10512BAE3EDDCFE467828128BAD2903269919F7086069C8C4DF6C732838) Y0 = Y(0xC7787964EAAC00E5921FB1498A60F4606766B3D9685001558D1A974E7341513E) + # Test constants from: + # https://github.com/C2SP/wycheproof/blob/4a6c2bf5dc4c0b67c770233ad33961ee653996a0/testvectors/ecdsa_webcrypto_test.json#L1064 + # k*G has a large x-coordinate which also gives very small r. + H1 = H(0x532EAABD9574880DBF76B9B8CC00832C20A6EC113D682299550D7A6E0F345E25) + R1 = R(0x000000000000000000000000000000004319055358E8617B0C46353D039CDAAB) + S1 = S(0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E) + X1 = X(0xD705D16F80987E2D9B1A6957D29CE22FEBF7D10FA515153182415C8361BAACA4) + Y1 = Y(0xB1FC105EE5CE80D514EC1238BEAE2037A6F83625593620D460819E8682160926) + @staticmethod def delegation_designation(address: Address) -> Bytes: """Return delegation designation for the given address.""" diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index 5da6e6215c..64475db80a 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -715,7 +715,25 @@ def test_precompile_will_return_success_with_tx_value( + X(0x0AD99500288D466940031D72A9F5445A4D43784640855BF0A69874D2DE5FE103) + Y(0xC5011E6EF2C42DCD50D5D3D29F99AE6EBA2C80C9244F4C5422F0979FF0C3BA5E), Spec.SUCCESS_RETURN_VALUE, - id="modular_comparison_x_coordinate_exceeds_n", + id="x_coordinate_exceeds_n", + ), + pytest.param( + Spec.H1 + Spec.R1 + Spec.S1 + Spec.X1 + Spec.Y1, + Spec.SUCCESS_RETURN_VALUE, + id="x_coordinate_exceeds_n_v2", + ), + # Test cases where compute x-coordinate exceeds curve order N, + # but the signature is invalid. + # This is a modification of the above test by taking -h, -r, -s + # what gives the same u1 and u2 and in the result the same point R. + pytest.param( + H(Spec.N - Spec.H1.value) + + R(Spec.N - Spec.R1.value) + + S(Spec.N - Spec.S1.value) + + Spec.X1 + + Spec.Y1, + Spec.INVALID_RETURN_VALUE, + id="invalid_x_coordinate_exceeds_n", ), pytest.param( Spec.H0 From 6d4be4e819a3713aa65ec6c48c726ee8bc7020ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2025 14:15:32 +0200 Subject: [PATCH 046/102] feat(tests): add test case for point doubling in P256 (#2218) Synthesize the `p256verify` precompile inputs where `u1 == u2` in two variants: `Q == G` and `Q != G`. In the first variant the computation of `R` involves point doubling. --- .../test_p256verify.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index 64475db80a..5dc256b053 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -156,6 +156,25 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t + Y(0x99B7A386F1D07C29DBCC42A27B5F9449ABE3D50DE25178E8D7407A95E8B06C0B), id="x_0_y_negative", ), + # Test case for u1==u2 and Q==G. + # This test case is important because u1*G + u2*Q is point doubling. + pytest.param( + H(0x7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978) + + R(0x7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978) + + S(0x830D84E672FCB08275ADC7FCFB4AE53BFC5D90CB2F25834F4DAE81C6B4FC8BD9) + + X(Spec.Gx) + + Y(Spec.Gy), + id="u1_eq_u2_and_Q_eq_G", + ), + # Test case for u1==u2 and Q!=G. + pytest.param( + H(0x65FB4407BCB2A33AE2E486366BAA79B3A8A17A83DDE0FED6F09014A8AC6F78A1) + + R(0x65FB4407BCB2A33AE2E486366BAA79B3A8A17A83DDE0FED6F09014A8AC6F78A1) + + S(0x65FB4407BCB2A33AE2E486366BAA79B3A8A17A83DDE0FED6F09014A8AC6F78A1) + + Spec.X0 + + Spec.Y0, + id="u1_eq_u2_and_Q_ne_G", + ), ], ) @pytest.mark.parametrize("expected_output", [Spec.SUCCESS_RETURN_VALUE], ids=[""]) From 3021a42861e058403b2053fa4d3423609ea7c088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2025 14:23:49 +0200 Subject: [PATCH 047/102] feat(tests): add test case for P256 with r max value (#2229) This test uses the max value for the `r` element of the `p256verify` precompile input. This is added for completeness only as there is no practical way to generate a semi-valid signature with arbitrary `r`. --- osaka/eip7951_p256verify_precompiles/test_p256verify.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index 5dc256b053..1b64c27a02 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -232,6 +232,10 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact Spec.H0 + R(Spec.N) + Spec.S0 + Spec.X0 + Spec.Y0, id="r_eq_to_n", ), + pytest.param( + Spec.H0 + R(2**256 - 1) + Spec.S0 + Spec.X0 + Spec.Y0, + id="r_max", + ), pytest.param( Spec.H0 + Spec.R0 + S(0) + Spec.X0 + Spec.Y0, id="s_eq_to_zero", From 63a19cf6edb05cef3b6517c5f26069a8b9dd62ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2025 15:40:40 +0200 Subject: [PATCH 048/102] feat(tests): add test cases for P256 for r,s above N (#2230) Add new test cases for the `p256verify` precompile where the input elements `r` or `s`are out of range by being greater than `N`. Moreover, the equivalent signatures taking `r % N` or `s % N` are valid. These have chance to detect implementations which don't perform proper range checks and pass `r` or `s` to Montgomery form. --- .../test_p256verify.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index 1b64c27a02..51b2a80cb2 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -232,6 +232,10 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact Spec.H0 + R(Spec.N) + Spec.S0 + Spec.X0 + Spec.Y0, id="r_eq_to_n", ), + pytest.param( + Spec.H1 + R(Spec.R1.value + Spec.N) + Spec.S1 + Spec.X1 + Spec.Y1, + id="r_above_n", + ), pytest.param( Spec.H0 + R(2**256 - 1) + Spec.S0 + Spec.X0 + Spec.Y0, id="r_max", @@ -286,6 +290,18 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact Spec.H0 + R(Spec.Gx) + S((2**256 - 1) % Spec.N) + X(Spec.Gx) + Y(Spec.Gy), id="s_max_mod_N", ), + pytest.param( + H(Spec.N + 1 - Spec.Gx) + R(Spec.Gx) + S(Spec.N + 1) + X(Spec.Gx) + Y(Spec.Gy), + id="s_N_plus_1", + ), + pytest.param( + H(((2**256 - 1) % Spec.N) - Spec.Gx + Spec.N) + + R(Spec.Gx) + + S(2**256 - 1) + + X(Spec.Gx) + + Y(Spec.Gy), + id="s_max", + ), pytest.param( Spec.H0 + Spec.R0 + Spec.S0 + X(Spec.P) + Spec.Y0, id="x_eq_to_p", From 330d15836b9808147fd846e5916783b813c41df9 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Tue, 30 Sep 2025 21:19:16 +0200 Subject: [PATCH 049/102] new(tests): Identity precompile (#1047) --- homestead/identity_precompile/__init__.py | 1 + .../identity_precompile/test_identity.py | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 homestead/identity_precompile/__init__.py create mode 100644 homestead/identity_precompile/test_identity.py diff --git a/homestead/identity_precompile/__init__.py b/homestead/identity_precompile/__init__.py new file mode 100644 index 0000000000..786785884f --- /dev/null +++ b/homestead/identity_precompile/__init__.py @@ -0,0 +1 @@ +"""abstract: EIP-2: Homestead Precompile Identity Test Cases.""" diff --git a/homestead/identity_precompile/test_identity.py b/homestead/identity_precompile/test_identity.py new file mode 100644 index 0000000000..376c7a7914 --- /dev/null +++ b/homestead/identity_precompile/test_identity.py @@ -0,0 +1,98 @@ +"""abstract: EIP-2: Homestead Identity Precompile Test Cases.""" + +import pytest + +from ethereum_test_tools import ( + Account, + Alloc, + Environment, + StateTestFiller, + Transaction, + keccak256, +) +from ethereum_test_tools import Opcodes as Op + + +@pytest.mark.with_all_call_opcodes() +@pytest.mark.valid_from("Byzantium") +def test_identity_return_overwrite( + state_test: StateTestFiller, + pre: Alloc, + call_opcode: Op, +): + """Test the return data of the identity precompile overwriting its input.""" + code = ( + sum(Op.MSTORE8(offset=i, value=(i + 1)) for i in range(4)) # memory = [1, 2, 3, 4] + + call_opcode( + address=4, + args_offset=0, + args_size=4, # args = [1, 2, 3, 4] + ret_offset=1, + ret_size=4, + ) # memory = [1, 1, 2, 3, 4] + + Op.RETURNDATACOPY( + dest_offset=0, offset=0, size=Op.RETURNDATASIZE() + ) # memory correct = [1, 2, 3, 4, 4], corrupt = [1, 1, 2, 3, 4] + + Op.SSTORE(1, Op.SHA3(offset=0, size=Op.MSIZE)) + ) + contract_address = pre.deploy_contract( + code=code, + ) + tx = Transaction( + sender=pre.fund_eoa(), + to=contract_address, + gas_limit=100_000, + ) + + post = { + contract_address: Account( + storage={ + 1: keccak256(bytes([1, 2, 3, 4, 4]).ljust(32, b"\0")), + }, + ), + } + + state_test(pre=pre, post=post, tx=tx) + + +@pytest.mark.with_all_call_opcodes() +@pytest.mark.valid_from("Byzantium") +def test_identity_return_buffer_modify( + state_test: StateTestFiller, + pre: Alloc, + call_opcode: Op, +): + """Test the modification of the input range to attempt to modify the return buffer.""" + env = Environment() + code = ( + sum(Op.MSTORE8(offset=i, value=(i + 1)) for i in range(4)) # memory = [1, 2, 3, 4] + + call_opcode( + address=4, + args_offset=0, + args_size=4, # args = [1, 2, 3, 4] + ) # memory = [1, 2, 3, 4] + + Op.MSTORE8(offset=0, value=5) # memory = [5, 2, 3, 4] + + Op.MSTORE8(offset=4, value=5) # memory = [5, 2, 3, 4, 5] + + Op.RETURNDATACOPY( + dest_offset=0, offset=0, size=Op.RETURNDATASIZE() + ) # memory correct = [1, 2, 3, 4, 5], corrupt = [5, 2, 3, 4, 5] + + Op.SSTORE(1, Op.SHA3(offset=0, size=Op.MSIZE)) + ) + contract_address = pre.deploy_contract( + code=code, + ) + tx = Transaction( + sender=pre.fund_eoa(), + to=contract_address, + gas_limit=100_000, + ) + + post = { + contract_address: Account( + storage={ + 1: keccak256(bytes([1, 2, 3, 4, 5]).ljust(32, b"\0")), + }, + ), + } + + state_test(env=env, pre=pre, post=post, tx=tx) From 21a3dd0b1fb9a2ab4ebb211bf8b529144469b630 Mon Sep 17 00:00:00 2001 From: felipe Date: Tue, 30 Sep 2025 16:14:51 -0600 Subject: [PATCH 050/102] Fix/warnings (#2239) * fix: warnings - closes #1009 * fix: lint errors on main * fix: del unused param --- homestead/identity_precompile/test_identity.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/homestead/identity_precompile/test_identity.py b/homestead/identity_precompile/test_identity.py index 376c7a7914..b818079738 100644 --- a/homestead/identity_precompile/test_identity.py +++ b/homestead/identity_precompile/test_identity.py @@ -20,7 +20,9 @@ def test_identity_return_overwrite( pre: Alloc, call_opcode: Op, ): - """Test the return data of the identity precompile overwriting its input.""" + """ + Test the return data of the identity precompile overwriting its input. + """ code = ( sum(Op.MSTORE8(offset=i, value=(i + 1)) for i in range(4)) # memory = [1, 2, 3, 4] + call_opcode( @@ -62,7 +64,10 @@ def test_identity_return_buffer_modify( pre: Alloc, call_opcode: Op, ): - """Test the modification of the input range to attempt to modify the return buffer.""" + """ + Test the modification of the input range to attempt to modify the return + buffer. + """ env = Environment() code = ( sum(Op.MSTORE8(offset=i, value=(i + 1)) for i in range(4)) # memory = [1, 2, 3, 4] From b72bc3f8d015e8ae430ad7ac500e7191753b7bec Mon Sep 17 00:00:00 2001 From: felipe Date: Tue, 30 Sep 2025 16:14:51 -0600 Subject: [PATCH 051/102] Fix/warnings (#2239) * fix: warnings - closes #1009 * fix: lint errors on main * fix: del unused param --- ethereum_clis/transition_tool.py | 2 +- ethereum_test_specs/blockchain.py | 19 +++++++++---------- ethereum_test_specs/static_state/account.py | 8 ++------ .../static_state/environment.py | 7 ++----- .../static_state/general_transaction.py | 7 ++----- .../static_state/state_static.py | 7 ++----- pytest_plugins/eels_resolver.py | 6 +++--- 7 files changed, 21 insertions(+), 35 deletions(-) diff --git a/ethereum_clis/transition_tool.py b/ethereum_clis/transition_tool.py index 80e5ba3a85..41875d3750 100644 --- a/ethereum_clis/transition_tool.py +++ b/ethereum_clis/transition_tool.py @@ -479,8 +479,8 @@ def _evaluate_stream( output.result.traces = self.collect_traces( output.result.receipts, temp_dir, debug_output_path ) - temp_dir.cleanup() + temp_dir.cleanup() return output def safe_t8n_args( diff --git a/ethereum_test_specs/blockchain.py b/ethereum_test_specs/blockchain.py index 6669ab2f27..810090d235 100644 --- a/ethereum_test_specs/blockchain.py +++ b/ethereum_test_specs/blockchain.py @@ -4,7 +4,7 @@ from typing import Any, Callable, ClassVar, Dict, Generator, List, Sequence, Tuple, Type import pytest -from pydantic import ConfigDict, Field, field_validator +from pydantic import ConfigDict, Field, field_validator, model_serializer from ethereum_clis import BlockExceptionWithMessage, Result, TransitionTool from ethereum_test_base_types import ( @@ -141,15 +141,14 @@ class Header(CamelModel): engine_api_error_code=EngineAPIError.InvalidParams, ) ``` """ - model_config = ConfigDict( - arbitrary_types_allowed=True, - # explicitly set Removable items to None so they are not included in - # the serialization (in combination with exclude_None=True in - # model.dump()). - json_encoders={ - Removable: lambda x: None, - }, - ) + model_config = ConfigDict(arbitrary_types_allowed=True) + + @model_serializer(mode="wrap", when_used="json") + def _serialize_model(self, serializer, info): + """Exclude Removable fields from serialization.""" + del info + data = serializer(self) + return {k: v for k, v in data.items() if not isinstance(v, Removable)} @field_validator("withdrawals_root", mode="before") @classmethod diff --git a/ethereum_test_specs/static_state/account.py b/ethereum_test_specs/static_state/account.py index 978312f9b2..70f4ecbdea 100644 --- a/ethereum_test_specs/static_state/account.py +++ b/ethereum_test_specs/static_state/account.py @@ -2,7 +2,7 @@ from typing import Any, Dict, List, Mapping, Set, Tuple -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict from ethereum_test_base_types import Bytes, EthereumTestRootModel, HexNumber, Storage from ethereum_test_types import Alloc @@ -54,11 +54,7 @@ class AccountInFiller(BaseModel, TagDependentData): nonce: ValueInFiller | None = None storage: StorageInPre | None = None - class Config: - """Model Config.""" - - extra = "forbid" - arbitrary_types_allowed = True # For CodeInFiller + model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid") def tag_dependencies(self) -> Mapping[str, Tag]: """Get tag dependencies.""" diff --git a/ethereum_test_specs/static_state/environment.py b/ethereum_test_specs/static_state/environment.py index 8ad5f09905..5f4525b0f6 100644 --- a/ethereum_test_specs/static_state/environment.py +++ b/ethereum_test_specs/static_state/environment.py @@ -2,7 +2,7 @@ from typing import Any, Dict -from pydantic import BaseModel, Field, model_validator +from pydantic import BaseModel, ConfigDict, Field, model_validator from ethereum_test_base_types import Address from ethereum_test_types import Environment @@ -26,10 +26,7 @@ class EnvironmentInStateTestFiller(BaseModel): current_excess_blob_gas: ValueInFiller | None = Field(None, alias="currentExcessBlobGas") - class Config: - """Model Config.""" - - extra = "forbid" + model_config = ConfigDict(extra="forbid") @model_validator(mode="after") def check_fields(self) -> "EnvironmentInStateTestFiller": diff --git a/ethereum_test_specs/static_state/general_transaction.py b/ethereum_test_specs/static_state/general_transaction.py index cafec7778c..7a649fc9de 100644 --- a/ethereum_test_specs/static_state/general_transaction.py +++ b/ethereum_test_specs/static_state/general_transaction.py @@ -2,7 +2,7 @@ from typing import Any, Dict, Generator, List, Mapping -from pydantic import BaseModel, Field, field_validator, model_validator +from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from ethereum_test_base_types import Address, CamelModel, EthereumTestRootModel, Hash from ethereum_test_exceptions import TransactionExceptionInstanceOrList @@ -127,10 +127,7 @@ class GeneralTransactionInFiller(BaseModel, TagDependentData): max_fee_per_blob_gas: ValueInFiller | None = Field(None, alias="maxFeePerBlobGas") blob_versioned_hashes: List[Hash] | None = Field(None, alias="blobVersionedHashes") - class Config: - """Model Config.""" - - extra = "forbid" + model_config = ConfigDict(extra="forbid") def tag_dependencies(self) -> Mapping[str, Tag]: """Get tag dependencies.""" diff --git a/ethereum_test_specs/static_state/state_static.py b/ethereum_test_specs/static_state/state_static.py index 322691b4cf..3f77eca94c 100644 --- a/ethereum_test_specs/static_state/state_static.py +++ b/ethereum_test_specs/static_state/state_static.py @@ -4,7 +4,7 @@ import pytest from _pytest.mark.structures import ParameterSet -from pydantic import BaseModel, Field, model_validator +from pydantic import BaseModel, ConfigDict, Field, model_validator from ethereum_test_forks import Fork from ethereum_test_types import Alloc @@ -37,10 +37,7 @@ class StateStaticTest(BaseStaticTest): transaction: GeneralTransactionInFiller expect: List[ExpectSectionInStateTestFiller] - class Config: - """Model Config.""" - - extra = "forbid" + model_config = ConfigDict(extra="forbid") def model_post_init(self, context): """Initialize StateStaticTest.""" diff --git a/pytest_plugins/eels_resolver.py b/pytest_plugins/eels_resolver.py index d78ee9b9db..36622d73e6 100644 --- a/pytest_plugins/eels_resolver.py +++ b/pytest_plugins/eels_resolver.py @@ -61,19 +61,19 @@ def pytest_configure(config: pytest.Config) -> None: config._eels_resolutions_file = eels_resolutions_file # type: ignore -def pytest_report_header(config: pytest.Config, startdir: Path) -> str: +def pytest_report_header(config: pytest.Config, start_path: Path) -> str: """ Report the EELS_RESOLUTIONS_FILE path to the pytest report header. Args: config (pytest.Config): The pytest configuration object. - startdir (Path): The starting directory for the test run. + start_path (Path): The starting directory for the test run. Returns: str: A string to add to the pytest report header. """ - del startdir + del start_path eels_resolutions_file = getattr(config, "_eels_resolutions_file", None) if eels_resolutions_file: From 83860d04c7593b0d00015135efb909868a24116c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Oct 2025 17:09:47 +0200 Subject: [PATCH 052/102] feat(tests): add test case for P256 with Q at infinity (#2235) Add a test case for the `p256verify` precompile with the input having public key (Q) as the point-at-infinity. If the implementation misses the check that Q is not at infinity, the signature should verify. --- .../test_p256verify.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index 51b2a80cb2..f8f04878f9 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -312,7 +312,17 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact ), pytest.param( Spec.H0 + Spec.R0 + Spec.S0 + X(0) + Y(0), - id="point_on_infinity", + id="point_at_infinity", + ), + # Test case with Q at infinity. If the implementation misses the check + # that Q is not the point at infinity, the signature should verify. + pytest.param( + Spec.H0 + + R(0x2DD5CBB0E37BAEC8D1460909B206CA2C87E50CA43B8F31E46168027A7F0AEEC6) + + Spec.S0 + + X(0) + + Y(0), + id="point_at_infinity_v2", ), pytest.param( Spec.H0 + Spec.R0 + Spec.S0 + X(Spec.X0.value + 1) + Spec.Y0, From 212557fc9ea643e250274c9b4abfd7e9908df1da Mon Sep 17 00:00:00 2001 From: SDartayet <44068466+SDartayet@users.noreply.github.com> Date: Wed, 1 Oct 2025 12:58:22 -0300 Subject: [PATCH 053/102] chore(cli): update exception mapping for ethrex (#2226) * Changed intrinsic gas too low for gas below floor gas cost * Fixing wrongly removing intrinsic gas too low error * Fixing message for intrinsic gas too low error * Improved error messages * Added mapping for nonce is max error --- ethereum_clis/clis/ethrex.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ethereum_clis/clis/ethrex.py b/ethereum_clis/clis/ethrex.py index 1d3c17a58d..c001d6cf54 100644 --- a/ethereum_clis/clis/ethrex.py +++ b/ethereum_clis/clis/ethrex.py @@ -63,7 +63,10 @@ class EthrexExceptionMapper(ExceptionMapper): ), TransactionException.INTRINSIC_GAS_TOO_LOW: ( r"gas floor exceeds the gas limit|call gas cost exceeds the gas limit|" - r"Intrinsic gas too low" + r"Transaction gas limit lower than the minimum gas cost to execute the transaction" + ), + TransactionException.INTRINSIC_GAS_BELOW_FLOOR_GAS_COST: ( + r"Transaction gas limit lower than the gas cost floor for calldata tokens" ), TransactionException.INSUFFICIENT_MAX_FEE_PER_GAS: ( r"gas price is less than basefee|Insufficient max fee per gas" @@ -75,6 +78,7 @@ class EthrexExceptionMapper(ExceptionMapper): TransactionException.INITCODE_SIZE_EXCEEDED: ( r"create initcode size limit|Initcode size exceeded.*" ), + TransactionException.NONCE_IS_MAX: (r"Nonce is max"), TransactionException.GAS_ALLOWANCE_EXCEEDED: (r"Gas allowance exceeded.*"), TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED: (r"Blob count exceeded.*"), BlockException.SYSTEM_CONTRACT_CALL_FAILED: (r"System call failed.*"), From 05e0cd2693961f34037a2b6eb84a5b90dcb40937 Mon Sep 17 00:00:00 2001 From: CPerezz <37264926+CPerezz@users.noreply.github.com> Date: Wed, 1 Oct 2025 18:14:35 +0200 Subject: [PATCH 054/102] feat(tests): multi opcode bloatnet ext cases (#2186) * Add BloatNet tests Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> * try building the contract Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> * fix: SSTORE 0 -> 1 match all values in the state Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> * add the tx for 0 -> 1 and 1 -> 2 Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> * fix: linter issues Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> * remove more whitespaces Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> remove leftover single whitespace :| * fix formatting * move to benchmarks Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> * fix linter value * use the gas limit from the environment * parameterize the written value in SSTORE * fix linter issues * update CHANGELOG.md * fix format * simplify syntax * fix: start with an empty contract storage * more fixes, but the result is still incorrect * fix: finally fix the tests * linter fix * add SLOAD tests * test(benchmark): implement CREATE2 addressing for bloatnet tests - Add CREATE2 deterministic address calculation to overcome 24KB bytecode limit - Fix While loop condition to properly iterate through contracts - Account for memory expansion costs in gas calculations - Add safety margins (50k gas reserve, 98% utilization) for stability - Tests now scale to any gas limit without bytecode constraints - Achieve 98% gas utilization with 10M and 20M gas limits * refactor(benchmark): optimize gas calculations in bloatnet tests - Remove gas reserve and 98% utilization logic for contract calculations - Directly calculate the number of contracts based on available gas - Introduce precise expected gas usage calculations for better accuracy - Ensure tests scale effectively without unnecessary constraints * refactor(benchmark): bloatnet tests with unique bytecode for I/O optimization - Update tests to generate unique bytecode for each contract, maximizing I/O reads during benchmarks. - Clarify comments regarding bytecode generation and its impact on gas costs. - Ensure CREATE2 addresses are calculated consistently using a base bytecode template. - Improve test descriptions to reflect the changes in contract deployment strategy. * refactor(benchmark): replace custom CREATE2 address calculation with utility function - Remove the custom `calculate_create2_address` function in favor of the `compute_create2_address` utility. - Update tests to utilize the new utility for consistent CREATE2 address calculations. - Simplify code by eliminating unnecessary complexity in address calculation logic. - Ensure that the CREATE2 prefix is directly set to 0xFF in the memory operation for clarity. * CREATE2 factory approach working * Version with EIP-7997 model working * refactor(benchmark): imrpove contract deployment script with interactive selection and bytecode generation - Introduced interactive contract type selection for deploying contracts in the bloatnet benchmark. - Added support for multiple contract types: max_size_24kb, sload_heavy, storage_heavy, and custom. - Refactored bytecode generation functions to improve clarity and maintainability. - Updated README to reflect changes in deployment process and contract types. - Ensured proper handling of factory deployment and transaction receipt checks. * delete: remove obsolete test_create2.py script This was commited unintentionally * refactor(benchmark): optimize gas calculations for BALANCE + EXTCODECOPY pattern - Updated the README to reflect the optimized gas cost for the BALANCE + EXTCODECOPY pattern, reducing it from ~5,007 to ~2,710 gas per contract. - Modified the test_bloatnet_balance_extcodecopy function to read only 1 byte from the end of the bytecode, minimizing gas costs while maximizing contract targeting. - Adjusted calculations for the number of contracts needed based on the new cost per contract, ensuring accurate benchmarks. * refactor(benchmark): support non-fixed max_codesize * chore: Remove all 24kB "hardcoded" refs * fix: pre-commit lint hooks * push updated deploy_create2_factory refactored with EEST as dep * refactor(benchmark): enhance CREATE2 factory deployment and testing - Updated the deploy_create2_factory_refactored.py script to improve the deployment of a CREATE2 factory with an initcode template, allowing for dynamic contract address generation. - Modified test_bloatnet.py to support on-the-fly CREATE2 address generation, optimizing gas costs and improving test accuracy. - Adjusted gas cost calculations in the README to reflect the new deployment approach, ensuring accurate benchmarks for BloatNet tests. * remove: old_deploy_factory script * chore: address PR review fixes * fix(benchmark): correct import path for ethereum_test_vm * chore(benchmark): update according to review comments Also, renamed the test file to include only multi-opcode tests there and have a more clean directory for future test inclusions. * refactor(benchmark): remove hardcoded parameters storing inside factory stub - Fixed offset at which we COPYCODE - Removed hardcoded values and added comments for clarity on factory storage layout and contract generation. * chore: update pyproject.toml configuration * refactor: rename test_mutiopcode.py to test_muti_opcode.py for consistency * fix: correct import sorting in test_muti_opcode.py to fix CI lint error * fix(benchmark): rename test file to fix typo Rename test_muti_opcode.py to test_multi_opcode.py to fix filename typo * fix(benchmark): update BloatNet tests to use factory's getConfig() method Replace direct storage access with STATICCALL to factory's getConfig() method in both test_bloatnet_balance_extcodesize and test_bloatnet_balance_extcodecopy. Changes: - Use STATICCALL to retrieve configuration from factory instead of SLOAD - Add proper error handling for failed configuration calls - Remove gas-limiting calculations, allowing tests to run until gas exhaustion - Store configuration data in memory positions 96 and 128 for cleaner access This makes the tests more robust and better aligned with the factory's public interface, avoiding direct storage access assumptions. * refactor(benchmark): enhance BloatNet test documentation and gas cost calculations * revert: restore pyproject.toml to match main branch Remove all changes to pyproject.toml to align with upstream main branch. This ensures CI compatibility and prevents configuration conflicts. * fix(benchmark): resolve W505 doc line length issues in test_multi_opcode.py Fixed all documentation and comment lines exceeding 79 characters to comply with lint requirements. * refactor(benchmark): simplify STATICCALL usage in BloatNet tests. * feat(benchmark): add gas exhaustion validation using expected_receipt Implement solution to address reviewer's concern about test validation by using EEST's expected_receipt feature to validate that benchmarks consume all gas. Changes: - Add TransactionReceipt import - Add expected_receipt to both test transactions validating gas_used equals gas_limit - Remove skip_gas_used_validation flag as validation is now explicit This ensures tests can distinguish between: - Early failure from invalid jump (~50K gas) indicating setup issues - Full gas exhaustion (all gas consumed) indicating successful benchmark run The invalid jump remains as a fail-fast mechanism for STATICCALL failures, while expected_receipt validates the benchmark actually executed. * fix(benchmark): restore skip_gas_used_validation flag Re-add skip_gas_used_validation=True to both blockchain_test calls as it was accidentally removed. This flag is still needed alongside the expected_receipt validation. * refactor(benchmark): improve readability using kwargs syntax for opcodes Apply reviewer suggestions to use more readable kwargs syntax for memory and stack operations throughout both test functions. Changes: - Use Op.MLOAD(offset) instead of Op.PUSH1(offset) + Op.MLOAD - Use Op.MSTORE(offset, value) for cleaner memory writes - Use Op.SHA3(offset, length) for hash operations - Use Op.POP(Op.BALANCE) and Op.POP(Op.EXTCODESIZE) for cleaner stack ops - Combine increment operations into single Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)) This makes the bytecode generation more concise and easier to understand. * fix(benchmark): shorten comment lines to meet doc length limit * fix(benchmark): correct MSTORE operation to store init_code_hash properly * fix(benchmark): address review comments - remove redundant validation and fix ADD syntax --------- Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> --- benchmark/bloatnet/__init__.py | 1 + benchmark/bloatnet/test_multi_opcode.py | 315 ++++++++++++++++++++++++ 2 files changed, 316 insertions(+) create mode 100644 benchmark/bloatnet/__init__.py create mode 100644 benchmark/bloatnet/test_multi_opcode.py diff --git a/benchmark/bloatnet/__init__.py b/benchmark/bloatnet/__init__.py new file mode 100644 index 0000000000..0f0656c832 --- /dev/null +++ b/benchmark/bloatnet/__init__.py @@ -0,0 +1 @@ +"""BloatNet benchmark tests for Ethereum execution spec tests.""" diff --git a/benchmark/bloatnet/test_multi_opcode.py b/benchmark/bloatnet/test_multi_opcode.py new file mode 100644 index 0000000000..4d27d6fca4 --- /dev/null +++ b/benchmark/bloatnet/test_multi_opcode.py @@ -0,0 +1,315 @@ +""" +abstract: BloatNet bench cases extracted from https://hackmd.io/9icZeLN7R0Sk5mIjKlZAHQ. + + The idea of all these tests is to stress client implementations to find out + where the limits of processing are focusing specifically on state-related + operations. +""" + +import pytest + +from ethereum_test_forks import Fork +from ethereum_test_tools import ( + Account, + Alloc, + Block, + BlockchainTestFiller, + Transaction, + While, +) +from ethereum_test_vm import Bytecode +from ethereum_test_vm import Opcodes as Op + +REFERENCE_SPEC_GIT_PATH = "DUMMY/bloatnet.md" +REFERENCE_SPEC_VERSION = "1.0" + + +# BLOATNET ARCHITECTURE: +# +# [Initcode Contract] [Factory Contract] [24KB Contracts] +# (9.5KB) (116B) (N x 24KB each) +# │ │ │ +# │ EXTCODECOPY │ CREATE2(salt++) │ +# └──────────────► ├──────────────────► Contract_0 +# ├──────────────────► Contract_1 +# ├──────────────────► Contract_2 +# └──────────────────► Contract_N +# +# [Attack Contract] ──STATICCALL──► [Factory.getConfig()] +# │ returns: (N, hash) +# └─► Loop(i=0 to N): +# 1. Generate CREATE2 addr: keccak256(0xFF|factory|i|hash)[12:] +# 2. BALANCE(addr) → 2600 gas (cold access) +# 3. EXTCODESIZE(addr) → 100 gas (warm access) +# +# HOW IT WORKS: +# 1. Factory uses EXTCODECOPY to load initcode, avoiding PC-relative jumps +# 2. Each CREATE2 deployment produces unique 24KB bytecode (via ADDRESS) +# 3. All contracts share same initcode hash for deterministic addresses +# 4. Attack rapidly accesses all contracts, stressing client's state handling + + +@pytest.mark.valid_from("Prague") +def test_bloatnet_balance_extcodesize( + blockchain_test: BlockchainTestFiller, + pre: Alloc, + fork: Fork, + gas_benchmark_value: int, +): + """ + BloatNet test using BALANCE + EXTCODESIZE with "on-the-fly" CREATE2 + address generation. + + This test: + 1. Assumes contracts are already deployed via the factory (salt 0 to N-1) + 2. Generates CREATE2 addresses dynamically during execution + 3. Calls BALANCE (cold) then EXTCODESIZE (warm) on each + 4. Maximizes cache eviction by accessing many contracts + """ + gas_costs = fork.gas_costs() + + # Calculate gas costs + intrinsic_gas = fork.transaction_intrinsic_cost_calculator()(calldata=b"") + + # Cost per contract access with CREATE2 address generation + cost_per_contract = ( + gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30) + + gas_costs.G_KECCAK_256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6) + + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold BALANCE (2600) + + gas_costs.G_BASE # POP balance (2) + + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm EXTCODESIZE (100) + + gas_costs.G_BASE # POP code size (2) + + gas_costs.G_BASE # DUP1 before BALANCE (3) + + gas_costs.G_VERY_LOW * 4 # PUSH1 operations (4 * 3) + + gas_costs.G_LOW # MLOAD for salt (3) + + gas_costs.G_VERY_LOW # ADD for increment (3) + + gas_costs.G_LOW # MSTORE salt back (3) + + 10 # While loop overhead + ) + + # Calculate how many contracts to access based on available gas + available_gas = gas_benchmark_value - intrinsic_gas - 1000 # Reserve for cleanup + contracts_needed = int(available_gas // cost_per_contract) + + # Deploy factory using stub contract - NO HARDCODED VALUES + # The stub "bloatnet_factory" must be provided via --address-stubs flag + # The factory at that address MUST have: + # - Slot 0: Number of deployed contracts + # - Slot 1: Init code hash for CREATE2 address calculation + factory_address = pre.deploy_contract( + code=Bytecode(), # Required parameter, but will be ignored for stubs + stub="bloatnet_factory", + ) + + # Log test requirements - deployed count read from factory storage + print( + f"Test needs {contracts_needed} contracts for " + f"{gas_benchmark_value / 1_000_000:.1f}M gas. " + f"Factory storage will be checked during execution." + ) + + # Build attack contract that reads config from factory and performs attack + attack_code = ( + # Call getConfig() on factory to get num_deployed and init_code_hash + Op.STATICCALL( + gas=Op.GAS, + address=factory_address, + args_offset=0, + args_size=0, + ret_offset=96, + ret_size=64, + ) + # Check if call succeeded + + Op.ISZERO + + Op.PUSH2(0x1000) # Jump to error handler if failed (far jump) + + Op.JUMPI + # Load results from memory + # Memory[96:128] = num_deployed_contracts + # Memory[128:160] = init_code_hash + + Op.MLOAD(96) # Load num_deployed_contracts + + Op.MLOAD(128) # Load init_code_hash + # Setup memory for CREATE2 address generation + # Memory layout at 0: 0xFF + factory_addr(20) + salt(32) + hash(32) + + Op.MSTORE(0, factory_address) # Store factory address at memory position 0 + + Op.MSTORE8(11, 0xFF) # Store 0xFF prefix at position (32 - 20 - 1) + + Op.MSTORE(32, 0) # Store salt at position 32 + # Stack now has: [num_contracts, init_code_hash] + + Op.PUSH1(64) # Push memory position + + Op.MSTORE # Store init_code_hash at memory[64] + # Stack now has: [num_contracts] + # Main attack loop - iterate through all deployed contracts + + While( + body=( + # Generate CREATE2 addr: keccak256(0xFF+factory+salt+hash) + Op.SHA3(11, 85) # Generate CREATE2 address from memory[11:96] + # The address is now on the stack + + Op.DUP1 # Duplicate for EXTCODESIZE + + Op.POP(Op.BALANCE) # Cold access + + Op.POP(Op.EXTCODESIZE) # Warm access + # Increment salt for next iteration + + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)) # Increment and store salt + ), + # Continue while we haven't reached the limit + condition=Op.DUP1 + Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO, + ) + + Op.POP # Clean up counter + ) + + # Deploy attack contract + attack_address = pre.deploy_contract(code=attack_code) + + # Run the attack + attack_tx = Transaction( + to=attack_address, + gas_limit=gas_benchmark_value, + sender=pre.fund_eoa(), + ) + + # Post-state: just verify attack contract exists + post = { + attack_address: Account(storage={}), + } + + blockchain_test( + pre=pre, + blocks=[Block(txs=[attack_tx])], + post=post, + ) + + +@pytest.mark.valid_from("Prague") +def test_bloatnet_balance_extcodecopy( + blockchain_test: BlockchainTestFiller, + pre: Alloc, + fork: Fork, + gas_benchmark_value: int, +): + """ + BloatNet test using BALANCE + EXTCODECOPY with on-the-fly CREATE2 + address generation. + + This test forces actual bytecode reads from disk by: + 1. Assumes contracts are already deployed via the factory + 2. Generating CREATE2 addresses dynamically during execution + 3. Using BALANCE (cold) to warm the account + 4. Using EXTCODECOPY (warm) to read 1 byte from the END of the bytecode + """ + gas_costs = fork.gas_costs() + max_contract_size = fork.max_code_size() + + # Calculate costs + intrinsic_gas = fork.transaction_intrinsic_cost_calculator()(calldata=b"") + + # Cost per contract with EXTCODECOPY and CREATE2 address generation + cost_per_contract = ( + gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30) + + gas_costs.G_KECCAK_256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6) + + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold BALANCE (2600) + + gas_costs.G_BASE # POP balance (2) + + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm EXTCODECOPY base (100) + + gas_costs.G_COPY * 1 # Copy cost for 1 byte (3) + + gas_costs.G_BASE * 2 # DUP1 before BALANCE, DUP4 for address (6) + + gas_costs.G_VERY_LOW * 8 # PUSH operations (8 * 3 = 24) + + gas_costs.G_LOW * 2 # MLOAD for salt twice (6) + + gas_costs.G_VERY_LOW * 2 # ADD operations (6) + + gas_costs.G_LOW # MSTORE salt back (3) + + gas_costs.G_BASE # POP after EXTCODECOPY (2) + + 10 # While loop overhead + ) + + # Calculate how many contracts to access + available_gas = gas_benchmark_value - intrinsic_gas - 1000 + contracts_needed = int(available_gas // cost_per_contract) + + # Deploy factory using stub contract - NO HARDCODED VALUES + # The stub "bloatnet_factory" must be provided via --address-stubs flag + # The factory at that address MUST have: + # - Slot 0: Number of deployed contracts + # - Slot 1: Init code hash for CREATE2 address calculation + factory_address = pre.deploy_contract( + code=Bytecode(), # Required parameter, but will be ignored for stubs + stub="bloatnet_factory", + ) + + # Log test requirements - deployed count read from factory storage + print( + f"Test needs {contracts_needed} contracts for " + f"{gas_benchmark_value / 1_000_000:.1f}M gas. " + f"Factory storage will be checked during execution." + ) + + # Build attack contract that reads config from factory and performs attack + attack_code = ( + # Call getConfig() on factory to get num_deployed and init_code_hash + Op.STATICCALL( + gas=Op.GAS, + address=factory_address, + args_offset=0, + args_size=0, + ret_offset=96, + ret_size=64, + ) + # Check if call succeeded + + Op.ISZERO + + Op.PUSH2(0x1000) # Jump to error handler if failed (far jump) + + Op.JUMPI + # Load results from memory + # Memory[96:128] = num_deployed_contracts + # Memory[128:160] = init_code_hash + + Op.MLOAD(96) # Load num_deployed_contracts + + Op.MLOAD(128) # Load init_code_hash + # Setup memory for CREATE2 address generation + # Memory layout at 0: 0xFF + factory_addr(20) + salt(32) + hash(32) + + Op.MSTORE(0, factory_address) # Store factory address at memory position 0 + + Op.MSTORE8(11, 0xFF) # Store 0xFF prefix at position (32 - 20 - 1) + + Op.MSTORE(32, 0) # Store salt at position 32 + # Stack now has: [num_contracts, init_code_hash] + + Op.PUSH1(64) # Push memory position + + Op.MSTORE # Store init_code_hash at memory[64] + # Stack now has: [num_contracts] + # Main attack loop - iterate through all deployed contracts + + While( + body=( + # Generate CREATE2 address + Op.SHA3(11, 85) # Generate CREATE2 address from memory[11:96] + # The address is now on the stack + + Op.DUP1 # Duplicate for later operations + + Op.POP(Op.BALANCE) # Cold access + # EXTCODECOPY(addr, mem_offset, last_byte_offset, 1) + # Read the LAST byte to force full contract load + + Op.PUSH1(1) # size (1 byte) + + Op.PUSH2(max_contract_size - 1) # code offset (last byte) + # Use salt as memory offset to avoid overlap + + Op.ADD(Op.MLOAD(32), 96) # Add base memory offset for unique position + + Op.DUP4 # address (duplicated earlier) + + Op.EXTCODECOPY + + Op.POP # Clean up address + # Increment salt for next iteration + + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)) # Increment and store salt + ), + # Continue while counter > 0 + condition=Op.DUP1 + Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO, + ) + + Op.POP # Clean up counter + ) + + # Deploy attack contract + attack_address = pre.deploy_contract(code=attack_code) + + # Run the attack + attack_tx = Transaction( + to=attack_address, + gas_limit=gas_benchmark_value, + sender=pre.fund_eoa(), + ) + + # Post-state + post = { + attack_address: Account(storage={}), + } + + blockchain_test( + pre=pre, + blocks=[Block(txs=[attack_tx])], + post=post, + ) From d9901a59fc381cfce8323f21d1068c2256d05aa8 Mon Sep 17 00:00:00 2001 From: CPerezz <37264926+CPerezz@users.noreply.github.com> Date: Wed, 1 Oct 2025 18:33:20 +0200 Subject: [PATCH 055/102] fix(execute): add gas validation for benchmark tests in execute mode (#2219) * fix(execute): add gas validation for benchmark tests in execute mode Previously, execute mode was not validating that transactions consumed the expected amount of gas when expected_benchmark_gas_used was set. This could cause benchmark tests to incorrectly pass even when consuming significantly less gas than expected (e.g., due to missing factory contracts). This feature is needed by benchmark tests like the ones in #2186 in order to make sure that the benchmarks are indeed consuming all gas available or causing a failure otherwise when the flag is set. Changes: - Add expected_benchmark_gas_used and skip_gas_used_validation fields to TransactionPost - Implement gas validation logic in TransactionPost.execute() using transaction receipts - Pass gas validation parameters from StateTest and BlockchainTest to TransactionPost - Add eth_getTransactionReceipt RPC method to fetch gas used from receipts This ensures benchmark tests fail appropriately when gas consumption doesn't match expectations, preventing false positives in performance testing. * refactor(execute): simplify gas validation implementation Addresses review comment to make execute mode gas validation cleaner: - Set expected_benchmark_gas_used to gas_benchmark_value as default in execute parametrizer - Remove gas_benchmark_value parameter from TransactionPost, StateTest, BlockchainTest, and BaseTest - Simplify gas validation logic in TransactionPost This ensures consistent gas validation behavior between fill and execute modes with a cleaner implementation that sets defaults at the parametrizer level. --- ethereum_test_execution/transaction_post.py | 27 +++++++++++++++++++++ ethereum_test_rpc/rpc.py | 12 +++++++++ ethereum_test_specs/blockchain.py | 3 +++ ethereum_test_specs/state.py | 3 +++ pytest_plugins/execute/execute.py | 5 ++++ 5 files changed, 50 insertions(+) diff --git a/ethereum_test_execution/transaction_post.py b/ethereum_test_execution/transaction_post.py index 5c97eb045b..a94af44db6 100644 --- a/ethereum_test_execution/transaction_post.py +++ b/ethereum_test_execution/transaction_post.py @@ -20,6 +20,9 @@ class TransactionPost(BaseExecute): blocks: List[List[Transaction]] post: Alloc + # Gas validation fields for benchmark tests + expected_benchmark_gas_used: int | None = None # Expected total gas to be consumed + skip_gas_used_validation: bool = False # Skip gas validation even if expected is set format_name: ClassVar[str] = "transaction_post_test" description: ClassVar[str] = ( @@ -33,6 +36,10 @@ def execute( assert not any(tx.ty == 3 for block in self.blocks for tx in block), ( "Transaction type 3 is not supported in execute mode." ) + + # Track transaction hashes for gas validation (benchmarking) + all_tx_hashes = [] + for block in self.blocks: signed_txs = [] for tx_index, tx in enumerate(block): @@ -51,11 +58,31 @@ def execute( for transaction in signed_txs: if transaction.error is None: eth_rpc.send_wait_transaction(transaction) + all_tx_hashes.append(transaction.hash) else: with pytest.raises(SendTransactionExceptionError): eth_rpc.send_transaction(transaction) else: eth_rpc.send_wait_transactions(signed_txs) + all_tx_hashes.extend([tx.hash for tx in signed_txs]) + + # Perform gas validation if required for benchmarking + # Ensures benchmark tests consume exactly the expected gas + if not self.skip_gas_used_validation and self.expected_benchmark_gas_used is not None: + total_gas_used = 0 + # Fetch transaction receipts to get actual gas used + for tx_hash in all_tx_hashes: + receipt = eth_rpc.get_transaction_receipt(tx_hash) + assert receipt is not None, f"Failed to get receipt for transaction {tx_hash}" + gas_used = int(receipt["gasUsed"], 16) + total_gas_used += gas_used + + # Verify that the total gas consumed matches expectations + assert total_gas_used == self.expected_benchmark_gas_used, ( + f"Total gas used ({total_gas_used}) does not match " + f"expected benchmark gas ({self.expected_benchmark_gas_used}), " + f"difference: {total_gas_used - self.expected_benchmark_gas_used}" + ) for address, account in self.post.root.items(): balance = eth_rpc.get_balance(address) diff --git a/ethereum_test_rpc/rpc.py b/ethereum_test_rpc/rpc.py index e654340c28..9ea2d279eb 100644 --- a/ethereum_test_rpc/rpc.py +++ b/ethereum_test_rpc/rpc.py @@ -292,6 +292,18 @@ def get_transaction_by_hash(self, transaction_hash: Hash) -> TransactionByHashRe pprint(e.errors()) raise e + def get_transaction_receipt(self, transaction_hash: Hash) -> dict | None: + """ + `eth_getTransactionReceipt`: Returns transaction receipt. + + Used to get the actual gas used by a transaction for gas validation + in benchmark tests. + """ + response = self.post_request( + method="getTransactionReceipt", params=[f"{transaction_hash}"] + ) + return response + def get_storage_at( self, address: Address, position: Hash, block_number: BlockNumberType = "latest" ) -> Hash: diff --git a/ethereum_test_specs/blockchain.py b/ethereum_test_specs/blockchain.py index 810090d235..7c523f2cc2 100644 --- a/ethereum_test_specs/blockchain.py +++ b/ethereum_test_specs/blockchain.py @@ -898,9 +898,12 @@ def execute( blocks: List[List[Transaction]] = [] for block in self.blocks: blocks += [block.txs] + # Pass gas validation params for benchmark tests return TransactionPost( blocks=blocks, post=self.post, + expected_benchmark_gas_used=self.expected_benchmark_gas_used, + skip_gas_used_validation=self.skip_gas_used_validation, ) raise Exception(f"Unsupported execute format: {execute_format}") diff --git a/ethereum_test_specs/state.py b/ethereum_test_specs/state.py index 24b0cb0816..917ed8a28e 100644 --- a/ethereum_test_specs/state.py +++ b/ethereum_test_specs/state.py @@ -444,9 +444,12 @@ def execute( ) -> BaseExecute: """Generate the list of test fixtures.""" if execute_format == TransactionPost: + # Pass gas validation params for benchmark tests return TransactionPost( blocks=[[self.tx]], post=self.post, + expected_benchmark_gas_used=self.expected_benchmark_gas_used, + skip_gas_used_validation=self.skip_gas_used_validation, ) raise Exception(f"Unsupported execute format: {execute_format}") diff --git a/pytest_plugins/execute/execute.py b/pytest_plugins/execute/execute.py index 42676a6211..62d5aa1cc6 100644 --- a/pytest_plugins/execute/execute.py +++ b/pytest_plugins/execute/execute.py @@ -342,6 +342,11 @@ def __init__(self, *args, **kwargs): kwargs["pre"] = pre elif kwargs["pre"] != pre: raise ValueError("The pre-alloc object was modified by the test.") + # Set default for expected_benchmark_gas_used + if "expected_benchmark_gas_used" not in kwargs: + kwargs["expected_benchmark_gas_used"] = request.getfixturevalue( + "gas_benchmark_value" + ) kwargs |= { p: request.getfixturevalue(p) for p in cls_fixture_parameters From 38bb9af17a4be76ea537b7fbe6e42182c71292d1 Mon Sep 17 00:00:00 2001 From: spencer Date: Wed, 1 Oct 2025 17:47:07 +0100 Subject: [PATCH 056/102] chore(tests): safer workaround for EIP-6110 deposit log checks (#2233) * chore(cli): safe solution to 6110. * chore(docs): changelog and lint fix. --- .../test_modified_contract.py | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/prague/eip6110_deposits/test_modified_contract.py b/prague/eip6110_deposits/test_modified_contract.py index 0d5132e232..65a10c2b6e 100644 --- a/prague/eip6110_deposits/test_modified_contract.py +++ b/prague/eip6110_deposits/test_modified_contract.py @@ -217,23 +217,6 @@ def test_invalid_layout( txs=[tx], exception=[ BlockException.INVALID_DEPOSIT_EVENT_LAYOUT, - BlockException.INVALID_REQUESTS, - # INVALID_REQUESTS is an alternative workaround for - # Geth/Reth only. - # - # Geth/Reth do not validate the sizes or offsets of the - # deposit contract logs. - # - # Although this is out of spec, it is understood that this - # will not cause an issue so long as the mainnet/testnet - # deposit contracts don't change. - # - # This offsets are checked second and the sizes are checked - # third within the `is_valid_deposit_event_data` function: - # https://eips.ethereum.org/EIPS/eip-6110#block-validity - # - # EELS definition for `is_valid_deposit_event_data`: - # https://github.com/ethereum/execution-specs/blob/5ddb904fa7ba27daeff423e78466744c51e8cb6a/src/ethereum/forks/prague/requests.py#L51 ], ), ], @@ -293,23 +276,6 @@ def test_invalid_log_length(blockchain_test: BlockchainTestFiller, pre: Alloc, s txs=[tx], exception=[ BlockException.INVALID_DEPOSIT_EVENT_LAYOUT, - BlockException.INVALID_REQUESTS, - # INVALID_REQUESTS is an alternative workaround for - # Geth/Reth only. - # - # Geth/Reth do not validate the sizes or offsets of the - # deposit contract logs. - # - # Although this is out of spec, it is understood that this - # will not cause an issue so long as the mainnet/testnet - # deposit contracts don't change. - # - # This offsets are checked second and the sizes are checked - # third within the `is_valid_deposit_event_data` function: - # https://eips.ethereum.org/EIPS/eip-6110#block-validity - # - # EELS definition for `is_valid_deposit_event_data`: - # https://github.com/ethereum/execution-specs/blob/5ddb904fa7ba27daeff423e78466744c51e8cb6a/src/ethereum/forks/prague/requests.py#L51 ], ), ], From b36d0045e68f790d705a07cffe99b425537d2762 Mon Sep 17 00:00:00 2001 From: spencer Date: Wed, 1 Oct 2025 17:47:07 +0100 Subject: [PATCH 057/102] chore(tests): safer workaround for EIP-6110 deposit log checks (#2233) * chore(cli): safe solution to 6110. * chore(docs): changelog and lint fix. --- ethereum_clis/clis/geth.py | 15 +++++++++++++++ ethereum_clis/clis/reth.py | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/ethereum_clis/clis/geth.py b/ethereum_clis/clis/geth.py index 769315aa4b..55e5f52f4c 100644 --- a/ethereum_clis/clis/geth.py +++ b/ethereum_clis/clis/geth.py @@ -77,6 +77,21 @@ class GethExceptionMapper(ExceptionMapper): BlockException.INCORRECT_EXCESS_BLOB_GAS: "invalid excessBlobGas", BlockException.INVALID_VERSIONED_HASHES: "invalid number of versionedHashes", BlockException.INVALID_REQUESTS: "invalid requests hash", + BlockException.INVALID_DEPOSIT_EVENT_LAYOUT: "invalid requests hash", + # Geth does not validate the sizes or offsets of the deposit + # contract logs. As a workaround we have set + # INVALID_DEPOSIT_EVENT_LAYOUT equal to INVALID_REQUESTS. + # + # Although this is out of spec, it is understood that this + # will not cause an issue so long as the mainnet/testnet + # deposit contracts don't change. + # + # The offsets are checked second and the sizes are checked + # third within the `is_valid_deposit_event_data` function: + # https://eips.ethereum.org/EIPS/eip-6110#block-validity + # + # EELS definition for `is_valid_deposit_event_data`: + # https://github.com/ethereum/execution-specs/blob/5ddb904fa7ba27daeff423e78466744c51e8cb6a/src/ethereum/forks/prague/requests.py#L51 BlockException.SYSTEM_CONTRACT_CALL_FAILED: "system call failed to execute:", BlockException.INVALID_BLOCK_HASH: "blockhash mismatch", BlockException.RLP_BLOCK_LIMIT_EXCEEDED: "block RLP-encoded size exceeds maximum", diff --git a/ethereum_clis/clis/reth.py b/ethereum_clis/clis/reth.py index ad6d986967..9b115916a7 100644 --- a/ethereum_clis/clis/reth.py +++ b/ethereum_clis/clis/reth.py @@ -33,6 +33,21 @@ class RethExceptionMapper(ExceptionMapper): "failed to decode deposit requests from receipts" ), BlockException.INVALID_REQUESTS: "mismatched block requests hash", + BlockException.INVALID_DEPOSIT_EVENT_LAYOUT: "mismatched block requests hash", + # Reth does not validate the sizes or offsets of the deposit + # contract logs. As a workaround we have set + # INVALID_DEPOSIT_EVENT_LAYOUT equal to INVALID_REQUESTS. + # + # Although this is out of spec, it is understood that this + # will not cause an issue so long as the mainnet/testnet + # deposit contracts don't change. + # + # The offsets are checked second and the sizes are checked + # third within the `is_valid_deposit_event_data` function: + # https://eips.ethereum.org/EIPS/eip-6110#block-validity + # + # EELS definition for `is_valid_deposit_event_data`: + # https://github.com/ethereum/execution-specs/blob/5ddb904fa7ba27daeff423e78466744c51e8cb6a/src/ethereum/forks/prague/requests.py#L51 BlockException.INVALID_RECEIPTS_ROOT: "receipt root mismatch", BlockException.INVALID_STATE_ROOT: "mismatched block state root", BlockException.INVALID_BLOCK_HASH: "block hash mismatch", From 3e7af3307e02b323374610ac08ad89c0a905630e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 1 Oct 2025 20:45:43 +0200 Subject: [PATCH 058/102] feat(tests): add more tests for P256 where R is at infinity (#2238) Add more tests cases for the `p256verify` precompile where the final computed point `R` is at infinity by passing `Q = -G` and `u1 == u2`. Similar test cases exist in "wycheproof_extra". --- .../eip7951_p256verify_precompiles/test_p256verify.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index f8f04878f9..f89d903b6e 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -344,6 +344,16 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact Spec.H0 + Spec.R0 + Spec.S0 + X(Spec.P + 1) + Spec.Y0, id="x_greater_than_p", ), + # Test case produces the point R at infinity: (R0/S0)*G + (R0/S0)*(-G). + pytest.param( + H(Spec.R0.value) + Spec.R0 + Spec.S0 + X(Spec.Gx) + Y(Spec.P - Spec.Gy), + id="R_at_infinity_v1", + ), + # Test case produces the point R at infinity: (1/1)*G + (1/1)*(-G). + pytest.param( + H(1) + R(1) + S(1) + X(Spec.Gx) + Y(Spec.P - Spec.Gy), + id="R_at_infinity_v2", + ), pytest.param( Spec.H0 + R(0x813EF79CCEFA9A56F7BA805F0E478584FE5F0DD5F567BC09B5123CCBC9832365) From f39dead5bd7b450c13013261169151c2b7e1ebfa Mon Sep 17 00:00:00 2001 From: spencer Date: Wed, 1 Oct 2025 20:18:22 +0100 Subject: [PATCH 059/102] chore(forks): update bpo hardfork params to match testnet (#2234) * chore(forks): update bpo hardfork params to match testnet. * feat(execute): Update eth-config networks.yml --------- Co-authored-by: Mario Vega --- ethereum_test_forks/forks/forks.py | 30 ++++++---- .../execute/eth_config/networks.yml | 59 ++++++++++++++++++- 2 files changed, 76 insertions(+), 13 deletions(-) diff --git a/ethereum_test_forks/forks/forks.py b/ethereum_test_forks/forks/forks.py index 3287a1ec1b..5c042a4ec2 100644 --- a/ethereum_test_forks/forks/forks.py +++ b/ethereum_test_forks/forks/forks.py @@ -1840,31 +1840,31 @@ def blob_base_cost(cls, block_number: int = 0, timestamp: int = 0) -> int: class BPO1(Osaka, bpo_fork=True): - """BPO1 fork - Blob Parameter Only fork 1.""" + """Mainnet BPO1 fork - Blob Parameter Only fork 1.""" @classmethod def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: """Return the blob base fee update fraction for BPO1.""" - return 8832827 + return 8346193 @classmethod def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: - """Blobs in BPO1 have a target of 9 blobs per block.""" - return 9 + """Blobs in BPO1 have a target of 10 blobs per block.""" + return 10 @classmethod def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: - """Blobs in BPO1 have a max of 14 blobs per block.""" - return 14 + """Blobs in BPO1 have a max of 15 blobs per block.""" + return 15 class BPO2(BPO1, bpo_fork=True): - """BPO2 fork - Blob Parameter Only fork 2.""" + """Mainnet BPO2 fork - Blob Parameter Only fork 2.""" @classmethod def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: """Return the blob base fee update fraction for BPO2.""" - return 13739630 + return 11684671 @classmethod def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: @@ -1878,7 +1878,10 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: class BPO3(BPO2, bpo_fork=True): - """BPO3 fork - Blob Parameter Only fork 3.""" + """ + Pseudo BPO3 fork - Blob Parameter Only fork 3. + For testing purposes only. + """ @classmethod def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: @@ -1897,7 +1900,10 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: class BPO4(BPO3, bpo_fork=True): - """BPO4 fork - Blob Parameter Only fork 4.""" + """ + Pseudo BPO4 fork - Blob Parameter Only fork 4. + For testing purposes only. Testing a decrease in values from BPO3. + """ @classmethod def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: @@ -1917,8 +1923,8 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: class BPO5(BPO4, bpo_fork=True): """ - BPO5 fork - Blob Parameter Only fork 5 (Required to parse Fusaka devnet - genesis files). + Pseudo BPO5 fork - Blob Parameter Only fork 5. + For testing purposes only. Required to parse Fusaka devnet genesis files. """ pass diff --git a/pytest_plugins/execute/eth_config/networks.yml b/pytest_plugins/execute/eth_config/networks.yml index a04898e07f..56d54f84ee 100644 --- a/pytest_plugins/execute/eth_config/networks.yml +++ b/pytest_plugins/execute/eth_config/networks.yml @@ -27,6 +27,18 @@ Mainnet: target: 6 max: 9 baseFeeUpdateFraction: 5007716 + Osaka: + target: 6 + max: 9 + baseFeeUpdateFraction: 5007716 + BPO1: + target: 10 + max: 15 + baseFeeUpdateFraction: 8346193 + BPO2: + target: 14 + max: 21 + baseFeeUpdateFraction: 11684671 Sepolia: chainId: 0xaa36a7 @@ -37,6 +49,9 @@ Sepolia: Shanghai: 1677557088 Cancun: 1706655072 Prague: 1741159776 + Osaka: 1760427360 + BPO1: 1761017184 + BPO2: 1761607008 blobSchedule: Cancun: target: 3 @@ -46,6 +61,18 @@ Sepolia: target: 6 max: 9 baseFeeUpdateFraction: 5007716 + Osaka: + target: 6 + max: 9 + baseFeeUpdateFraction: 5007716 + BPO1: + target: 10 + max: 15 + baseFeeUpdateFraction: 8346193 + BPO2: + target: 14 + max: 21 + baseFeeUpdateFraction: 11684671 addressOverrides: 0x00000000219ab540356cbb839cbe05303d7705fa: 0x7f02c3e3c98b133055b8b348b2ac625669ed295d @@ -55,6 +82,9 @@ Hoodi: forkActivationTimes: Cancun: 0 Prague: 1742999832 + Osaka: 1761677592 + BPO1: 1762365720 + BPO2: 1762955544 blobSchedule: Cancun: target: 3 @@ -64,6 +94,18 @@ Hoodi: target: 6 max: 9 baseFeeUpdateFraction: 5007716 + Osaka: + target: 6 + max: 9 + baseFeeUpdateFraction: 5007716 + BPO1: + target: 10 + max: 15 + baseFeeUpdateFraction: 8346193 + BPO2: + target: 14 + max: 21 + baseFeeUpdateFraction: 11684671 Holesky: chainId: 0x4268 @@ -73,6 +115,9 @@ Holesky: Shanghai: 1696000704 Cancun: 1707305664 Prague: 1740434112 + Osaka: 1759308480 + BPO1: 1759800000 + BPO2: 1760389824 addressOverrides: 0x00000000219ab540356cbb839cbe05303d7705fa: 0x4242424242424242424242424242424242424242 blobSchedule: @@ -83,4 +128,16 @@ Holesky: Prague: target: 6 max: 9 - baseFeeUpdateFraction: 5007716 \ No newline at end of file + baseFeeUpdateFraction: 5007716 + Osaka: + target: 6 + max: 9 + baseFeeUpdateFraction: 5007716 + BPO1: + target: 10 + max: 15 + baseFeeUpdateFraction: 8346193 + BPO2: + target: 14 + max: 21 + baseFeeUpdateFraction: 11684671 \ No newline at end of file From d5ecf5161a64488f5ba5c18223c68675aab00242 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Wed, 1 Oct 2025 21:31:54 +0200 Subject: [PATCH 060/102] test(tests): add BLOCKHASH genesis hash availability test (#2228) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test(tests): add BLOCKHASH genesis hash availability test Add regression test verifying BLOCKHASH(0) returns genesis hash in block 1. Tests blockchain test infrastructure properly populates genesis hash before execution, preventing BLOCKHASH(0) from returning 0. Regression context: revm blockchaintest runner wasn't inserting block_hashes into state, causing BLOCKHASH(0) to return 0. This broke tests with dynamic address computations like BLOCKHASH(0) | TIMESTAMP, where the computed address would be incorrect, leading to balance transfer failures. Test validates infrastructure setup by storing ISZERO(BLOCKHASH(0)) which should be 0 (false) when genesis hash is properly available. * test(tests): extend BLOCKHASH test to verify block 1 hash availability Extends test_genesis_hash_available to verify both genesis (block 0) and first executed block (block 1) hash insertion by adding a second block that calls the contract, testing BLOCKHASH(0) and BLOCKHASH(1). Addresses PR feedback to test complete block hash infrastructure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --------- Co-authored-by: Claude --- frontier/opcodes/test_blockhash.py | 74 ++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 frontier/opcodes/test_blockhash.py diff --git a/frontier/opcodes/test_blockhash.py b/frontier/opcodes/test_blockhash.py new file mode 100644 index 0000000000..f213f791b5 --- /dev/null +++ b/frontier/opcodes/test_blockhash.py @@ -0,0 +1,74 @@ +"""Tests for BLOCKHASH opcode.""" + +import pytest + +from ethereum_test_tools import ( + Account, + Alloc, + Block, + BlockchainTestFiller, + Storage, + Transaction, +) +from ethereum_test_tools import Opcodes as Op + + +@pytest.mark.valid_from("Frontier") +def test_genesis_hash_available(blockchain_test: BlockchainTestFiller, pre: Alloc): + """ + Verify BLOCKHASH returns genesis and block 1 hashes. + + Regression test: Blockchain test infrastructure must populate block hashes + before execution. Without this, BLOCKHASH returns 0, breaking dynamic + address computations like BLOCKHASH(0) | TIMESTAMP. + + Tests both genesis (block 0) and first executed block (block 1) hash + insertion by calling the contract in block 2. + + Bug context: revm blockchaintest runner wasn't inserting block_hashes, + causing failures in tests with BLOCKHASH-derived addresses. + """ + storage = Storage() + + # Store ISZERO(BLOCKHASH(0)) and ISZERO(BLOCKHASH(1)) + # Both should be 0 (false) if hashes exist + code = Op.SSTORE(storage.store_next(0), Op.ISZERO(Op.BLOCKHASH(0))) + Op.SSTORE( + storage.store_next(0), Op.ISZERO(Op.BLOCKHASH(1)) + ) + + contract = pre.deploy_contract(code=code) + sender = pre.fund_eoa() + + blocks = [ + Block( + txs=[ + Transaction( + sender=sender, + to=contract, + gas_limit=100_000, + protected=False, + ) + ] + ), + Block( + txs=[ + Transaction( + sender=sender, + to=contract, + gas_limit=100_000, + protected=False, + ) + ] + ), + ] + + post = { + contract: Account( + storage={ + 0: 0, # ISZERO(BLOCKHASH(0)) = 0 (genesis hash exists) + 1: 0, # ISZERO(BLOCKHASH(1)) = 0 (block 1 hash exists) + } + ) + } + + blockchain_test(pre=pre, post=post, blocks=blocks) From cff8c8fe2344e316e7d67136376b056bea902157 Mon Sep 17 00:00:00 2001 From: SDartayet <44068466+SDartayet@users.noreply.github.com> Date: Wed, 1 Oct 2025 17:47:06 -0300 Subject: [PATCH 061/102] chore(cli): add mapping for TYPE_3_TX_CONTRACT_CREATION error (#2244) * Changed intrinsic gas too low for gas below floor gas cost * Fixing wrongly removing intrinsic gas too low error * Fixing message for intrinsic gas too low error * Improved error messages * Added mapping for TYPE_3_TX_CONTRACT_CREATION error --- ethereum_clis/clis/ethrex.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ethereum_clis/clis/ethrex.py b/ethereum_clis/clis/ethrex.py index c001d6cf54..bd3fd6c073 100644 --- a/ethereum_clis/clis/ethrex.py +++ b/ethereum_clis/clis/ethrex.py @@ -54,6 +54,10 @@ class EthrexExceptionMapper(ExceptionMapper): r"unexpected length|Contract creation in type 4 transaction|" r"Error decoding field 'to' of type primitive_types::H160: InvalidLength" ), + TransactionException.TYPE_3_TX_CONTRACT_CREATION: ( + r"unexpected length|Contract creation in type 3 transaction|" + r"Error decoding field 'to' of type primitive_types::H160: InvalidLength" + ), TransactionException.TYPE_4_TX_PRE_FORK: ( r"eip 7702 transactions present in pre-prague payload|" r"Type 4 transactions are not supported before the Prague fork" From 0274aee1076f5787d6dcc748cd46a435f8f2027c Mon Sep 17 00:00:00 2001 From: Abhishek Kafle <144969576+akafle01@users.noreply.github.com> Date: Wed, 1 Oct 2025 20:41:59 -0400 Subject: [PATCH 062/102] feat(forks): Enforce keyword-only arguments in fork methods (#1714) * Enforce keyword-only arguments in calldata_gas_calculator methods and calls * Apply keyword-only enforcement to all BaseFork methods and implementations * fixes --------- Co-authored-by: Abhishek Kafle Co-authored-by: Mario Vega --- ethereum_test_fixtures/blockchain.py | 34 +- ethereum_test_forks/base_fork.py | 130 ++--- ethereum_test_forks/forks/forks.py | 496 +++++++++--------- ethereum_test_forks/tests/test_forks.py | 78 ++- ethereum_test_specs/blockchain.py | 14 +- ethereum_test_specs/state.py | 2 +- ethereum_test_types/block_types.py | 20 +- pytest_plugins/execute/pre_alloc.py | 2 +- .../execute/rpc/chain_builder_eth_rpc.py | 16 +- 9 files changed, 441 insertions(+), 351 deletions(-) diff --git a/ethereum_test_fixtures/blockchain.py b/ethereum_test_fixtures/blockchain.py index b5ef43cb40..e1323efffa 100644 --- a/ethereum_test_fixtures/blockchain.py +++ b/ethereum_test_fixtures/blockchain.py @@ -103,7 +103,9 @@ def __new__(cls, value: str) -> "HeaderForkRequirement": def required(self, fork: Fork, block_number: int, timestamp: int) -> bool: """Check if the field is required for the given fork.""" - return getattr(fork, f"header_{self}_required")(block_number, timestamp) + return getattr(fork, f"header_{self}_required")( + block_number=block_number, timestamp=timestamp + ) @classmethod def get_from_annotation(cls, field_hints: Any) -> "HeaderForkRequirement | None": @@ -238,9 +240,13 @@ def genesis(cls, fork: Fork, env: Environment, state_root: Hash) -> "FixtureHead environment_values["extra_data"] = env.extra_data extras = { "state_root": state_root, - "requests_hash": Requests() if fork.header_requests_required(0, 0) else None, + "requests_hash": Requests() + if fork.header_requests_required(block_number=0, timestamp=0) + else None, "block_access_list_hash": ( - BlockAccessList().rlp_hash if fork.header_bal_hash_required(0, 0) else None + BlockAccessList().rlp_hash + if fork.header_bal_hash_required(block_number=0, timestamp=0) + else None ), "fork": fork, } @@ -356,14 +362,18 @@ def from_fixture_header( **kwargs, ) -> "FixtureEngineNewPayload": """Create `FixtureEngineNewPayload` from a `FixtureHeader`.""" - new_payload_version = fork.engine_new_payload_version(header.number, header.timestamp) + new_payload_version = fork.engine_new_payload_version( + block_number=header.number, timestamp=header.timestamp + ) forkchoice_updated_version = fork.engine_forkchoice_updated_version( - header.number, header.timestamp + block_number=header.number, timestamp=header.timestamp ) assert new_payload_version is not None, "Invalid header for engine_newPayload" - if fork.engine_execution_payload_block_access_list(header.number, header.timestamp): + if fork.engine_execution_payload_block_access_list( + block_number=header.number, timestamp=header.timestamp + ): if block_access_list is None: raise ValueError( f"`block_access_list` is required in engine `ExecutionPayload` for >={fork}." @@ -377,19 +387,25 @@ def from_fixture_header( ) params: List[Any] = [execution_payload] - if fork.engine_new_payload_blob_hashes(header.number, header.timestamp): + if fork.engine_new_payload_blob_hashes( + block_number=header.number, timestamp=header.timestamp + ): blob_hashes = Transaction.list_blob_versioned_hashes(transactions) if blob_hashes is None: raise ValueError(f"Blob hashes are required for ${fork}.") params.append(blob_hashes) - if fork.engine_new_payload_beacon_root(header.number, header.timestamp): + if fork.engine_new_payload_beacon_root( + block_number=header.number, timestamp=header.timestamp + ): parent_beacon_block_root = header.parent_beacon_block_root if parent_beacon_block_root is None: raise ValueError(f"Parent beacon block root is required for ${fork}.") params.append(parent_beacon_block_root) - if fork.engine_new_payload_requests(header.number, header.timestamp): + if fork.engine_new_payload_requests( + block_number=header.number, timestamp=header.timestamp + ): if requests is None: raise ValueError(f"Requests are required for ${fork}.") params.append(requests) diff --git a/ethereum_test_forks/base_fork.py b/ethereum_test_forks/base_fork.py index 69af59800d..a08fc617cd 100644 --- a/ethereum_test_forks/base_fork.py +++ b/ethereum_test_forks/base_fork.py @@ -271,55 +271,55 @@ def __init_subclass__( # Header information abstract methods @classmethod @abstractmethod - def header_base_fee_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_base_fee_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Return true if the header must contain base fee.""" pass @classmethod @abstractmethod - def header_prev_randao_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_prev_randao_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Return true if the header must contain Prev Randao value.""" pass @classmethod @abstractmethod - def header_zero_difficulty_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_zero_difficulty_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Return true if the header must have difficulty zero.""" pass @classmethod @abstractmethod - def header_withdrawals_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_withdrawals_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Return true if the header must contain withdrawals.""" pass @classmethod @abstractmethod - def header_excess_blob_gas_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_excess_blob_gas_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Return true if the header must contain excess blob gas.""" pass @classmethod @abstractmethod - def header_blob_gas_used_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_blob_gas_used_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Return true if the header must contain blob gas used.""" pass @classmethod @abstractmethod - def header_beacon_root_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_beacon_root_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Return true if the header must contain parent beacon block root.""" pass @classmethod @abstractmethod - def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_requests_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Return true if the header must contain beacon chain requests.""" pass @classmethod @abstractmethod - def header_bal_hash_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_bal_hash_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Return true if the header must contain block access list hash.""" pass @@ -327,14 +327,14 @@ def header_bal_hash_required(cls, block_number: int = 0, timestamp: int = 0) -> @classmethod @abstractmethod - def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: + def gas_costs(cls, *, block_number: int = 0, timestamp: int = 0) -> GasCosts: """Return dataclass with the gas costs constants for the fork.""" pass @classmethod @abstractmethod def memory_expansion_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> MemoryExpansionGasCalculator: """ Return a callable that calculates the gas cost of memory expansion for @@ -345,7 +345,7 @@ def memory_expansion_gas_calculator( @classmethod @abstractmethod def calldata_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> CalldataGasCalculator: """ Return callable that calculates the transaction gas cost for its @@ -356,7 +356,7 @@ def calldata_gas_calculator( @classmethod @abstractmethod def base_fee_per_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> BaseFeePerGasCalculator: """ Return a callable that calculates the base fee per gas at a given fork. @@ -366,7 +366,7 @@ def base_fee_per_gas_calculator( @classmethod @abstractmethod def base_fee_change_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> BaseFeeChangeCalculator: """ Return a callable that calculates the gas that needs to be used to @@ -376,26 +376,26 @@ def base_fee_change_calculator( @classmethod @abstractmethod - def base_fee_max_change_denominator(cls, block_number: int = 0, timestamp: int = 0) -> int: + def base_fee_max_change_denominator(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the base fee max change denominator at a given fork.""" pass @classmethod @abstractmethod - def base_fee_elasticity_multiplier(cls, block_number: int = 0, timestamp: int = 0) -> int: + def base_fee_elasticity_multiplier(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the base fee elasticity multiplier at a given fork.""" pass @classmethod @abstractmethod - def max_refund_quotient(cls) -> int: + def max_refund_quotient(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the max refund quotient at a given fork.""" pass @classmethod @abstractmethod def transaction_data_floor_cost_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> TransactionDataFloorCostCalculator: """ Return a callable that calculates the transaction floor cost due to its @@ -406,7 +406,7 @@ def transaction_data_floor_cost_calculator( @classmethod @abstractmethod def transaction_intrinsic_cost_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> TransactionIntrinsicCostCalculator: """ Return callable that calculates the intrinsic gas cost of a transaction @@ -417,7 +417,7 @@ def transaction_intrinsic_cost_calculator( @classmethod @abstractmethod def blob_gas_price_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> BlobGasPriceCalculator: """ Return a callable that calculates the blob gas price at a given fork. @@ -427,7 +427,7 @@ def blob_gas_price_calculator( @classmethod @abstractmethod def excess_blob_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> ExcessBlobGasCalculator: """ Return a callable that calculates the excess blob gas for a block at a @@ -437,49 +437,49 @@ def excess_blob_gas_calculator( @classmethod @abstractmethod - def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int: + def min_base_fee_per_blob_gas(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the minimum base fee per blob gas at a given fork.""" pass @classmethod @abstractmethod - def blob_gas_per_blob(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_gas_per_blob(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the amount of blob gas used per blob at a given fork.""" pass @classmethod @abstractmethod - def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the blob base fee update fraction at a given fork.""" pass @classmethod @abstractmethod - def supports_blobs(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def supports_blobs(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Return whether the given fork supports blobs or not.""" pass @classmethod @abstractmethod - def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the target blobs per block at a given fork.""" pass @classmethod @abstractmethod - def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_tx(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the max blobs per transaction at a given fork.""" pass @classmethod @abstractmethod - def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the max blobs per block at a given fork.""" pass @classmethod @abstractmethod - def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def blob_reserve_price_active(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """ Return whether the fork uses a reserve price mechanism for blobs or not. @@ -488,13 +488,15 @@ def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> @classmethod @abstractmethod - def blob_base_cost(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_cost(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the base cost of a blob at a given fork.""" pass @classmethod @abstractmethod - def full_blob_tx_wrapper_version(cls, block_number: int = 0, timestamp: int = 0) -> int | None: + def full_blob_tx_wrapper_version( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> int | None: """ Return the version of the full blob transaction wrapper at a given fork. @@ -504,13 +506,13 @@ def full_blob_tx_wrapper_version(cls, block_number: int = 0, timestamp: int = 0) @classmethod @prefer_transition_to_method @abstractmethod - def blob_schedule(cls, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None: + def blob_schedule(cls, *, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None: """Return the blob schedule up until the given fork.""" pass @classmethod @abstractmethod - def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: + def get_reward(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return expected reward amount in wei of a given fork.""" pass @@ -518,13 +520,13 @@ def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: @classmethod @abstractmethod - def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: + def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]: """Return list of the transaction types supported by the fork.""" pass @classmethod @abstractmethod - def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: + def contract_creating_tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]: """ Return list of the transaction types supported by the fork that can create contracts. @@ -533,7 +535,7 @@ def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) - @classmethod @abstractmethod - def transaction_gas_limit_cap(cls, block_number: int = 0, timestamp: int = 0) -> int | None: + def transaction_gas_limit_cap(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None: """ Return the transaction gas limit cap, or None if no limit is imposed. """ @@ -541,7 +543,7 @@ def transaction_gas_limit_cap(cls, block_number: int = 0, timestamp: int = 0) -> @classmethod @abstractmethod - def block_rlp_size_limit(cls, block_number: int = 0, timestamp: int = 0) -> int | None: + def block_rlp_size_limit(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None: """ Return the maximum RLP size of a block in bytes, or None if no limit is imposed. @@ -550,20 +552,20 @@ def block_rlp_size_limit(cls, block_number: int = 0, timestamp: int = 0) -> int @classmethod @abstractmethod - def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """Return list pre-compiles supported by the fork.""" pass @classmethod @abstractmethod - def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def system_contracts(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """Return list system-contracts supported by the fork.""" pass @classmethod @prefer_transition_to_method @abstractmethod - def pre_allocation(cls) -> Mapping: + def pre_allocation(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping: """ Return required pre-allocation of accounts for any kind of test. @@ -576,7 +578,7 @@ def pre_allocation(cls) -> Mapping: @classmethod @prefer_transition_to_method @abstractmethod - def pre_allocation_blockchain(cls) -> Mapping: + def pre_allocation_blockchain(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping: """ Return required pre-allocation of accounts for any blockchain tests. @@ -590,7 +592,7 @@ def pre_allocation_blockchain(cls) -> Mapping: @classmethod @abstractmethod def engine_new_payload_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """ Return `None` if this fork's payloads cannot be sent over the engine @@ -600,7 +602,7 @@ def engine_new_payload_version( @classmethod @abstractmethod - def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def engine_new_payload_blob_hashes(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """ Return true if the engine api version requires new payload calls to include blob hashes. @@ -609,7 +611,7 @@ def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = @classmethod @abstractmethod - def engine_new_payload_beacon_root(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def engine_new_payload_beacon_root(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """ Return true if the engine api version requires new payload calls to include a parent beacon block root. @@ -618,7 +620,7 @@ def engine_new_payload_beacon_root(cls, block_number: int = 0, timestamp: int = @classmethod @abstractmethod - def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def engine_new_payload_requests(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """ Return true if the engine api version requires new payload calls to include requests. @@ -628,7 +630,7 @@ def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) @classmethod @abstractmethod def engine_new_payload_target_blobs_per_block( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> bool: """ Return true if the engine api version requires new payload calls to @@ -639,7 +641,7 @@ def engine_new_payload_target_blobs_per_block( @classmethod @abstractmethod def engine_execution_payload_block_access_list( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> bool: """ Return `True` if the engine api version requires execution payload to @@ -650,7 +652,7 @@ def engine_execution_payload_block_access_list( @classmethod @abstractmethod def engine_payload_attribute_target_blobs_per_block( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> bool: """ Return true if the payload attributes include the target blobs per @@ -661,7 +663,7 @@ def engine_payload_attribute_target_blobs_per_block( @classmethod @abstractmethod def engine_payload_attribute_max_blobs_per_block( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> bool: """ Return true if the payload attributes include the max blobs per block. @@ -671,7 +673,7 @@ def engine_payload_attribute_max_blobs_per_block( @classmethod @abstractmethod def engine_forkchoice_updated_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """ Return `None` if the forks canonical chain cannot be set using the @@ -682,7 +684,7 @@ def engine_forkchoice_updated_version( @classmethod @abstractmethod def engine_get_payload_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """ Return `None` if the forks canonical chain cannot build a payload using @@ -692,7 +694,9 @@ def engine_get_payload_version( @classmethod @abstractmethod - def engine_get_blobs_version(cls, block_number: int = 0, timestamp: int = 0) -> Optional[int]: + def engine_get_blobs_version( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> Optional[int]: """ Return `None` if the fork does not support the engine get blobs version. @@ -702,13 +706,13 @@ def engine_get_blobs_version(cls, block_number: int = 0, timestamp: int = 0) -> # EVM information abstract methods @classmethod @abstractmethod - def evm_code_types(cls, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]: + def evm_code_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]: """Return list of EVM code types supported by the fork.""" pass @classmethod @abstractmethod - def max_code_size(cls) -> int: + def max_code_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ Return the maximum code size allowed to be deployed in a contract creation. @@ -717,13 +721,13 @@ def max_code_size(cls) -> int: @classmethod @abstractmethod - def max_stack_height(cls) -> int: + def max_stack_height(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the maximum stack height allowed in the EVM stack.""" pass @classmethod @abstractmethod - def max_initcode_size(cls) -> int: + def max_initcode_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ Return the maximum initcode size allowed to be used in a contract creation. @@ -733,7 +737,7 @@ def max_initcode_size(cls) -> int: @classmethod @abstractmethod def call_opcodes( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> List[Tuple[Opcodes, EVMCodeType]]: """ Return list of tuples with the call opcodes and its corresponding EVM @@ -743,16 +747,14 @@ def call_opcodes( @classmethod @abstractmethod - def valid_opcodes( - cls, - ) -> List[Opcodes]: + def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]: """Return list of Opcodes that are valid to work on this fork.""" pass @classmethod @abstractmethod def create_opcodes( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> List[Tuple[Opcodes, EVMCodeType]]: """ Return list of tuples with the create opcodes and its corresponding EVM @@ -762,7 +764,7 @@ def create_opcodes( @classmethod @abstractmethod - def max_request_type(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_request_type(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return max request type supported by the fork.""" pass @@ -773,7 +775,7 @@ def name(cls) -> str: return cls.__name__ @classmethod - def fork_at(cls, block_number: int = 0, timestamp: int = 0) -> Type["BaseFork"]: + def fork_at(cls, *, block_number: int = 0, timestamp: int = 0) -> Type["BaseFork"]: """ Return fork at the given block number and timestamp. Useful only for transition forks, and it's a no-op for normal forks. @@ -782,7 +784,7 @@ def fork_at(cls, block_number: int = 0, timestamp: int = 0) -> Type["BaseFork"]: @classmethod @abstractmethod - def transition_tool_name(cls, block_number: int = 0, timestamp: int = 0) -> str: + def transition_tool_name(cls, *, block_number: int = 0, timestamp: int = 0) -> str: """ Return fork name as it's meant to be passed to the transition tool for execution. diff --git a/ethereum_test_forks/forks/forks.py b/ethereum_test_forks/forks/forks.py index 5c042a4ec2..a5f44a6734 100644 --- a/ethereum_test_forks/forks/forks.py +++ b/ethereum_test_forks/forks/forks.py @@ -33,7 +33,7 @@ class Frontier(BaseFork, solc_name="homestead"): """Frontier fork.""" @classmethod - def transition_tool_name(cls, block_number: int = 0, timestamp: int = 0) -> str: + def transition_tool_name(cls, *, block_number: int = 0, timestamp: int = 0) -> str: """ Return fork name as it's meant to be passed to the transition tool for execution. @@ -50,37 +50,37 @@ def solc_name(cls) -> str: return cls.name().lower() @classmethod - def header_base_fee_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_base_fee_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, header must not contain base fee.""" return False @classmethod - def header_prev_randao_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_prev_randao_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, header must not contain Prev Randao value.""" return False @classmethod - def header_zero_difficulty_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_zero_difficulty_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, header must not have difficulty zero.""" return False @classmethod - def header_withdrawals_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_withdrawals_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, header must not contain withdrawals.""" return False @classmethod - def header_excess_blob_gas_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_excess_blob_gas_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, header must not contain excess blob gas.""" return False @classmethod - def header_blob_gas_used_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_blob_gas_used_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, header must not contain blob gas used.""" return False @classmethod - def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: + def gas_costs(cls, *, block_number: int = 0, timestamp: int = 0) -> GasCosts: """ Return dataclass with the defined gas costs constants for genesis. """ @@ -129,13 +129,13 @@ def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: @classmethod def memory_expansion_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> MemoryExpansionGasCalculator: """ Return callable that calculates the gas cost of memory expansion for the fork. """ - gas_costs = cls.gas_costs(block_number, timestamp) + gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp) def fn(*, new_bytes: int, previous_bytes: int = 0) -> int: if new_bytes <= previous_bytes: @@ -152,13 +152,13 @@ def c(w: int) -> int: @classmethod def calldata_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> CalldataGasCalculator: """ Return callable that calculates the transaction gas cost for its calldata depending on its contents. """ - gas_costs = cls.gas_costs(block_number, timestamp) + gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp) def fn(*, data: BytesConvertible, floor: bool = False) -> int: del floor @@ -175,7 +175,7 @@ def fn(*, data: BytesConvertible, floor: bool = False) -> int: @classmethod def base_fee_per_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> BaseFeePerGasCalculator: """ Return a callable that calculates the base fee per gas at a given fork. @@ -184,7 +184,7 @@ def base_fee_per_gas_calculator( @classmethod def base_fee_change_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> BaseFeeChangeCalculator: """ Return a callable that calculates the gas that needs to be used to @@ -193,14 +193,14 @@ def base_fee_change_calculator( raise NotImplementedError(f"Base fee change calculator is not supported in {cls.name()}") @classmethod - def base_fee_max_change_denominator(cls, block_number: int = 0, timestamp: int = 0) -> int: + def base_fee_max_change_denominator(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the base fee max change denominator at a given fork.""" raise NotImplementedError( f"Base fee max change denominator is not supported in {cls.name()}" ) @classmethod - def base_fee_elasticity_multiplier(cls, block_number: int = 0, timestamp: int = 0) -> int: + def base_fee_elasticity_multiplier(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the base fee elasticity multiplier at a given fork.""" raise NotImplementedError( f"Base fee elasticity multiplier is not supported in {cls.name()}" @@ -208,7 +208,7 @@ def base_fee_elasticity_multiplier(cls, block_number: int = 0, timestamp: int = @classmethod def transaction_data_floor_cost_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> TransactionDataFloorCostCalculator: """At frontier, the transaction data floor cost is a constant zero.""" @@ -220,14 +220,16 @@ def fn(*, data: BytesConvertible) -> int: @classmethod def transaction_intrinsic_cost_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> TransactionIntrinsicCostCalculator: """ Return callable that calculates the intrinsic gas cost of a transaction for the fork. """ - gas_costs = cls.gas_costs(block_number, timestamp) - calldata_gas_calculator = cls.calldata_gas_calculator(block_number, timestamp) + gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp) + calldata_gas_calculator = cls.calldata_gas_calculator( + block_number=block_number, timestamp=timestamp + ) def fn( *, @@ -257,7 +259,7 @@ def fn( @classmethod def blob_gas_price_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> BlobGasPriceCalculator: """ Return a callable that calculates the blob gas price at a given fork. @@ -266,7 +268,7 @@ def blob_gas_price_calculator( @classmethod def excess_blob_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> ExcessBlobGasCalculator: """ Return a callable that calculates the excess blob gas for a block at a @@ -275,39 +277,39 @@ def excess_blob_gas_calculator( raise NotImplementedError(f"Excess blob gas calculator is not supported in {cls.name()}") @classmethod - def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int: + def min_base_fee_per_blob_gas(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the amount of blob gas used per blob at a given fork.""" raise NotImplementedError(f"Base fee per blob gas is not supported in {cls.name()}") @classmethod - def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the blob base fee update fraction at a given fork.""" raise NotImplementedError( f"Blob base fee update fraction is not supported in {cls.name()}" ) @classmethod - def blob_gas_per_blob(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_gas_per_blob(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the amount of blob gas used per blob at a given fork.""" return 0 @classmethod - def supports_blobs(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def supports_blobs(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Blobs are not supported at Frontier.""" return False @classmethod - def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the target number of blobs per block at a given fork.""" raise NotImplementedError(f"Target blobs per block is not supported in {cls.name()}") @classmethod - def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the max number of blobs per block at a given fork.""" raise NotImplementedError(f"Max blobs per block is not supported in {cls.name()}") @classmethod - def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def blob_reserve_price_active(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """ Return whether the fork uses a reserve price mechanism for blobs or not. @@ -315,67 +317,69 @@ def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> raise NotImplementedError(f"Blob reserve price is not supported in {cls.name()}") @classmethod - def blob_base_cost(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_cost(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the base cost of a blob at a given fork.""" raise NotImplementedError(f"Blob base cost is not supported in {cls.name()}") @classmethod - def full_blob_tx_wrapper_version(cls, block_number: int = 0, timestamp: int = 0) -> int | None: + def full_blob_tx_wrapper_version( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> int | None: """Return the version of the full blob transaction wrapper.""" raise NotImplementedError( f"Full blob transaction wrapper version is not supported in {cls.name()}" ) @classmethod - def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_tx(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the max number of blobs per tx at a given fork.""" raise NotImplementedError(f"Max blobs per tx is not supported in {cls.name()}") @classmethod - def blob_schedule(cls, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None: + def blob_schedule(cls, *, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None: """At genesis, no blob schedule is used.""" return None @classmethod - def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_requests_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, header must not contain beacon chain requests.""" return False @classmethod - def header_bal_hash_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_bal_hash_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, header must not contain block access list hash.""" return False @classmethod def engine_new_payload_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """At genesis, payloads cannot be sent through the engine API.""" return None @classmethod - def header_beacon_root_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_beacon_root_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, header must not contain parent beacon block root.""" return False @classmethod - def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def engine_new_payload_blob_hashes(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, payloads do not have blob hashes.""" return False @classmethod - def engine_new_payload_beacon_root(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def engine_new_payload_beacon_root(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, payloads do not have a parent beacon block root.""" return False @classmethod - def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def engine_new_payload_requests(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At genesis, payloads do not have requests.""" return False @classmethod def engine_execution_payload_block_access_list( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> bool: """At genesis, payloads do not have block access list.""" return False @@ -383,6 +387,7 @@ def engine_execution_payload_block_access_list( @classmethod def engine_new_payload_target_blobs_per_block( cls, + *, block_number: int = 0, timestamp: int = 0, ) -> bool: @@ -391,7 +396,7 @@ def engine_new_payload_target_blobs_per_block( @classmethod def engine_payload_attribute_target_blobs_per_block( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> bool: """ At genesis, payload attributes do not include the target blobs per @@ -401,7 +406,7 @@ def engine_payload_attribute_target_blobs_per_block( @classmethod def engine_payload_attribute_max_blobs_per_block( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> bool: """ At genesis, payload attributes do not include the max blobs per block. @@ -410,27 +415,29 @@ def engine_payload_attribute_max_blobs_per_block( @classmethod def engine_forkchoice_updated_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """ At genesis, forkchoice updates cannot be sent through the engine API. """ - return cls.engine_new_payload_version(block_number, timestamp) + return cls.engine_new_payload_version(block_number=block_number, timestamp=timestamp) @classmethod def engine_get_payload_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """At genesis, payloads cannot be retrieved through the engine API.""" - return cls.engine_new_payload_version(block_number, timestamp) + return cls.engine_new_payload_version(block_number=block_number, timestamp=timestamp) @classmethod - def engine_get_blobs_version(cls, block_number: int = 0, timestamp: int = 0) -> Optional[int]: + def engine_get_blobs_version( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> Optional[int]: """At genesis, blobs cannot be retrieved through the engine API.""" return None @classmethod - def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: + def get_reward(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ At Genesis the expected reward amount in wei is 5_000_000_000_000_000_000. @@ -438,42 +445,42 @@ def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: return 5_000_000_000_000_000_000 @classmethod - def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: + def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]: """At Genesis, only legacy transactions are allowed.""" return [0] @classmethod - def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: + def contract_creating_tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]: """At Genesis, only legacy transactions are allowed.""" return [0] @classmethod - def transaction_gas_limit_cap(cls, block_number: int = 0, timestamp: int = 0) -> int | None: + def transaction_gas_limit_cap(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None: """At Genesis, no transaction gas limit cap is imposed.""" return None @classmethod - def block_rlp_size_limit(cls, block_number: int = 0, timestamp: int = 0) -> int | None: + def block_rlp_size_limit(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None: """At Genesis, no RLP block size limit is imposed.""" return None @classmethod - def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """At Genesis, no pre-compiles are present.""" return [] @classmethod - def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def system_contracts(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """At Genesis, no system-contracts are present.""" return [] @classmethod - def evm_code_types(cls, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]: + def evm_code_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]: """At Genesis, only legacy EVM code is supported.""" return [EVMCodeType.LEGACY] @classmethod - def max_code_size(cls) -> int: + def max_code_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ At genesis, there is no upper bound for code size (bounded by block gas limit). @@ -483,19 +490,19 @@ def max_code_size(cls) -> int: return 0x6000 @classmethod - def max_stack_height(cls) -> int: + def max_stack_height(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """At genesis, the maximum stack height is 1024.""" return 1024 @classmethod - def max_initcode_size(cls) -> int: + def max_initcode_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """At genesis, there is no upper bound for initcode size.""" """However, the default is set to the limit of EIP-3860 (Shanghai)""" return 0xC000 @classmethod def call_opcodes( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> List[Tuple[Opcodes, EVMCodeType]]: """Return list of call opcodes supported by the fork.""" return [ @@ -504,9 +511,7 @@ def call_opcodes( ] @classmethod - def valid_opcodes( - cls, - ) -> List[Opcodes]: + def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]: """Return list of Opcodes that are valid to work on this fork.""" return [ Opcodes.STOP, @@ -642,7 +647,7 @@ def valid_opcodes( @classmethod def create_opcodes( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> List[Tuple[Opcodes, EVMCodeType]]: """At Genesis, only `CREATE` opcode is supported.""" return [ @@ -650,17 +655,17 @@ def create_opcodes( ] @classmethod - def max_refund_quotient(cls) -> int: + def max_refund_quotient(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the max refund quotient at Genesis.""" return 2 @classmethod - def max_request_type(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_request_type(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """At genesis, no request type is supported, signaled by -1.""" return -1 @classmethod - def pre_allocation(cls) -> Mapping: + def pre_allocation(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping: """ Return whether the fork expects pre-allocation of accounts. @@ -669,7 +674,7 @@ def pre_allocation(cls) -> Mapping: return {} @classmethod - def pre_allocation_blockchain(cls) -> Mapping: + def pre_allocation_blockchain(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping: """ Return whether the fork expects pre-allocation of accounts. @@ -682,7 +687,7 @@ class Homestead(Frontier): """Homestead fork.""" @classmethod - def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """ At Homestead, EC-recover, SHA256, RIPEMD160, and Identity pre-compiles are introduced. @@ -692,36 +697,34 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address] Address(2, label="SHA256"), Address(3, label="RIPEMD160"), Address(4, label="ID"), - ] + super(Homestead, cls).precompiles(block_number, timestamp) + ] + super(Homestead, cls).precompiles(block_number=block_number, timestamp=timestamp) @classmethod def call_opcodes( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> List[Tuple[Opcodes, EVMCodeType]]: """At Homestead, DELEGATECALL opcode was introduced.""" return [(Opcodes.DELEGATECALL, EVMCodeType.LEGACY)] + super(Homestead, cls).call_opcodes( - block_number, timestamp + block_number=block_number, timestamp=timestamp ) @classmethod - def valid_opcodes( - cls, - ) -> List[Opcodes]: + def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]: """Return the list of Opcodes that are valid to work on this fork.""" return [Opcodes.DELEGATECALL] + super(Homestead, cls).valid_opcodes() @classmethod def transaction_intrinsic_cost_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> TransactionIntrinsicCostCalculator: """ At Homestead, the transaction intrinsic cost needs to take contract creation into account. """ super_fn = super(Homestead, cls).transaction_intrinsic_cost_calculator( - block_number, timestamp + block_number=block_number, timestamp=timestamp ) - gas_costs = cls.gas_costs(block_number, timestamp) + gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp) def fn( *, @@ -768,7 +771,7 @@ class Byzantium(Homestead): """Byzantium fork.""" @classmethod - def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: + def get_reward(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ At Byzantium, the block reward is reduced to 3_000_000_000_000_000_000 wei. @@ -776,7 +779,7 @@ def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: return 3_000_000_000_000_000_000 @classmethod - def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """ At Byzantium, pre-compiles for bigint modular exponentiation, addition and scalar multiplication on elliptic curve alt_bn128, and optimal ate @@ -787,10 +790,10 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address] Address(6, label="BN254_ADD"), Address(7, label="BN254_MUL"), Address(8, label="BN254_PAIRING"), - ] + super(Byzantium, cls).precompiles(block_number, timestamp) + ] + super(Byzantium, cls).precompiles(block_number=block_number, timestamp=timestamp) @classmethod - def max_code_size(cls) -> int: + def max_code_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int: # NOTE: Move this to Spurious Dragon once this fork is introduced. See # EIP-170. """ @@ -801,17 +804,15 @@ def max_code_size(cls) -> int: @classmethod def call_opcodes( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> List[Tuple[Opcodes, EVMCodeType]]: """At Byzantium, STATICCALL opcode was introduced.""" return [(Opcodes.STATICCALL, EVMCodeType.LEGACY)] + super(Byzantium, cls).call_opcodes( - block_number, timestamp + block_number=block_number, timestamp=timestamp ) @classmethod - def valid_opcodes( - cls, - ) -> List[Opcodes]: + def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]: """Return list of Opcodes that are valid to work on this fork.""" return [ Opcodes.REVERT, @@ -825,7 +826,7 @@ class Constantinople(Byzantium): """Constantinople fork.""" @classmethod - def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: + def get_reward(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ At Constantinople, the block reward is reduced to 2_000_000_000_000_000_000 wei. @@ -834,17 +835,15 @@ def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: @classmethod def create_opcodes( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> List[Tuple[Opcodes, EVMCodeType]]: """At Constantinople, `CREATE2` opcode is added.""" return [(Opcodes.CREATE2, EVMCodeType.LEGACY)] + super(Constantinople, cls).create_opcodes( - block_number, timestamp + block_number=block_number, timestamp=timestamp ) @classmethod - def valid_opcodes( - cls, - ) -> List[Opcodes]: + def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]: """Return list of Opcodes that are valid to work on this fork.""" return [ Opcodes.SHL, @@ -865,27 +864,25 @@ class Istanbul(ConstantinopleFix): """Istanbul fork.""" @classmethod - def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """At Istanbul, pre-compile for blake2 compression is introduced.""" return [ Address(9, label="BLAKE2F"), - ] + super(Istanbul, cls).precompiles(block_number, timestamp) + ] + super(Istanbul, cls).precompiles(block_number=block_number, timestamp=timestamp) @classmethod - def valid_opcodes( - cls, - ) -> List[Opcodes]: + def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]: """Return list of Opcodes that are valid to work on this fork.""" return [Opcodes.CHAINID, Opcodes.SELFBALANCE] + super(Istanbul, cls).valid_opcodes() @classmethod - def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: + def gas_costs(cls, *, block_number: int = 0, timestamp: int = 0) -> GasCosts: """ On Istanbul, the non-zero transaction data byte cost is reduced to 16 due to EIP-2028. """ return replace( - super(Istanbul, cls).gas_costs(block_number, timestamp), + super(Istanbul, cls).gas_costs(block_number=block_number, timestamp=timestamp), G_TX_DATA_NON_ZERO=16, # https://eips.ethereum.org/EIPS/eip-2028 ) @@ -901,27 +898,29 @@ class Berlin(Istanbul): """Berlin fork.""" @classmethod - def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: + def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]: """At Berlin, access list transactions are introduced.""" - return [1] + super(Berlin, cls).tx_types(block_number, timestamp) + return [1] + super(Berlin, cls).tx_types(block_number=block_number, timestamp=timestamp) @classmethod - def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: + def contract_creating_tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]: """At Berlin, access list transactions are introduced.""" - return [1] + super(Berlin, cls).contract_creating_tx_types(block_number, timestamp) + return [1] + super(Berlin, cls).contract_creating_tx_types( + block_number=block_number, timestamp=timestamp + ) @classmethod def transaction_intrinsic_cost_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> TransactionIntrinsicCostCalculator: """ At Berlin, the transaction intrinsic cost needs to take the access list into account. """ super_fn = super(Berlin, cls).transaction_intrinsic_cost_calculator( - block_number, timestamp + block_number=block_number, timestamp=timestamp ) - gas_costs = cls.gas_costs(block_number, timestamp) + gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp) def fn( *, @@ -952,45 +951,45 @@ class London(Berlin): """London fork.""" @classmethod - def header_base_fee_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_base_fee_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Header must contain the Base Fee starting from London.""" return True @classmethod - def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: + def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]: """At London, dynamic fee transactions are introduced.""" - return [2] + super(London, cls).tx_types(block_number, timestamp) + return [2] + super(London, cls).tx_types(block_number=block_number, timestamp=timestamp) @classmethod - def contract_creating_tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: + def contract_creating_tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]: """At London, dynamic fee transactions are introduced.""" - return [2] + super(London, cls).contract_creating_tx_types(block_number, timestamp) + return [2] + super(London, cls).contract_creating_tx_types( + block_number=block_number, timestamp=timestamp + ) @classmethod - def valid_opcodes( - cls, - ) -> List[Opcodes]: + def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]: """Return list of Opcodes that are valid to work on this fork.""" return [Opcodes.BASEFEE] + super(London, cls).valid_opcodes() @classmethod - def max_refund_quotient(cls) -> int: + def max_refund_quotient(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the max refund quotient at London.""" return 5 @classmethod - def base_fee_max_change_denominator(cls, block_number: int = 0, timestamp: int = 0) -> int: + def base_fee_max_change_denominator(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the base fee max change denominator at London.""" return 8 @classmethod - def base_fee_elasticity_multiplier(cls, block_number: int = 0, timestamp: int = 0) -> int: + def base_fee_elasticity_multiplier(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the base fee elasticity multiplier at London.""" return 2 @classmethod def base_fee_per_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> BaseFeePerGasCalculator: """ Return a callable that calculates the base fee per gas at London. @@ -1019,9 +1018,11 @@ def base_fee_per_gas_calculator( base_fee_per_gas_delta """ base_fee_max_change_denominator = cls.base_fee_max_change_denominator( - block_number, timestamp + block_number=block_number, timestamp=timestamp + ) + elasticity_multiplier = cls.base_fee_elasticity_multiplier( + block_number=block_number, timestamp=timestamp ) - elasticity_multiplier = cls.base_fee_elasticity_multiplier(block_number, timestamp) def fn( *, parent_base_fee_per_gas: int, parent_gas_used: int, parent_gas_limit: int @@ -1053,17 +1054,21 @@ def fn( @classmethod def base_fee_change_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> BaseFeeChangeCalculator: """ Return a callable that calculates the gas that needs to be used to change the base fee. """ base_fee_max_change_denominator = cls.base_fee_max_change_denominator( - block_number, timestamp + block_number=block_number, timestamp=timestamp + ) + elasticity_multiplier = cls.base_fee_elasticity_multiplier( + block_number=block_number, timestamp=timestamp + ) + base_fee_per_gas_calculator = cls.base_fee_per_gas_calculator( + block_number=block_number, timestamp=timestamp ) - elasticity_multiplier = cls.base_fee_elasticity_multiplier(block_number, timestamp) - base_fee_per_gas_calculator = cls.base_fee_per_gas_calculator(block_number, timestamp) def fn( *, @@ -1133,23 +1138,23 @@ class Paris( """Paris (Merge) fork.""" @classmethod - def header_prev_randao_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_prev_randao_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Prev Randao is required starting from Paris.""" return True @classmethod - def header_zero_difficulty_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_zero_difficulty_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Zero difficulty is required starting from Paris.""" return True @classmethod - def get_reward(cls, block_number: int = 0, timestamp: int = 0) -> int: + def get_reward(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Paris updates the reward to 0.""" return 0 @classmethod def engine_new_payload_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """From Paris, payloads can be sent through the engine API.""" return 1 @@ -1159,26 +1164,24 @@ class Shanghai(Paris): """Shanghai fork.""" @classmethod - def header_withdrawals_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_withdrawals_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Withdrawals are required starting from Shanghai.""" return True @classmethod def engine_new_payload_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """From Shanghai, new payload calls must use version 2.""" return 2 @classmethod - def max_initcode_size(cls) -> int: + def max_initcode_size(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """From Shanghai, the initcode size is now limited. See EIP-3860.""" return 0xC000 @classmethod - def valid_opcodes( - cls, - ) -> List[Opcodes]: + def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]: """Return list of Opcodes that are valid to work on this fork.""" return [Opcodes.PUSH0] + super(Shanghai, cls).valid_opcodes() @@ -1212,27 +1215,31 @@ def get_blob_constant(cls, name: str) -> int | Literal["big"]: return retrieved_constant @classmethod - def header_excess_blob_gas_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_excess_blob_gas_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Excess blob gas is required starting from Cancun.""" return True @classmethod - def header_blob_gas_used_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_blob_gas_used_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Blob gas used is required starting from Cancun.""" return True @classmethod - def header_beacon_root_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_beacon_root_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Parent beacon block root is required starting from Cancun.""" return True @classmethod def blob_gas_price_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> BlobGasPriceCalculator: """Return a callable that calculates the blob gas price at Cancun.""" - min_base_fee_per_blob_gas = cls.min_base_fee_per_blob_gas(block_number, timestamp) - blob_base_fee_update_fraction = cls.blob_base_fee_update_fraction(block_number, timestamp) + min_base_fee_per_blob_gas = cls.min_base_fee_per_blob_gas( + block_number=block_number, timestamp=timestamp + ) + blob_base_fee_update_fraction = cls.blob_base_fee_update_fraction( + block_number=block_number, timestamp=timestamp + ) def fn(*, excess_blob_gas) -> int: return fake_exponential( @@ -1245,14 +1252,16 @@ def fn(*, excess_blob_gas) -> int: @classmethod def excess_blob_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> ExcessBlobGasCalculator: """ Return a callable that calculates the excess blob gas for a block at Cancun. """ - target_blobs_per_block = cls.target_blobs_per_block(block_number, timestamp) - blob_gas_per_blob = cls.blob_gas_per_blob(block_number, timestamp) + target_blobs_per_block = cls.target_blobs_per_block( + block_number=block_number, timestamp=timestamp + ) + blob_gas_per_blob = cls.blob_gas_per_blob(block_number=block_number, timestamp=timestamp) target_blob_gas_per_block = target_blobs_per_block * blob_gas_per_blob def fn( @@ -1280,27 +1289,27 @@ def fn( return fn @classmethod - def min_base_fee_per_blob_gas(cls, block_number: int = 0, timestamp: int = 0) -> int: + def min_base_fee_per_blob_gas(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the minimum base fee per blob gas for Cancun.""" return 1 @classmethod - def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the blob base fee update fraction for Cancun.""" return 3338477 @classmethod - def blob_gas_per_blob(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_gas_per_blob(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs are enabled starting from Cancun.""" return 2**17 @classmethod - def supports_blobs(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def supports_blobs(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """At Cancun, blobs support is enabled.""" return True @classmethod - def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ Blobs are enabled starting from Cancun, with a static target of 3 blobs per block. @@ -1308,7 +1317,7 @@ def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> in return 3 @classmethod - def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ Blobs are enabled starting from Cancun, with a static max of 6 blobs per block. @@ -1316,12 +1325,14 @@ def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: return 6 @classmethod - def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def blob_reserve_price_active(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Blob reserve price is not supported in Cancun.""" return False @classmethod - def full_blob_tx_wrapper_version(cls, block_number: int = 0, timestamp: int = 0) -> int | None: + def full_blob_tx_wrapper_version( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> int | None: """ Pre-Osaka forks don't use tx wrapper versions for full blob transactions. @@ -1329,49 +1340,58 @@ def full_blob_tx_wrapper_version(cls, block_number: int = 0, timestamp: int = 0) return None @classmethod - def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_tx(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ Blobs are enabled starting from Cancun, with a static max equal to the max per block. """ - return cls.max_blobs_per_block(block_number, timestamp) + return cls.max_blobs_per_block(block_number=block_number, timestamp=timestamp) @classmethod - def blob_schedule(cls, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None: + def blob_schedule(cls, *, block_number: int = 0, timestamp: int = 0) -> BlobSchedule | None: """ At Cancun, the fork object runs this routine to get the updated blob schedule. """ parent_fork = cls.parent() assert parent_fork is not None, "Parent fork must be defined" - blob_schedule = parent_fork.blob_schedule(block_number, timestamp) or BlobSchedule() + blob_schedule = ( + parent_fork.blob_schedule(block_number=block_number, timestamp=timestamp) + or BlobSchedule() + ) current_blob_schedule = ForkBlobSchedule( - target_blobs_per_block=cls.target_blobs_per_block(block_number, timestamp), - max_blobs_per_block=cls.max_blobs_per_block(block_number, timestamp), - base_fee_update_fraction=cls.blob_base_fee_update_fraction(block_number, timestamp), + target_blobs_per_block=cls.target_blobs_per_block( + block_number=block_number, timestamp=timestamp + ), + max_blobs_per_block=cls.max_blobs_per_block( + block_number=block_number, timestamp=timestamp + ), + base_fee_update_fraction=cls.blob_base_fee_update_fraction( + block_number=block_number, timestamp=timestamp + ), ) blob_schedule.append(fork=cls.name(), schedule=current_blob_schedule) return blob_schedule @classmethod - def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: + def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]: """At Cancun, blob type transactions are introduced.""" - return [3] + super(Cancun, cls).tx_types(block_number, timestamp) + return [3] + super(Cancun, cls).tx_types(block_number=block_number, timestamp=timestamp) @classmethod - def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """At Cancun, pre-compile for kzg point evaluation is introduced.""" return [ Address(10, label="KZG_POINT_EVALUATION"), - ] + super(Cancun, cls).precompiles(block_number, timestamp) + ] + super(Cancun, cls).precompiles(block_number=block_number, timestamp=timestamp) @classmethod - def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def system_contracts(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """Cancun introduces the system contract for EIP-4788.""" return [Address(0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02, label="BEACON_ROOTS_ADDRESS")] @classmethod - def pre_allocation_blockchain(cls) -> Mapping: + def pre_allocation_blockchain(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping: """ Cancun requires pre-allocation of the beacon root contract for EIP-4788 on blockchain type tests. @@ -1388,30 +1408,30 @@ def pre_allocation_blockchain(cls) -> Mapping: @classmethod def engine_new_payload_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """From Cancun, new payload calls must use version 3.""" return 3 @classmethod - def engine_get_blobs_version(cls, block_number: int = 0, timestamp: int = 0) -> Optional[int]: + def engine_get_blobs_version( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> Optional[int]: """At Cancun, the engine get blobs version is 1.""" return 1 @classmethod - def engine_new_payload_blob_hashes(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def engine_new_payload_blob_hashes(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """From Cancun, payloads must have blob hashes.""" return True @classmethod - def engine_new_payload_beacon_root(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def engine_new_payload_beacon_root(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """From Cancun, payloads must have a parent beacon block root.""" return True @classmethod - def valid_opcodes( - cls, - ) -> List[Opcodes]: + def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]: """Return list of Opcodes that are valid to work on this fork.""" return [ Opcodes.BLOBHASH, @@ -1436,7 +1456,7 @@ class Prague(Cancun): } @classmethod - def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """ At Prague, pre-compile for BLS operations are added. @@ -1456,21 +1476,21 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address] Address(15, label="BLS12_PAIRING_CHECK"), Address(16, label="BLS12_MAP_FP_TO_G1"), Address(17, label="BLS12_MAP_FP2_TO_G2"), - ] + super(Prague, cls).precompiles(block_number, timestamp) + ] + super(Prague, cls).precompiles(block_number=block_number, timestamp=timestamp) @classmethod - def tx_types(cls, block_number: int = 0, timestamp: int = 0) -> List[int]: + def tx_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[int]: """At Prague, set-code type transactions are introduced.""" - return [4] + super(Prague, cls).tx_types(block_number, timestamp) + return [4] + super(Prague, cls).tx_types(block_number=block_number, timestamp=timestamp) @classmethod - def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: + def gas_costs(cls, *, block_number: int = 0, timestamp: int = 0) -> GasCosts: """ On Prague, the standard token cost and the floor token costs are introduced due to EIP-7623. """ return replace( - super(Prague, cls).gas_costs(block_number, timestamp), + super(Prague, cls).gas_costs(block_number=block_number, timestamp=timestamp), G_TX_DATA_STANDARD_TOKEN_COST=4, # https://eips.ethereum.org/EIPS/eip-7623 G_TX_DATA_FLOOR_TOKEN_COST=10, G_AUTHORIZATION=25_000, @@ -1478,7 +1498,7 @@ def gas_costs(cls, block_number: int = 0, timestamp: int = 0) -> GasCosts: ) @classmethod - def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def system_contracts(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """ Prague introduces the system contracts for EIP-6110, EIP-7002, EIP-7251 and EIP-2935. @@ -1500,10 +1520,10 @@ def system_contracts(cls, block_number: int = 0, timestamp: int = 0) -> List[Add 0x0000F90827F1C53A10CB7A02335B175320002935, label="HISTORY_STORAGE_ADDRESS", ), - ] + super(Prague, cls).system_contracts(block_number, timestamp) + ] + super(Prague, cls).system_contracts(block_number=block_number, timestamp=timestamp) @classmethod - def max_request_type(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_request_type(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ At Prague, three request types are introduced, hence the max request type is 2. @@ -1512,13 +1532,13 @@ def max_request_type(cls, block_number: int = 0, timestamp: int = 0) -> int: @classmethod def calldata_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> CalldataGasCalculator: """ Return a callable that calculates the transaction gas cost for its calldata depending on its contents. """ - gas_costs = cls.gas_costs(block_number, timestamp) + gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp) def fn(*, data: BytesConvertible, floor: bool = False) -> int: tokens = 0 @@ -1535,14 +1555,16 @@ def fn(*, data: BytesConvertible, floor: bool = False) -> int: @classmethod def transaction_data_floor_cost_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> TransactionDataFloorCostCalculator: """ On Prague, due to EIP-7623, the transaction data floor cost is introduced. """ - calldata_gas_calculator = cls.calldata_gas_calculator(block_number, timestamp) - gas_costs = cls.gas_costs(block_number, timestamp) + calldata_gas_calculator = cls.calldata_gas_calculator( + block_number=block_number, timestamp=timestamp + ) + gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp) def fn(*, data: BytesConvertible) -> int: return calldata_gas_calculator(data=data, floor=True) + gas_costs.G_TRANSACTION @@ -1551,18 +1573,18 @@ def fn(*, data: BytesConvertible) -> int: @classmethod def transaction_intrinsic_cost_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> TransactionIntrinsicCostCalculator: """ At Prague, the transaction intrinsic cost needs to take the authorizations into account. """ super_fn = super(Prague, cls).transaction_intrinsic_cost_calculator( - block_number, timestamp + block_number=block_number, timestamp=timestamp ) - gas_costs = cls.gas_costs(block_number, timestamp) + gas_costs = cls.gas_costs(block_number=block_number, timestamp=timestamp) transaction_data_floor_cost_calculator = cls.transaction_data_floor_cost_calculator( - block_number, timestamp + block_number=block_number, timestamp=timestamp ) def fn( @@ -1593,22 +1615,22 @@ def fn( return fn @classmethod - def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the blob base fee update fraction for Prague.""" return 5007716 @classmethod - def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs in Prague, have a static target of 6 blobs per block.""" return 6 @classmethod - def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs in Prague, have a static max of 9 blobs per block.""" return 9 @classmethod - def pre_allocation_blockchain(cls) -> Mapping: + def pre_allocation_blockchain(cls, *, block_number: int = 0, timestamp: int = 0) -> Mapping: """ Prague requires pre-allocation of the beacon chain deposit contract for EIP-6110, the exits contract for EIP-7002, and the history storage @@ -1671,7 +1693,7 @@ def pre_allocation_blockchain(cls) -> Mapping: return new_allocation | super(Prague, cls).pre_allocation_blockchain() # type: ignore @classmethod - def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_requests_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """ Prague requires that the execution layer header contains the beacon chain requests hash. @@ -1679,7 +1701,7 @@ def header_requests_required(cls, block_number: int = 0, timestamp: int = 0) -> return True @classmethod - def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def engine_new_payload_requests(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """ From Prague, new payloads include the requests hash as a parameter. """ @@ -1687,14 +1709,14 @@ def engine_new_payload_requests(cls, block_number: int = 0, timestamp: int = 0) @classmethod def engine_new_payload_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """From Prague, new payload calls must use version 4.""" return 4 @classmethod def engine_forkchoice_updated_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """ At Prague, version number of NewPayload and ForkchoiceUpdated diverge. @@ -1713,28 +1735,30 @@ class Osaka(Prague, solc_name="cancun"): @classmethod def engine_get_payload_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """From Osaka, get payload calls must use version 5.""" return 5 @classmethod - def engine_get_blobs_version(cls, block_number: int = 0, timestamp: int = 0) -> Optional[int]: + def engine_get_blobs_version( + cls, *, block_number: int = 0, timestamp: int = 0 + ) -> Optional[int]: """At Osaka, the engine get blobs version is 2.""" return 2 @classmethod - def full_blob_tx_wrapper_version(cls, block_number=0, timestamp=0) -> int | None: + def full_blob_tx_wrapper_version(cls, *, block_number=0, timestamp=0) -> int | None: """At Osaka, the full blob transaction wrapper version is defined.""" return 1 @classmethod - def transaction_gas_limit_cap(cls, block_number: int = 0, timestamp: int = 0) -> int | None: + def transaction_gas_limit_cap(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None: """At Osaka, transaction gas limit is capped at 16 million (2**24).""" return 16_777_216 @classmethod - def block_rlp_size_limit(cls, block_number: int = 0, timestamp: int = 0) -> int | None: + def block_rlp_size_limit(cls, *, block_number: int = 0, timestamp: int = 0) -> int | None: """From Osaka, block RLP size is limited as specified in EIP-7934.""" max_block_size = 10_485_760 safety_margin = 2_097_152 @@ -1749,16 +1773,14 @@ def is_deployed(cls) -> bool: return False @classmethod - def valid_opcodes( - cls, - ) -> List[Opcodes]: + def valid_opcodes(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Opcodes]: """Return list of Opcodes that are valid to work on this fork.""" return [ Opcodes.CLZ, ] + super(Prague, cls).valid_opcodes() @classmethod - def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address]: + def precompiles(cls, *, block_number: int = 0, timestamp: int = 0) -> List[Address]: """ At Osaka, pre-compile for p256verify operation is added. @@ -1766,19 +1788,23 @@ def precompiles(cls, block_number: int = 0, timestamp: int = 0) -> List[Address] """ return [ Address(0x100, label="P256VERIFY"), - ] + super(Osaka, cls).precompiles(block_number, timestamp) + ] + super(Osaka, cls).precompiles(block_number=block_number, timestamp=timestamp) @classmethod def excess_blob_gas_calculator( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> ExcessBlobGasCalculator: """ Return a callable that calculates the excess blob gas for a block. """ - target_blobs_per_block = cls.target_blobs_per_block(block_number, timestamp) - blob_gas_per_blob = cls.blob_gas_per_blob(block_number, timestamp) + target_blobs_per_block = cls.target_blobs_per_block( + block_number=block_number, timestamp=timestamp + ) + blob_gas_per_blob = cls.blob_gas_per_blob(block_number=block_number, timestamp=timestamp) target_blob_gas_per_block = target_blobs_per_block * blob_gas_per_blob - max_blobs_per_block = cls.max_blobs_per_block(block_number, timestamp) + max_blobs_per_block = cls.max_blobs_per_block( + block_number=block_number, timestamp=timestamp + ) blob_base_cost = 2**13 # EIP-7918 new parameter def fn( @@ -1821,7 +1847,7 @@ def fn( return fn @classmethod - def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_tx(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """ Blobs in Osaka, have a static max of 6 blobs per tx. Differs from the max per block. @@ -1829,12 +1855,12 @@ def max_blobs_per_tx(cls, block_number: int = 0, timestamp: int = 0) -> int: return 6 @classmethod - def blob_reserve_price_active(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def blob_reserve_price_active(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """Blob reserve price is supported in Osaka.""" return True @classmethod - def blob_base_cost(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_cost(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the base cost of a blob at a given fork.""" return 2**13 # EIP-7918 new parameter @@ -1843,17 +1869,17 @@ class BPO1(Osaka, bpo_fork=True): """Mainnet BPO1 fork - Blob Parameter Only fork 1.""" @classmethod - def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the blob base fee update fraction for BPO1.""" return 8346193 @classmethod - def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs in BPO1 have a target of 10 blobs per block.""" return 10 @classmethod - def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs in BPO1 have a max of 15 blobs per block.""" return 15 @@ -1862,17 +1888,17 @@ class BPO2(BPO1, bpo_fork=True): """Mainnet BPO2 fork - Blob Parameter Only fork 2.""" @classmethod - def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the blob base fee update fraction for BPO2.""" return 11684671 @classmethod - def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs in BPO2 have a target of 14 blobs per block.""" return 14 @classmethod - def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs in BPO2 have a max of 21 blobs per block.""" return 21 @@ -1884,17 +1910,17 @@ class BPO3(BPO2, bpo_fork=True): """ @classmethod - def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the blob base fee update fraction for BPO3.""" return 20609697 @classmethod - def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs in BPO3 have a target of 21 blobs per block.""" return 21 @classmethod - def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs in BPO3 have a max of 32 blobs per block.""" return 32 @@ -1906,17 +1932,17 @@ class BPO4(BPO3, bpo_fork=True): """ @classmethod - def blob_base_fee_update_fraction(cls, block_number: int = 0, timestamp: int = 0) -> int: + def blob_base_fee_update_fraction(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Return the blob base fee update fraction for BPO4.""" return 13739630 @classmethod - def target_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def target_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs in BPO4 have a target of 14 blobs per block.""" return 14 @classmethod - def max_blobs_per_block(cls, block_number: int = 0, timestamp: int = 0) -> int: + def max_blobs_per_block(cls, *, block_number: int = 0, timestamp: int = 0) -> int: """Blobs in BPO4 have a max of 21 blobs per block.""" return 21 @@ -1934,7 +1960,7 @@ class Amsterdam(Osaka): """Amsterdam fork.""" @classmethod - def header_bal_hash_required(cls, block_number: int = 0, timestamp: int = 0) -> bool: + def header_bal_hash_required(cls, *, block_number: int = 0, timestamp: int = 0) -> bool: """ From Amsterdam, header must contain block access list hash (EIP-7928). """ @@ -1947,14 +1973,14 @@ def is_deployed(cls) -> bool: @classmethod def engine_new_payload_version( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> Optional[int]: """From Amsterdam, new payload calls must use version 5.""" return 5 @classmethod def engine_execution_payload_block_access_list( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> bool: """ From Amsterdam, engine execution payload includes `block_access_list` @@ -1967,23 +1993,23 @@ class EOFv1(Prague, solc_name="cancun"): """EOF fork.""" @classmethod - def evm_code_types(cls, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]: + def evm_code_types(cls, *, block_number: int = 0, timestamp: int = 0) -> List[EVMCodeType]: """EOF V1 is supported starting from Osaka.""" return super(EOFv1, cls).evm_code_types( - block_number, - timestamp, + block_number=block_number, + timestamp=timestamp, ) + [EVMCodeType.EOF_V1] @classmethod def call_opcodes( - cls, block_number: int = 0, timestamp: int = 0 + cls, *, block_number: int = 0, timestamp: int = 0 ) -> List[Tuple[Opcodes, EVMCodeType]]: """EOF V1 introduces EXTCALL, EXTSTATICCALL, EXTDELEGATECALL.""" return [ (Opcodes.EXTCALL, EVMCodeType.EOF_V1), (Opcodes.EXTSTATICCALL, EVMCodeType.EOF_V1), (Opcodes.EXTDELEGATECALL, EVMCodeType.EOF_V1), - ] + super(EOFv1, cls).call_opcodes(block_number, timestamp) + ] + super(EOFv1, cls).call_opcodes(block_number=block_number, timestamp=timestamp) @classmethod def is_deployed(cls) -> bool: diff --git a/ethereum_test_forks/tests/test_forks.py b/ethereum_test_forks/tests/test_forks.py index 3ef47b5c7d..794924bb97 100644 --- a/ethereum_test_forks/tests/test_forks.py +++ b/ethereum_test_forks/tests/test_forks.py @@ -64,30 +64,45 @@ def test_transition_forks(): assert BerlinToLondonAt5.transitions_to() == London assert BerlinToLondonAt5.transitions_from() == Berlin - assert BerlinToLondonAt5.transition_tool_name(4, 0) == "Berlin" - assert BerlinToLondonAt5.transition_tool_name(5, 0) == "London" + assert BerlinToLondonAt5.transition_tool_name(block_number=4, timestamp=0) == "Berlin" + assert BerlinToLondonAt5.transition_tool_name(block_number=5, timestamp=0) == "London" # Default values of transition forks is the transition block assert BerlinToLondonAt5.transition_tool_name() == "London" - assert ParisToShanghaiAtTime15k.transition_tool_name(0, 14_999) == "Merge" - assert ParisToShanghaiAtTime15k.transition_tool_name(0, 15_000) == "Shanghai" + assert ( + ParisToShanghaiAtTime15k.transition_tool_name(block_number=0, timestamp=14_999) == "Merge" + ) + assert ( + ParisToShanghaiAtTime15k.transition_tool_name(block_number=0, timestamp=15_000) + == "Shanghai" + ) assert ParisToShanghaiAtTime15k.transition_tool_name() == "Shanghai" - assert BerlinToLondonAt5.header_base_fee_required(4, 0) is False - assert BerlinToLondonAt5.header_base_fee_required(5, 0) is True + assert BerlinToLondonAt5.header_base_fee_required(block_number=4, timestamp=0) is False + assert BerlinToLondonAt5.header_base_fee_required(block_number=5, timestamp=0) is True - assert ParisToShanghaiAtTime15k.header_withdrawals_required(0, 14_999) is False - assert ParisToShanghaiAtTime15k.header_withdrawals_required(0, 15_000) is True + assert ( + ParisToShanghaiAtTime15k.header_withdrawals_required(block_number=0, timestamp=14_999) + is False + ) + assert ( + ParisToShanghaiAtTime15k.header_withdrawals_required(block_number=0, timestamp=15_000) + is True + ) - assert ParisToShanghaiAtTime15k.engine_new_payload_version(0, 14_999) == 1 - assert ParisToShanghaiAtTime15k.engine_new_payload_version(0, 15_000) == 2 + assert ( + ParisToShanghaiAtTime15k.engine_new_payload_version(block_number=0, timestamp=14_999) == 1 + ) + assert ( + ParisToShanghaiAtTime15k.engine_new_payload_version(block_number=0, timestamp=15_000) == 2 + ) - assert BerlinToLondonAt5.fork_at(4, 0) == Berlin - assert BerlinToLondonAt5.fork_at(5, 0) == London - assert ParisToShanghaiAtTime15k.fork_at(0, 14_999) == Paris - assert ParisToShanghaiAtTime15k.fork_at(0, 15_000) == Shanghai + assert BerlinToLondonAt5.fork_at(block_number=4, timestamp=0) == Berlin + assert BerlinToLondonAt5.fork_at(block_number=5, timestamp=0) == London + assert ParisToShanghaiAtTime15k.fork_at(block_number=0, timestamp=14_999) == Paris + assert ParisToShanghaiAtTime15k.fork_at(block_number=0, timestamp=15_000) == Shanghai assert ParisToShanghaiAtTime15k.fork_at() == Paris - assert ParisToShanghaiAtTime15k.fork_at(10_000_000, 14_999) == Paris + assert ParisToShanghaiAtTime15k.fork_at(block_number=10_000_000, timestamp=14_999) == Paris def test_forks_from(): # noqa: D103 @@ -125,17 +140,32 @@ def test_forks(): assert f"{ParisToShanghaiAtTime15k}" == "ParisToShanghaiAtTime15k" # Test some fork properties - assert Berlin.header_base_fee_required(0, 0) is False - assert London.header_base_fee_required(0, 0) is True - assert Paris.header_base_fee_required(0, 0) is True + assert Berlin.header_base_fee_required(block_number=0, timestamp=0) is False + assert London.header_base_fee_required(block_number=0, timestamp=0) is True + assert Paris.header_base_fee_required(block_number=0, timestamp=0) is True # Default values of normal forks if the genesis block assert Paris.header_base_fee_required() is True # Transition forks too - assert cast(Fork, BerlinToLondonAt5).header_base_fee_required(4, 0) is False - assert cast(Fork, BerlinToLondonAt5).header_base_fee_required(5, 0) is True - assert cast(Fork, ParisToShanghaiAtTime15k).header_withdrawals_required(0, 14_999) is False - assert cast(Fork, ParisToShanghaiAtTime15k).header_withdrawals_required(0, 15_000) is True + assert ( + cast(Fork, BerlinToLondonAt5).header_base_fee_required(block_number=4, timestamp=0) + is False + ) + assert ( + cast(Fork, BerlinToLondonAt5).header_base_fee_required(block_number=5, timestamp=0) is True + ) + assert ( + cast(Fork, ParisToShanghaiAtTime15k).header_withdrawals_required( + block_number=0, timestamp=14_999 + ) + is False + ) + assert ( + cast(Fork, ParisToShanghaiAtTime15k).header_withdrawals_required( + block_number=0, timestamp=15_000 + ) + is True + ) assert cast(Fork, ParisToShanghaiAtTime15k).header_withdrawals_required() is True @@ -266,7 +296,7 @@ class PrePreAllocFork(Shanghai): """Dummy fork used for testing.""" @classmethod - def pre_allocation(cls) -> Dict: + def pre_allocation(cls, *, block_number: int = 0, timestamp: int = 0) -> Dict: """Return some starting point for allocation.""" return {"test": "test"} @@ -275,7 +305,7 @@ class PreAllocFork(PrePreAllocFork): """Dummy fork used for testing.""" @classmethod - def pre_allocation(cls) -> Dict: + def pre_allocation(cls, *, block_number: int = 0, timestamp: int = 0) -> Dict: """Add allocation to the pre-existing one from previous fork.""" return {"test2": "test2"} | super(PreAllocFork, cls).pre_allocation() diff --git a/ethereum_test_specs/blockchain.py b/ethereum_test_specs/blockchain.py index 7c523f2cc2..458b5dd110 100644 --- a/ethereum_test_specs/blockchain.py +++ b/ethereum_test_specs/blockchain.py @@ -524,7 +524,7 @@ def generate_block_data( env=env, fork=fork, chain_id=self.chain_id, - reward=fork.get_reward(env.number, env.timestamp), + reward=fork.get_reward(block_number=env.number, timestamp=env.timestamp), blob_schedule=fork.blob_schedule(), ), debug_output_path=self.get_next_transition_tool_output_path(), @@ -537,7 +537,11 @@ def generate_block_data( # executing the block by simply counting the type-3 txs, we need to set # the correct value by default. blob_gas_used: int | None = None - if (blob_gas_per_blob := fork.blob_gas_per_blob(env.number, env.timestamp)) > 0: + if ( + blob_gas_per_blob := fork.blob_gas_per_blob( + block_number=env.number, timestamp=env.timestamp + ) + ) > 0: blob_gas_used = blob_gas_per_blob * count_blobs(txs) header = FixtureHeader( @@ -575,7 +579,7 @@ def generate_block_data( ) requests_list: List[Bytes] | None = None - if fork.header_requests_required(header.number, header.timestamp): + if fork.header_requests_required(block_number=header.number, timestamp=header.timestamp): assert transition_tool_output.result.requests is not None, ( "Requests are required for this block" ) @@ -594,7 +598,7 @@ def generate_block_data( header.requests_hash = Hash(Requests(requests_lists=list(block.requests))) requests_list = block.requests - if fork.header_bal_hash_required(header.number, header.timestamp): + if fork.header_bal_hash_required(block_number=header.number, timestamp=header.timestamp): assert transition_tool_output.result.block_access_list is not None, ( "Block access list is required for this block but was not provided " "by the transition tool" @@ -798,7 +802,7 @@ def make_hive_fixture( ) self.check_exception_test(exception=invalid_blocks > 0) fcu_version = fork.engine_forkchoice_updated_version( - built_block.header.number, built_block.header.timestamp + block_number=built_block.header.number, timestamp=built_block.header.timestamp ) assert fcu_version is not None, ( "A hive fixture was requested but no forkchoice update is defined." diff --git a/ethereum_test_specs/state.py b/ethereum_test_specs/state.py index 917ed8a28e..3e7c27041c 100644 --- a/ethereum_test_specs/state.py +++ b/ethereum_test_specs/state.py @@ -278,7 +278,7 @@ def make_state_test_fixture( # We can't generate a state test fixture that names a transition fork, # so we get the fork at the block number and timestamp of the state # test - fork = fork.fork_at(self.env.number, self.env.timestamp) + fork = fork.fork_at(block_number=self.env.number, timestamp=self.env.timestamp) env = self.env.set_fork_requirements(fork) tx = self.tx.with_signature_and_sender(keep_secret_key=True) diff --git a/ethereum_test_types/block_types.py b/ethereum_test_types/block_types.py index 8e7977a3b1..6df95e52d6 100644 --- a/ethereum_test_types/block_types.py +++ b/ethereum_test_types/block_types.py @@ -140,40 +140,46 @@ def set_fork_requirements(self, fork: Fork) -> "Environment": updated_values: Dict[str, Any] = {} - if fork.header_prev_randao_required(number, timestamp) and self.prev_randao is None: + if ( + fork.header_prev_randao_required(block_number=number, timestamp=timestamp) + and self.prev_randao is None + ): updated_values["prev_randao"] = 0 - if fork.header_withdrawals_required(number, timestamp) and self.withdrawals is None: + if ( + fork.header_withdrawals_required(block_number=number, timestamp=timestamp) + and self.withdrawals is None + ): updated_values["withdrawals"] = [] if ( - fork.header_base_fee_required(number, timestamp) + fork.header_base_fee_required(block_number=number, timestamp=timestamp) and self.base_fee_per_gas is None and self.parent_base_fee_per_gas is None ): updated_values["base_fee_per_gas"] = DEFAULT_BASE_FEE - if fork.header_zero_difficulty_required(number, timestamp): + if fork.header_zero_difficulty_required(block_number=number, timestamp=timestamp): updated_values["difficulty"] = 0 elif self.difficulty is None and self.parent_difficulty is None: updated_values["difficulty"] = 0x20000 if ( - fork.header_excess_blob_gas_required(number, timestamp) + fork.header_excess_blob_gas_required(block_number=number, timestamp=timestamp) and self.excess_blob_gas is None and self.parent_excess_blob_gas is None ): updated_values["excess_blob_gas"] = 0 if ( - fork.header_blob_gas_used_required(number, timestamp) + fork.header_blob_gas_used_required(block_number=number, timestamp=timestamp) and self.blob_gas_used is None and self.parent_blob_gas_used is None ): updated_values["blob_gas_used"] = 0 if ( - fork.header_beacon_root_required(number, timestamp) + fork.header_beacon_root_required(block_number=number, timestamp=timestamp) and self.parent_beacon_block_root is None ): updated_values["parent_beacon_block_root"] = 0 diff --git a/pytest_plugins/execute/pre_alloc.py b/pytest_plugins/execute/pre_alloc.py index 239de55f93..58131e5cbb 100644 --- a/pytest_plugins/execute/pre_alloc.py +++ b/pytest_plugins/execute/pre_alloc.py @@ -293,7 +293,7 @@ def deploy_contract( f"initcode too large {len(initcode)} > {MAX_INITCODE_SIZE}" ) - calldata_gas_calculator = self._fork.calldata_gas_calculator() + calldata_gas_calculator = self._fork.calldata_gas_calculator(block_number=0, timestamp=0) deploy_gas_limit += calldata_gas_calculator(data=initcode) # Limit the gas limit diff --git a/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py b/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py index d41fd68843..fb5d4f89cf 100644 --- a/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py +++ b/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py @@ -247,7 +247,9 @@ def generate_block(self: "ChainBuilderEthRPC"): forkchoice_state = ForkchoiceState( head_block_hash=head_block["hash"], ) - parent_beacon_block_root = Hash(0) if self.fork.header_beacon_root_required(0, 0) else None + parent_beacon_block_root = ( + Hash(0) if self.fork.header_beacon_root_required(block_number=0, timestamp=0) else None + ) payload_attributes = PayloadAttributes( timestamp=HexNumber(head_block["timestamp"]) + 1, prev_randao=Hash(0), @@ -255,13 +257,17 @@ def generate_block(self: "ChainBuilderEthRPC"): withdrawals=[] if self.fork.header_withdrawals_required() else None, parent_beacon_block_root=parent_beacon_block_root, target_blobs_per_block=( - self.fork.target_blobs_per_block(0, 0) - if self.fork.engine_payload_attribute_target_blobs_per_block(0, 0) + self.fork.target_blobs_per_block(block_number=0, timestamp=0) + if self.fork.engine_payload_attribute_target_blobs_per_block( + block_number=0, timestamp=0 + ) else None ), max_blobs_per_block=( - self.fork.max_blobs_per_block(0, 0) - if self.fork.engine_payload_attribute_max_blobs_per_block(0, 0) + self.fork.max_blobs_per_block(block_number=0, timestamp=0) + if self.fork.engine_payload_attribute_max_blobs_per_block( + block_number=0, timestamp=0 + ) else None ), ) From 7a486e3f56c2b66935685a16799a00b5cae57d0f Mon Sep 17 00:00:00 2001 From: Abhishek Kafle <144969576+akafle01@users.noreply.github.com> Date: Wed, 1 Oct 2025 20:41:59 -0400 Subject: [PATCH 063/102] feat(forks): Enforce keyword-only arguments in fork methods (#1714) * Enforce keyword-only arguments in calldata_gas_calculator methods and calls * Apply keyword-only enforcement to all BaseFork methods and implementations * fixes --------- Co-authored-by: Abhishek Kafle Co-authored-by: Mario Vega --- .../eip4788_beacon_root/test_beacon_root_contract.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cancun/eip4788_beacon_root/test_beacon_root_contract.py b/cancun/eip4788_beacon_root/test_beacon_root_contract.py index 7ffb004920..bc91bc93f2 100644 --- a/cancun/eip4788_beacon_root/test_beacon_root_contract.py +++ b/cancun/eip4788_beacon_root/test_beacon_root_contract.py @@ -544,7 +544,7 @@ def test_beacon_root_transition( ): timestamp_index = timestamp % Spec.HISTORY_BUFFER_LENGTH - transitioned = fork.header_beacon_root_required(i, timestamp) + transitioned = fork.header_beacon_root_required(block_number=i, timestamp=timestamp) if transitioned: # We've transitioned, the current timestamp must contain a value in # the contract @@ -650,7 +650,7 @@ def test_no_beacon_root_contract_at_transition( Tests the fork transition to cancun in the case where the beacon root pre-deploy was not deployed in time for the fork. """ - assert fork.header_beacon_root_required(1, timestamp) + assert fork.header_beacon_root_required(block_number=1, timestamp=timestamp) blocks: List[Block] = [ Block( txs=[tx], @@ -730,7 +730,7 @@ def test_beacon_root_contract_deploy( Tests the fork transition to cancun deploying the contract during Shanghai and verifying the code deployed and its functionality after Cancun. """ - assert fork.header_beacon_root_required(1, timestamp) + assert fork.header_beacon_root_required(block_number=1, timestamp=timestamp) tx_gas_limit = 0x3D090 tx_gas_price = 0xE8D4A51000 deployer_required_balance = tx_gas_limit * tx_gas_price @@ -764,7 +764,9 @@ def test_beacon_root_contract_deploy( txs=[deploy_tx], parent_beacon_block_root=( beacon_root - if fork.header_beacon_root_required(1, current_timestamp) + if fork.header_beacon_root_required( + block_number=1, timestamp=current_timestamp + ) else None ), timestamp=timestamp // 2, From 6b867141e4b53379b67954ca13449591c5d14932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:34:32 +0800 Subject: [PATCH 064/102] feat(benchmarks): add bloatnet marker support (#2169) Co-authored-by: Mario Vega --- pytest_plugins/filler/gen_test_doc/gen_test_doc.py | 13 ++++++++++++- pytest_plugins/filler/gen_test_doc/page_props.py | 1 + pytest_plugins/shared/execute_fill.py | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pytest_plugins/filler/gen_test_doc/gen_test_doc.py b/pytest_plugins/filler/gen_test_doc/gen_test_doc.py index aae46ab5fe..6f1d162a68 100644 --- a/pytest_plugins/filler/gen_test_doc/gen_test_doc.py +++ b/pytest_plugins/filler/gen_test_doc/gen_test_doc.py @@ -431,6 +431,7 @@ def create_function_page_props(self, test_functions: Dict["str", List[Item]]) -> ) is_benchmark = items[0].get_closest_marker("benchmark") is not None + is_stateful = items[0].get_closest_marker("stateful") is not None self.function_page_props[function_id] = FunctionPageProps( title=get_test_function_name(items[0]), @@ -447,6 +448,7 @@ def create_function_page_props(self, test_functions: Dict["str", List[Item]]) -> html_static_page_target=f"./{get_test_function_name(items[0])}.html", mkdocs_function_page_target=f"./{get_test_function_name(items[0])}/", is_benchmark=is_benchmark, + is_stateful=is_stateful, ) def create_module_page_props(self) -> None: @@ -462,6 +464,7 @@ def create_module_page_props(self) -> None: pytest_node_id=str(module_path), package_name=get_import_path(module_path), is_benchmark=function_page.is_benchmark, + is_stateful=function_page.is_stateful, test_functions=[ TestFunction( name=function_page.title, @@ -475,6 +478,8 @@ def create_module_page_props(self) -> None: existing_module_page = self.module_page_props[str(function_page.path)] if function_page.is_benchmark: existing_module_page.is_benchmark = True + if function_page.is_stateful: + existing_module_page.is_stateful = True existing_module_page.test_functions.append( TestFunction( name=function_page.title, @@ -511,7 +516,12 @@ def add_directory_page_props(self) -> None: is_benchmark = any( module_page.is_benchmark for module_page in self.module_page_props.values() - if module_page.path.parent == directory + if directory in module_page.path.parents or module_page.path.parent == directory + ) + is_stateful = any( + module_page.is_stateful + for module_page in self.module_page_props.values() + if directory in module_page.path.parents or module_page.path.parent == directory ) self.page_props[str(directory)] = DirectoryPageProps( @@ -526,6 +536,7 @@ def add_directory_page_props(self) -> None: # init.py will be used for docstrings package_name=get_import_path(directory), is_benchmark=is_benchmark, + is_stateful=is_stateful, ) def find_files_within_collection_scope(self, file_pattern: str) -> List[Path]: diff --git a/pytest_plugins/filler/gen_test_doc/page_props.py b/pytest_plugins/filler/gen_test_doc/page_props.py index 471cd1f2d5..cf6d8adb5a 100644 --- a/pytest_plugins/filler/gen_test_doc/page_props.py +++ b/pytest_plugins/filler/gen_test_doc/page_props.py @@ -111,6 +111,7 @@ class PagePropsBase: pytest_node_id: str package_name: str is_benchmark: bool = False + is_stateful: bool = False @property @abstractmethod diff --git a/pytest_plugins/shared/execute_fill.py b/pytest_plugins/shared/execute_fill.py index 0df88c2ef3..e1f91d55a4 100644 --- a/pytest_plugins/shared/execute_fill.py +++ b/pytest_plugins/shared/execute_fill.py @@ -100,6 +100,10 @@ def pytest_configure(config: pytest.Config): "markers", "benchmark: Tests relevant to benchmarking EVMs.", ) + config.addinivalue_line( + "markers", + "stateful: Tests for stateful benchmarking scenarios.", + ) config.addinivalue_line( "markers", "exception_test: Negative tests that include an invalid block or transaction.", From ccf865ad915ed3554ced74492728e87eecaf61e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:34:32 +0800 Subject: [PATCH 065/102] feat(benchmarks): add bloatnet marker support (#2169) Co-authored-by: Mario Vega --- benchmark/bloatnet/__init__.py | 1 - benchmark/conftest.py | 18 +++-- benchmark/stateful/__init__.py | 1 + benchmark/stateful/bloatnet/__init__.py | 1 + benchmark/stateful/bloatnet/test_bloatnet.py | 6 ++ .../bloatnet/test_multi_opcode.py | 0 benchmark/stateful/conftest.py | 66 +++++++++++++++++++ 7 files changed, 88 insertions(+), 5 deletions(-) delete mode 100644 benchmark/bloatnet/__init__.py create mode 100644 benchmark/stateful/__init__.py create mode 100644 benchmark/stateful/bloatnet/__init__.py create mode 100644 benchmark/stateful/bloatnet/test_bloatnet.py rename benchmark/{ => stateful}/bloatnet/test_multi_opcode.py (100%) create mode 100644 benchmark/stateful/conftest.py diff --git a/benchmark/bloatnet/__init__.py b/benchmark/bloatnet/__init__.py deleted file mode 100644 index 0f0656c832..0000000000 --- a/benchmark/bloatnet/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""BloatNet benchmark tests for Ethereum execution spec tests.""" diff --git a/benchmark/conftest.py b/benchmark/conftest.py index d51b47dda8..d4225107ae 100644 --- a/benchmark/conftest.py +++ b/benchmark/conftest.py @@ -38,8 +38,10 @@ def pytest_collection_modifyitems(config, items): if gen_docs: for item in items: - if benchmark_dir in Path(item.fspath).parents and not item.get_closest_marker( - "benchmark" + if ( + benchmark_dir in Path(item.fspath).parents + and not item.get_closest_marker("benchmark") + and not item.get_closest_marker("stateful") ): item.add_marker(benchmark_marker) return @@ -47,12 +49,18 @@ def pytest_collection_modifyitems(config, items): marker_expr = config.getoption("-m", default="") run_benchmarks = ( marker_expr and "benchmark" in marker_expr and "not benchmark" not in marker_expr - ) or config.getoption("--gas-benchmark-values", default=None) + ) + run_stateful_tests = ( + marker_expr and "stateful" in marker_expr and "not stateful" not in marker_expr + ) items_for_removal = [] for i, item in enumerate(items): is_in_benchmark_dir = benchmark_dir in Path(item.fspath).parents - is_benchmark_test = is_in_benchmark_dir or item.get_closest_marker("benchmark") + has_stateful_marker = item.get_closest_marker("stateful") + is_benchmark_test = ( + is_in_benchmark_dir and not has_stateful_marker + ) or item.get_closest_marker("benchmark") if is_benchmark_test: if is_in_benchmark_dir and not item.get_closest_marker("benchmark"): @@ -61,6 +69,8 @@ def pytest_collection_modifyitems(config, items): items_for_removal.append(i) elif run_benchmarks: items_for_removal.append(i) + elif is_in_benchmark_dir and has_stateful_marker and not run_stateful_tests: + items_for_removal.append(i) for i in reversed(items_for_removal): items.pop(i) diff --git a/benchmark/stateful/__init__.py b/benchmark/stateful/__init__.py new file mode 100644 index 0000000000..f06e177ebd --- /dev/null +++ b/benchmark/stateful/__init__.py @@ -0,0 +1 @@ +"""Benchmark state tests package.""" diff --git a/benchmark/stateful/bloatnet/__init__.py b/benchmark/stateful/bloatnet/__init__.py new file mode 100644 index 0000000000..ec32f5790d --- /dev/null +++ b/benchmark/stateful/bloatnet/__init__.py @@ -0,0 +1 @@ +"""Bloatnet benchmark tests package.""" diff --git a/benchmark/stateful/bloatnet/test_bloatnet.py b/benchmark/stateful/bloatnet/test_bloatnet.py new file mode 100644 index 0000000000..e489de3aaf --- /dev/null +++ b/benchmark/stateful/bloatnet/test_bloatnet.py @@ -0,0 +1,6 @@ +""" +abstract: Tests benchmark worst-case bloatnet scenarios. + Tests benchmark worst-case bloatnet scenarios. + +Tests running worst-case bloatnet scenarios for benchmarking purposes. +""" diff --git a/benchmark/bloatnet/test_multi_opcode.py b/benchmark/stateful/bloatnet/test_multi_opcode.py similarity index 100% rename from benchmark/bloatnet/test_multi_opcode.py rename to benchmark/stateful/bloatnet/test_multi_opcode.py diff --git a/benchmark/stateful/conftest.py b/benchmark/stateful/conftest.py new file mode 100644 index 0000000000..d208dee4e4 --- /dev/null +++ b/benchmark/stateful/conftest.py @@ -0,0 +1,66 @@ +"""Pytest configuration for state tests.""" + +from pathlib import Path + +import pytest + +DEFAULT_BENCHMARK_FORK = "Prague" + + +def pytest_generate_tests(metafunc): + """ + Add default valid_from marker to state tests without explicit fork + specification. + """ + state_dir = Path(__file__).parent + test_file_path = Path(metafunc.definition.fspath) + + if state_dir in test_file_path.parents: + has_valid_from = any( + marker.name == "valid_from" for marker in metafunc.definition.iter_markers() + ) + if not has_valid_from: + metafunc.definition.add_marker(pytest.mark.valid_from(DEFAULT_BENCHMARK_FORK)) + + +def pytest_collection_modifyitems(config, items): + """Manage stateful test markers and filtering.""" + state_dir = Path(__file__).parent + gen_docs = config.getoption("--gen-docs", default=False) + + if gen_docs: + _add_stateful_markers_for_docs(items, state_dir) + return + + marker_expr = config.getoption("-m", default="") + + items_to_remove = [] + + for i, item in enumerate(items): + item_path = Path(item.fspath) + is_in_state_dir = state_dir in item_path.parents + + # Add stateful marker to tests in state directory that don't have it + if is_in_state_dir and not item.get_closest_marker("stateful"): + item.add_marker(pytest.mark.stateful) + + has_stateful_marker = item.get_closest_marker("stateful") + + run_stateful = ( + marker_expr and ("stateful" in marker_expr) and ("not stateful" not in marker_expr) + ) + + # When not running stateful tests, remove all stateful tests + if not run_stateful and has_stateful_marker: + items_to_remove.append(i) + + for i in reversed(items_to_remove): + items.pop(i) + + +def _add_stateful_markers_for_docs(items, state_dir): + """Add stateful markers for documentation generation.""" + for item in items: + item_path = Path(item.fspath) + if state_dir in item_path.parents and not item.get_closest_marker("stateful"): + item.add_marker(pytest.mark.stateful) From 1d74617b1aa82acfb092d685b69e340e453c31fe Mon Sep 17 00:00:00 2001 From: spencer Date: Thu, 2 Oct 2025 13:26:02 +0100 Subject: [PATCH 066/102] chore(cli): erigon 7825 exception bump. (#2250) --- ethereum_clis/clis/erigon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum_clis/clis/erigon.py b/ethereum_clis/clis/erigon.py index c549d0deb6..b16bcb4b51 100644 --- a/ethereum_clis/clis/erigon.py +++ b/ethereum_clis/clis/erigon.py @@ -45,7 +45,7 @@ class ErigonExceptionMapper(ExceptionMapper): } mapping_regex = { TransactionException.GAS_LIMIT_EXCEEDS_MAXIMUM: ( - r"invalid block, txnIdx=\d+, gas limit too high" + r"invalid block, txnIdx=\d+,.*gas limit too high" ), BlockException.INCORRECT_BLOB_GAS_USED: r"blobGasUsed by execution: \d+, in header: \d+", BlockException.INCORRECT_EXCESS_BLOB_GAS: r"invalid excessBlobGas: have \d+, want \d+", From a821064fd8c6fc7adce0fe759010a0567f8f9082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 2 Oct 2025 14:48:53 +0200 Subject: [PATCH 067/102] feat(tests): add tests for P256 with x,y out of range (#2237) Add better test cases for the `p256verify` precompile where `x` or `y` coordinate of the public key point are incorrectly bigger than `P`. The difference from the previous similar cases is that reducing the invalid values by `P` creates a valid signature. The reduction can happen unintentionally by converting values to the Montgomery form. --- .../scripts/find_low_p256_points.sage | 54 ++++++++++++++ .../test_p256verify.py | 72 +++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 osaka/eip7951_p256verify_precompiles/scripts/find_low_p256_points.sage diff --git a/osaka/eip7951_p256verify_precompiles/scripts/find_low_p256_points.sage b/osaka/eip7951_p256verify_precompiles/scripts/find_low_p256_points.sage new file mode 100644 index 0000000000..d785afa721 --- /dev/null +++ b/osaka/eip7951_p256verify_precompiles/scripts/find_low_p256_points.sage @@ -0,0 +1,54 @@ +# Find points on P256 with low x or y coordinates by solving the curve equation +# independently for range of low x and y values. +# +# Can be executed online: https://sagecell.sagemath.org/?q=pmqnkn +# +# Test cases generated: +# +# x_0_y_positive: +# (0x0000000000000000000000000000000000000000000000000000000000000000, 0x66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4) +# x_0_y_negative: +# (0x0000000000000000000000000000000000000000000000000000000000000000, 0x99b7a386f1d07c29dbcc42a27b5f9449abe3d50de25178e8d7407a95e8b06c0b) +# x_5_y_positive: +# x_P_plus_5_y_positive: +# (0x0000000000000000000000000000000000000000000000000000000000000005, 0x459243b9aa581806fe913bce99817ade11ca503c64d9a3c533415c083248fbcc) +# x_5_y_negative: +# x_P_plus_5_y_negative: +# (0x0000000000000000000000000000000000000000000000000000000000000005, 0xba6dbc4555a7e7fa016ec431667e8521ee35afc49b265c3accbea3f7cdb70433) +# y_1: +# y_P_plus_1: +# (0x09e78d4ef60d05f750f6636209092bc43cbdd6b47e11a9de20a9feb2a50bb96c, 0x0000000000000000000000000000000000000000000000000000000000000001) + + +p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff +a = -3 +b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b + +F = GF(p) +aF = F(a) +bF = F(b) + +M = 11 + +for x_int in range(0, M): + print(f"x = {x_int}:") + xF = F(x_int) + rhs = xF**3 + aF*xF + bF + + if rhs.is_square(): + y = rhs.sqrt() + for yF in [y, -y]: + print(f" (0x{int(xF):064x}, 0x{int(yF):064x})") + +R. = PolynomialRing(F) +for y_int in range(0, M): + yF = F(y_int) + # Solve x^3 + a*x + (b - y^2) == 0 over F_p + c = bF - yF * yF + f = x^3 + aF * x + c + + roots = [r for (r, mult) in f.roots()] # distinct roots over F_p + + print(f"y = {y_int}:") + for xF in sorted(roots): + print(f" (0x{int(xF):064x}, 0x{y_int:064x})") diff --git a/osaka/eip7951_p256verify_precompiles/test_p256verify.py b/osaka/eip7951_p256verify_precompiles/test_p256verify.py index f89d903b6e..68ad5779cc 100644 --- a/osaka/eip7951_p256verify_precompiles/test_p256verify.py +++ b/osaka/eip7951_p256verify_precompiles/test_p256verify.py @@ -156,6 +156,38 @@ def test_wycheproof_extra(state_test: StateTestFiller, pre: Alloc, post: dict, t + Y(0x99B7A386F1D07C29DBCC42A27B5F9449ABE3D50DE25178E8D7407A95E8B06C0B), id="x_0_y_negative", ), + pytest.param( + H(0x5F95DCD6E41662D1E0AEFCCDB7877877C1FD88C9E67FC3CDA0D1D520FA8A3AC2) + + R(0xAF5DFDDB7EDC789D7C9C42A44AFBBF13C8F1D77D576B6EE5F11FEA4F33E2CB39) + + S(0xA28F8C5625AD622950F2FCE9672784B287EF9E032ADE8C23BA218413A1CF6522) + + X(5) + + Y(0x459243B9AA581806FE913BCE99817ADE11CA503C64D9A3C533415C083248FBCC), + id="x_5_y_positive", + ), + pytest.param( + H(0x31CE0B00FA8DD61EF28C7DC5F839C78CF70D60E625E0670BF9C9FCE25E89D99F) + + R(0x0FA19CBE154513BA348F2DB951AFB6E135BAC5BD8891282781A032103C3F1289) + + S(0xD9ABF5C4E61098A6E653F265770BDBA36ECC8073CEF99548D89FE2C39A7AFA9B) + + X(5) + + Y(0xBA6DBC4555A7E7FA016EC431667E8521EE35AFC49B265C3ACCBEA3F7CDB70433), + id="x_5_y_negative", + ), + pytest.param( + H(0x65B0E03E7A27E6F9F4989C72486FCAF0A3ECF3EF60D14F1C11FB5BF071A8FD1B) + + R(0x0B0CC9E314E4180FE18D205010DD1C4410632D472CC4E7AB56CBC04091ABE006) + + S(0x8D12C4F19AC41D7877705453A247AB96394E7C093F57EC073A9D150CDE6B68C6) + + X(0x09E78D4EF60D05F750F6636209092BC43CBDD6B47E11A9DE20A9FEB2A50BB96C) + + Y(1), + id="y_1", + ), + pytest.param( + H(0x744084AD41EE67ED1802A6868ACE7815FD6FC0585A3479FF68E69ADB8DD2B420) + + R(0xB481C7650CBE85BCD15565811966DA2DA4E4E2931F0892D911520B6A06C340D8) + + S(0xE4C2D9FB9A4E3E29B7414F0408B2EBC4421D5BC8ADDCCF864AFF9E7E10DA31BB) + + X(0x09E78D4EF60D05F750F6636209092BC43CBDD6B47E11A9DE20A9FEB2A50BB96C) + + Y(Spec.P - 1), + id="y_P_minus_1", + ), # Test case for u1==u2 and Q==G. # This test case is important because u1*G + u2*Q is point doubling. pytest.param( @@ -344,6 +376,46 @@ def test_valid(state_test: StateTestFiller, pre: Alloc, post: dict, tx: Transact Spec.H0 + Spec.R0 + Spec.S0 + X(Spec.P + 1) + Spec.Y0, id="x_greater_than_p", ), + pytest.param( + H(0xC3D3BE9EB3577F217AE0AB360529A30B18ADC751AEC886328593D7D6FE042809) + + R(0x3A4E97B44CBF88B90E6205A45BA957E520F63F3C6072B53C244653278A1819D8) + + S(0x6A184AA037688A5EBD25081FD2C0B10BB64FA558B671BD81955CA86E09D9D722) + + X(Spec.P) # Valid for X(0) + + Y(0x66485C780E2F83D72433BD5D84A06BB6541C2AF31DAE871728BF856A174F93F4), + id="x_P_y_positive", + ), + pytest.param( + H(0xF98A88895CB0866C5BAD58CF03000DDF9D21CB9407892FF54D637E6A046AFBB3) + + R(0x81DC074973D3222F3930981AD98D022517C91063FFB83CFD620E29B86DC30A8F) + + S(0x365E4CD085617A265765062A2D9954ED86309DFA33CF5AE1464FE119419FC34A) + + X(Spec.P) # Valid for X(0) + + Y(0x99B7A386F1D07C29DBCC42A27B5F9449ABE3D50DE25178E8D7407A95E8B06C0B), + id="x_P_y_negative", + ), + pytest.param( + H(0x5F95DCD6E41662D1E0AEFCCDB7877877C1FD88C9E67FC3CDA0D1D520FA8A3AC2) + + R(0xAF5DFDDB7EDC789D7C9C42A44AFBBF13C8F1D77D576B6EE5F11FEA4F33E2CB39) + + S(0xA28F8C5625AD622950F2FCE9672784B287EF9E032ADE8C23BA218413A1CF6522) + + X(Spec.P + 5) # Valid for X(5) + + Y(0x459243B9AA581806FE913BCE99817ADE11CA503C64D9A3C533415C083248FBCC), + id="x_P_plus_5_y_positive", + ), + pytest.param( + H(0x31CE0B00FA8DD61EF28C7DC5F839C78CF70D60E625E0670BF9C9FCE25E89D99F) + + R(0x0FA19CBE154513BA348F2DB951AFB6E135BAC5BD8891282781A032103C3F1289) + + S(0xD9ABF5C4E61098A6E653F265770BDBA36ECC8073CEF99548D89FE2C39A7AFA9B) + + X(Spec.P + 5) # Valid for X(5) + + Y(0xBA6DBC4555A7E7FA016EC431667E8521EE35AFC49B265C3ACCBEA3F7CDB70433), + id="x_P_plus_5_y_negative", + ), + pytest.param( + H(0x65B0E03E7A27E6F9F4989C72486FCAF0A3ECF3EF60D14F1C11FB5BF071A8FD1B) + + R(0x0B0CC9E314E4180FE18D205010DD1C4410632D472CC4E7AB56CBC04091ABE006) + + S(0x8D12C4F19AC41D7877705453A247AB96394E7C093F57EC073A9D150CDE6B68C6) + + X(0x09E78D4EF60D05F750F6636209092BC43CBDD6B47E11A9DE20A9FEB2A50BB96C) + + Y(Spec.P + 1), # Valid for Y(1) + id="y_P_plus_1", + ), # Test case produces the point R at infinity: (R0/S0)*G + (R0/S0)*(-G). pytest.param( H(Spec.R0.value) + Spec.R0 + Spec.S0 + X(Spec.Gx) + Y(Spec.P - Spec.Gy), From 625a8e7f9a83a102e37002cd1bc77adb6d81d8e4 Mon Sep 17 00:00:00 2001 From: felix Date: Thu, 2 Oct 2025 17:01:56 +0000 Subject: [PATCH 068/102] chore**s**(src): use `--chain-id` in ProgramChainid (#2232) * use --chain-id in ProgramChainid * Update tests/frontier/scenarios/programs/context_calls.py --------- Co-authored-by: Mario Vega --- frontier/scenarios/programs/context_calls.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontier/scenarios/programs/context_calls.py b/frontier/scenarios/programs/context_calls.py index ea4d893838..7a44035c9e 100644 --- a/frontier/scenarios/programs/context_calls.py +++ b/frontier/scenarios/programs/context_calls.py @@ -4,6 +4,7 @@ from ethereum_test_forks import Byzantium, Cancun, Constantinople, Fork, Istanbul, London, Shanghai from ethereum_test_tools import Alloc, Bytecode +from ethereum_test_types import ChainConfigDefaults from ethereum_test_vm import Opcodes as Op from ..common import ( @@ -429,7 +430,10 @@ def id(self) -> str: def result(self) -> ProgramResult: """Test result.""" - return ProgramResult(result=1, from_fork=Istanbul) + # TODO: use `chain_config` fixture instead. + chain_id = ChainConfigDefaults.chain_id + + return ProgramResult(result=chain_id, from_fork=Istanbul) class ProgramSelfbalance(ScenarioTestProgram): From 58caafcebee85594757b897434e9f308b3204142 Mon Sep 17 00:00:00 2001 From: felipe Date: Thu, 2 Oct 2025 13:57:37 -0600 Subject: [PATCH 069/102] chore(consume): mark sync tests flaky (#2252) * chore(consume): Mark all consume sync tests as flaky * refactor: simplify consume sync logic * chore: CHANGELOG entry --- .../simulator_logic/test_via_sync.py | 114 +++++------------- .../consume/simulators/sync/conftest.py | 4 + 2 files changed, 31 insertions(+), 87 deletions(-) diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py index 2781b7540f..ee57f7fcb9 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py @@ -16,7 +16,6 @@ import pytest -from ethereum_test_base_types import Hash from ethereum_test_exceptions import UndefinedException from ethereum_test_fixtures import BlockchainEngineSyncFixture from ethereum_test_rpc import AdminRPC, EngineRPC, EthRPC, NetRPC @@ -42,65 +41,6 @@ def __init__(self, *args: object) -> None: logger.fail(str(self)) -def wait_for_sync( - sync_eth_rpc: EthRPC, - expected_block_hash: str | Hash, - timeout: int = 10, - poll_interval: float = 1.0, -) -> bool: - """Wait for the sync client to reach the expected block hash.""" - start_time = time.time() - last_block_number = 0 - no_progress_count = 0 - - while time.time() - start_time < timeout: - try: - # First check if we have the expected block - block = sync_eth_rpc.get_block_by_hash(Hash(expected_block_hash)) - if block is not None: - logger.info(f"Sync complete! Client has block {expected_block_hash}") - return True - - # Check current sync progress - current_block = sync_eth_rpc.get_block_by_number("latest") - if current_block: - current_number = int(current_block.get("number", "0x0"), 16) - current_hash = current_block.get("hash", "unknown") - if current_number > last_block_number: - logger.info(f"Sync progress: block {current_number} (hash: {current_hash})") - last_block_number = current_number - no_progress_count = 0 - else: - no_progress_count += 1 - if no_progress_count == 1: - logger.info( - f"Sync client is at block {current_number} (hash: {current_hash})" - ) - elif no_progress_count % 10 == 0: - logger.debug( - f"No sync progress for {no_progress_count} polls, " - f"still at block {current_number}" - ) - - except Exception as e: - logger.debug(f"Error checking sync status: {e}") - - time.sleep(poll_interval) - - # Log final state - try: - final_block = sync_eth_rpc.get_block_by_number("latest") - if final_block: - logger.warning( - f"Sync timeout! Final block: {final_block.get('number', 'unknown')} " - f"(hash: {final_block.get('hash', 'unknown')})" - ) - except Exception: - pass - - return False - - def test_blockchain_via_sync( timing_data: TimingData, eth_rpc: EthRPC, @@ -445,7 +385,7 @@ def test_blockchain_via_sync( last_forkchoice_time = time.time() forkchoice_interval = 2.0 # Send forkchoice updates every 2 seconds - while time.time() - sync_start_time < 60: # 60 second timeout + while time.time() - sync_start_time < 15: # 15 second timeout # Send periodic forkchoice updates to keep sync alive if time.time() - last_forkchoice_time >= forkchoice_interval: try: @@ -473,35 +413,35 @@ def test_blockchain_via_sync( f"within timeout" ) - # Final verification + logger.info("Sync verification successful!") + + # Verify the final state but give a few tries + assert eth_rpc is not None, "eth_rpc is required" assert sync_eth_rpc is not None, "sync_eth_rpc is required" - assert sync_engine_rpc is not None, "sync_engine_rpc is required" - if wait_for_sync(sync_eth_rpc, last_valid_block_hash, timeout=5): - logger.info("Sync verification successful!") - - # Verify the final state - sync_block = sync_eth_rpc.get_block_by_hash(last_valid_block_hash) - client_block = eth_rpc.get_block_by_hash(last_valid_block_hash) - - if sync_block["stateRoot"] != client_block["stateRoot"]: - raise LoggedError( - f"State root mismatch after sync. " - f"Sync client: {sync_block['stateRoot']}, " - f"Client under test: {client_block['stateRoot']}" - ) - # Verify post state if available - if fixture.post_state_hash: - if sync_block["stateRoot"] != str(fixture.post_state_hash): + for attempt in range(3): + try: + sync_block = sync_eth_rpc.get_block_by_hash(last_valid_block_hash) + client_block = eth_rpc.get_block_by_hash(last_valid_block_hash) + + if sync_block["stateRoot"] != client_block["stateRoot"]: raise LoggedError( - f"Final state root mismatch. " - f"Expected: {fixture.post_state_hash}, " - f"Got: {sync_block['stateRoot']}" + f"State root mismatch after sync. " + f"Sync client: {sync_block['stateRoot']}, " + f"Client under test: {client_block['stateRoot']}" ) - else: - raise LoggedError( - f"Sync client failed to synchronize to block {last_valid_block_hash} " - f"within timeout" - ) + + if fixture.post_state_hash: + if sync_block["stateRoot"] != str(fixture.post_state_hash): + raise LoggedError( + f"Final state root mismatch. " + f"Expected: {fixture.post_state_hash}, " + f"Got: {sync_block['stateRoot']}" + ) + except Exception as e: + if attempt < 2: + time.sleep(1) + continue + raise e logger.info("Sync test completed successfully!") diff --git a/pytest_plugins/consume/simulators/sync/conftest.py b/pytest_plugins/consume/simulators/sync/conftest.py index 9447ea4728..dcc884d3d6 100644 --- a/pytest_plugins/consume/simulators/sync/conftest.py +++ b/pytest_plugins/consume/simulators/sync/conftest.py @@ -47,6 +47,10 @@ def pytest_collection_modifyitems(session, config, items): del session, config for item in items: + # Auto-mark all verify_sync tests as flaky with 3 reruns + if item.get_closest_marker("blockchain_test_sync"): + item.add_marker(pytest.mark.flaky(reruns=3)) + # Check if this test has both client_type and sync_client_type if ( hasattr(item, "callspec") From 78689e65f201192037ae7b4101a8bbaa237d495b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jerem=C3=ADas=20Salom=C3=B3n?= <48994069+JereSalo@users.noreply.github.com> Date: Thu, 2 Oct 2025 17:08:38 -0300 Subject: [PATCH 070/102] feat(tests): test accessing slots in address that appears more than once in access list (#2253) * add test for repeated address in acl * ruff lint --- berlin/eip2930_access_list/test_acl.py | 64 ++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/berlin/eip2930_access_list/test_acl.py b/berlin/eip2930_access_list/test_acl.py index 8b9899026a..a1f52e5da6 100644 --- a/berlin/eip2930_access_list/test_acl.py +++ b/berlin/eip2930_access_list/test_acl.py @@ -253,3 +253,67 @@ def test_transaction_intrinsic_gas_cost( ), } state_test(env=env, pre=pre, post=post, tx=tx) + + +def test_repeated_address_acl( + state_test: StateTestFiller, + pre: Alloc, + fork: Fork, +): + """ + Tests that slots are warmed correctly in an access list that has the same + address repeated more than once, each time with different slots. + + Difference with other ACL tests is that we actually try to + access both slots at runtime. We also measure the gas cost + of each access in order to make debugging easier. + """ + sender = pre.fund_eoa() + gsc = fork.gas_costs() + + sload0_measure = CodeGasMeasure( + code=Op.SLOAD(0), + overhead_cost=gsc.G_VERY_LOW * len(Op.SLOAD.kwargs), # Cost of pushing SLOAD args + extra_stack_items=1, # SLOAD pushes 1 item to the stack + sstore_key=0, + stop=False, # Because it's the first CodeGasMeasure + ) + + sload1_measure = CodeGasMeasure( + code=Op.SLOAD(1), + overhead_cost=gsc.G_VERY_LOW * len(Op.SLOAD.kwargs), # Cost of pushing SLOAD args + extra_stack_items=1, # SLOAD pushes 1 item to the stack + sstore_key=1, + ) + + contract = pre.deploy_contract(sload0_measure + sload1_measure) + + tx = Transaction( + gas_limit=500_000, + to=contract, + value=0, + sender=sender, + access_list=[ + AccessList( + address=contract, + storage_keys=[0], + ), + AccessList( + address=contract, + storage_keys=[1], + ), + ], + ) + + sload_cost = gsc.G_WARM_ACCOUNT_ACCESS + + state_test( + env=Environment(), + pre=pre, + tx=tx, + post={ + contract: Account( + storage={0: sload_cost, 1: sload_cost}, + ) + }, + ) From eb915bb7782713e90e708128e15cc23fe062b670 Mon Sep 17 00:00:00 2001 From: raxhvl <10168946+raxhvl@users.noreply.github.com> Date: Thu, 2 Oct 2025 23:58:00 +0200 Subject: [PATCH 071/102] =?UTF-8?q?=E2=9C=A8=20feat(tests):=20EIP-7928=20S?= =?UTF-8?q?ingle-Opcode=20Success=20and=20OOG=20test=20cases=20(#2118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat(EIP-7928): OOG: Intrinsic gas * 🚧 wip(EIP-7928): OOG tests * fix: BAL expectations for OOG 7928 tests - fix linter * remove equivalent test cases as covered by opcode cases * 🥢 nit: named parameters * fix: Tighten up validation for empty lists on BALs * chore: CHANGELOG entry * chore: fix docstring after refactor --------- Co-authored-by: raxhvl Co-authored-by: fselmo --- .../test_block_access_lists.py | 84 --- .../test_block_access_lists_opcodes.py | 533 ++++++++++++++++++ 2 files changed, 533 insertions(+), 84 deletions(-) create mode 100644 amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py index b5e9e54214..a99b01e15c 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py @@ -11,7 +11,6 @@ Block, BlockchainTestFiller, Initcode, - Storage, Transaction, compute_create_address, ) @@ -128,89 +127,6 @@ def test_bal_balance_changes( ) -def test_bal_storage_writes( - pre: Alloc, - blockchain_test: BlockchainTestFiller, -): - """Ensure BAL captures storage writes.""" - storage = Storage({0x01: 0}) # type: ignore - storage_contract = pre.deploy_contract( - code=Op.SSTORE(0x01, 0x42) + Op.STOP, - # pre-fill with canary value to detect writes in post-state - storage=storage.canary(), - ) - alice = pre.fund_eoa() - - tx = Transaction( - sender=alice, - to=storage_contract, - gas_limit=100000, - ) - - block = Block( - txs=[tx], - expected_block_access_list=BlockAccessListExpectation( - account_expectations={ - storage_contract: BalAccountExpectation( - storage_changes=[ - BalStorageSlot( - slot=0x01, - slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)], - ) - ], - ), - } - ), - ) - - blockchain_test( - pre=pre, - blocks=[block], - post={ - alice: Account(nonce=1), - storage_contract: Account(storage={0x01: 0x42}), - }, - ) - - -def test_bal_storage_reads( - pre: Alloc, - blockchain_test: BlockchainTestFiller, -): - """Ensure BAL captures storage reads.""" - storage_contract = pre.deploy_contract( - code=Op.SLOAD(0x01) + Op.STOP, - storage={0x01: 0x42}, - ) - alice = pre.fund_eoa() - - tx = Transaction( - sender=alice, - to=storage_contract, - gas_limit=100000, - ) - - block = Block( - txs=[tx], - expected_block_access_list=BlockAccessListExpectation( - account_expectations={ - storage_contract: BalAccountExpectation( - storage_reads=[0x01], - ), - } - ), - ) - - blockchain_test( - pre=pre, - blocks=[block], - post={ - alice: Account(nonce=1), - storage_contract: Account(storage={0x01: 0x42}), - }, - ) - - def test_bal_code_changes( pre: Alloc, blockchain_test: BlockchainTestFiller, diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py new file mode 100644 index 0000000000..7f3aa2baa9 --- /dev/null +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py @@ -0,0 +1,533 @@ +""" +Tests for EIP-7928 Block Access Lists with single-opcode success and OOG +scenarios. + +Block access lists (BAL) are generated via a client's state tracing journal. +Residual journal entries may persist when opcodes run out of gas, resulting +in a bloated BAL payload. + +Issues identified in: +https://github.com/paradigmxyz/reth/issues/17765 +https://github.com/bluealloy/revm/pull/2903 + +These tests ensure out-of-gas operations are not recorded in BAL, +preventing consensus issues. +""" + +import pytest + +from ethereum_test_forks import Fork +from ethereum_test_tools import ( + Account, + Alloc, + Block, + BlockchainTestFiller, + Transaction, +) +from ethereum_test_tools import ( + Opcodes as Op, +) +from ethereum_test_types.block_access_list import ( + BalAccountExpectation, + BalStorageChange, + BalStorageSlot, + BlockAccessListExpectation, +) +from ethereum_test_vm import Bytecode + +from .spec import ref_spec_7928 + +REFERENCE_SPEC_GIT_PATH = ref_spec_7928.git_path +REFERENCE_SPEC_VERSION = ref_spec_7928.version + + +pytestmark = pytest.mark.valid_from("Amsterdam") + + +@pytest.mark.parametrize( + "fails_at_sstore", [True, False], ids=["oog_at_sstore", "successful_sstore"] +) +def test_bal_sstore_and_oog( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork: Fork, + fails_at_sstore: bool, +): + """ + Ensure BAL handles SSTORE and OOG during SSTORE appropriately. + """ + alice = pre.fund_eoa() + gas_costs = fork.gas_costs() + + # Create contract that attempts SSTORE to cold storage slot 0x01 + storage_contract_code = Bytecode( + Op.PUSH1(0x42) # Value to store + + Op.PUSH1(0x01) # Storage slot (cold) + + Op.SSTORE # Store value in slot - this will OOG + + Op.STOP + ) + + storage_contract = pre.deploy_contract(code=storage_contract_code) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_calculator() + + # Costs: + # - PUSH1 (value and slot) = G_VERY_LOW * 2 + # - SSTORE cold (to zero slot) = G_STORAGE_SET + G_COLD_SLOAD + sstore_cold_cost = gas_costs.G_STORAGE_SET + gas_costs.G_COLD_SLOAD + push_cost = gas_costs.G_VERY_LOW * 2 + tx_gas_limit = intrinsic_gas_cost + push_cost + sstore_cold_cost + + if fails_at_sstore: + # subtract 1 gas to ensure OOG at SSTORE + tx_gas_limit -= 1 + + tx = Transaction( + sender=alice, + to=storage_contract, + gas_limit=tx_gas_limit, + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + storage_contract: BalAccountExpectation( + storage_changes=[] + if fails_at_sstore + else [ + BalStorageSlot( + slot=0x01, + slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)], + ), + ] + ) + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + storage_contract: Account(storage={} if fails_at_sstore else {0x01: 0x42}), + }, + ) + + +@pytest.mark.parametrize( + "fails_at_sload", + [True, False], + ids=["oog_at_sload", "successful_sload"], +) +def test_bal_sload_and_oog( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork: Fork, + fails_at_sload: bool, +): + """ + Ensure BAL handles SLOAD and OOG during SLOAD appropriately. + """ + alice = pre.fund_eoa() + gas_costs = fork.gas_costs() + + # Create contract that attempts SLOAD from cold storage slot 0x01 + storage_contract_code = Bytecode( + Op.PUSH1(0x01) # Storage slot (cold) + + Op.SLOAD # Load value from slot - this will OOG + + Op.STOP + ) + + storage_contract = pre.deploy_contract(code=storage_contract_code) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_calculator() + + # Costs: + # - PUSH1 (slot) = G_VERY_LOW + # - SLOAD cold = G_COLD_SLOAD + push_cost = gas_costs.G_VERY_LOW + sload_cold_cost = gas_costs.G_COLD_SLOAD + tx_gas_limit = intrinsic_gas_cost + push_cost + sload_cold_cost + + # if fails_at_sload: + # # subtract 1 gas to ensure OOG at SLOAD + # tx_gas_limit -= 1 + + tx = Transaction( + sender=alice, + to=storage_contract, + gas_limit=tx_gas_limit, + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + storage_contract: BalAccountExpectation( + storage_reads=[] if fails_at_sload else [0x01], + ) + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + storage_contract: Account(storage={}), + }, + ) + + +@pytest.mark.parametrize( + "fails_at_balance", [True, False], ids=["oog_at_balance", "successful_balance"] +) +def test_bal_balance_and_oog( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork: Fork, + fails_at_balance: bool, +): + """Ensure BAL handles BALANCE and OOG during BALANCE appropriately.""" + alice = pre.fund_eoa() + bob = pre.fund_eoa() + gas_costs = fork.gas_costs() + + # Create contract that attempts to check Bob's balance + balance_checker_code = Bytecode( + Op.PUSH20(bob) # Bob's address + + Op.BALANCE # Check balance (cold access) + + Op.STOP + ) + + balance_checker = pre.deploy_contract(code=balance_checker_code) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_calculator() + + # Costs: + # - PUSH20 = G_VERY_LOW + # - BALANCE cold = G_COLD_ACCOUNT_ACCESS + push_cost = gas_costs.G_VERY_LOW + balance_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + tx_gas_limit = intrinsic_gas_cost + push_cost + balance_cold_cost + + if fails_at_balance: + # subtract 1 gas to ensure OOG at BALANCE + tx_gas_limit -= 1 + + tx = Transaction( + sender=alice, + to=balance_checker, + gas_limit=tx_gas_limit, + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + balance_checker: BalAccountExpectation(), + # Bob should only appear in BAL if BALANCE succeeded + **({} if fails_at_balance else {bob: BalAccountExpectation()}), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + bob: Account(), + balance_checker: Account(), + }, + ) + + +@pytest.mark.parametrize( + "fails_at_extcodesize", [True, False], ids=["oog_at_extcodesize", "successful_extcodesize"] +) +def test_bal_extcodesize_and_oog( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork: Fork, + fails_at_extcodesize: bool, +): + """ + Ensure BAL handles EXTCODESIZE and OOG during EXTCODESIZE appropriately. + """ + alice = pre.fund_eoa() + gas_costs = fork.gas_costs() + + # Create target contract with some code + target_contract = pre.deploy_contract(code=Bytecode(Op.STOP)) + + # Create contract that checks target's code size + codesize_checker_code = Bytecode( + Op.PUSH20(target_contract) # Target contract address + + Op.EXTCODESIZE # Check code size (cold access) + + Op.STOP + ) + + codesize_checker = pre.deploy_contract(code=codesize_checker_code) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_calculator() + + # Costs: + # - PUSH20 = G_VERY_LOW + # - EXTCODESIZE cold = G_COLD_ACCOUNT_ACCESS + push_cost = gas_costs.G_VERY_LOW + extcodesize_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + tx_gas_limit = intrinsic_gas_cost + push_cost + extcodesize_cold_cost + + if fails_at_extcodesize: + # subtract 1 gas to ensure OOG at EXTCODESIZE + tx_gas_limit -= 1 + + tx = Transaction( + sender=alice, + to=codesize_checker, + gas_limit=tx_gas_limit, + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + codesize_checker: BalAccountExpectation(), + # Target should only appear if EXTCODESIZE succeeded + **({} if fails_at_extcodesize else {target_contract: BalAccountExpectation()}), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + codesize_checker: Account(), + target_contract: Account(), + }, + ) + + +@pytest.mark.parametrize("fails_at_call", [True, False], ids=["oog_at_call", "successful_call"]) +def test_bal_call_and_oog( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork: Fork, + fails_at_call: bool, +): + """Ensure BAL handles CALL and OOG during CALL appropriately.""" + alice = pre.fund_eoa() + bob = pre.fund_eoa() + gas_costs = fork.gas_costs() + + # Create contract that attempts to call Bob + call_contract_code = Bytecode( + Op.PUSH1(0) # retSize + + Op.PUSH1(0) # retOffset + + Op.PUSH1(0) # argsSize + + Op.PUSH1(0) # argsOffset + + Op.PUSH1(0) # value + + Op.PUSH20(bob) # address + + Op.PUSH2(0xFFFF) # gas (provide enough for the call) + + Op.CALL # Call (cold account access) + + Op.STOP + ) + + call_contract = pre.deploy_contract(code=call_contract_code) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_calculator() + + # Costs: + # - 7 PUSH operations = G_VERY_LOW * 7 + # - CALL cold = G_COLD_ACCOUNT_ACCESS (minimum for account access) + push_cost = gas_costs.G_VERY_LOW * 7 + call_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + tx_gas_limit = intrinsic_gas_cost + push_cost + call_cold_cost + + if fails_at_call: + # subtract 1 gas to ensure OOG at CALL + tx_gas_limit -= 1 + + tx = Transaction( + sender=alice, + to=call_contract, + gas_limit=tx_gas_limit, + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + call_contract: BalAccountExpectation(), + # Bob should only appear if CALL succeeded + **({} if fails_at_call else {bob: BalAccountExpectation()}), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + call_contract: Account(), + }, + ) + + +@pytest.mark.parametrize( + "fails_at_delegatecall", [True, False], ids=["oog_at_delegatecall", "successful_delegatecall"] +) +def test_bal_delegatecall_and_oog( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork: Fork, + fails_at_delegatecall: bool, +): + """ + Ensure BAL handles DELEGATECALL and OOG during DELEGATECALL + appropriately. + """ + alice = pre.fund_eoa() + gas_costs = fork.gas_costs() + + # Create target contract + target_contract = pre.deploy_contract(code=Bytecode(Op.STOP)) + + # Create contract that attempts delegatecall to target + delegatecall_contract_code = Bytecode( + Op.PUSH1(0) # retSize + + Op.PUSH1(0) # retOffset + + Op.PUSH1(0) # argsSize + + Op.PUSH1(0) # argsOffset + + Op.PUSH20(target_contract) # address + + Op.PUSH2(0xFFFF) # gas (provide enough for the call) + + Op.DELEGATECALL # Delegatecall (cold account access) + + Op.STOP + ) + + delegatecall_contract = pre.deploy_contract(code=delegatecall_contract_code) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_calculator() + + # Costs: + # - 6 PUSH operations = G_VERY_LOW * 6 + # - DELEGATECALL cold = G_COLD_ACCOUNT_ACCESS + push_cost = gas_costs.G_VERY_LOW * 6 + delegatecall_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + tx_gas_limit = intrinsic_gas_cost + push_cost + delegatecall_cold_cost + + if fails_at_delegatecall: + # subtract 1 gas to ensure OOG at DELEGATECALL + tx_gas_limit -= 1 + + tx = Transaction( + sender=alice, + to=delegatecall_contract, + gas_limit=tx_gas_limit, + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + delegatecall_contract: BalAccountExpectation(), + # Target should only appear if DELEGATECALL succeeded + **({} if fails_at_delegatecall else {target_contract: BalAccountExpectation()}), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + delegatecall_contract: Account(), + target_contract: Account(), + }, + ) + + +@pytest.mark.parametrize( + "fails_at_extcodecopy", [True, False], ids=["oog_at_extcodecopy", "successful_extcodecopy"] +) +def test_bal_extcodecopy_and_oog( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork: Fork, + fails_at_extcodecopy: bool, +): + """ + Ensure BAL handles EXTCODECOPY and OOG during EXTCODECOPY appropriately. + """ + alice = pre.fund_eoa() + gas_costs = fork.gas_costs() + + # Create target contract with some code + target_contract = pre.deploy_contract(code=Bytecode(Op.PUSH1(0x42) + Op.STOP)) + + # Create contract that attempts to copy code from target + extcodecopy_contract_code = Bytecode( + Op.PUSH1(0) # size - copy 0 bytes to minimize memory expansion cost + + Op.PUSH1(0) # codeOffset + + Op.PUSH1(0) # destOffset + + Op.PUSH20(target_contract) # address + + Op.EXTCODECOPY # Copy code (cold access + base cost) + + Op.STOP + ) + + extcodecopy_contract = pre.deploy_contract(code=extcodecopy_contract_code) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_calculator() + + # Costs: + # - 4 PUSH operations = G_VERY_LOW * 4 + # - EXTCODECOPY cold = G_COLD_ACCOUNT_ACCESS + G_COPY (base cost) + push_cost = gas_costs.G_VERY_LOW * 4 + extcodecopy_cold_cost = gas_costs.G_COLD_ACCOUNT_ACCESS + gas_costs.G_COPY + tx_gas_limit = intrinsic_gas_cost + push_cost + extcodecopy_cold_cost + + if fails_at_extcodecopy: + # subtract 1 gas to ensure OOG at EXTCODECOPY + tx_gas_limit -= 1 + + tx = Transaction( + sender=alice, + to=extcodecopy_contract, + gas_limit=tx_gas_limit, + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + extcodecopy_contract: BalAccountExpectation(), + # Target should only appear if EXTCODECOPY succeeded + **({} if fails_at_extcodecopy else {target_contract: BalAccountExpectation()}), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + extcodecopy_contract: Account(), + target_contract: Account(), + }, + ) From 114d6f9bc0f19126bfd76de34ffd1af99a765cb1 Mon Sep 17 00:00:00 2001 From: raxhvl <10168946+raxhvl@users.noreply.github.com> Date: Thu, 2 Oct 2025 23:58:00 +0200 Subject: [PATCH 072/102] =?UTF-8?q?=E2=9C=A8=20feat(tests):=20EIP-7928=20S?= =?UTF-8?q?ingle-Opcode=20Success=20and=20OOG=20test=20cases=20(#2118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat(EIP-7928): OOG: Intrinsic gas * 🚧 wip(EIP-7928): OOG tests * fix: BAL expectations for OOG 7928 tests - fix linter * remove equivalent test cases as covered by opcode cases * 🥢 nit: named parameters * fix: Tighten up validation for empty lists on BALs * chore: CHANGELOG entry * chore: fix docstring after refactor --------- Co-authored-by: raxhvl Co-authored-by: fselmo --- .../block_access_list/expectations.py | 74 +++++++++---------- .../tests/test_block_access_lists.py | 55 +++++++++----- 2 files changed, 69 insertions(+), 60 deletions(-) diff --git a/ethereum_test_types/block_access_list/expectations.py b/ethereum_test_types/block_access_list/expectations.py index 5a69d45e7d..ddb3d19f49 100644 --- a/ethereum_test_types/block_access_list/expectations.py +++ b/ethereum_test_types/block_access_list/expectations.py @@ -305,6 +305,10 @@ def _compare_account_expectations( if field_name not in expected.model_fields_set: continue + # Check if explicitly set to empty but actual has values + if not expected_list and actual_list: + raise AssertionError(f"Expected {field_name} to be empty but found {actual_list}") + if field_name == "storage_reads": # storage_reads is a simple list of StorageKey actual_idx = 0 @@ -377,49 +381,39 @@ def _compare_account_expectations( else: # Handle nonce_changes, balance_changes, code_changes - if not expected_list and actual_list: - # Empty expected but non-empty actual - error - item_type = field_name.replace("_changes", "") - raise AssertionError( - f"Expected {field_name} to be empty but found {actual_list}" - ) - + # Create tuples for comparison (ordering already validated) + if field_name == "nonce_changes": + expected_tuples = [(c.tx_index, c.post_nonce) for c in expected_list] + actual_tuples = [(c.tx_index, c.post_nonce) for c in actual_list] + item_type = "nonce" + elif field_name == "balance_changes": + expected_tuples = [(c.tx_index, int(c.post_balance)) for c in expected_list] + actual_tuples = [(c.tx_index, int(c.post_balance)) for c in actual_list] + item_type = "balance" + elif field_name == "code_changes": + expected_tuples = [(c.tx_index, bytes(c.new_code)) for c in expected_list] + actual_tuples = [(c.tx_index, bytes(c.new_code)) for c in actual_list] + item_type = "code" else: - # Create tuples for comparison (ordering already validated) - if field_name == "nonce_changes": - expected_tuples = [(c.tx_index, c.post_nonce) for c in expected_list] - actual_tuples = [(c.tx_index, c.post_nonce) for c in actual_list] - item_type = "nonce" - elif field_name == "balance_changes": - expected_tuples = [ - (c.tx_index, int(c.post_balance)) for c in expected_list - ] - actual_tuples = [(c.tx_index, int(c.post_balance)) for c in actual_list] - item_type = "balance" - elif field_name == "code_changes": - expected_tuples = [(c.tx_index, bytes(c.new_code)) for c in expected_list] - actual_tuples = [(c.tx_index, bytes(c.new_code)) for c in actual_list] - item_type = "code" - else: - # sanity check - raise ValueError(f"Unexpected field type: {field_name}") - - # Check that expected forms a subsequence of actual - actual_idx = 0 - for exp_tuple in expected_tuples: - found = False - while actual_idx < len(actual_tuples): - if actual_tuples[actual_idx] == exp_tuple: - found = True - actual_idx += 1 - break + # sanity check + raise ValueError(f"Unexpected field type: {field_name}") + + # Check that expected forms a subsequence of actual + actual_idx = 0 + for exp_tuple in expected_tuples: + found = False + while actual_idx < len(actual_tuples): + if actual_tuples[actual_idx] == exp_tuple: + found = True actual_idx += 1 + break + actual_idx += 1 - if not found: - raise AssertionError( - f"{item_type.capitalize()} change {exp_tuple} not found " - f"or not in correct order. Actual changes: {actual_tuples}" - ) + if not found: + raise AssertionError( + f"{item_type.capitalize()} change {exp_tuple} not found " + f"or not in correct order. Actual changes: {actual_tuples}" + ) __all__ = [ diff --git a/ethereum_test_types/tests/test_block_access_lists.py b/ethereum_test_types/tests/test_block_access_lists.py index 20ad08b497..40ab13c3e7 100644 --- a/ethereum_test_types/tests/test_block_access_lists.py +++ b/ethereum_test_types/tests/test_block_access_lists.py @@ -77,8 +77,11 @@ def test_empty_list_validation(): [ BalAccountChange( address=alice, - nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], - balance_changes=[], # no balance changes + nonce_changes=[], + balance_changes=[], + code_changes=[], + storage_changes=[], + storage_reads=[], ), ] ) @@ -86,8 +89,11 @@ def test_empty_list_validation(): expectation = BlockAccessListExpectation( account_expectations={ alice: BalAccountExpectation( - nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], - balance_changes=[], # explicitly expect no balance changes + nonce_changes=[], + balance_changes=[], + code_changes=[], + storage_changes=[], + storage_reads=[], ), } ) @@ -95,29 +101,38 @@ def test_empty_list_validation(): expectation.verify_against(actual_bal) -def test_empty_list_validation_fails(): +@pytest.mark.parametrize( + "field,value", + [ + ["nonce_changes", BalNonceChange(tx_index=1, post_nonce=1)], + ["balance_changes", BalBalanceChange(tx_index=1, post_balance=100)], + ["code_changes", BalCodeChange(tx_index=1, new_code=b"code")], + [ + "storage_changes", + BalStorageSlot( + slot=0x01, + slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)], + ), + ], + ["storage_reads", 0x01], + ], +) +def test_empty_list_validation_fails(field: str, value) -> None: """Test that validation fails when expecting empty but field has values.""" alice = Address(0xA) - actual_bal = BlockAccessList( - [ - BalAccountChange( - address=alice, - balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)], - ), - ] - ) + bal_acct_change = BalAccountChange(address=alice) + setattr(bal_acct_change, field, [value]) + actual_bal = BlockAccessList([bal_acct_change]) - expectation = BlockAccessListExpectation( - account_expectations={ - # expect no balance changes (wrongly) - alice: BalAccountExpectation(balance_changes=[]), - } - ) + alice_acct_expectation = BalAccountExpectation() + setattr(alice_acct_expectation, field, []) + + expectation = BlockAccessListExpectation(account_expectations={alice: alice_acct_expectation}) with pytest.raises( BlockAccessListValidationError, - match="Expected balance_changes to be empty", + match=f"Expected {field} to be empty", ): expectation.verify_against(actual_bal) From 74764ab92437d0a61f69e12a402056f89bb60c86 Mon Sep 17 00:00:00 2001 From: winsvega Date: Fri, 3 Oct 2025 01:39:04 +0300 Subject: [PATCH 073/102] type(tests): convert create suicide during init (#1871) * type(tests): convert create suicide during init * Fixes, increase coverage * fix: Coverage script * Add coveraged missed reason --------- Co-authored-by: Mario Vega --- .../create/test_create_suicide_during_init.py | 104 ++++++++++++++++++ ...REATE_ContractSuicideDuringInitFiller.json | 66 ----------- ...eDuringInit_ThenStoreThenReturnFiller.json | 80 -------------- ...ractSuicideDuringInit_WithValueFiller.json | 66 ----------- ...ideDuringInit_WithValueToItselfFiller.json | 70 ------------ 5 files changed, 104 insertions(+), 282 deletions(-) create mode 100644 frontier/create/test_create_suicide_during_init.py delete mode 100644 static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInitFiller.json delete mode 100644 static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_ThenStoreThenReturnFiller.json delete mode 100644 static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueFiller.json delete mode 100644 static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueToItselfFiller.json diff --git a/frontier/create/test_create_suicide_during_init.py b/frontier/create/test_create_suicide_during_init.py new file mode 100644 index 0000000000..1e5c77c7f4 --- /dev/null +++ b/frontier/create/test_create_suicide_during_init.py @@ -0,0 +1,104 @@ +"""Deploy contract that calls selfdestruct in it's initcode.""" + +from enum import Enum + +import pytest + +from ethereum_test_forks import Byzantium, Fork +from ethereum_test_tools import ( + Account, + Alloc, + Environment, + Initcode, + StateTestFiller, + Transaction, + compute_create_address, +) +from ethereum_test_tools import Opcodes as Op + + +class Operation(Enum): + """Enum for created contract actions.""" + + SUICIDE = 1 + SUICIDE_TO_ITSELF = 2 + + def __int__(self): + """Convert to int.""" + return int(self.value) + + +@pytest.mark.ported_from( + [ + "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stCreateTest/CREATE_ContractSuicideDuringInit_ThenStoreThenReturnFiller.json", + "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueFiller.json", + "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueToItselfFiller.json", + "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stCreateTest/CREATE_ContractSuicideDuringInitFiller.json", + ], + pr=["https://github.com/ethereum/execution-spec-tests/pull/1871"], + coverage_missed_reason="Tip to coinbase, original test contains empty account.", +) +@pytest.mark.valid_from("Frontier") +@pytest.mark.with_all_create_opcodes +@pytest.mark.parametrize("transaction_create", [False, True]) +@pytest.mark.parametrize( + "operation", + [Operation.SUICIDE, Operation.SUICIDE_TO_ITSELF], +) +def test_create_suicide_during_transaction_create( + state_test: StateTestFiller, + fork: Fork, + pre: Alloc, + create_opcode: Op, + operation: Operation, + transaction_create: bool, +): + """Contract init code calls suicide then measures different metrics.""" + if create_opcode != Op.CREATE and transaction_create: + pytest.skip(f"Excluded: {create_opcode} with transaction_create=True") + + sender = pre.fund_eoa() + contract_deploy = pre.deploy_contract( + code=Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + + create_opcode(size=Op.CALLDATASIZE(), value=Op.CALLVALUE()) + ) + contract_success = pre.deploy_contract(code=Op.SSTORE(1, 1)) + self_destruct_destination = pre.deploy_contract(code=Op.STOP) + contract_after_suicide = pre.deploy_contract(code=Op.SSTORE(1, 1)) + + contract_initcode = Initcode( + initcode_prefix=Op.CALL(address=contract_success, gas=Op.SUB(Op.GAS, 100_000)) + + Op.SELFDESTRUCT( + Op.ADDRESS if operation == Operation.SUICIDE_TO_ITSELF else self_destruct_destination + ) + + Op.CALL(address=contract_after_suicide, gas=Op.SUB(Op.GAS, 100_000)), + deploy_code=Op.SSTORE(0, 1), + ) + + expected_create_address = compute_create_address( + address=sender if transaction_create else contract_deploy, + nonce=1 if transaction_create else 0, + initcode=contract_initcode, + opcode=create_opcode, + ) + + tx_value = 100 + tx = Transaction( + gas_limit=1_000_000, + to=None if transaction_create else contract_deploy, + data=contract_initcode, + value=tx_value, + sender=sender, + protected=fork >= Byzantium, + ) + + post = { + contract_success: Account(storage={1: 1}), + self_destruct_destination: Account( + balance=0 if operation == Operation.SUICIDE_TO_ITSELF else tx_value + ), + contract_deploy: Account(storage={0: 0}), + contract_after_suicide: Account(storage={1: 0}), # suicide eats all gas + expected_create_address: Account.NONEXISTENT, + } + state_test(env=Environment(), pre=pre, post=post, tx=tx) diff --git a/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInitFiller.json b/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInitFiller.json deleted file mode 100644 index fdca1044d1..0000000000 --- a/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInitFiller.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "CREATE_ContractSuicideDuringInit" : { - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentGasLimit" : "10000000", - "currentNumber" : "1", - "currentTimestamp" : "1000" - }, - "expect" : [ - { - "indexes" : { - "data" : -1, - "gas" : -1, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { - "shouldnotexist" : "1" - }, - "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0", - "storage" : { - "0x01" : "0x0c" - } - } - } - } - ], - "pre" : - { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000", - "code" : "", - "nonce" : "0", - "storage" : { - } - }, - "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0", - "// code" : "This indicates that a call from transaction was initiated", - "code" : "{[[1]]12}", - "nonce" : "0", - "storage" : { - } - } - }, - "transaction" : { - "// data" : "{(CALL 60000 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b 0 0 0 0 0) (MSTORE 0 0x64600c6000556000526005601bf3) (SELFDESTRUCT 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b)}", - "data" : [ - ":raw 0x6000600060006000600073c94f5374fce5edbc8e2a8697c15331677e6ebf0b61ea60f1506d64600c6000556000526005601bf360005273c94f5374fce5edbc8e2a8697c15331677e6ebf0bff" - ], - "gasLimit" : [ - "150000" - ], - "gasPrice" : "10", - "nonce" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "", - "value" : [ - "0" - ] - } - } -} diff --git a/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_ThenStoreThenReturnFiller.json b/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_ThenStoreThenReturnFiller.json deleted file mode 100644 index 8b13ce103a..0000000000 --- a/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_ThenStoreThenReturnFiller.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "CREATE_ContractSuicideDuringInit_ThenStoreThenReturn" : { - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentGasLimit" : "10000000", - "currentNumber" : "1", - "currentTimestamp" : "1000" - }, - "expect" : [ - { - "indexes" : { - "data" : -1, - "gas" : -1, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { - "shouldnotexist" : "1" - }, - "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0", - "storage" : { - "0x01" : "0x0c" - } - }, - "d94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "10", - "storage" : { - "0x01" : "0x00" - } - } - } - } - ], - "pre" : - { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000", - "code" : "", - "nonce" : "0", - "storage" : { - } - }, - "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0", - "// code" : "This indicates that a call from transaction was initiated", - "code" : "{[[1]]12}", - "nonce" : "0", - "storage" : { - } - }, - "d94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0", - "// code" : "This indicates that a call from transaction was initiated", - "code" : "{[[1]]12}", - "nonce" : "0", - "storage" : { - } - } - }, - "transaction" : { - "// data" : "{ (CALL 60000 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b 0 0 0 0 0) (MSTORE 0 0x64600c6000556000526005601bf3) (SELFDESTRUCT 0xd94f5374fce5edbc8e2a8697c15331677e6ebf0b) (CALL 60000 0xd94f5374fce5edbc8e2a8697c15331677e6ebf0b 0 0 0 0 0) [[0]]11 (RETURN 18 14)}", - "data" : [ - ":raw 0x6000600060006000600073c94f5374fce5edbc8e2a8697c15331677e6ebf0b61ea60f1506d64600c6000556000526005601bf360005273d94f5374fce5edbc8e2a8697c15331677e6ebf0bff6000600060006000600073d94f5374fce5edbc8e2a8697c15331677e6ebf0b61ea60f150600b600055600e6012f3" - ], - "gasLimit" : [ - "600000" - ], - "gasPrice" : "10", - "nonce" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "", - "value" : [ - "10" - ] - } - } -} diff --git a/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueFiller.json b/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueFiller.json deleted file mode 100644 index e2ce0d3a8a..0000000000 --- a/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueFiller.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "CREATE_ContractSuicideDuringInit_WithValue" : { - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentGasLimit" : "10000000", - "currentNumber" : "1", - "currentTimestamp" : "1000" - }, - "expect" : [ - { - "indexes" : { - "data" : -1, - "gas" : -1, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { - "shouldnotexist" : "1" - }, - "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "10", - "storage" : { - "0x01" : "0x0c" - } - } - } - } - ], - "pre" : - { - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "1000000000000", - "code" : "", - "nonce" : "0", - "storage" : { - } - }, - "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0", - "// code" : "This indicates that a call from transaction was initiated", - "code" : "{[[1]]12}", - "nonce" : "0", - "storage" : { - } - } - }, - "transaction" : { - "// data" : "{(CALL 60000 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b 0 0 0 0 0) (MSTORE 0 0x64600c6000556000526005601bf3) (SELFDESTRUCT 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b)}", - "data" : [ - ":raw 0x6000600060006000600073c94f5374fce5edbc8e2a8697c15331677e6ebf0b61ea60f1506d64600c6000556000526005601bf360005273c94f5374fce5edbc8e2a8697c15331677e6ebf0bff" - ], - "gasLimit" : [ - "150000" - ], - "gasPrice" : "10", - "nonce" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "", - "value" : [ - "10" - ] - } - } -} diff --git a/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueToItselfFiller.json b/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueToItselfFiller.json deleted file mode 100644 index fe8bf0a99d..0000000000 --- a/static/state_tests/stCreateTest/CREATE_ContractSuicideDuringInit_WithValueToItselfFiller.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "CREATE_ContractSuicideDuringInit_WithValueToItself" : { - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentGasLimit" : "10000000", - "currentNumber" : "1", - "currentTimestamp" : "1000" - }, - "expect" : [ - { - "network" : [">=Cancun"], - "result" : { - "6295ee1b4f6dd65047762f924ecd367c17eabf8f" : { - "shouldnotexist" : "1" - }, - "1a3e089e89a1d995552b4005c40cd5c8832b929b" : { - "shouldnotexist" : "1" - }, - "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0", - "storage" : { - "0x01" : "0x0c" - } - } - } - } - ], - "pre" : - { - "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "0", - "code" : "", - "nonce" : "1", - "storage" : { - } - }, - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "100000000000000", - "code" : "", - "nonce" : "0", - "storage" : { - } - }, - "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0", - "// code" : "This indicates that a call from transaction was initiated", - "code" : "{[[1]]12}", - "nonce" : "0", - "storage" : { - } - } - }, - "transaction" : { - "data" : [ - "{(CALL 60000 0xc94f5374fce5edbc8e2a8697c15331677e6ebf0b 0 0 0 0 0) (MSTORE 0 0x64600c6000556000526005601bf3) (SELFDESTRUCT (ADDRESS))}" - ], - "gasLimit" : [ - "150000" - ], - "gasPrice" : "10", - "nonce" : "0", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "", - "value" : [ - "10" - ] - } - } -} From cccfcb91efdc0f7b7194923e5efaa742c199917b Mon Sep 17 00:00:00 2001 From: raxhvl <10168946+raxhvl@users.noreply.github.com> Date: Fri, 3 Oct 2025 01:14:33 +0200 Subject: [PATCH 074/102] =?UTF-8?q?=E2=9C=A8=20feat(tests):=20EIP-7928=20t?= =?UTF-8?q?est=20cases=20for=20EIP-2930=20transactions=20(#2167)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat(tests): EIP-7928 tests for EIP-2930: 🧹 chore(tests): Move to new test file ✨ feat(tests): EIP-7928test_bal_2930_slot_listed_and_unlisted_reads ✨ feat(tests): EIP-7928 test_bal_2930_slot_listed_and_unlisted_writes ✨ feat(tests): EIP-7928 test_bal_2930_slot_listed_but_untouched * fix: issues after refactor; rename test file * ✨ feat(test): test_bal_2930_account_listed_but_untouched * chore: move 2930 tests into main test file * chore: add changelog entry * fix: fix rebase error for OOG 7928 tests * fix: validate expected empty account changes --------- Co-authored-by: raxhvl Co-authored-by: fselmo --- .../test_block_access_lists.py | 219 +++++++++++++++++- .../test_block_access_lists_opcodes.py | 6 +- .../test_cases.md | 8 +- 3 files changed, 224 insertions(+), 9 deletions(-) diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py index a99b01e15c..f488da1555 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py @@ -4,7 +4,7 @@ import pytest -from ethereum_test_base_types import Address +from ethereum_test_base_types import AccessList, Address, Hash from ethereum_test_tools import ( Account, Alloc, @@ -345,7 +345,7 @@ def test_bal_self_destruct( pytest.param(lambda target_addr: Op.EXTCODESIZE(target_addr), id="extcodesize"), pytest.param(lambda target_addr: Op.EXTCODECOPY(target_addr, 0, 0, 32), id="extcodecopy"), pytest.param(lambda target_addr: Op.EXTCODEHASH(target_addr), id="extcodehash"), - pytest.param(lambda target_addr: Op.CALL(0, target_addr, 50, 0, 0, 0, 0), id="call"), + pytest.param(lambda target_addr: Op.CALL(0, target_addr, 0, 0, 0, 0, 0), id="call"), pytest.param( lambda target_addr: Op.CALLCODE(0, target_addr, 0, 0, 0, 0, 0), id="callcode" ), @@ -647,3 +647,218 @@ def test_bal_block_rewards( blocks=[block], post={}, ) + + +def test_bal_2930_account_listed_but_untouched( + pre: Alloc, + blockchain_test: BlockchainTestFiller, +): + """Ensure BAL excludes untouched access list accounts.""" + alice = pre.fund_eoa() + bob = pre.fund_eoa() + oracle = pre.deploy_contract(code=Op.STOP) + + access_list = AccessList( + address=oracle, + storage_keys=[Hash(0x1)], + ) + + gas_limit = 1_000_000 + + tx = Transaction(ty=1, sender=alice, to=bob, gas_limit=gas_limit, access_list=[access_list]) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + # The address excluded from BAL since state is not accessed + oracle: None, + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + }, + ) + + +def test_bal_2930_slot_listed_but_untouched( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork, +): + """Ensure BAL excludes untouched access list storage slots.""" + alice = pre.fund_eoa() + pure_calculator = pre.deploy_contract( + # Pure add operation + Op.ADD(35, 7) + ) + + access_list = AccessList( + address=pure_calculator, + storage_keys=[Hash(0x1)], + ) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + gas_limit = ( + intrinsic_gas_calculator( + calldata=b"", + contract_creation=False, + access_list=[access_list], + ) + + 1000 + ) # intrinsic + buffer + + tx = Transaction( + ty=1, sender=alice, to=pure_calculator, gas_limit=gas_limit, access_list=[access_list] + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + # The account was loaded. + pure_calculator: BalAccountExpectation(), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + }, + ) + + +def test_bal_2930_slot_listed_and_unlisted_writes( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork, +): + """ + Ensure BAL includes storage writes regardless of access list presence. + """ + alice = pre.fund_eoa() + storage_writer = pre.deploy_contract(code=Op.SSTORE(0x01, 0x42) + Op.SSTORE(0x02, 0x43)) + + # Access list only includes slot 0x01, but contract writes to both + # 0x01 and 0x02 + access_list = AccessList( + address=storage_writer, + storage_keys=[Hash(0x01)], + ) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + gas_limit = ( + intrinsic_gas_calculator( + calldata=b"", + contract_creation=False, + access_list=[access_list], + ) + + 50000 + ) # intrinsic + buffer for storage writes + + tx = Transaction( + ty=1, sender=alice, to=storage_writer, gas_limit=gas_limit, access_list=[access_list] + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + storage_writer: BalAccountExpectation( + storage_changes=[ + BalStorageSlot( + slot=0x01, + slot_changes=[BalStorageChange(tx_index=1, post_value=0x42)], + ), + BalStorageSlot( + slot=0x02, + slot_changes=[BalStorageChange(tx_index=1, post_value=0x43)], + ), + ], + ), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + storage_writer: Account(storage={0x01: 0x42, 0x02: 0x43}), + }, + ) + + +def test_bal_2930_slot_listed_and_unlisted_reads( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork, +): + """Ensure BAL includes storage reads regardless of access list presence.""" + alice = pre.fund_eoa() + storage_reader = pre.deploy_contract( + code=Op.SLOAD(0x01) + Op.SLOAD(0x02), + storage={0x01: 0x42, 0x02: 0x43}, # Pre-populate storage with values + ) + + # Access list only includes slot 0x01, but contract reads from both + # 0x01 and 0x02 + access_list = AccessList( + address=storage_reader, + storage_keys=[Hash(0x01)], + ) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + gas_limit = ( + intrinsic_gas_calculator( + calldata=b"", + contract_creation=False, + access_list=[access_list], + ) + + 50000 + ) # intrinsic + buffer for storage reads + + tx = Transaction( + ty=1, sender=alice, to=storage_reader, gas_limit=gas_limit, access_list=[access_list] + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + storage_reader: BalAccountExpectation( + storage_reads=[0x01, 0x02], + ), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={ + alice: Account(nonce=1), + storage_reader: Account(storage={0x01: 0x42, 0x02: 0x43}), + }, + ) diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py index 7f3aa2baa9..7d8ea698d3 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py @@ -153,9 +153,9 @@ def test_bal_sload_and_oog( sload_cold_cost = gas_costs.G_COLD_SLOAD tx_gas_limit = intrinsic_gas_cost + push_cost + sload_cold_cost - # if fails_at_sload: - # # subtract 1 gas to ensure OOG at SLOAD - # tx_gas_limit -= 1 + if fails_at_sload: + # subtract 1 gas to ensure OOG at SLOAD + tx_gas_limit -= 1 tx = Transaction( sender=alice, diff --git a/amsterdam/eip7928_block_level_access_lists/test_cases.md b/amsterdam/eip7928_block_level_access_lists/test_cases.md index a627b34cfa..2977e4da93 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_cases.md +++ b/amsterdam/eip7928_block_level_access_lists/test_cases.md @@ -8,15 +8,16 @@ | `test_bal_storage_reads` | Ensure BAL captures storage reads | Alice calls contract that reads from storage slot `0x01` | BAL MUST include storage access for the read operation | ✅ Completed | | `test_bal_code_changes` | Ensure BAL captures changes to account code | Alice deploys factory contract that creates new contract | BAL MUST include code changes for newly deployed contract | ✅ Completed | | `test_bal_self_destruct` | Ensure BAL captures storage access and balance changes caused by `SELFDESTRUCT` | Parameterized test: Alice interacts with a contract (either existing or created same-tx) that reads from storage slot 0x01, writes to storage slot 0x02, then executes `SELFDESTRUCT` with Bob as recipient. Contract may be pre-funded with 10 wei | BAL MUST include Alice's nonce change (increment) and Bob's balance change (100 or 110 depending on pre-funding). For the self-destructing contract: storage_reads=[0x01], empty storage_changes=[], and if pre-funded, balance_changes with post_balance=0; if not pre-funded, no balance change recorded. MUST NOT have code_changes or nonce_changes entries | ✅ Completed | -| `test_bal_2930_slot_listed_but_untouched` | Ensure 2930 access list alone doesn't appear in BAL | Include `(KV, S=0x01)` in tx's EIP-2930 access list; tx executes code that does **no** `SLOAD`/`SSTORE` to `S` (e.g., pure arithmetic/log). | BAL **MUST NOT** contain any entry for `(KV, S)` — neither reads nor writes — because the slot wasn't touched. | 🟡 Planned | | `test_bal_account_access_target` | Ensure BAL captures target addresses of account access opcodes | Alice calls `Oracle` contract which uses account access opcodes (`BALANCE`, `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH`, `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`) on `TargetContract`. | BAL MUST include Alice, `Oracle`, and `TargetContract` with empty changes for `TargetContract` and nonce changes for Alice. | ✅ Completed | | `test_bal_call_with_value_transfer` | Ensure BAL captures balance changes from `CALL` opcode with value transfer | Alice calls `Oracle` contract (200 wei balance) which uses `CALL` opcode to transfer 100 wei to Bob (0 wei balance). | BAL MUST include Alice (nonce changes), Oracle (balance change to 100 wei), and Bob (balance change to 100 wei). | ✅ Completed | | `test_bal_callcode_with_value_transfer` | Ensure BAL captures balance changes from `CALLCODE` opcode with value transfer | Alice calls `Oracle` contract (200 wei balance) which uses `CALLCODE` opcode to execute `TargetContract`'s code with 100 wei value transfer to Bob (0 wei balance). | BAL MUST include Alice (nonce changes), `Oracle` (balance change to 100 wei), Bob (balance change to 100 wei), and `TargetContract` (empty changes). | ✅ Completed | | `test_bal_delegated_storage_writes` | Ensure BAL captures delegated storage writes via `DELEGATECALL` and `CALLCODE` | Alice calls `Oracle` contract which uses `DELEGATECALL`/`CALLCODE` to `TargetContract` that writes `0x42` to slot `0x01`. | BAL MUST include Alice (nonce changes), `Oracle` (storage changes for slot `0x01` = `0x42`), and `TargetContract` (empty changes). | ✅ Completed | | `test_bal_delegated_storage_reads` | Ensure BAL captures delegated storage reads via `DELEGATECALL` and `CALLCODE` | Alice calls `Oracle` contract (with slot `0x01` = `0x42`) which uses `DELEGATECALL`/`CALLCODE` to `TargetContract` that reads from slot `0x01`. | BAL MUST include Alice (nonce changes), `Oracle` (storage reads for slot `0x01`), and `TargetContract` (empty changes). | ✅ Completed | | `test_bal_block_rewards` | BAL tracks fee recipient balance changes from block rewards | Alice sends 100 wei to Bob with Charlie as fee recipient | BAL MUST include fee recipient Charlie with `balance_changes` reflecting transaction fees collected from the block. | ✅ Completed | -| `test_bal_2930_slot_listed_but_untouched` | Ensure 2930 access list alone doesn’t appear in BAL | Include `(KV, S=0x01)` in tx’s EIP-2930 access list; tx executes code that does **no** `SLOAD`/`SSTORE` to `S` (e.g., pure arithmetic/log). | BAL **MUST NOT** contain any entry for `(KV, S)` — neither reads nor writes — because the slot wasn’t touched. | 🟡 Planned | -| `test_bal_2930_slot_listed_and_modified` | Ensure BAL records writes only because the slot is touched | Same access list as above, but tx executes `SSTORE` to `S`. | BAL **MUST** include `storage_changes` for `(KV, S)` (and no separate read record for that slot if implementation deduplicates). Presence in the access list is irrelevant; inclusion is due to the actual write. | 🟡 Planned | +| `test_bal_2930_account_listed_but_untouched` | Ensure BAL excludes listed but untouched account | Alice sends a simple eth transfer tx to Bob with EIP-2930 access list including `Oracle` | BAL MUST NOT include any entry for `Oracle` because it wasn't accessed. | ✅ Completed | +| `test_bal_2930_slot_listed_but_untouched` | Ensure BAL excludes listed but untouched storage slots | Alice sends tx with EIP-2930 access list including `(PureCalculator, slot=0x01)`; PureCalculator executes pure arithmetic (adding two numbers) without touching slot `0x01` | BAL MUST NOT include any entry for PureCalculator's slot `0x01` because it doesn't access state | ✅ Completed | +| `test_bal_2930_slot_listed_and_unlisted_writes` | Ensure BAL includes storage writes regardless of access list presence | Alice sends tx with EIP-2930 access list including `(StorageWriter, slot=0x01)`; StorageWriter executes `SSTORE` to slots `0x01` and `0x02` | BAL MUST include `storage_changes` for StorageWriter's slots `0x01` and `0x02` | ✅ Completed | +| `test_bal_2930_slot_listed_and_unlisted_reads` | Ensure BAL includes storage reads regardless of access list presence | Alice sends tx with EIP-2930 access list including `(StorageReader, slot=0x01)`; StorageReader executes `SLOAD` from slots `0x01` and `0x02` | BAL MUST include `storage_reads` for StorageReader's slots `0x01` and `0x02` | ✅ Completed | | `test_bal_7702_delegated_create` | BAL tracks EIP-7702 delegation indicator write and contract creation | Alice sends a type-4 (7702) tx authorizing herself to delegate to `Deployer` code which executes `CREATE` | BAL MUST include for **Alice**: `code_changes` (delegation indicator), `nonce_changes` (increment from 7702 processing), and `balance_changes` (post-gas). For **Child**: `code_changes` (runtime bytecode) and `nonce_changes = 1`. | 🟡 Planned | | `test_bal_self_transfer` | BAL handles self-transfers correctly | Alice sends `1 ETH` to **Alice** | BAL MUST include **one** entry for Alice with `balance_changes` reflecting **gas only** (value cancels out) and a nonce change; Coinbase balance updated for fees; no separate recipient row. | 🟡 Planned | | `test_bal_system_contracts_2935_4788` | BAL includes pre-exec system writes for parent hash & beacon root | Build a block with `N` normal txs; 2935 & 4788 active | BAL MUST include `HISTORY_STORAGE_ADDRESS` (EIP-2935) and `BEACON_ROOTS_ADDRESS` (EIP-4788) with `storage_changes` to ring-buffer slots; each write uses `tx_index = N` (system op). | 🟡 Planned | @@ -27,5 +28,4 @@ | `test_bal_precompile_funded_then_called` | BAL records precompile with balance change (fund) and access (call) | **Tx0**: Alice sends `1 ETH` to `ecrecover` (0x01). **Tx1**: Alice (or Bob) calls `ecrecover` with valid input and `0 ETH`. | BAL **MUST** include address `0x01` with `balance_changes` (from Tx0). No `storage_changes` or `code_changes`. | 🟡 Planned | | `test_bal_precompile_call_only` | BAL records precompile when called with no balance change | Alice calls `ecrecover` (0x01) with a valid input, sending **0 ETH**. | BAL **MUST** include address `0x01` in access list, with **no** `balance_changes`, `storage_changes`, or `code_changes`. | 🟡 Planned | - > ℹ️ Scope describes whether a test spans a single transaction (`tx`) or entire block (`blk`). From bd5fab484450c99198ab53cc8cd64b0f2c5aa54e Mon Sep 17 00:00:00 2001 From: raxhvl <10168946+raxhvl@users.noreply.github.com> Date: Fri, 3 Oct 2025 01:14:33 +0200 Subject: [PATCH 075/102] =?UTF-8?q?=E2=9C=A8=20feat(tests):=20EIP-7928=20t?= =?UTF-8?q?est=20cases=20for=20EIP-2930=20transactions=20(#2167)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat(tests): EIP-7928 tests for EIP-2930: 🧹 chore(tests): Move to new test file ✨ feat(tests): EIP-7928test_bal_2930_slot_listed_and_unlisted_reads ✨ feat(tests): EIP-7928 test_bal_2930_slot_listed_and_unlisted_writes ✨ feat(tests): EIP-7928 test_bal_2930_slot_listed_but_untouched * fix: issues after refactor; rename test file * ✨ feat(test): test_bal_2930_account_listed_but_untouched * chore: move 2930 tests into main test file * chore: add changelog entry * fix: fix rebase error for OOG 7928 tests * fix: validate expected empty account changes --------- Co-authored-by: raxhvl Co-authored-by: fselmo --- .../block_access_list/expectations.py | 7 +++ .../tests/test_block_access_lists.py | 53 +++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/ethereum_test_types/block_access_list/expectations.py b/ethereum_test_types/block_access_list/expectations.py index ddb3d19f49..7eb8e64e06 100644 --- a/ethereum_test_types/block_access_list/expectations.py +++ b/ethereum_test_types/block_access_list/expectations.py @@ -168,6 +168,13 @@ def verify_against(self, actual_bal: "BlockAccessList") -> None: raise BlockAccessListValidationError( f"Address {address} should not be in BAL but was found" ) + elif expectation == BalAccountExpectation(): + # explicit check for NO account changes for the address + if actual_accounts_by_addr.get(address) != BalAccountChange(address=address): + raise BlockAccessListValidationError( + f"No account changes expected for {address} but found " + f"changes: {actual_accounts_by_addr[address]}" + ) else: # check address is present and validate changes if address not in actual_accounts_by_addr: diff --git a/ethereum_test_types/tests/test_block_access_lists.py b/ethereum_test_types/tests/test_block_access_lists.py index 40ab13c3e7..0142dce413 100644 --- a/ethereum_test_types/tests/test_block_access_lists.py +++ b/ethereum_test_types/tests/test_block_access_lists.py @@ -69,6 +69,31 @@ def test_address_exclusion_validation_raises_when_address_is_present(): expectation.verify_against(actual_bal) +def test_empty_account_changes_raises_when_changes_are_present(): + """ + Test that validation fails when expected empty changes but actual + has changes. + """ + alice = Address(0xA) + + actual_bal = BlockAccessList( + [ + BalAccountChange( + address=alice, + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + ] + ) + + expectation = BlockAccessListExpectation(account_expectations={alice: BalAccountExpectation()}) + + with pytest.raises( + BlockAccessListValidationError, + match=f"No account changes expected for {alice}", + ): + expectation.verify_against(actual_bal) + + def test_empty_list_validation(): """Test that empty list validates correctly.""" alice = Address(0xA) @@ -121,12 +146,30 @@ def test_empty_list_validation_fails(field: str, value) -> None: """Test that validation fails when expecting empty but field has values.""" alice = Address(0xA) - bal_acct_change = BalAccountChange(address=alice) - setattr(bal_acct_change, field, [value]) - actual_bal = BlockAccessList([bal_acct_change]) + alice_acct_change = BalAccountChange( + address=alice, + storage_reads=[0x02], + ) + + if field == "storage_reads": + alice_acct_change.storage_reads = [value] + # set another field to non-empty to avoid all-empty account change + alice_acct_change.nonce_changes = [BalNonceChange(tx_index=1, post_nonce=1)] + + else: + setattr(alice_acct_change, field, [value]) + actual_bal = BlockAccessList([alice_acct_change]) - alice_acct_expectation = BalAccountExpectation() - setattr(alice_acct_expectation, field, []) + alice_acct_expectation = BalAccountExpectation( + storage_reads=[0x02], + ) + if field == "storage_reads": + alice_acct_expectation.storage_reads = [] + # match the filled field in actual to avoid all-empty + # account expectation + alice_acct_expectation.nonce_changes = [BalNonceChange(tx_index=1, post_nonce=1)] + else: + setattr(alice_acct_expectation, field, []) expectation = BlockAccessListExpectation(account_expectations={alice: alice_acct_expectation}) From 8b31c88145831c78be0ed4175d103cdf8659e999 Mon Sep 17 00:00:00 2001 From: CPerezz <37264926+CPerezz@users.noreply.github.com> Date: Fri, 3 Oct 2025 15:00:36 +0200 Subject: [PATCH 076/102] refactor(tests): use pytest parametrize to reduce code duplication in BloatNet tests (#2242) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace duplicate test functions with parametrized versions to avoid repetitive code. Each test now accepts a `balance_first` parameter that controls the order of operations, eliminating the need for separate `_extcodesize_balance`, `_extcodecopy_balance`, and `_extcodehash_balance` variants. Changes: - Add @pytest.mark.parametrize to test_bloatnet_balance_extcodesize, test_bloatnet_balance_extcodecopy, and test_bloatnet_balance_extcodehash - Each test now generates two variants via parametrization with descriptive IDs (e.g., "balance_extcodesize" and "extcodesize_balance") - Extract operation sequences into variables and conditionally compose them based on balance_first parameter - Remove test_bloatnet_extcodesize_balance, test_bloatnet_extcodecopy_balance, and test_bloatnet_extcodehash_balance (now covered by parametrization) This reduces the file from 793 lines to 462 lines while maintaining the same test coverage (6 tests total: 3 test functions × 2 parametrization values). To run specific parameter variants, use the -k flag: fill -k "balance_extcodesize" tests/benchmark/bloatnet/test_multi_opcode.py fill -k "extcodesize_balance" tests/benchmark/bloatnet/test_multi_opcode.py --- .../stateful/bloatnet/test_multi_opcode.py | 204 +++++++++++++++--- 1 file changed, 178 insertions(+), 26 deletions(-) diff --git a/benchmark/stateful/bloatnet/test_multi_opcode.py b/benchmark/stateful/bloatnet/test_multi_opcode.py index 4d27d6fca4..ea6f987264 100644 --- a/benchmark/stateful/bloatnet/test_multi_opcode.py +++ b/benchmark/stateful/bloatnet/test_multi_opcode.py @@ -49,12 +49,18 @@ # 4. Attack rapidly accesses all contracts, stressing client's state handling +@pytest.mark.parametrize( + "balance_first", + [True, False], + ids=["balance_extcodesize", "extcodesize_balance"], +) @pytest.mark.valid_from("Prague") def test_bloatnet_balance_extcodesize( blockchain_test: BlockchainTestFiller, pre: Alloc, fork: Fork, gas_benchmark_value: int, + balance_first: bool, ): """ BloatNet test using BALANCE + EXTCODESIZE with "on-the-fly" CREATE2 @@ -63,7 +69,7 @@ def test_bloatnet_balance_extcodesize( This test: 1. Assumes contracts are already deployed via the factory (salt 0 to N-1) 2. Generates CREATE2 addresses dynamically during execution - 3. Calls BALANCE (cold) then EXTCODESIZE (warm) on each + 3. Calls BALANCE and EXTCODESIZE (order controlled by balance_first param) 4. Maximizes cache eviction by accessing many contracts """ gas_costs = fork.gas_costs() @@ -75,11 +81,11 @@ def test_bloatnet_balance_extcodesize( cost_per_contract = ( gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30) + gas_costs.G_KECCAK_256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6) - + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold BALANCE (2600) - + gas_costs.G_BASE # POP balance (2) - + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm EXTCODESIZE (100) - + gas_costs.G_BASE # POP code size (2) - + gas_costs.G_BASE # DUP1 before BALANCE (3) + + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold access (2600) + + gas_costs.G_BASE # POP first result (2) + + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm access (100) + + gas_costs.G_BASE # POP second result (2) + + gas_costs.G_BASE # DUP1 before first op (3) + gas_costs.G_VERY_LOW * 4 # PUSH1 operations (4 * 3) + gas_costs.G_LOW # MLOAD for salt (3) + gas_costs.G_VERY_LOW # ADD for increment (3) @@ -108,6 +114,13 @@ def test_bloatnet_balance_extcodesize( f"Factory storage will be checked during execution." ) + # Define operations that differ based on parameter + balance_op = Op.POP(Op.BALANCE) + extcodesize_op = Op.POP(Op.EXTCODESIZE) + benchmark_ops = ( + (balance_op + extcodesize_op) if balance_first else (extcodesize_op + balance_op) + ) + # Build attack contract that reads config from factory and performs attack attack_code = ( # Call getConfig() on factory to get num_deployed and init_code_hash @@ -143,9 +156,8 @@ def test_bloatnet_balance_extcodesize( # Generate CREATE2 addr: keccak256(0xFF+factory+salt+hash) Op.SHA3(11, 85) # Generate CREATE2 address from memory[11:96] # The address is now on the stack - + Op.DUP1 # Duplicate for EXTCODESIZE - + Op.POP(Op.BALANCE) # Cold access - + Op.POP(Op.EXTCODESIZE) # Warm access + + Op.DUP1 # Duplicate for second operation + + benchmark_ops # Execute operations in specified order # Increment salt for next iteration + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)) # Increment and store salt ), @@ -177,12 +189,18 @@ def test_bloatnet_balance_extcodesize( ) +@pytest.mark.parametrize( + "balance_first", + [True, False], + ids=["balance_extcodecopy", "extcodecopy_balance"], +) @pytest.mark.valid_from("Prague") def test_bloatnet_balance_extcodecopy( blockchain_test: BlockchainTestFiller, pre: Alloc, fork: Fork, gas_benchmark_value: int, + balance_first: bool, ): """ BloatNet test using BALANCE + EXTCODECOPY with on-the-fly CREATE2 @@ -191,8 +209,8 @@ def test_bloatnet_balance_extcodecopy( This test forces actual bytecode reads from disk by: 1. Assumes contracts are already deployed via the factory 2. Generating CREATE2 addresses dynamically during execution - 3. Using BALANCE (cold) to warm the account - 4. Using EXTCODECOPY (warm) to read 1 byte from the END of the bytecode + 3. Using BALANCE and EXTCODECOPY (order controlled by balance_first param) + 4. Reading 1 byte from the END of the bytecode to force full contract load """ gas_costs = fork.gas_costs() max_contract_size = fork.max_code_size() @@ -204,16 +222,16 @@ def test_bloatnet_balance_extcodecopy( cost_per_contract = ( gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30) + gas_costs.G_KECCAK_256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6) - + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold BALANCE (2600) - + gas_costs.G_BASE # POP balance (2) - + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm EXTCODECOPY base (100) + + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold access (2600) + + gas_costs.G_BASE # POP first result (2) + + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm access base (100) + gas_costs.G_COPY * 1 # Copy cost for 1 byte (3) - + gas_costs.G_BASE * 2 # DUP1 before BALANCE, DUP4 for address (6) + + gas_costs.G_BASE * 2 # DUP1 before first op, DUP4 for address (6) + gas_costs.G_VERY_LOW * 8 # PUSH operations (8 * 3 = 24) + gas_costs.G_LOW * 2 # MLOAD for salt twice (6) + gas_costs.G_VERY_LOW * 2 # ADD operations (6) + gas_costs.G_LOW # MSTORE salt back (3) - + gas_costs.G_BASE # POP after EXTCODECOPY (2) + + gas_costs.G_BASE # POP after second op (2) + 10 # While loop overhead ) @@ -238,6 +256,20 @@ def test_bloatnet_balance_extcodecopy( f"Factory storage will be checked during execution." ) + # Define operations that differ based on parameter + balance_op = Op.POP(Op.BALANCE) + extcodecopy_op = ( + Op.PUSH1(1) # size (1 byte) + + Op.PUSH2(max_contract_size - 1) # code offset (last byte) + + Op.ADD(Op.MLOAD(32), 96) # unique memory offset + + Op.DUP4 # address (duplicated earlier) + + Op.EXTCODECOPY + + Op.POP # clean up address + ) + benchmark_ops = ( + (balance_op + extcodecopy_op) if balance_first else (extcodecopy_op + balance_op) + ) + # Build attack contract that reads config from factory and performs attack attack_code = ( # Call getConfig() on factory to get num_deployed and init_code_hash @@ -274,16 +306,7 @@ def test_bloatnet_balance_extcodecopy( Op.SHA3(11, 85) # Generate CREATE2 address from memory[11:96] # The address is now on the stack + Op.DUP1 # Duplicate for later operations - + Op.POP(Op.BALANCE) # Cold access - # EXTCODECOPY(addr, mem_offset, last_byte_offset, 1) - # Read the LAST byte to force full contract load - + Op.PUSH1(1) # size (1 byte) - + Op.PUSH2(max_contract_size - 1) # code offset (last byte) - # Use salt as memory offset to avoid overlap - + Op.ADD(Op.MLOAD(32), 96) # Add base memory offset for unique position - + Op.DUP4 # address (duplicated earlier) - + Op.EXTCODECOPY - + Op.POP # Clean up address + + benchmark_ops # Execute operations in specified order # Increment salt for next iteration + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)) # Increment and store salt ), @@ -313,3 +336,132 @@ def test_bloatnet_balance_extcodecopy( blocks=[Block(txs=[attack_tx])], post=post, ) + + +@pytest.mark.parametrize( + "balance_first", + [True, False], + ids=["balance_extcodehash", "extcodehash_balance"], +) +@pytest.mark.valid_from("Prague") +def test_bloatnet_balance_extcodehash( + blockchain_test: BlockchainTestFiller, + pre: Alloc, + fork: Fork, + gas_benchmark_value: int, + balance_first: bool, +): + """ + BloatNet test using BALANCE + EXTCODEHASH with on-the-fly CREATE2 + address generation. + + This test: + 1. Assumes contracts are already deployed via the factory + 2. Generates CREATE2 addresses dynamically during execution + 3. Calls BALANCE and EXTCODEHASH (order controlled by balance_first param) + 4. Forces client to compute code hash for 24KB bytecode + """ + gas_costs = fork.gas_costs() + + # Calculate gas costs + intrinsic_gas = fork.transaction_intrinsic_cost_calculator()(calldata=b"") + + # Cost per contract access with CREATE2 address generation + cost_per_contract = ( + gas_costs.G_KECCAK_256 # SHA3 static cost for address generation (30) + + gas_costs.G_KECCAK_256_WORD * 3 # SHA3 dynamic cost (85 bytes = 3 words * 6) + + gas_costs.G_COLD_ACCOUNT_ACCESS # Cold access (2600) + + gas_costs.G_BASE # POP first result (2) + + gas_costs.G_WARM_ACCOUNT_ACCESS # Warm access (100) + + gas_costs.G_BASE # POP second result (2) + + gas_costs.G_BASE # DUP1 before first op (3) + + gas_costs.G_VERY_LOW * 4 # PUSH1 operations (4 * 3) + + gas_costs.G_LOW # MLOAD for salt (3) + + gas_costs.G_VERY_LOW # ADD for increment (3) + + gas_costs.G_LOW # MSTORE salt back (3) + + 10 # While loop overhead + ) + + # Calculate how many contracts to access based on available gas + available_gas = gas_benchmark_value - intrinsic_gas - 1000 # Reserve for cleanup + contracts_needed = int(available_gas // cost_per_contract) + + # Deploy factory using stub contract + factory_address = pre.deploy_contract( + code=Bytecode(), + stub="bloatnet_factory", + ) + + # Log test requirements + print( + f"Test needs {contracts_needed} contracts for " + f"{gas_benchmark_value / 1_000_000:.1f}M gas. " + f"Factory storage will be checked during execution." + ) + + # Define operations that differ based on parameter + balance_op = Op.POP(Op.BALANCE) + extcodehash_op = Op.POP(Op.EXTCODEHASH) + benchmark_ops = ( + (balance_op + extcodehash_op) if balance_first else (extcodehash_op + balance_op) + ) + + # Build attack contract that reads config from factory and performs attack + attack_code = ( + # Call getConfig() on factory to get num_deployed and init_code_hash + Op.STATICCALL( + gas=Op.GAS, + address=factory_address, + args_offset=0, + args_size=0, + ret_offset=96, + ret_size=64, + ) + # Check if call succeeded + + Op.ISZERO + + Op.PUSH2(0x1000) # Jump to error handler if failed + + Op.JUMPI + # Load results from memory + + Op.MLOAD(96) # Load num_deployed_contracts + + Op.MLOAD(128) # Load init_code_hash + # Setup memory for CREATE2 address generation + + Op.MSTORE(0, factory_address) + + Op.MSTORE8(11, 0xFF) + + Op.MSTORE(32, 0) # Initial salt + + Op.PUSH1(64) + + Op.MSTORE # Store init_code_hash + # Main attack loop + + While( + body=( + # Generate CREATE2 address + Op.SHA3(11, 85) + + Op.DUP1 # Duplicate for second operation + + benchmark_ops # Execute operations in specified order + # Increment salt + + Op.MSTORE(32, Op.ADD(Op.MLOAD(32), 1)) + ), + condition=Op.DUP1 + Op.PUSH1(1) + Op.SWAP1 + Op.SUB + Op.DUP1 + Op.ISZERO + Op.ISZERO, + ) + + Op.POP # Clean up counter + ) + + # Deploy attack contract + attack_address = pre.deploy_contract(code=attack_code) + + # Run the attack + attack_tx = Transaction( + to=attack_address, + gas_limit=gas_benchmark_value, + sender=pre.fund_eoa(), + ) + + # Post-state + post = { + attack_address: Account(storage={}), + } + + blockchain_test( + pre=pre, + blocks=[Block(txs=[attack_tx])], + post=post, + ) From 09528386d36a31b8558cc02bf7c3110b9fb31ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Oct 2025 17:59:49 +0200 Subject: [PATCH 077/102] feat(tests): add test for modexp with 2**32 exp len (#2254) --- byzantium/eip198_modexp_precompile/test_modexp.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/byzantium/eip198_modexp_precompile/test_modexp.py b/byzantium/eip198_modexp_precompile/test_modexp.py index 978963ec6d..2af5a203be 100644 --- a/byzantium/eip198_modexp_precompile/test_modexp.py +++ b/byzantium/eip198_modexp_precompile/test_modexp.py @@ -72,6 +72,16 @@ ModExpInput(base="", exponent="", modulus="0001"), ModExpOutput(returned_data="0x0000"), ), + ( + ModExpInput( + base="", + exponent="", + modulus="", + declared_exponent_length=2**32, + declared_modulus_length=1, + ), + ModExpOutput(returned_data="0x00", call_success=False), + ), # Test cases from EIP 198. pytest.param( ModExpInput( From 1446713e0730188743f835b1aa28d1fe9ca56b08 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Fri, 3 Oct 2025 18:47:35 +0200 Subject: [PATCH 078/102] feat(vm): evm memory variable abstraction (#1609) * feat(vm): Implement `MemoryVariable` * refactor(tests): Use MemoryVariable in tests/frontier/scenarios/common.py * Rename "store" to "set" * Fixup * refactor * chore: ruff 79 line lenght. --------- Co-authored-by: spencer-tb --- frontier/scenarios/common.py | 65 +++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/frontier/scenarios/common.py b/frontier/scenarios/common.py index 1d7a95296c..cb17f44cf1 100644 --- a/frontier/scenarios/common.py +++ b/frontier/scenarios/common.py @@ -5,7 +5,7 @@ from enum import Enum from ethereum_test_forks import Fork, Frontier -from ethereum_test_tools import Address, Alloc, Bytecode, Conditional +from ethereum_test_tools import Address, Alloc, Bytecode, Conditional, MemoryVariable from ethereum_test_vm import Opcodes as Op @@ -196,20 +196,41 @@ def make_gas_hash_contract(pre: Alloc) -> Address: So that if we can't check exact value in expect section, we at least could spend unique gas amount. """ + # EVM memory variables + byte_offset = MemoryVariable(0) + current_byte = MemoryVariable(32) + + # Code for memory initialization + initialize_code = byte_offset.set(0) + calldata_copy = Op.JUMPDEST + Op.CALLDATACOPY( + dest_offset=current_byte.offset + 32 - 1, + offset=byte_offset, + size=1, + ) + + # Code offsets + offset_calldata_copy = len(initialize_code) + offset_conditional = offset_calldata_copy + len(calldata_copy) + + # Deploy contract gas_hash_address = pre.deploy_contract( - code=Op.MSTORE(0, 0) - + Op.JUMPDEST - + Op.CALLDATACOPY(63, Op.MLOAD(0), 1) - + Op.JUMPDEST + code=initialize_code + + calldata_copy # offset_calldata_copy + + Op.JUMPDEST # offset_conditional + Conditional( - condition=Op.ISZERO(Op.MLOAD(32)), - if_true=Op.MSTORE(0, Op.ADD(1, Op.MLOAD(0))) - + Conditional( - condition=Op.GT(Op.MLOAD(0), 32), - if_true=Op.RETURN(0, 0), - if_false=Op.JUMP(5), + condition=Op.ISZERO(current_byte), + if_true=( + # Increase the calldata byte offset, and if it's greater than + # the calldata size, return, otherwise jump to the calldata + # copy code and read the next byte. + byte_offset.add(1) + + Conditional( + condition=Op.GT(byte_offset, Op.CALLDATASIZE()), + if_true=Op.RETURN(offset=0, size=0), + if_false=Op.JUMP(offset_calldata_copy), + ) ), - if_false=Op.MSTORE(32, Op.SUB(Op.MLOAD(32), 1)) + Op.JUMP(14), + if_false=(current_byte.sub(1) + Op.JUMP(offset_conditional)), ) ) return gas_hash_address @@ -241,19 +262,25 @@ def make_invalid_opcode_contract(pre: Alloc, fork: Fork) -> Address: if op not in valid_opcode_values: invalid_opcodes.append(op) + results_sum = MemoryVariable(0) + current_opcode = MemoryVariable(32) + code = Bytecode( sum( - Op.MSTORE(64, opcode) - + Op.MSTORE( - 32, - Op.CALL(gas=50000, address=invalid_opcode_caller, args_offset=64, args_size=32), + current_opcode.set(opcode) + + results_sum.add( + Op.CALL( + gas=50000, + address=invalid_opcode_caller, + args_offset=current_opcode.offset, + args_size=32, + ), ) - + Op.MSTORE(0, Op.ADD(Op.MLOAD(0), Op.MLOAD(32))) for opcode in invalid_opcodes ) # If any of invalid instructions works, mstore[0] will be > 1 - + Op.MSTORE(0, Op.ADD(Op.MLOAD(0), 1)) - + Op.RETURN(0, 32) + + results_sum.add(1) + + results_sum.return_value() ) return pre.deploy_contract(code=code) From dbe04c4693fec27c63b837f4e7cc83a499656057 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Fri, 3 Oct 2025 18:47:35 +0200 Subject: [PATCH 079/102] feat(vm): evm memory variable abstraction (#1609) * feat(vm): Implement `MemoryVariable` * refactor(tests): Use MemoryVariable in tests/frontier/scenarios/common.py * Rename "store" to "set" * Fixup * refactor * chore: ruff 79 line lenght. --------- Co-authored-by: spencer-tb --- ethereum_test_tools/__init__.py | 2 + ethereum_test_vm/__init__.py | 3 +- ethereum_test_vm/helpers.py | 84 +++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/ethereum_test_tools/__init__.py b/ethereum_test_tools/__init__.py index fc8057c001..9625cb2da9 100644 --- a/ethereum_test_tools/__init__.py +++ b/ethereum_test_tools/__init__.py @@ -82,6 +82,7 @@ EVMCodeType, Macro, Macros, + MemoryVariable, Opcode, OpcodeCallArg, Opcodes, @@ -157,6 +158,7 @@ "JumpLoopGenerator", "Macro", "Macros", + "MemoryVariable", "NetworkWrappedTransaction", "Opcode", "OpcodeCallArg", diff --git a/ethereum_test_vm/__init__.py b/ethereum_test_vm/__init__.py index cd84471f20..0b35318fee 100644 --- a/ethereum_test_vm/__init__.py +++ b/ethereum_test_vm/__init__.py @@ -2,7 +2,7 @@ from .bytecode import Bytecode from .evm_types import EVMCodeType -from .helpers import call_return_code +from .helpers import MemoryVariable, call_return_code from .opcodes import Macro, Macros, Opcode, OpcodeCallArg, Opcodes, UndefinedOpcodes __all__ = ( @@ -10,6 +10,7 @@ "EVMCodeType", "Macro", "Macros", + "MemoryVariable", "Opcode", "OpcodeCallArg", "Opcodes", diff --git a/ethereum_test_vm/helpers.py b/ethereum_test_vm/helpers.py index 2b7a723d5b..05c10be45a 100644 --- a/ethereum_test_vm/helpers.py +++ b/ethereum_test_vm/helpers.py @@ -1,8 +1,92 @@ """Helper functions for the EVM.""" +from .bytecode import Bytecode from .opcodes import Opcodes as Op +class MemoryVariable(Bytecode): + """ + Variable abstraction to help keep track values that are stored in memory. + + To use, simply declare a variable with an unique offset that is not used + by any other variable. + + The variable then can be used in-place to read the value from memory: + + ```python + v = MemoryVariable(128) + + bytecode = Op.ADD(v, Op.CALLDATASIZE()) + ``` + + The previous example is equivalent to: + + ```python + bytecode = Op.ADD(Op.MLOAD(offset=128), Op.CALLDATASIZE()) + ``` + + The variable also contains methods to add and subtract values from the + memory offset. + + ```python + v = MemoryVariable(128) + + bytecode = ( + v.set(0xff) + + v.add(1) + + v.return_value() + ) + ``` + + The previous example is equivalent to: + + ```python + bytecode = ( + Op.MSTORE(offset=128, value=0xff) + + Op.MSTORE(offset=128, value=Op.ADD(Op.MLOAD(offset=128), 1)) + + Op.RETURN(offset=128, size=32) + ) + ``` + + """ + + offset: int + + def __new__(cls, offset: int): + """ + Instantiate a new EVM memory variable. + + When used with normal bytecode, this class simply returns the MLOAD + with the provided offset. + """ + instance = super().__new__(cls, Op.MLOAD(offset=offset)) + instance.offset = offset + return instance + + def set(self, value: int | Bytecode) -> Bytecode: + """Set the given value at the memory location of this variable.""" + return Op.MSTORE(offset=self.offset, value=value) + + def add(self, value: int | Bytecode) -> Bytecode: + """In-place add the given value to the one currently in memory.""" + return Op.MSTORE(offset=self.offset, value=Op.ADD(Op.MLOAD(offset=self.offset), value)) + + def sub(self, value: int | Bytecode) -> Bytecode: + """ + In-place subtract the given value from the one currently + in memory. + """ + return Op.MSTORE(offset=self.offset, value=Op.SUB(Op.MLOAD(offset=self.offset), value)) + + def store_value(self, key: int | Bytecode) -> Bytecode: + """Op.SSTORE the value that is currently in memory.""" + return Op.SSTORE(key, Op.MLOAD(offset=self.offset)) + + def return_value(self) -> Bytecode: + """Op.RETURN the value that is currently in memory.""" + return Op.RETURN(offset=self.offset, size=32) + + def call_return_code(opcode: Op, success: bool, *, revert: bool = False) -> int: """Return return code for a CALL operation.""" if opcode in [Op.CALL, Op.CALLCODE, Op.DELEGATECALL, Op.STATICCALL]: From f10bfce584498cd4580954a20a22560827408eb4 Mon Sep 17 00:00:00 2001 From: felix Date: Fri, 3 Oct 2025 19:29:28 +0000 Subject: [PATCH 080/102] chores(fill, pytest): mark slow tests that were not marked as such yet (#2220) * mark slow tests that were not marked as such yet * Apply suggestions from code review --------- Co-authored-by: Mario Vega --- berlin/eip2929_gas_cost_increases/test_precompile_warming.py | 1 + berlin/eip2930_access_list/test_tx_intrinsic_gas.py | 1 + cancun/eip4844_blobs/test_blob_txs.py | 2 ++ cancun/eip4844_blobs/test_excess_blob_gas.py | 3 +++ cancun/eip4844_blobs/test_point_evaluation_precompile.py | 1 + constantinople/eip1014_create2/test_create_returndata.py | 1 + frontier/opcodes/test_calldatasize.py | 1 + frontier/opcodes/test_push.py | 1 + frontier/scenarios/test_scenarios.py | 5 +++-- istanbul/eip152_blake2/test_blake2.py | 1 + osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py | 1 + prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py | 1 + prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py | 2 ++ prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py | 1 + .../test_bls12_variable_length_input_contracts.py | 1 + prague/eip7702_set_code_tx/test_gas.py | 1 + prague/eip7702_set_code_tx/test_set_code_txs.py | 3 +++ shanghai/eip3860_initcode/test_initcode.py | 2 ++ shanghai/eip4895_withdrawals/test_withdrawals.py | 1 + 19 files changed, 28 insertions(+), 2 deletions(-) diff --git a/berlin/eip2929_gas_cost_increases/test_precompile_warming.py b/berlin/eip2929_gas_cost_increases/test_precompile_warming.py index f8ad64a3d4..a4f2270c04 100644 --- a/berlin/eip2929_gas_cost_increases/test_precompile_warming.py +++ b/berlin/eip2929_gas_cost_increases/test_precompile_warming.py @@ -79,6 +79,7 @@ def precompile_addresses_in_predecessor_successor( ) @EIPChecklist.Precompile.Test.ForkTransition.Before.Cold(eip=[7951]) @EIPChecklist.Precompile.Test.ForkTransition.After.Warm(eip=[7951]) +@pytest.mark.slow() def test_precompile_warming( blockchain_test: BlockchainTestFiller, fork: Fork, diff --git a/berlin/eip2930_access_list/test_tx_intrinsic_gas.py b/berlin/eip2930_access_list/test_tx_intrinsic_gas.py index cb5fe94b96..d0a55054d2 100644 --- a/berlin/eip2930_access_list/test_tx_intrinsic_gas.py +++ b/berlin/eip2930_access_list/test_tx_intrinsic_gas.py @@ -145,6 +145,7 @@ ], ) @pytest.mark.with_all_tx_types(selector=lambda tx_type: tx_type in [1, 2]) +@pytest.mark.slow() def test_tx_intrinsic_gas( state_test: StateTestFiller, tx_type: int, diff --git a/cancun/eip4844_blobs/test_blob_txs.py b/cancun/eip4844_blobs/test_blob_txs.py index b242595ef6..4ce5104580 100644 --- a/cancun/eip4844_blobs/test_blob_txs.py +++ b/cancun/eip4844_blobs/test_blob_txs.py @@ -629,6 +629,7 @@ def test_invalid_block_blob_count( @pytest.mark.parametrize("tx_error", [TransactionException.INSUFFICIENT_ACCOUNT_FUNDS], ids=[""]) @pytest.mark.exception_test @pytest.mark.valid_from("Cancun") +@pytest.mark.slow() def test_insufficient_balance_blob_tx( state_test: StateTestFiller, state_env: Environment, @@ -1405,6 +1406,7 @@ def test_blob_tx_attribute_gasprice_opcode( ) @pytest.mark.exception_test @pytest.mark.valid_at_transition_to("Cancun") +@pytest.mark.slow() def test_blob_type_tx_pre_fork( state_test: StateTestFiller, pre: Alloc, diff --git a/cancun/eip4844_blobs/test_excess_blob_gas.py b/cancun/eip4844_blobs/test_excess_blob_gas.py index 298460ce7d..92f6efc8f5 100644 --- a/cancun/eip4844_blobs/test_excess_blob_gas.py +++ b/cancun/eip4844_blobs/test_excess_blob_gas.py @@ -480,6 +480,7 @@ def all_invalid_blob_gas_used_combinations(fork: Fork) -> Iterator[Tuple[int, in ) @pytest.mark.parametrize("parent_blobs", [0]) @pytest.mark.exception_test +@pytest.mark.slow() def test_invalid_blob_gas_used_in_header( blockchain_test: BlockchainTestFiller, env: Environment, @@ -759,6 +760,7 @@ def test_invalid_excess_blob_gas_change( lambda fork: range(fork.target_blobs_per_block()), ) @pytest.mark.exception_test +@pytest.mark.slow() def test_invalid_negative_excess_blob_gas( blockchain_test: BlockchainTestFiller, env: Environment, @@ -809,6 +811,7 @@ def test_invalid_negative_excess_blob_gas( lambda fork: [fork.target_blobs_per_block() + 1], ) @pytest.mark.exception_test +@pytest.mark.slow() def test_invalid_non_multiple_excess_blob_gas( blockchain_test: BlockchainTestFiller, env: Environment, diff --git a/cancun/eip4844_blobs/test_point_evaluation_precompile.py b/cancun/eip4844_blobs/test_point_evaluation_precompile.py index 24562a11e2..4e650b8ffd 100644 --- a/cancun/eip4844_blobs/test_point_evaluation_precompile.py +++ b/cancun/eip4844_blobs/test_point_evaluation_precompile.py @@ -449,6 +449,7 @@ def all_external_vectors() -> List: ) @pytest.mark.parametrize("versioned_hash", [None]) @pytest.mark.valid_from("Cancun") +@pytest.mark.slow() def test_external_vectors( state_test: StateTestFiller, pre: Alloc, diff --git a/constantinople/eip1014_create2/test_create_returndata.py b/constantinople/eip1014_create2/test_create_returndata.py index 99b6690d05..94dfcf1069 100644 --- a/constantinople/eip1014_create2/test_create_returndata.py +++ b/constantinople/eip1014_create2/test_create_returndata.py @@ -28,6 +28,7 @@ @pytest.mark.parametrize("create_type", [Op.CREATE, Op.CREATE2]) @pytest.mark.parametrize("return_type", [Op.RETURN, Op.REVERT]) @pytest.mark.parametrize("return_type_in_create", [Op.RETURN, Op.REVERT]) +@pytest.mark.slow() def test_create2_return_data( call_return_size: int, create_type: Op, diff --git a/frontier/opcodes/test_calldatasize.py b/frontier/opcodes/test_calldatasize.py index 2106524015..9eae9de863 100644 --- a/frontier/opcodes/test_calldatasize.py +++ b/frontier/opcodes/test_calldatasize.py @@ -19,6 +19,7 @@ [0, 2, 16, 33, 257], ) @pytest.mark.parametrize("calldata_source", ["contract", "tx"]) +@pytest.mark.slow() def test_calldatasize( state_test: StateTestFiller, fork: Fork, diff --git a/frontier/opcodes/test_push.py b/frontier/opcodes/test_push.py index fc407f9c4d..516c6f8091 100644 --- a/frontier/opcodes/test_push.py +++ b/frontier/opcodes/test_push.py @@ -91,6 +91,7 @@ def test_push(state_test: StateTestFiller, fork: Fork, pre: Alloc, push_opcode: ) @pytest.mark.parametrize("stack_height", range(1024, 1026)) @pytest.mark.valid_from("Frontier") +@pytest.mark.slow() def test_stack_overflow( state_test: StateTestFiller, fork: Fork, pre: Alloc, push_opcode: Op, stack_height: int ): diff --git a/frontier/scenarios/test_scenarios.py b/frontier/scenarios/test_scenarios.py index bb820d81d0..263e8fa71d 100644 --- a/frontier/scenarios/test_scenarios.py +++ b/frontier/scenarios/test_scenarios.py @@ -144,7 +144,7 @@ def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List ProgramTstoreTload(), ProgramLogs(), ProgramSuicide(), - pytest.param(ProgramInvalidOpcode(), marks=[pytest.mark.slow()]), + ProgramInvalidOpcode(), ProgramAddress(), ProgramBalance(), ProgramOrigin(), @@ -159,7 +159,7 @@ def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List ProgramReturnDataSize(), ProgramReturnDataCopy(), ProgramExtCodehash(), - pytest.param(ProgramBlockhash(), marks=[pytest.mark.slow()]), + ProgramBlockhash(), ProgramCoinbase(), ProgramTimestamp(), ProgramNumber(), @@ -176,6 +176,7 @@ def scenarios(fork: Fork, pre: Alloc, test_program: ScenarioTestProgram) -> List ProgramAllFrontierOpcodes(), ], ) +@pytest.mark.slow() def test_scenarios( blockchain_test: BlockchainTestFiller, fork: Fork, diff --git a/istanbul/eip152_blake2/test_blake2.py b/istanbul/eip152_blake2/test_blake2.py index 6e575947c8..f22b4ef3ef 100644 --- a/istanbul/eip152_blake2/test_blake2.py +++ b/istanbul/eip152_blake2/test_blake2.py @@ -389,6 +389,7 @@ ), ], ) +@pytest.mark.slow() def test_blake2b( state_test: StateTestFiller, pre: Alloc, diff --git a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py index 9264d3db7f..f397b7c110 100644 --- a/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py +++ b/osaka/eip7883_modexp_gas_increase/test_modexp_thresholds.py @@ -39,6 +39,7 @@ @EIPChecklist.Precompile.Test.InputLengths.Dynamic.Valid() @EIPChecklist.GasCostChanges.Test.GasUpdatesMeasurement() @pytest.mark.valid_from("Berlin") +@pytest.mark.slow() def test_vectors_from_eip( state_test: StateTestFiller, pre: Alloc, diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py index 6d6effdde0..b59f1764bd 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_g1add.py @@ -386,6 +386,7 @@ def test_valid( ], ) @pytest.mark.parametrize("expected_output", [Spec.INVALID], ids=[""]) +@pytest.mark.slow() def test_invalid( state_test: StateTestFiller, pre: Alloc, diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py index 8d5a4e89c3..307b232269 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_g1msm.py @@ -87,6 +87,7 @@ ), ], ) +@pytest.mark.slow() def test_valid( state_test: StateTestFiller, pre: Alloc, @@ -247,6 +248,7 @@ def test_invalid( ), ], ) +@pytest.mark.slow() def test_call_types( state_test: StateTestFiller, pre: Alloc, diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py index 87a9cf7785..01d56f9fab 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_g2msm.py @@ -89,6 +89,7 @@ ), ], ) +@pytest.mark.slow() def test_valid( state_test: StateTestFiller, pre: Alloc, diff --git a/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py b/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py index 8cc70be6af..b176da02e9 100644 --- a/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py +++ b/prague/eip2537_bls_12_381_precompiles/test_bls12_variable_length_input_contracts.py @@ -564,6 +564,7 @@ def test_invalid_length_g2msm( @pytest.mark.parametrize("gas_modifier", [pytest.param(0, id="exact_gas")]) @pytest.mark.parametrize("expected_output", [Spec.PAIRING_TRUE], ids=[""]) @pytest.mark.parametrize("precompile_address", [Spec.PAIRING]) +@pytest.mark.slow() def test_valid_gas_pairing( state_test: StateTestFiller, env: Environment, diff --git a/prague/eip7702_set_code_tx/test_gas.py b/prague/eip7702_set_code_tx/test_gas.py index 1b416b28fb..48b5cc0831 100644 --- a/prague/eip7702_set_code_tx/test_gas.py +++ b/prague/eip7702_set_code_tx/test_gas.py @@ -753,6 +753,7 @@ def gas_test_parameter_args( @pytest.mark.parametrize( **gas_test_parameter_args(include_pre_authorized=False, execution_gas_allowance=True) ) +@pytest.mark.slow() def test_gas_cost( state_test: StateTestFiller, pre: Alloc, diff --git a/prague/eip7702_set_code_tx/test_set_code_txs.py b/prague/eip7702_set_code_tx/test_set_code_txs.py index c401488bd4..82409427d0 100644 --- a/prague/eip7702_set_code_tx/test_set_code_txs.py +++ b/prague/eip7702_set_code_tx/test_set_code_txs.py @@ -522,6 +522,7 @@ def test_set_code_to_self_destruct( @pytest.mark.with_all_create_opcodes +@pytest.mark.slow() def test_set_code_to_contract_creator( state_test: StateTestFiller, pre: Alloc, @@ -3562,6 +3563,7 @@ def test_creating_delegation_designation_contract( ), ], ) +@pytest.mark.slow() def test_many_delegations( state_test: StateTestFiller, fork: Fork, @@ -3824,6 +3826,7 @@ def test_set_code_from_account_with_non_delegating_code( ], ) @pytest.mark.exception_test +@pytest.mark.slow() def test_set_code_transaction_fee_validations( state_test: StateTestFiller, pre: Alloc, diff --git a/shanghai/eip3860_initcode/test_initcode.py b/shanghai/eip3860_initcode/test_initcode.py index 8f31bb2f20..c88ff6fc12 100644 --- a/shanghai/eip3860_initcode/test_initcode.py +++ b/shanghai/eip3860_initcode/test_initcode.py @@ -339,6 +339,7 @@ def post( return Alloc({create_contract_address: Account(code=initcode.deploy_code)}) return Alloc({create_contract_address: Account.NONEXISTENT}) + @pytest.mark.slow() def test_gas_usage( self, state_test: StateTestFiller, @@ -501,6 +502,7 @@ def create2_word_cost(self, opcode: Op, fork: Fork, initcode: Initcode) -> int: return ceiling_division(len(initcode), 32) * gas_costs.G_KECCAK_256_WORD @pytest.mark.xdist_group(name="bigmem") + @pytest.mark.slow() def test_create_opcode_initcode( self, state_test: StateTestFiller, diff --git a/shanghai/eip4895_withdrawals/test_withdrawals.py b/shanghai/eip4895_withdrawals/test_withdrawals.py index df2124df95..a5365c3b0e 100644 --- a/shanghai/eip4895_withdrawals/test_withdrawals.py +++ b/shanghai/eip4895_withdrawals/test_withdrawals.py @@ -694,6 +694,7 @@ def test_large_amount( @pytest.mark.xdist_group(name="bigmem") @pytest.mark.parametrize("amount", [0, 1]) @pytest.mark.with_all_precompiles +@pytest.mark.slow() def test_withdrawing_to_precompiles( blockchain_test: BlockchainTestFiller, pre: Alloc, From 766a5f9c18d38636bf836609537944e2a9ab5f41 Mon Sep 17 00:00:00 2001 From: felipe Date: Fri, 3 Oct 2025 16:35:36 -0600 Subject: [PATCH 081/102] fix(tests): BALs - set genesis environment to calculate base fee appropriately (#2262) * fix(tests): set genesis environment to calculate base fee appropriately * add header_verify check for block base_fee - comment on #2262 * chore: add changelog entry --- .../test_block_access_lists.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py index f488da1555..7142d7877e 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py @@ -5,6 +5,7 @@ import pytest from ethereum_test_base_types import AccessList, Address, Hash +from ethereum_test_specs.blockchain import Header from ethereum_test_tools import ( Account, Alloc, @@ -14,6 +15,7 @@ Transaction, compute_create_address, ) +from ethereum_test_types import Environment from ethereum_test_types.block_access_list import ( BalAccountExpectation, BalBalanceChange, @@ -595,14 +597,13 @@ def test_bal_block_rewards( charlie = pre.fund_eoa(amount=0) # fee recipient intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() - intrinsic_gas_cost = intrinsic_gas_calculator( + intrinsic_gas = intrinsic_gas_calculator( calldata=b"", contract_creation=False, access_list=[], ) - tx_gas_limit = intrinsic_gas_cost + 1000 # add a small buffer + tx_gas_limit = intrinsic_gas + 1000 # add a small buffer gas_price = 0xA - base_fee_per_gas = 0x2 # Set base fee for EIP-1559 tx = Transaction( sender=alice, @@ -614,16 +615,23 @@ def test_bal_block_rewards( # EIP-1559 fee calculation: # - Total gas cost - total_gas_cost = intrinsic_gas_cost * gas_price + total_gas_cost = intrinsic_gas * gas_price # - Tip portion - tip_to_charlie = intrinsic_gas_cost * (gas_price - base_fee_per_gas) + + genesis_env = Environment(base_fee_per_gas=0x7) + base_fee_per_gas = fork.base_fee_per_gas_calculator()( + parent_base_fee_per_gas=genesis_env.base_fee_per_gas, + parent_gas_used=0, + parent_gas_limit=genesis_env.gas_limit, + ) + tip_to_charlie = (gas_price - base_fee_per_gas) * intrinsic_gas alice_final_balance = alice_initial_balance - 100 - total_gas_cost block = Block( txs=[tx], fee_recipient=charlie, # Set Charlie as the fee recipient - base_fee_per_gas=base_fee_per_gas, # Set base fee for EIP-1559 + header_verify=Header(base_fee_per_gas=base_fee_per_gas), expected_block_access_list=BlockAccessListExpectation( account_expectations={ alice: BalAccountExpectation( @@ -646,6 +654,7 @@ def test_bal_block_rewards( pre=pre, blocks=[block], post={}, + genesis_environment=genesis_env, ) From c1423421c60fced9d1b6ca50f144380088a04be0 Mon Sep 17 00:00:00 2001 From: Luis Mastrangelo Date: Mon, 6 Oct 2025 05:27:01 +0200 Subject: [PATCH 082/102] chore(tools): add support for large `int`s in `Wei` class (#2265) * Add support for large ints in `Wei` class Signed-off-by: Luis Mastrangelo * Avoid using lambda Signed-off-by: Luis Mastrangelo --------- Signed-off-by: Luis Mastrangelo --- ethereum_test_base_types/base_types.py | 2 +- ethereum_test_base_types/tests/test_base_types.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ethereum_test_base_types/base_types.py b/ethereum_test_base_types/base_types.py index 041df926ca..8900eafd8a 100644 --- a/ethereum_test_base_types/base_types.py +++ b/ethereum_test_base_types/base_types.py @@ -83,7 +83,7 @@ def __new__(cls, input_number: NumberConvertible | Self): base, exp = value_str.split("**") value = float(base) ** int(exp) else: - value = float(value_str) + value = int(value_str) if value_str.isdecimal() else float(value_str) return super(Number, cls).__new__(cls, value * multiplier) return super(Number, cls).__new__(cls, to_number(input_number)) diff --git a/ethereum_test_base_types/tests/test_base_types.py b/ethereum_test_base_types/tests/test_base_types.py index a521cbb971..719b2a5633 100644 --- a/ethereum_test_base_types/tests/test_base_types.py +++ b/ethereum_test_base_types/tests/test_base_types.py @@ -163,6 +163,9 @@ def test_address_padding(): ("1e18", 10**18), ("1 ether", 10**18), ("2 ether", 2 * 10**18), + ("70000 ether", 70000 * 10**18), + ("123456 ether", 123456 * 10**18), + ("123456.789 ether", 123456.789 * 10**18), ("2.1 ether", 2.1 * 10**18), ("2.1 Ether", 2.1 * 10**18), ("2.1 ETHER", 2.1 * 10**18), From 07ddbf3dfed60fe70ff682e71135b349f1b64f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:37:12 +0800 Subject: [PATCH 083/102] feat(pre_alloc): Add maximum bytecode size limit for contract deployment (#2150) * feat(pre_alloc): Add maximum bytecode size limit for contract deployment * refactor(benchmark): resolve contract size limit failing cases * feat(pre_alloc): integrate fork dependency for dynamic bytecode size limit * refactor: remove hardcoded value --- pytest_plugins/filler/pre_alloc.py | 14 +++++++++++++- pytest_plugins/filler/tests/test_pre_alloc.py | 6 +++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pytest_plugins/filler/pre_alloc.py b/pytest_plugins/filler/pre_alloc.py index 3bb74b3e0f..50f9fe40f7 100644 --- a/pytest_plugins/filler/pre_alloc.py +++ b/pytest_plugins/filler/pre_alloc.py @@ -96,6 +96,7 @@ class Alloc(BaseAlloc): _contract_address_iterator: Iterator[Address] = PrivateAttr() _eoa_iterator: Iterator[EOA] = PrivateAttr() _evm_code_type: EVMCodeType | None = PrivateAttr(None) + _fork: Fork = PrivateAttr() def __init__( self, @@ -103,6 +104,7 @@ def __init__( alloc_mode: AllocMode, contract_address_iterator: Iterator[Address], eoa_iterator: Iterator[EOA], + fork: Fork, evm_code_type: EVMCodeType | None = None, **kwargs, ): @@ -112,6 +114,7 @@ def __init__( self._contract_address_iterator = contract_address_iterator self._eoa_iterator = eoa_iterator self._evm_code_type = evm_code_type + self._fork = fork def __setitem__(self, address: Address | FixedSizeBytesConvertible, account: Account | None): """Set account associated with an address.""" @@ -163,12 +166,19 @@ def deploy_contract( if self._alloc_mode == AllocMode.STRICT: assert Number(nonce) >= 1, "impossible to deploy contract with nonce lower than one" + code = self.code_pre_processor(code, evm_code_type=evm_code_type) + code_bytes = bytes(code) if not isinstance(code, (bytes, str)) else code + max_code_size = self._fork.max_code_size() + assert len(code_bytes) <= max_code_size, ( + f"code too large: {len(code_bytes)} > {max_code_size}" + ) + super().__setitem__( contract_address, Account( nonce=nonce, balance=balance, - code=self.code_pre_processor(code, evm_code_type=evm_code_type), + code=code, storage=storage, ), ) @@ -424,11 +434,13 @@ def pre( contract_address_iterator: Iterator[Address], eoa_iterator: Iterator[EOA], evm_code_type: EVMCodeType, + fork: Fork, ) -> Alloc: """Return default pre allocation for all tests (Empty alloc).""" return Alloc( alloc_mode=alloc_mode, contract_address_iterator=contract_address_iterator, eoa_iterator=eoa_iterator, + fork=fork, evm_code_type=evm_code_type, ) diff --git a/pytest_plugins/filler/tests/test_pre_alloc.py b/pytest_plugins/filler/tests/test_pre_alloc.py index e7c09a6425..ba7b9290d4 100644 --- a/pytest_plugins/filler/tests/test_pre_alloc.py +++ b/pytest_plugins/filler/tests/test_pre_alloc.py @@ -5,6 +5,7 @@ import pytest from ethereum_test_base_types import Address, TestPrivateKey, TestPrivateKey2 +from ethereum_test_forks import Fork, Prague from ethereum_test_types import EOA from ethereum_test_vm import EVMCodeType from ethereum_test_vm import Opcodes as Op @@ -18,7 +19,9 @@ def create_test_alloc( - alloc_mode: AllocMode = AllocMode.PERMISSIVE, evm_code_type: EVMCodeType = EVMCodeType.LEGACY + alloc_mode: AllocMode = AllocMode.PERMISSIVE, + fork: Fork = Prague, + evm_code_type: EVMCodeType = EVMCodeType.LEGACY, ) -> Alloc: """Create a test Alloc instance with default iterators.""" contract_iter = iter( @@ -33,6 +36,7 @@ def create_test_alloc( alloc_mode=alloc_mode, contract_address_iterator=contract_iter, eoa_iterator=eoa_iter, + fork=fork, evm_code_type=evm_code_type, ) From 9657da84cde7d2380d4244c5937e28f0e7743dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:37:12 +0800 Subject: [PATCH 084/102] feat(pre_alloc): Add maximum bytecode size limit for contract deployment (#2150) * feat(pre_alloc): Add maximum bytecode size limit for contract deployment * refactor(benchmark): resolve contract size limit failing cases * feat(pre_alloc): integrate fork dependency for dynamic bytecode size limit * refactor: remove hardcoded value --- benchmark/test_worst_compute.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/benchmark/test_worst_compute.py b/benchmark/test_worst_compute.py index 504b231051..3de15e61cc 100644 --- a/benchmark/test_worst_compute.py +++ b/benchmark/test_worst_compute.py @@ -2978,13 +2978,20 @@ def test_worst_push( ): """Test running a block with as many PUSH as possible.""" op = opcode[1] if opcode.has_data_portion() else opcode - opcode_sequence = op * fork.max_stack_height() - target_contract_address = pre.deploy_contract(code=opcode_sequence) + + op_seq = Bytecode() + for _ in range(fork.max_stack_height()): + if len(op_seq) + len(op) > fork.max_code_size(): + break + op_seq += op + + target_contract_address = pre.deploy_contract(code=op_seq) calldata = Bytecode() attack_block = Op.POP(Op.STATICCALL(Op.GAS, target_contract_address, 0, 0, 0, 0)) code = code_loop_precompile_call(calldata, attack_block, fork) + code_address = pre.deploy_contract(code=code) tx = Transaction( From b59303d08b5b2917f317e06df0ad6a9b8d3e32a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Mon, 6 Oct 2025 21:33:40 +0800 Subject: [PATCH 085/102] fix(benchmark): relax gas validation rule for non benchmark mode (#2269) --- ethereum_test_specs/blockchain.py | 4 ++++ ethereum_test_specs/state.py | 3 +++ 2 files changed, 7 insertions(+) diff --git a/ethereum_test_specs/blockchain.py b/ethereum_test_specs/blockchain.py index 458b5dd110..65e6e882cd 100644 --- a/ethereum_test_specs/blockchain.py +++ b/ethereum_test_specs/blockchain.py @@ -903,6 +903,10 @@ def execute( for block in self.blocks: blocks += [block.txs] # Pass gas validation params for benchmark tests + # If not benchmark mode, skip gas used validation + if self._operation_mode != OpMode.BENCHMARKING: + self.skip_gas_used_validation = True + return TransactionPost( blocks=blocks, post=self.post, diff --git a/ethereum_test_specs/state.py b/ethereum_test_specs/state.py index 3e7c27041c..b14ef89640 100644 --- a/ethereum_test_specs/state.py +++ b/ethereum_test_specs/state.py @@ -445,6 +445,9 @@ def execute( """Generate the list of test fixtures.""" if execute_format == TransactionPost: # Pass gas validation params for benchmark tests + # If not benchmark mode, skip gas used validation + if self._operation_mode != OpMode.BENCHMARKING: + self.skip_gas_used_validation = True return TransactionPost( blocks=[[self.tx]], post=self.post, From 689e489b553c816b882df137313fcc38b10af33d Mon Sep 17 00:00:00 2001 From: raxhvl <10168946+raxhvl@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:20:32 +0200 Subject: [PATCH 086/102] =?UTF-8?q?=E2=9C=A8=20feat(tests):=20EIP-7928=20N?= =?UTF-8?q?o-op=20and=20adjacent=20test=20case=20(#2178)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat(tests): EIP-7928 test_bal_self_transfer * ✨ feat(tests): EIP-7928 test_bal_zero_value_transfer * ✨ feat(tests): EIP-7928 test_bal_self_transfer * 🚧 wip: noop reverts * 🚧 wip: noop reverts * 🚧 wip: aborted account access * 🥢 nit: * ✨ feat(tests): test_bal_fully_unmutated_account * fix: issues after rebase * feat: Use `BalAccountExpectation.empty()` for explicit empty checks * refactor: remove duplicate test for BAL noop * chore: move noop tests into main bal test file * chore: add changelog entry * 🥢 nit: Add call value * feat: add back unmutated test with explicit no balance change check --------- Co-authored-by: raxhvl Co-authored-by: fselmo --- .../test_block_access_lists.py | 298 +++++++++++++++++- .../test_block_access_lists_opcodes.py | 32 +- .../test_cases.md | 7 +- 3 files changed, 320 insertions(+), 17 deletions(-) diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py index 7142d7877e..ad19a2687b 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py @@ -5,6 +5,7 @@ import pytest from ethereum_test_base_types import AccessList, Address, Hash +from ethereum_test_forks import Fork from ethereum_test_specs.blockchain import Header from ethereum_test_tools import ( Account, @@ -382,8 +383,8 @@ def test_bal_account_access_target( alice: BalAccountExpectation( nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)] ), - target_contract: BalAccountExpectation(), - oracle_contract: BalAccountExpectation(), + target_contract: BalAccountExpectation.empty(), + oracle_contract: BalAccountExpectation.empty(), } ), ) @@ -462,7 +463,7 @@ def test_bal_callcode_with_value_transfer( bob: BalAccountExpectation( balance_changes=[BalBalanceChange(tx_index=1, post_balance=100)], ), - target_contract: BalAccountExpectation(), + target_contract: BalAccountExpectation.empty(), } ), ) @@ -522,7 +523,7 @@ def test_bal_delegated_storage_writes( ) ], ), - target_contract: BalAccountExpectation(), + target_contract: BalAccountExpectation.empty(), } ), ) @@ -577,7 +578,7 @@ def test_bal_delegated_storage_reads( oracle_contract: BalAccountExpectation( storage_reads=[0x01], ), - target_contract: BalAccountExpectation(), + target_contract: BalAccountExpectation.empty(), } ), ) @@ -737,7 +738,7 @@ def test_bal_2930_slot_listed_but_untouched( nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], ), # The account was loaded. - pure_calculator: BalAccountExpectation(), + pure_calculator: BalAccountExpectation.empty(), } ), ) @@ -871,3 +872,288 @@ def test_bal_2930_slot_listed_and_unlisted_reads( storage_reader: Account(storage={0x01: 0x42, 0x02: 0x43}), }, ) + + +def test_bal_self_transfer( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork, +): + """Test that BAL correctly handles self-transfers.""" + start_balance = 1_000_000 + alice = pre.fund_eoa(amount=start_balance) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_calculator() + + tx = Transaction( + sender=alice, to=alice, gas_limit=intrinsic_gas_cost, value=100, gas_price=0xA + ) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + balance_changes=[ + BalBalanceChange( + tx_index=1, + post_balance=start_balance - intrinsic_gas_cost * tx.gas_price, + ) + ], + ) + } + ), + ) + + blockchain_test(pre=pre, blocks=[block], post={}) + + +def test_bal_zero_value_transfer( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork, +): + """Test that BAL correctly handles zero-value transfers.""" + start_balance = 1_000_000 + alice = pre.fund_eoa(amount=start_balance) + bob = pre.fund_eoa(amount=100) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + intrinsic_gas_cost = intrinsic_gas_calculator() + + tx = Transaction(sender=alice, to=bob, gas_limit=intrinsic_gas_cost, value=0, gas_price=0xA) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + balance_changes=[ + BalBalanceChange( + tx_index=1, + post_balance=start_balance - intrinsic_gas_cost * tx.gas_price, + ) + ], + ), + # Include the address; omit from balance_changes. + bob: BalAccountExpectation(balance_changes=[]), + } + ), + ) + + blockchain_test(pre=pre, blocks=[block], post={}) + + +def test_bal_pure_contract_call( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork: Fork, +): + """Test that BAL captures contract access for pure computation calls.""" + alice = pre.fund_eoa() + pure_contract = pre.deploy_contract(code=Op.ADD(0x3, 0x2)) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + gas_limit = intrinsic_gas_calculator() + 5_000 # Buffer + + tx = Transaction(sender=alice, to=pure_contract, gas_limit=gas_limit, gas_price=0xA) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + # Ensure called contract is tracked + pure_contract: BalAccountExpectation.empty(), + } + ), + ) + + blockchain_test(pre=pre, blocks=[block], post={}) + + +def test_bal_noop_storage_write( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + fork: Fork, +): + """Test that BAL correctly handles no-op storage write.""" + alice = pre.fund_eoa() + storage_contract = pre.deploy_contract(code=Op.SSTORE(0x01, 0x42), storage={0x01: 0x42}) + + intrinsic_gas_calculator = fork.transaction_intrinsic_cost_calculator() + gas_limit = ( + intrinsic_gas_calculator() + # Sufficient gas for write + + fork.gas_costs().G_COLD_SLOAD + + fork.gas_costs().G_COLD_ACCOUNT_ACCESS + + fork.gas_costs().G_STORAGE_SET + + fork.gas_costs().G_BASE * 10 # Buffer for push + ) + + tx = Transaction(sender=alice, to=storage_contract, gas_limit=gas_limit, gas_price=0xA) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + storage_contract: BalAccountExpectation( + storage_reads=[0x01], + storage_changes=[], + ), + } + ), + ) + + blockchain_test(pre=pre, blocks=[block], post={}) + + +@pytest.mark.parametrize( + "abort_opcode", + [ + pytest.param(Op.REVERT(0, 0), id="revert"), + pytest.param(Op.INVALID, id="invalid"), + ], +) +def test_bal_aborted_storage_access( + pre: Alloc, blockchain_test: BlockchainTestFiller, abort_opcode: Op +): + """Ensure BAL captures storage access in aborted transactions correctly.""" + alice = pre.fund_eoa() + storage_contract = pre.deploy_contract( + code=Op.SLOAD(0x01) + Op.SSTORE(0x02, 0x42) + abort_opcode, + storage={0x01: 0x10}, # Pre-existing value in slot 0x01 + ) + + tx = Transaction(sender=alice, to=storage_contract, gas_limit=5_000_000, gas_price=0xA) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)] + ), + storage_contract: BalAccountExpectation( + storage_changes=[], + storage_reads=[0x01, 0x02], + ), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={}, + ) + + +@pytest.mark.parametrize( + "account_access_opcode", + [ + pytest.param(lambda target_addr: Op.BALANCE(target_addr), id="balance"), + pytest.param(lambda target_addr: Op.EXTCODESIZE(target_addr), id="extcodesize"), + pytest.param(lambda target_addr: Op.EXTCODECOPY(target_addr, 0, 0, 32), id="extcodecopy"), + pytest.param(lambda target_addr: Op.EXTCODEHASH(target_addr), id="extcodehash"), + pytest.param(lambda target_addr: Op.CALL(0, target_addr, 50, 0, 0, 0, 0), id="call"), + pytest.param( + lambda target_addr: Op.CALLCODE(0, target_addr, 50, 0, 0, 0, 0), id="callcode" + ), + pytest.param( + lambda target_addr: Op.DELEGATECALL(0, target_addr, 0, 0, 0, 0), id="delegatecall" + ), + pytest.param( + lambda target_addr: Op.STATICCALL(0, target_addr, 0, 0, 0, 0), id="staticcall" + ), + ], +) +@pytest.mark.parametrize( + "abort_opcode", + [ + pytest.param(Op.REVERT(0, 0), id="revert"), + pytest.param(Op.INVALID, id="invalid"), + ], +) +def test_bal_aborted_account_access( + pre: Alloc, + blockchain_test: BlockchainTestFiller, + account_access_opcode, + abort_opcode: Op, +): + """Ensure BAL captures account access in aborted transactions.""" + alice = pre.fund_eoa() + target_contract = pre.deploy_contract(code=Op.STOP) + + abort_contract = pre.deploy_contract( + balance=100, + code=account_access_opcode(target_contract) + abort_opcode, + ) + + tx = Transaction(sender=alice, to=abort_contract, gas_limit=5_000_000, gas_price=0xA) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)] + ), + target_contract: BalAccountExpectation.empty(), + abort_contract: BalAccountExpectation.empty(), + } + ), + ) + + blockchain_test( + pre=pre, + blocks=[block], + post={}, + ) + + +def test_bal_fully_unmutated_account( + pre: Alloc, + blockchain_test: BlockchainTestFiller, +): + """ + Test that BAL captures account that has zero net mutations. + + oracle account: + 1. Storage read and write the same value (no net change). + 2. Receives `0` value transfer (no net change). + """ + alice = pre.fund_eoa() + # Deploy Oracle contract with pre-existing storage value + oracle = pre.deploy_contract( + code=Op.SSTORE(0x01, 0x42) + Op.STOP, + storage={0x01: 0x42}, # Pre-existing value + ) + + tx = Transaction(sender=alice, to=oracle, gas_limit=1_000_000, value=0, gas_price=0xA) + + block = Block( + txs=[tx], + expected_block_access_list=BlockAccessListExpectation( + account_expectations={ + alice: BalAccountExpectation( + nonce_changes=[BalNonceChange(tx_index=1, post_nonce=1)], + ), + oracle: BalAccountExpectation( + storage_changes=[], # No net storage changes + storage_reads=[0x01], # But storage was accessed + balance_changes=[], # No net balance changes + ), + } + ), + ) + + blockchain_test(pre=pre, blocks=[block], post={}) diff --git a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py index 7d8ea698d3..1bfb3fcb63 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py +++ b/amsterdam/eip7928_block_level_access_lists/test_block_access_lists_opcodes.py @@ -231,9 +231,9 @@ def test_bal_balance_and_oog( txs=[tx], expected_block_access_list=BlockAccessListExpectation( account_expectations={ - balance_checker: BalAccountExpectation(), + balance_checker: BalAccountExpectation.empty(), # Bob should only appear in BAL if BALANCE succeeded - **({} if fails_at_balance else {bob: BalAccountExpectation()}), + **({} if fails_at_balance else {bob: BalAccountExpectation.empty()}), } ), ) @@ -300,9 +300,13 @@ def test_bal_extcodesize_and_oog( txs=[tx], expected_block_access_list=BlockAccessListExpectation( account_expectations={ - codesize_checker: BalAccountExpectation(), + codesize_checker: BalAccountExpectation.empty(), # Target should only appear if EXTCODESIZE succeeded - **({} if fails_at_extcodesize else {target_contract: BalAccountExpectation()}), + **( + {} + if fails_at_extcodesize + else {target_contract: BalAccountExpectation.empty()} + ), } ), ) @@ -369,9 +373,9 @@ def test_bal_call_and_oog( txs=[tx], expected_block_access_list=BlockAccessListExpectation( account_expectations={ - call_contract: BalAccountExpectation(), + call_contract: BalAccountExpectation.empty(), # Bob should only appear if CALL succeeded - **({} if fails_at_call else {bob: BalAccountExpectation()}), + **({} if fails_at_call else {bob: BalAccountExpectation.empty()}), } ), ) @@ -443,9 +447,13 @@ def test_bal_delegatecall_and_oog( txs=[tx], expected_block_access_list=BlockAccessListExpectation( account_expectations={ - delegatecall_contract: BalAccountExpectation(), + delegatecall_contract: BalAccountExpectation.empty(), # Target should only appear if DELEGATECALL succeeded - **({} if fails_at_delegatecall else {target_contract: BalAccountExpectation()}), + **( + {} + if fails_at_delegatecall + else {target_contract: BalAccountExpectation.empty()} + ), } ), ) @@ -515,9 +523,13 @@ def test_bal_extcodecopy_and_oog( txs=[tx], expected_block_access_list=BlockAccessListExpectation( account_expectations={ - extcodecopy_contract: BalAccountExpectation(), + extcodecopy_contract: BalAccountExpectation.empty(), # Target should only appear if EXTCODECOPY succeeded - **({} if fails_at_extcodecopy else {target_contract: BalAccountExpectation()}), + **( + {} + if fails_at_extcodecopy + else {target_contract: BalAccountExpectation.empty()} + ), } ), ) diff --git a/amsterdam/eip7928_block_level_access_lists/test_cases.md b/amsterdam/eip7928_block_level_access_lists/test_cases.md index 2977e4da93..033e37d5ca 100644 --- a/amsterdam/eip7928_block_level_access_lists/test_cases.md +++ b/amsterdam/eip7928_block_level_access_lists/test_cases.md @@ -19,13 +19,18 @@ | `test_bal_2930_slot_listed_and_unlisted_writes` | Ensure BAL includes storage writes regardless of access list presence | Alice sends tx with EIP-2930 access list including `(StorageWriter, slot=0x01)`; StorageWriter executes `SSTORE` to slots `0x01` and `0x02` | BAL MUST include `storage_changes` for StorageWriter's slots `0x01` and `0x02` | ✅ Completed | | `test_bal_2930_slot_listed_and_unlisted_reads` | Ensure BAL includes storage reads regardless of access list presence | Alice sends tx with EIP-2930 access list including `(StorageReader, slot=0x01)`; StorageReader executes `SLOAD` from slots `0x01` and `0x02` | BAL MUST include `storage_reads` for StorageReader's slots `0x01` and `0x02` | ✅ Completed | | `test_bal_7702_delegated_create` | BAL tracks EIP-7702 delegation indicator write and contract creation | Alice sends a type-4 (7702) tx authorizing herself to delegate to `Deployer` code which executes `CREATE` | BAL MUST include for **Alice**: `code_changes` (delegation indicator), `nonce_changes` (increment from 7702 processing), and `balance_changes` (post-gas). For **Child**: `code_changes` (runtime bytecode) and `nonce_changes = 1`. | 🟡 Planned | -| `test_bal_self_transfer` | BAL handles self-transfers correctly | Alice sends `1 ETH` to **Alice** | BAL MUST include **one** entry for Alice with `balance_changes` reflecting **gas only** (value cancels out) and a nonce change; Coinbase balance updated for fees; no separate recipient row. | 🟡 Planned | +| `test_bal_self_transfer` | BAL handles self-transfers correctly | Alice sends `100 wei` to Alice | BAL **MUST** include one entry for Alice with `balance_changes` reflecting gas cost only (value cancels out) and nonce change. | ✅ Completed | +| `test_bal_zero_value_transfer` | BAL handles zero-value transfers correctly | Alice sends `0 wei` to Bob | BAL **MUST** include Alice with `balance_changes` (gas cost only) and nonce change, and Bob in `account_changes` with empty `balance_changes`. | ✅ Completed | | `test_bal_system_contracts_2935_4788` | BAL includes pre-exec system writes for parent hash & beacon root | Build a block with `N` normal txs; 2935 & 4788 active | BAL MUST include `HISTORY_STORAGE_ADDRESS` (EIP-2935) and `BEACON_ROOTS_ADDRESS` (EIP-4788) with `storage_changes` to ring-buffer slots; each write uses `tx_index = N` (system op). | 🟡 Planned | | `test_bal_system_dequeue_withdrawals_eip7002` | BAL tracks post-exec system dequeues for withdrawals | Pre-populate EIP-7002 withdrawal requests; produce a block where dequeues occur | BAL MUST include the 7002 system contract with `storage_changes` (queue head/tail slots 0–3) using `tx_index = len(txs)` and balance changes for withdrawal recipients. | 🟡 Planned | | `test_bal_system_dequeue_consolidations_eip7251` | BAL tracks post-exec system dequeues for consolidations | Pre-populate EIP-7251 consolidation requests; produce a block where dequeues occur | BAL MUST include the 7251 system contract with `storage_changes` (queue slots 0–3) using `tx_index = len(txs)`. | 🟡 Planned | +| `test_bal_aborted_storage_access` | Ensure BAL captures storage access in aborted transactions correctly | Alice calls contract that reads storage slot `0x01`, writes to slot `0x02`, then aborts with `REVERT`/`INVALID` | BAL MUST include storage_reads for slots `0x01` and `0x02` (aborted writes become reads), empty storage_changes. Only nonce changes for Alice. | ✅ Completed | +| `test_bal_aborted_account_access` | Ensure BAL captures account access in aborted transactions for all account accessing opcodes | Alice calls `AbortContract` that performs account access operations (`BALANCE`, `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH`, `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`) on `TargetContract` and aborts via `REVERT`/`INVALID` | BAL MUST include Alice, `TargetContract`, and `AbortContract` in account_changes and nonce changes for Alice. | ✅ Completed | +| `test_bal_pure_contract_call` | Ensure BAL captures contract access for pure computation calls | Alice calls `PureContract` that performs pure arithmetic (ADD operation) without storage or balance changes | BAL MUST include Alice and `PureContract` in `account_changes`, and `nonce_changes` for Alice. | ✅ Completed | | `test_bal_create2_to_A_read_then_selfdestruct` | BAL records balance change for A and storage access (no persistent change) | Tx0: Alice sends ETH to address **A**. Tx1: Deployer `CREATE2` a contract **at A**; contract does `SLOAD(B)` and immediately `SELFDESTRUCT(beneficiary=X)` in the same tx. | BAL **MUST** include **A** with `balance_changes` (funding in Tx0 and transfer on selfdestruct in Tx1). BAL **MUST** include storage key **B** as an accessed `StorageKey`, and **MUST NOT** include **B** under `storage_changes` (no persistence due to same-tx create+destruct). | 🟡 Planned | | `test_bal_create2_to_A_write_then_selfdestruct` | BAL records balance change for A and storage access even if a write occurred (no persistent change) | Tx0: Alice sends ETH to **A**. Tx1: Deployer `CREATE2` contract **at A**; contract does `SSTORE(B, v)` (optionally `SLOAD(B)`), then `SELFDESTRUCT(beneficiary=Y)` in the same tx. | BAL **MUST** include **A** with `balance_changes` (Tx0 fund; Tx1 outflow to `Y`). BAL **MUST** include **B** as `StorageKey` accessed, and **MUST NOT** include **B** under `storage_changes` (ephemeral write discarded because the contract was created and destroyed in the same tx). | 🟡 Planned | | `test_bal_precompile_funded_then_called` | BAL records precompile with balance change (fund) and access (call) | **Tx0**: Alice sends `1 ETH` to `ecrecover` (0x01). **Tx1**: Alice (or Bob) calls `ecrecover` with valid input and `0 ETH`. | BAL **MUST** include address `0x01` with `balance_changes` (from Tx0). No `storage_changes` or `code_changes`. | 🟡 Planned | | `test_bal_precompile_call_only` | BAL records precompile when called with no balance change | Alice calls `ecrecover` (0x01) with a valid input, sending **0 ETH**. | BAL **MUST** include address `0x01` in access list, with **no** `balance_changes`, `storage_changes`, or `code_changes`. | 🟡 Planned | +| `test_bal_fully_unmutated_account` | Ensure BAL captures account that has zero net mutations | Alice sends 0 wei to `Oracle` which writes same pre-existing value to storage | BAL MUST include Alice with `nonce_changes` and balance changes (gas), `Oracle` with `storage_reads` for accessed slot but empty `storage_changes`. | ✅ Completed | > ℹ️ Scope describes whether a test spans a single transaction (`tx`) or entire block (`blk`). From efd71b7476723274495387db3fcd143a28844fc1 Mon Sep 17 00:00:00 2001 From: raxhvl <10168946+raxhvl@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:20:32 +0200 Subject: [PATCH 087/102] =?UTF-8?q?=E2=9C=A8=20feat(tests):=20EIP-7928=20N?= =?UTF-8?q?o-op=20and=20adjacent=20test=20case=20(#2178)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat(tests): EIP-7928 test_bal_self_transfer * ✨ feat(tests): EIP-7928 test_bal_zero_value_transfer * ✨ feat(tests): EIP-7928 test_bal_self_transfer * 🚧 wip: noop reverts * 🚧 wip: noop reverts * 🚧 wip: aborted account access * 🥢 nit: * ✨ feat(tests): test_bal_fully_unmutated_account * fix: issues after rebase * feat: Use `BalAccountExpectation.empty()` for explicit empty checks * refactor: remove duplicate test for BAL noop * chore: move noop tests into main bal test file * chore: add changelog entry * 🥢 nit: Add call value * feat: add back unmutated test with explicit no balance change check --------- Co-authored-by: raxhvl Co-authored-by: fselmo --- .../block_access_list/expectations.py | 52 ++++++++++++++++--- .../tests/test_block_access_lists.py | 22 +++++--- 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/ethereum_test_types/block_access_list/expectations.py b/ethereum_test_types/block_access_list/expectations.py index 7eb8e64e06..4d9ecc7fa4 100644 --- a/ethereum_test_types/block_access_list/expectations.py +++ b/ethereum_test_types/block_access_list/expectations.py @@ -5,7 +5,7 @@ BAL values in tests. """ -from typing import Any, Callable, Dict, List, Optional +from typing import Any, Callable, ClassVar, Dict, List, Optional from pydantic import Field, PrivateAttr @@ -53,6 +53,33 @@ class BalAccountExpectation(CamelModel): default=None, description="Explicit absent value expectations using BalAccountAbsentValues" ) + _EMPTY: ClassVar[Optional["BalAccountExpectation"]] = None + + @classmethod + def empty(cls) -> "BalAccountExpectation": + """ + Create an expectation that validates the account has NO changes. + + This is distinct from `BalAccountExpectation()` with no fields set, + which is ambiguous and clashes with `model_fields_set` logic, and + will raise a clarifying error if used in expectations. + + Returns: + A BalAccountExpectation instance with all change lists empty. + This uses a classvar to facilitate identity checks across + multiple expectation instances. + + """ + if cls._EMPTY is None: + cls._EMPTY = cls( + nonce_changes=[], + balance_changes=[], + code_changes=[], + storage_changes=[], + storage_reads=[], + ) + return cls._EMPTY + def compose( *modifiers: Callable[["BlockAccessList"], "BlockAccessList"], @@ -168,13 +195,14 @@ def verify_against(self, actual_bal: "BlockAccessList") -> None: raise BlockAccessListValidationError( f"Address {address} should not be in BAL but was found" ) - elif expectation == BalAccountExpectation(): - # explicit check for NO account changes for the address - if actual_accounts_by_addr.get(address) != BalAccountChange(address=address): - raise BlockAccessListValidationError( - f"No account changes expected for {address} but found " - f"changes: {actual_accounts_by_addr[address]}" - ) + elif not expectation.model_fields_set: + # Disallow ambiguous BalAccountExpectation() with no fields set + raise BlockAccessListValidationError( + f"Address {address}: BalAccountExpectation() with no fields set is " + f"ambiguous. Use BalAccountExpectation.empty() to validate no changes, " + f"or explicitly set the fields to validate " + f"(e.g., nonce_changes=[...])." + ) else: # check address is present and validate changes if address not in actual_accounts_by_addr: @@ -182,6 +210,14 @@ def verify_against(self, actual_bal: "BlockAccessList") -> None: f"Expected address {address} not found in actual BAL" ) + if expectation is BalAccountExpectation.empty(): + # explicit check for "no changes" validation w/ .empty() + if actual_accounts_by_addr.get(address) != BalAccountChange(address=address): + raise BlockAccessListValidationError( + f"No account changes expected for {address} but found " + f"changes: {actual_accounts_by_addr[address]}" + ) + actual_account = actual_accounts_by_addr[address] try: self._compare_account_expectations(expectation, actual_account) diff --git a/ethereum_test_types/tests/test_block_access_lists.py b/ethereum_test_types/tests/test_block_access_lists.py index 0142dce413..cd78a1cfe9 100644 --- a/ethereum_test_types/tests/test_block_access_lists.py +++ b/ethereum_test_types/tests/test_block_access_lists.py @@ -69,7 +69,18 @@ def test_address_exclusion_validation_raises_when_address_is_present(): expectation.verify_against(actual_bal) -def test_empty_account_changes_raises_when_changes_are_present(): +@pytest.mark.parametrize( + "empty_changes_definition,exception_message", + [ + [BalAccountExpectation(), "ambiguous. Use BalAccountExpectation.empty()"], + [BalAccountExpectation.empty(), "No account changes expected for "], + ], + ids=["BalAccountExpectation()", "BalAccountExpectation.empty()"], +) +def test_empty_account_changes_definitions( + empty_changes_definition, + exception_message, +): """ Test that validation fails when expected empty changes but actual has changes. @@ -85,12 +96,11 @@ def test_empty_account_changes_raises_when_changes_are_present(): ] ) - expectation = BlockAccessListExpectation(account_expectations={alice: BalAccountExpectation()}) + expectation = BlockAccessListExpectation( + account_expectations={alice: empty_changes_definition} + ) - with pytest.raises( - BlockAccessListValidationError, - match=f"No account changes expected for {alice}", - ): + with pytest.raises(BlockAccessListValidationError, match=exception_message): expectation.verify_against(actual_bal) From 7582d850012e9a8a99d67360e7123d94f3442dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E4=BD=B3=E8=AA=A0=20Louis=20Tsai?= <72684086+LouisTsai-Csie@users.noreply.github.com> Date: Tue, 7 Oct 2025 03:11:36 +0800 Subject: [PATCH 088/102] feat(benchmark): add eip7702 case (#2227) * feat(benchmark): add eip7702 case * refactor: update nonce management * refactor: consider gas refund logic --- benchmark/test_worst_blocks.py | 58 ++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/benchmark/test_worst_blocks.py b/benchmark/test_worst_blocks.py index 6d95ef657b..3bb85cdddd 100644 --- a/benchmark/test_worst_blocks.py +++ b/benchmark/test_worst_blocks.py @@ -12,6 +12,7 @@ AccessList, Address, Alloc, + AuthorizationTuple, Block, BlockchainTestFiller, Environment, @@ -19,6 +20,7 @@ StateTestFiller, Transaction, ) +from ethereum_test_vm import Opcodes as Op @pytest.fixture @@ -330,3 +332,59 @@ def test_block_full_access_list_and_data( access_list=access_list, ), ) + + +@pytest.mark.parametrize("empty_authority", [True, False]) +@pytest.mark.parametrize("zero_delegation", [True, False]) +def test_worst_case_auth_block( + blockchain_test: BlockchainTestFiller, + pre: Alloc, + intrinsic_cost: int, + gas_benchmark_value: int, + fork: Fork, + empty_authority: bool, + zero_delegation: bool, +): + """Test an auth block.""" + gas_costs = fork.gas_costs() + + iteration_count = (gas_benchmark_value - intrinsic_cost) // gas_costs.G_AUTHORIZATION + + code = Op.STOP * fork.max_code_size() + auth_target = Address(0) if zero_delegation else pre.deploy_contract(code=code) + + auth_tuples = [] + for _ in range(iteration_count): + signer = ( + pre.fund_eoa(amount=0, delegation=None) + if empty_authority + else pre.fund_eoa(amount=0, delegation=auth_target) + ) + auth_tuple = AuthorizationTuple(address=auth_target, nonce=signer.nonce, signer=signer) + auth_tuples.append(auth_tuple) + + tx = Transaction( + to=pre.empty_account(), + gas_limit=gas_benchmark_value, + sender=pre.fund_eoa(), + authorization_list=auth_tuples, + ) + + gas_used = fork.transaction_intrinsic_cost_calculator()( + authorization_list_or_count=auth_tuples + ) + + refund = 0 + if not empty_authority: + refund = min( + gas_used // 5, + (gas_costs.G_AUTHORIZATION - gas_costs.R_AUTHORIZATION_EXISTING_AUTHORITY) + * iteration_count, + ) + + blockchain_test( + pre=pre, + post={}, + blocks=[Block(txs=[tx])], + expected_benchmark_gas_used=gas_used - refund, + ) From 83413a27e8be0ed9c34ee72e51d4fd2ecd13b809 Mon Sep 17 00:00:00 2001 From: spencer Date: Tue, 7 Oct 2025 14:26:03 +0100 Subject: [PATCH 089/102] chore(cli): reth/geth 6110 exception mapper (#2271) * chore(cli): reth 6110 exception mapper. * chore(cli): lint me baby one more time. * chore(cli): bump geth 6110 as well. * Update src/ethereum_clis/clis/reth.py --------- Co-authored-by: Mario Vega --- ethereum_clis/clis/geth.py | 33 +++++++++++++++++---------------- ethereum_clis/clis/reth.py | 15 --------------- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/ethereum_clis/clis/geth.py b/ethereum_clis/clis/geth.py index 55e5f52f4c..e8589dd63e 100644 --- a/ethereum_clis/clis/geth.py +++ b/ethereum_clis/clis/geth.py @@ -72,26 +72,10 @@ class GethExceptionMapper(ExceptionMapper): TransactionException.INITCODE_SIZE_EXCEEDED: "max initcode size exceeded", TransactionException.NONCE_MISMATCH_TOO_LOW: "nonce too low", TransactionException.NONCE_MISMATCH_TOO_HIGH: "nonce too high", - BlockException.INVALID_DEPOSIT_EVENT_LAYOUT: "unable to parse deposit data", BlockException.INCORRECT_BLOB_GAS_USED: "blob gas used mismatch", BlockException.INCORRECT_EXCESS_BLOB_GAS: "invalid excessBlobGas", BlockException.INVALID_VERSIONED_HASHES: "invalid number of versionedHashes", BlockException.INVALID_REQUESTS: "invalid requests hash", - BlockException.INVALID_DEPOSIT_EVENT_LAYOUT: "invalid requests hash", - # Geth does not validate the sizes or offsets of the deposit - # contract logs. As a workaround we have set - # INVALID_DEPOSIT_EVENT_LAYOUT equal to INVALID_REQUESTS. - # - # Although this is out of spec, it is understood that this - # will not cause an issue so long as the mainnet/testnet - # deposit contracts don't change. - # - # The offsets are checked second and the sizes are checked - # third within the `is_valid_deposit_event_data` function: - # https://eips.ethereum.org/EIPS/eip-6110#block-validity - # - # EELS definition for `is_valid_deposit_event_data`: - # https://github.com/ethereum/execution-specs/blob/5ddb904fa7ba27daeff423e78466744c51e8cb6a/src/ethereum/forks/prague/requests.py#L51 BlockException.SYSTEM_CONTRACT_CALL_FAILED: "system call failed to execute:", BlockException.INVALID_BLOCK_HASH: "blockhash mismatch", BlockException.RLP_BLOCK_LIMIT_EXCEEDED: "block RLP-encoded size exceeds maximum", @@ -107,6 +91,23 @@ class GethExceptionMapper(ExceptionMapper): r"blob gas used \d+ exceeds maximum allowance \d+" ), BlockException.INVALID_GAS_USED_ABOVE_LIMIT: r"invalid gasUsed: have \d+, gasLimit \d+", + BlockException.INVALID_DEPOSIT_EVENT_LAYOUT: ( + r"invalid requests hash|failed to parse deposit logs" + ), + # Geth does not validate the sizes or offsets of the deposit + # contract logs. As a workaround we have set + # INVALID_DEPOSIT_EVENT_LAYOUT equal to INVALID_REQUESTS. + # + # Although this is out of spec, it is understood that this + # will not cause an issue so long as the mainnet/testnet + # deposit contracts don't change. + # + # The offsets are checked second and the sizes are checked + # third within the `is_valid_deposit_event_data` function: + # https://eips.ethereum.org/EIPS/eip-6110#block-validity + # + # EELS definition for `is_valid_deposit_event_data`: + # https://github.com/ethereum/execution-specs/blob/5ddb904fa7ba27daeff423e78466744c51e8cb6a/src/ethereum/forks/prague/requests.py#L51 } diff --git a/ethereum_clis/clis/reth.py b/ethereum_clis/clis/reth.py index 9b115916a7..ad6d986967 100644 --- a/ethereum_clis/clis/reth.py +++ b/ethereum_clis/clis/reth.py @@ -33,21 +33,6 @@ class RethExceptionMapper(ExceptionMapper): "failed to decode deposit requests from receipts" ), BlockException.INVALID_REQUESTS: "mismatched block requests hash", - BlockException.INVALID_DEPOSIT_EVENT_LAYOUT: "mismatched block requests hash", - # Reth does not validate the sizes or offsets of the deposit - # contract logs. As a workaround we have set - # INVALID_DEPOSIT_EVENT_LAYOUT equal to INVALID_REQUESTS. - # - # Although this is out of spec, it is understood that this - # will not cause an issue so long as the mainnet/testnet - # deposit contracts don't change. - # - # The offsets are checked second and the sizes are checked - # third within the `is_valid_deposit_event_data` function: - # https://eips.ethereum.org/EIPS/eip-6110#block-validity - # - # EELS definition for `is_valid_deposit_event_data`: - # https://github.com/ethereum/execution-specs/blob/5ddb904fa7ba27daeff423e78466744c51e8cb6a/src/ethereum/forks/prague/requests.py#L51 BlockException.INVALID_RECEIPTS_ROOT: "receipt root mismatch", BlockException.INVALID_STATE_ROOT: "mismatched block state root", BlockException.INVALID_BLOCK_HASH: "block hash mismatch", From efc90589a37a0bec13f67f26f4e5a0452409c63d Mon Sep 17 00:00:00 2001 From: spencer Date: Tue, 7 Oct 2025 14:39:21 +0100 Subject: [PATCH 090/102] chore(consume): fix consume sync logger errors. (#2272) --- .../simulators/simulator_logic/test_via_sync.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py index ee57f7fcb9..d9f2dc3197 100644 --- a/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py +++ b/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py @@ -419,11 +419,17 @@ def test_blockchain_via_sync( assert eth_rpc is not None, "eth_rpc is required" assert sync_eth_rpc is not None, "sync_eth_rpc is required" - for attempt in range(3): + for attempt in range(5): try: sync_block = sync_eth_rpc.get_block_by_hash(last_valid_block_hash) client_block = eth_rpc.get_block_by_hash(last_valid_block_hash) + if sync_block is None or client_block is None: + raise LoggedError( + f"Failed to retrieve block {last_valid_block_hash} " + f"on attempt {attempt + 1}" + ) + if sync_block["stateRoot"] != client_block["stateRoot"]: raise LoggedError( f"State root mismatch after sync. " @@ -438,8 +444,9 @@ def test_blockchain_via_sync( f"Expected: {fixture.post_state_hash}, " f"Got: {sync_block['stateRoot']}" ) + break except Exception as e: - if attempt < 2: + if attempt < 4: time.sleep(1) continue raise e From 6f64a45a179d158981087f9d880e332d2aab5e64 Mon Sep 17 00:00:00 2001 From: Luis Mastrangelo Date: Tue, 7 Oct 2025 15:52:32 +0200 Subject: [PATCH 091/102] fix(tests): fix storage slot of actual value for `eip7516_blobgasfee` tests in `execute remote` (#2266) * Fix storage slot of expected value Signed-off-by: Luis Mastrangelo * Fix test for `fill` mode Signed-off-by: Luis Mastrangelo * Apply reviewer's suggestion to rename parameter Signed-off-by: Luis Mastrangelo * Apply suggestion to use `SELFBALANCE` as result slot Signed-off-by: Luis Mastrangelo --------- Signed-off-by: Luis Mastrangelo --- cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py b/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py index 8fc048309b..0080477326 100644 --- a/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py +++ b/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py @@ -52,7 +52,7 @@ def caller_code( callee_address: Address, ) -> Bytecode: """Bytecode used to call the bytecode containing the BLOBBASEFEE opcode.""" - return Op.SSTORE(Op.NUMBER, Op.CALL(gas=call_gas, address=callee_address)) + return Op.SSTORE(Op.SELFBALANCE, Op.CALL(gas=call_gas, address=callee_address)) @pytest.fixture @@ -83,6 +83,7 @@ def tx(pre: Alloc, caller_address: Address) -> Transaction: sender=pre.fund_eoa(), gas_limit=1_000_000, to=caller_address, + value=1, ) From f8ed1858fd73a860e802039ac4a0f410fe3700d4 Mon Sep 17 00:00:00 2001 From: pdobacz <5735525+pdobacz@users.noreply.github.com> Date: Tue, 7 Oct 2025 15:54:38 +0200 Subject: [PATCH 092/102] feat(consume): `consume direct` using evmone-state and blockchaintest (#2243) * feat(consume): `consume direct` using evmone-statetest * feat(consume): `consume direct` using evmone-blockchaintest --- ethereum_clis/__init__.py | 9 +- ethereum_clis/clis/evmone.py | 246 ++++++++++++++++++++++++++++++++++- 2 files changed, 253 insertions(+), 2 deletions(-) diff --git a/ethereum_clis/__init__.py b/ethereum_clis/__init__.py index 6a21ab3c2e..6fffde82a9 100644 --- a/ethereum_clis/__init__.py +++ b/ethereum_clis/__init__.py @@ -12,7 +12,12 @@ ) from .clis.besu import BesuTransitionTool from .clis.ethereumjs import EthereumJSTransitionTool -from .clis.evmone import EvmoneExceptionMapper, EvmOneTransitionTool +from .clis.evmone import ( + EvmOneBlockchainFixtureConsumer, + EvmoneExceptionMapper, + EvmOneStateFixtureConsumer, + EvmOneTransitionTool, +) from .clis.execution_specs import ExecutionSpecsTransitionTool from .clis.geth import GethFixtureConsumer, GethTransitionTool from .clis.nethermind import Nethtest, NethtestFixtureConsumer @@ -31,6 +36,8 @@ "EthereumJSTransitionTool", "EvmoneExceptionMapper", "EvmOneTransitionTool", + "EvmOneStateFixtureConsumer", + "EvmOneBlockchainFixtureConsumer", "ExecutionSpecsTransitionTool", "FixtureConsumerTool", "GethFixtureConsumer", diff --git a/ethereum_clis/clis/evmone.py b/ethereum_clis/clis/evmone.py index e2f34f8fb0..fb59826ad1 100644 --- a/ethereum_clis/clis/evmone.py +++ b/ethereum_clis/clis/evmone.py @@ -1,15 +1,29 @@ """Evmone Transition tool interface.""" +import json import re +import shlex +import shutil +import subprocess +import tempfile +import textwrap +from functools import cache from pathlib import Path -from typing import ClassVar, Dict, Optional +from typing import Any, ClassVar, Dict, List, Optional +import pytest + +from ethereum_clis.file_utils import dump_files_to_directory +from ethereum_clis.fixture_consumer_tool import FixtureConsumerTool from ethereum_test_exceptions import ( EOFException, ExceptionBase, ExceptionMapper, TransactionException, ) +from ethereum_test_fixtures.base import FixtureFormat +from ethereum_test_fixtures.blockchain import BlockchainFixture +from ethereum_test_fixtures.state import StateFixture from ethereum_test_forks import Fork from ..transition_tool import TransitionTool @@ -43,6 +57,236 @@ def is_fork_supported(self, fork: Fork) -> bool: return True +class EvmoneFixtureConsumerCommon: + """Common functionality for Evmone fixture consumers.""" + + binary: Path + version_flag: str = "--version" + + cached_version: Optional[str] = None + + def __init__( + self, + trace: bool = False, + ): + """Initialize the EvmoneFixtureConsumerCommon class.""" + self._info_metadata: Optional[Dict[str, Any]] = {} + + def _run_command(self, command: List[str]) -> subprocess.CompletedProcess: + try: + return subprocess.run( + command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True + ) + except subprocess.CalledProcessError as e: + raise Exception("Command failed with non-zero status.") from e + except Exception as e: + raise Exception("Unexpected exception calling evm tool.") from e + + # TODO: copied from geth.py, needs to be deduplicated, but nethermind.py + # also has its version + def _consume_debug_dump( + self, + command: List[str], + result: subprocess.CompletedProcess, + fixture_path: Path, + debug_output_path: Path, + ): + # our assumption is that each command element is a string + assert all(isinstance(x, str) for x in command), ( + f"Not all elements of 'command' list are strings: {command}" + ) + assert len(command) > 0 + + # replace last value with debug fixture path + debug_fixture_path = str(debug_output_path / "fixtures.json") + command[-1] = debug_fixture_path + + # ensure that flags with spaces are wrapped in double-quotes + consume_direct_call = " ".join(shlex.quote(arg) for arg in command) + + consume_direct_script = textwrap.dedent( + f"""\ + #!/bin/bash + {consume_direct_call} + """ + ) + dump_files_to_directory( + str(debug_output_path), + { + "consume_direct_args.py": command, + "consume_direct_returncode.txt": result.returncode, + "consume_direct_stdout.txt": result.stdout, + "consume_direct_stderr.txt": result.stderr, + "consume_direct.sh+x": consume_direct_script, + }, + ) + shutil.copyfile(fixture_path, debug_fixture_path) + + def _skip_message(self, fixture_format: FixtureFormat) -> str: + return f"Fixture format {fixture_format.format_name} not supported by {self.binary}" + + @cache # noqa + def consume_test_file( + self, + fixture_path: Path, + debug_output_path: Optional[Path] = None, + ) -> Dict[str, Any]: + """ + Consume an entire state or blockchain test file. + + The `evmone-...test` will always execute all the tests contained in a + file without the possibility of selecting a single test, so this + function is cached in order to only call the command once and + `consume_test` can simply select the result that was requested. + """ + global_options: List[str] = [] + if debug_output_path: + global_options += ["--trace"] + + with tempfile.NamedTemporaryFile() as tempfile_json: + # `evmone` uses `gtest` and generates JSON output to a file, + # c.f. https://google.github.io/googletest/advanced.html#generating-a-json-report + # see there for the JSON schema. + global_options += ["--gtest_output=json:{}".format(tempfile_json.name)] + command = [str(self.binary)] + global_options + [str(fixture_path)] + result = self._run_command(command) + + if result.returncode not in [0, 1]: + raise Exception( + f"Unexpected exit code:\n{' '.join(command)}\n\n Error:\n{result.stderr}" + ) + + try: + output_data = json.load(tempfile_json) + except json.JSONDecodeError as e: + raise Exception( + f"Failed to parse JSON output from evmone-state/blockchaintest: {e}" + ) from e + + if debug_output_path: + self._consume_debug_dump(command, result, fixture_path, debug_output_path) + + return output_data + + def _failure_msg(self, file_results: Dict[str, Any]) -> str: + # Assumes only one test has run and there has been a failure, + # as asserted before. + failures = file_results["testsuites"][0]["testsuite"][0]["failures"] + return ", ".join([f["failure"] for f in failures]) + + def consume_test( + self, + fixture_path: Path, + fixture_name: Optional[str] = None, + debug_output_path: Optional[Path] = None, + ): + """ + Consume a single state or blockchain test. + + Uses the cached result from `consume_test_file` in order to not + call the command every time an select a single result from there. + """ + file_results = self.consume_test_file( + fixture_path=fixture_path, + debug_output_path=debug_output_path, + ) + if not fixture_name: + fixture_hint = fixture_path.stem + else: + fixture_hint = fixture_name + assert file_results["tests"] == 1, f"Multiple tests ran for {fixture_hint}" + assert file_results["disabled"] == 0, f"Disabled tests for {fixture_hint}" + assert file_results["errors"] == 0, f"Errors during test for {fixture_hint}" + assert file_results["failures"] == 0, ( + f"Failures for {fixture_hint}: {self._failure_msg(file_results)}" + ) + + test_name = file_results["testsuites"][0]["testsuite"][0]["name"] + assert test_name == fixture_path.stem, ( + f"Test name mismatch, expected {fixture_path.stem}, got {test_name}" + ) + + +class EvmOneStateFixtureConsumer( + EvmoneFixtureConsumerCommon, + FixtureConsumerTool, + fixture_formats=[StateFixture], +): + """Evmone's implementation of the fixture consumer for state tests.""" + + default_binary = Path("evmone-statetest") + detect_binary_pattern = re.compile(r"^evmone-statetest\b") + + def __init__( + self, + binary: Optional[Path] = None, + trace: bool = False, + ): + """Initialize the EvmOneStateFixtureConsumer class.""" + self.binary = binary if binary else self.default_binary + super().__init__(trace=trace) + + def consume_fixture( + self, + fixture_format: FixtureFormat, + fixture_path: Path, + fixture_name: Optional[str] = None, + debug_output_path: Optional[Path] = None, + ): + """ + Execute the appropriate fixture consumer for the fixture at + `fixture_path`. + """ + if fixture_format == StateFixture: + self.consume_test( + fixture_path=fixture_path, + fixture_name=fixture_name, + debug_output_path=debug_output_path, + ) + else: + pytest.skip(self._skip_message(fixture_format)) + + +class EvmOneBlockchainFixtureConsumer( + EvmoneFixtureConsumerCommon, + FixtureConsumerTool, + fixture_formats=[BlockchainFixture], +): + """Evmone's implementation of the fixture consumer for blockchain tests.""" + + default_binary = Path("evmone-blockchaintest") + detect_binary_pattern = re.compile(r"^evmone-blockchaintest\b") + + def __init__( + self, + binary: Optional[Path] = None, + trace: bool = False, + ): + """Initialize the EvmOneBlockchainFixtureConsumer class.""" + self.binary = binary if binary else self.default_binary + super().__init__(trace=trace) + + def consume_fixture( + self, + fixture_format: FixtureFormat, + fixture_path: Path, + fixture_name: Optional[str] = None, + debug_output_path: Optional[Path] = None, + ): + """ + Execute the appropriate fixture consumer for the fixture at + `fixture_path`. + """ + if fixture_format == BlockchainFixture: + self.consume_test( + fixture_path=fixture_path, + fixture_name=fixture_name, + debug_output_path=debug_output_path, + ) + else: + pytest.skip(self._skip_message(fixture_format)) + + class EvmoneExceptionMapper(ExceptionMapper): """ Translate between EEST exceptions and error strings returned by Evmone. From 98be2d631482e49ceae1607424f8f02243de829e Mon Sep 17 00:00:00 2001 From: Mercy Boma Naps Nkari <96525594+bomanaps@users.noreply.github.com> Date: Tue, 7 Oct 2025 18:34:07 +0100 Subject: [PATCH 093/102] feat(tests): port ethereum/tests swap opcode tests (#1163) * Port test for swap opcode * Swap-test-update * store_next_update * Storage update * Fix underflow test by reducing unnecessary stack pushes * Update uv.lock * Lint, add ported_from marker * Add more storage slots to improve coverage * Add coverage_missed_reason * Remove static test swapFiller.yml --------- Co-authored-by: kclowes --- frontier/opcodes/test_swap.py | 147 ++++ .../VMTests/vmTests/swapFiller.yml | 713 ------------------ 2 files changed, 147 insertions(+), 713 deletions(-) create mode 100644 frontier/opcodes/test_swap.py delete mode 100644 static/state_tests/VMTests/vmTests/swapFiller.yml diff --git a/frontier/opcodes/test_swap.py b/frontier/opcodes/test_swap.py new file mode 100644 index 0000000000..c6bde78a5d --- /dev/null +++ b/frontier/opcodes/test_swap.py @@ -0,0 +1,147 @@ +""" +A State test for the set of `SWAP*` opcodes. +Ported from: https://github.com/ethereum/tests/ +blob/develop/src/GeneralStateTestsFiller/VMTests/vmTests/swapFiller.yml. +""" + +import pytest # noqa: I001 + +from ethereum_test_forks import Fork, Frontier, Homestead +from ethereum_test_tools import Account, Alloc, Bytecode, Environment +from ethereum_test_tools import Opcodes as Op +from ethereum_test_tools import StateTestFiller, Storage, Transaction + + +@pytest.mark.ported_from( + [ + "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/VMTests/vmTests/swapFiller.yml" + ], + pr=["https://github.com/ethereum/execution-spec-tests/pull/1163"], + coverage_missed_reason=( + "Test isolation (1 contract per execution) reduces evmone state " + "comparisons vs old dispatcher pattern (16 contracts per execution)" + ), +) +@pytest.mark.parametrize( + "swap_opcode", + [getattr(Op, f"SWAP{i}") for i in range(1, 17)], + ids=lambda op: str(op), +) +@pytest.mark.valid_from("Frontier") +def test_swap(state_test: StateTestFiller, fork: Fork, pre: Alloc, swap_opcode: Op): + """ + The set of `SWAP*` opcodes swaps the top of the stack with a specific + element. + + In this test, we ensure that the set of `SWAP*` opcodes correctly swaps + the top element with the nth element and stores the result in storage. + """ + env = Environment() + + # Calculate which position we're swapping with (1-based index) + swap_pos = swap_opcode.int() - 0x90 + 1 + + # Generate stack values + stack_values = list(range(swap_pos + 16)) + + # Push the stack values onto the stack (in reverse order). + contract_code = Bytecode() + for value in reversed(stack_values): + contract_code += Op.PUSH1(value) + + # Perform the SWAP operation. + contract_code += swap_opcode + + # Store multiple values to storage. + for slot in range(16): + contract_code += Op.PUSH1(slot) + Op.SSTORE + + # Deploy the contract with the generated bytecode. + contract_address = pre.deploy_contract(contract_code) + + # Create a transaction to execute the contract. + tx = Transaction( + sender=pre.fund_eoa(), + to=contract_address, + gas_limit=500_000, + protected=False if fork in [Frontier, Homestead] else True, + ) + + # Calculate expected storage values after SWAP and storage operations + # Initial stack (after pushes, before swap): [0, 1, 2, ..., swap_pos+15] + # (top is index 0) + # After SWAP at position swap_pos: top and position swap_pos are swapped + # Then we do: PUSH1(slot) SSTORE 16 times, which pops values from stack + + # Build the stack state after SWAP + stack_after_swap = stack_values.copy() + stack_after_swap[0], stack_after_swap[swap_pos] = ( + stack_after_swap[swap_pos], + stack_after_swap[0], + ) + + # Store the first 16 values from the post-swap stack + storage = Storage() + for value in stack_after_swap[:16]: + storage.store_next(value) + + post = {contract_address: Account(storage=storage)} + + # Run the state test. + state_test(env=env, pre=pre, post=post, tx=tx) + + +@pytest.mark.parametrize( + "swap_opcode", + [getattr(Op, f"SWAP{i}") for i in range(1, 17)], + ids=lambda op: str(op), +) +@pytest.mark.valid_from("Frontier") +def test_stack_underflow( + state_test: StateTestFiller, + fork: Fork, + pre: Alloc, + swap_opcode: Op, +): + """ + A test to ensure that the stack underflow when there are not enough + elements for the `SWAP*` opcode to operate. + + For each SWAPn operation, we push exactly (n-1) elements to cause an + underflow when trying to swap with the nth element. + """ + env = Environment() + + # Calculate which position we're swapping with (1-based index) + swap_pos = swap_opcode.int() - 0x90 + 1 + + # Push exactly (n-1) elements for SWAPn to cause underflow + contract_code = Bytecode() + for i in range(swap_pos - 1): + contract_code += Op.PUSH1(i % 256) + + # Attempt to perform the SWAP operation + contract_code += swap_opcode + + # Store the top of the stack in storage slot 0 + contract_code += Op.PUSH1(0) + Op.SSTORE + + # Deploy the contract with the generated bytecode. + contract = pre.deploy_contract(contract_code) + + # Create a transaction to execute the contract. + tx = Transaction( + sender=pre.fund_eoa(), + to=contract, + gas_limit=500_000, + protected=False if fork in [Frontier, Homestead] else True, + ) + + # Define the expected post-state. + post = {} + storage = Storage() + storage.store_next(0, f"SWAP{swap_pos} failed due to stack underflow") + post[contract] = Account(storage=storage) + + # Run the state test. + state_test(env=env, pre=pre, post=post, tx=tx) diff --git a/static/state_tests/VMTests/vmTests/swapFiller.yml b/static/state_tests/VMTests/vmTests/swapFiller.yml deleted file mode 100644 index 209c69ecae..0000000000 --- a/static/state_tests/VMTests/vmTests/swapFiller.yml +++ /dev/null @@ -1,713 +0,0 @@ -# Check the various swap opcodes -# -# NOTE: The functionality of the old swap2errorFiller.json is available in -# GeneralStateTests/stStackTests/underflowTest. -# -# I fail to see the point of the old swapjump1 -# -# We can't use lll with SWAP, swap, or push (lll needs to manage the stack -# on its own). Instead, we do -# [1] PUSH1 0x00 -# [3] PUSH1 0x01 -# [5] PUSH1 0x02 -# . -# . -# . -# [31] PUSH1 0x0F -# [33] PUSH1 0x10 -# [34] **** OPCODE BEING TESTED -# [36] PUSH1 0x00 -# [37] SSTORE put stack top at @@0 -# [39] PUSH1 0x01 -# [40] SSTORE put next value down at @@1 -# . -# . -# . -# [78] PUSH1 0x0E -# [79] SSTORE -# [81] PUSH1 0x0F -# [82] SSTORE - -swap: - - env: - currentCoinbase: 2adc25665018aa1fe0e6bc666dac8fc2697ff9ba - currentDifficulty: 0x20000 - currentGasLimit: 100000000 - currentNumber: 1 - currentTimestamp: 1000 - - _info: - comment: Ori Pomerantz qbzzt1@gmail.com - - pre: - - # SWAP1 - 0000000000000000000000000000000000001000: - balance: '0x0ba1a9ce0ba1a9ce' - code: :raw 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601090600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP2 - 0000000000000000000000000000000000001001: - balance: '0x0ba1a9ce0ba1a9ce' - code: :raw 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601091600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP3 - 0000000000000000000000000000000000001002: - balance: '0x0ba1a9ce0ba1a9ce' - code: :raw 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601092600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP4 - 0000000000000000000000000000000000001003: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601093600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - - - # SWAP5 - 0000000000000000000000000000000000001004: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601094600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP6 - 0000000000000000000000000000000000001005: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601095600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP7 - 0000000000000000000000000000000000001006: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601096600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP8 - 0000000000000000000000000000000000001007: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601097600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - - - # SWAP9 - 0000000000000000000000000000000000001008: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601098600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP10 - 0000000000000000000000000000000000001009: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F601099600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP11 - 000000000000000000000000000000000000100A: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109A600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP12 - 000000000000000000000000000000000000100B: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109B600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - - - # SWAP13 - 000000000000000000000000000000000000100C: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109C600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP14 - 000000000000000000000000000000000000100D: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109D600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP15 - 000000000000000000000000000000000000100E: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109E600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - # SWAP16 - 000000000000000000000000000000000000100F: - balance: '0x0ba1a9ce0ba1a9ce' - code: 0x6000600160026003600460056006600760086009600A600B600C600D600E600F60109F600055600155600255600355600455600555600655600755600855600955600A55600B55600C55600D55600E55600F55 - # PUSH1 0x01 ... PUSH1 0x10@@ - # @@ is the opcode being tested - nonce: '0' - storage: {} - - - - - - - - - cccccccccccccccccccccccccccccccccccccccc: - balance: '0x0ba1a9ce0ba1a9ce' - code: | - { - (call (gas) (+ 0x1000 $4) 0 0 0 0 0) - } - nonce: '0' - storage: {} - - - a94f5374fce5edbc8e2a8697c15331677e6ebf0b: - balance: 0x100000000000 - code: '0x' - nonce: '0' - storage: {} - - - - - transaction: - data: - - :label swap1 :abi f(uint) 0 - - :label swap2 :abi f(uint) 1 - - :label swap3 :abi f(uint) 2 - - :label swap4 :abi f(uint) 3 - - :label swap5 :abi f(uint) 4 - - :label swap6 :abi f(uint) 5 - - :label swap7 :abi f(uint) 6 - - :label swap8 :abi f(uint) 7 - - :label swap9 :abi f(uint) 8 - - :label swap10 :abi f(uint) 9 - - :label swap11 :abi f(uint) 10 - - :label swap12 :abi f(uint) 11 - - :label swap13 :abi f(uint) 12 - - :label swap14 :abi f(uint) 13 - - :label swap15 :abi f(uint) 14 - - :label swap16 :abi f(uint) 15 - - gasLimit: - - '16777216' - gasPrice: '10' - nonce: '0' - to: cccccccccccccccccccccccccccccccccccccccc - value: - - '1' - secretKey: "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - - - expect: - - indexes: - data: :label swap1 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001000: - storage: - 0x00: 0x0F - 0x01: 0x10 - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - indexes: - data: :label swap2 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001001: - storage: - 0x00: 0x0E - 0x01: 0x0F - 0x02: 0x10 - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - indexes: - data: :label swap3 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001002: - storage: - 0x00: 0x0D - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x10 - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - indexes: - data: :label swap4 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001003: - storage: - 0x00: 0x0C - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x10 - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - - indexes: - data: :label swap5 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001004: - storage: - 0x00: 0x0B - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x10 - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - indexes: - data: :label swap6 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001005: - storage: - 0x00: 0x0A - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x10 - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - indexes: - data: :label swap7 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001006: - storage: - 0x00: 0x09 - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x10 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - indexes: - data: :label swap8 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001007: - storage: - 0x00: 0x08 - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x10 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - - indexes: - data: :label swap9 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001008: - storage: - 0x00: 0x07 - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x10 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - indexes: - data: :label swap10 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001009: - storage: - 0x00: 0x06 - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x10 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - indexes: - data: :label swap11 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 000000000000000000000000000000000000100A: - storage: - 0x00: 0x05 - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x10 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - indexes: - data: :label swap12 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 000000000000000000000000000000000000100B: - storage: - 0x00: 0x04 - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x10 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 - - - - - indexes: - data: :label swap13 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 000000000000000000000000000000000000100C: - storage: - 0x00: 0x03 - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x10 - 0x0E: 0x02 - 0x0F: 0x01 - - - - indexes: - data: :label swap14 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 000000000000000000000000000000000000100D: - storage: - 0x00: 0x02 - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x10 - 0x0F: 0x01 - - - - indexes: - data: :label swap15 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 000000000000000000000000000000000000100E: - storage: - 0x00: 0x01 - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x10 - - - - indexes: - data: :label swap16 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 000000000000000000000000000000000000100F: - storage: - 0x00: 0x00 - 0x01: 0x0F - 0x02: 0x0E - 0x03: 0x0D - 0x04: 0x0C - 0x05: 0x0B - 0x06: 0x0A - 0x07: 0x09 - 0x08: 0x08 - 0x09: 0x07 - 0x0A: 0x06 - 0x0B: 0x05 - 0x0C: 0x04 - 0x0D: 0x03 - 0x0E: 0x02 - 0x0F: 0x01 From 7f32108367d566750ccb94a92ab74cd910e4e31f Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Tue, 7 Oct 2025 23:42:11 +0200 Subject: [PATCH 094/102] feat(t8n): Support evmone's `--opcode.count` option (#1956) * Temp: Gather opcode counts in fixtures * feat(cli): Add diff_opcode_counts command * fix: Tox * fix imports * fix comments --- cli/diff_opcode_counts.py | 192 ++++++++++++++++++++++++++++++ ethereum_clis/cli_types.py | 38 +++++- ethereum_clis/clis/evmone.py | 1 + ethereum_clis/transition_tool.py | 23 ++++ ethereum_test_specs/base.py | 3 + ethereum_test_specs/blockchain.py | 14 +++ 6 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 cli/diff_opcode_counts.py diff --git a/cli/diff_opcode_counts.py b/cli/diff_opcode_counts.py new file mode 100644 index 0000000000..d33ce9f4bd --- /dev/null +++ b/cli/diff_opcode_counts.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +""" +Compare opcode counts between two folders of JSON fixtures. + +This script crawls two folders for JSON files, parses them using the Fixtures +model, and compares the opcode_count field from the info section between +fixtures with the same name. +""" + +import sys +from pathlib import Path +from typing import Dict, List, Optional + +import click + +from ethereum_clis.cli_types import OpcodeCount +from ethereum_test_fixtures.file import Fixtures + + +def find_json_files(directory: Path) -> List[Path]: + """Find all JSON files in a directory, excluding index.json files.""" + json_files = [] + if directory.is_dir(): + for file_path in directory.rglob("*.json"): + if file_path.name != "index.json": + json_files.append(file_path) + return json_files + + +def load_fixtures_from_file( + file_path: Path, remove_from_fixture_names: List[str] +) -> Optional[Fixtures]: + """Load fixtures from a JSON file using the Fixtures model.""" + try: + fixtures = Fixtures.model_validate_json(file_path.read_text()) + renames = [] + for k in fixtures.root: + new_name = None + for s in remove_from_fixture_names: + if s in k: + if new_name is None: + new_name = k.replace(s, "") + else: + new_name = new_name.replace(s, "") + if new_name is not None: + renames.append((k, new_name)) + for old_name, new_name in renames: + fixtures.root[new_name] = fixtures.root.pop(old_name) + return fixtures + except Exception as e: + print(f"Error loading {file_path}: {e}", file=sys.stderr) + return None + + +def extract_opcode_counts_from_fixtures(fixtures: Fixtures) -> Dict[str, OpcodeCount]: + """Extract opcode_count from info field for each fixture.""" + opcode_counts = {} + for fixture_name, fixture in fixtures.items(): + if hasattr(fixture, "info") and fixture.info and "opcode_count" in fixture.info: + try: + opcode_count = OpcodeCount.model_validate(fixture.info["opcode_count"]) + opcode_counts[fixture_name] = opcode_count + except Exception as e: + print(f"Error parsing opcode_count for {fixture_name}: {e}", file=sys.stderr) + return opcode_counts + + +def load_all_opcode_counts( + directory: Path, remove_from_fixture_names: List[str] +) -> Dict[str, OpcodeCount]: + """Load all opcode counts from all JSON files in a directory.""" + all_opcode_counts = {} + json_files = find_json_files(directory) + + for json_file in json_files: + fixtures = load_fixtures_from_file( + json_file, remove_from_fixture_names=remove_from_fixture_names + ) + if fixtures: + file_opcode_counts = extract_opcode_counts_from_fixtures(fixtures) + # Use fixture name as key, if there are conflicts, choose the last + all_opcode_counts.update(file_opcode_counts) + + return all_opcode_counts + + +def compare_opcode_counts(count1: OpcodeCount, count2: OpcodeCount) -> Dict[str, int]: + """Compare two opcode counts and return the differences.""" + differences = {} + + # Get all unique opcodes from both counts + all_opcodes = set(count1.root.keys()) | set(count2.root.keys()) + + for opcode in all_opcodes: + val1 = count1.root.get(opcode, 0) + val2 = count2.root.get(opcode, 0) + diff = val2 - val1 + if diff != 0: + differences[str(opcode)] = diff + + return differences + + +@click.command() +@click.argument("base", type=click.Path(exists=True, file_okay=False, path_type=Path)) +@click.argument("patch", type=click.Path(exists=True, file_okay=False, path_type=Path)) +@click.option( + "--show-common", + is_flag=True, + help="Print fixtures that contain identical opcode counts.", +) +@click.option( + "--show-missing", + is_flag=True, + help="Print fixtures only found in one of the folders.", +) +@click.option( + "--remove-from-fixture-names", + "-r", + multiple=True, + help="String to be removed from the fixture name, in case the fixture names have changed, " + "in order to make the comparison easier. " + "Can be specified multiple times.", +) +def main( + base: Path, + patch: Path, + show_common: bool, + show_missing: bool, + remove_from_fixture_names: List[str], +): + """Crawl two folders, compare and print the opcode count diffs.""" + print(f"Loading opcode counts from {base}...") + opcode_counts1 = load_all_opcode_counts(base, remove_from_fixture_names) + print(f"Found {len(opcode_counts1)} fixtures with opcode counts") + + print(f"Loading opcode counts from {patch}...") + opcode_counts2 = load_all_opcode_counts(patch, remove_from_fixture_names) + print(f"Found {len(opcode_counts2)} fixtures with opcode counts") + + # Find common fixture names + common_names = set(opcode_counts1.keys()) & set(opcode_counts2.keys()) + only_in_1 = set(opcode_counts1.keys()) - set(opcode_counts2.keys()) + only_in_2 = set(opcode_counts2.keys()) - set(opcode_counts1.keys()) + + print("\nSummary:") + print(f" Common fixtures: {len(common_names)}") + print(f" Only in {base.name}: {len(only_in_1)}") + print(f" Only in {patch.name}: {len(only_in_2)}") + + # Show missing fixtures if requested + if show_missing: + if only_in_1: + print(f"\nFixtures only in {base.name}:") + for name in sorted(only_in_1): + print(f" {name}") + + if only_in_2: + print(f"\nFixtures only in {patch.name}:") + for name in sorted(only_in_2): + print(f" {name}") + + # Compare common fixtures + differences_found = False + common_with_same_counts = 0 + + for fixture_name in sorted(common_names): + count1 = opcode_counts1[fixture_name] + count2 = opcode_counts2[fixture_name] + + differences = compare_opcode_counts(count1, count2) + + if differences: + differences_found = True + print(f"\n{fixture_name}:") + for opcode, diff in sorted(differences.items()): + if diff > 0: + print(f" +{diff} {opcode}") + else: + print(f" {diff} {opcode}") + elif show_common: + print(f"\n{fixture_name}: No differences") + common_with_same_counts += 1 + + if not differences_found: + print("\nNo differences found in opcode counts between common fixtures!") + elif show_common: + print(f"\n{common_with_same_counts} fixtures have identical opcode counts") + + +if __name__ == "__main__": + main() diff --git a/ethereum_clis/cli_types.py b/ethereum_clis/cli_types.py index d8745a1034..0cb8389239 100644 --- a/ethereum_clis/cli_types.py +++ b/ethereum_clis/cli_types.py @@ -4,7 +4,7 @@ from pathlib import Path from typing import Annotated, Any, Dict, List, Self -from pydantic import Field +from pydantic import Field, PlainSerializer, PlainValidator from ethereum_test_base_types import ( BlobSchedule, @@ -29,6 +29,7 @@ Transaction, TransactionReceipt, ) +from ethereum_test_vm import Opcode, Opcodes from pytest_plugins.custom_logging import get_logger logger = get_logger(__name__) @@ -175,6 +176,40 @@ def print(self): tx.print() +_opcode_synonyms = { + "KECCAK256": "SHA3", +} + + +def validate_opcode(obj: Any) -> Opcodes | Opcode: + """Validate an opcode from a string.""" + if isinstance(obj, Opcode) or isinstance(obj, Opcodes): + return obj + if isinstance(obj, str): + if obj in _opcode_synonyms: + obj = _opcode_synonyms[obj] + for op in Opcodes: + if str(op) == obj: + return op + raise Exception(f"Unable to validate {obj} (type={type(obj)})") + + +class OpcodeCount(EthereumTestRootModel): + """Opcode count returned from the evm tool.""" + + root: Dict[ + Annotated[Opcodes, PlainValidator(validate_opcode), PlainSerializer(lambda o: str(o))], int + ] + + def __add__(self, other: Self) -> Self: + """Add two instances of opcode count dictionaries.""" + assert isinstance(other, OpcodeCount), f"Incompatible type {type(other)}" + new_dict = self.model_dump() | other.model_dump() + for match_key in self.root.keys() & other.root.keys(): + new_dict[match_key] = self.root[match_key] + other.root[match_key] + return self.__class__(new_dict) + + class Result(CamelModel): """Result of a transition tool output.""" @@ -202,6 +237,7 @@ class Result(CamelModel): BlockExceptionWithMessage | UndefinedException | None, ExceptionMapperValidator ] = None traces: Traces | None = None + opcode_count: OpcodeCount | None = None class TransitionToolInput(CamelModel): diff --git a/ethereum_clis/clis/evmone.py b/ethereum_clis/clis/evmone.py index fb59826ad1..1cb71f9096 100644 --- a/ethereum_clis/clis/evmone.py +++ b/ethereum_clis/clis/evmone.py @@ -39,6 +39,7 @@ class EvmOneTransitionTool(TransitionTool): binary: Path cached_version: Optional[str] = None trace: bool + supports_opcode_count: ClassVar[bool] = True def __init__( self, diff --git a/ethereum_clis/transition_tool.py b/ethereum_clis/transition_tool.py index 41875d3750..f141f3ff70 100644 --- a/ethereum_clis/transition_tool.py +++ b/ethereum_clis/transition_tool.py @@ -25,6 +25,7 @@ from ethereum_test_types import Alloc, Environment, Transaction from .cli_types import ( + OpcodeCount, Traces, TransactionReceipt, TransactionTraces, @@ -71,6 +72,7 @@ class TransitionTool(EthereumCLI): t8n_use_server: bool = False server_url: str | None = None process: Optional[subprocess.Popen] = None + supports_opcode_count: ClassVar[bool] = False supports_xdist: ClassVar[bool] = True @@ -248,6 +250,13 @@ def _evaluate_filesystem( "--state.chainid", str(t8n_data.chain_id), ] + if self.supports_opcode_count: + args.extend( + [ + "--opcode.count", + "opcodes.json", + ] + ) if self.trace: args.append("--trace") @@ -308,6 +317,20 @@ def _evaluate_filesystem( output = TransitionToolOutput.model_validate( output_contents, context={"exception_mapper": self.exception_mapper} ) + if self.supports_opcode_count: + opcode_count_file_path = Path(temp_dir.name) / "opcodes.json" + if opcode_count_file_path.exists(): + opcode_count = OpcodeCount.model_validate_json(opcode_count_file_path.read_text()) + output.result.opcode_count = opcode_count + + if debug_output_path: + dump_files_to_directory( + debug_output_path, + { + "opcodes.json": opcode_count.model_dump(), + }, + ) + if self.trace: output.result.traces = self.collect_traces( output.result.receipts, temp_dir, debug_output_path diff --git a/ethereum_test_specs/base.py b/ethereum_test_specs/base.py index 3fee6ba4bc..c512028389 100644 --- a/ethereum_test_specs/base.py +++ b/ethereum_test_specs/base.py @@ -15,6 +15,7 @@ from typing_extensions import Self from ethereum_clis import Result, TransitionTool +from ethereum_clis.cli_types import OpcodeCount from ethereum_test_base_types import to_hex from ethereum_test_execution import BaseExecute, ExecuteFormat, LabeledExecuteFormat from ethereum_test_fixtures import ( @@ -75,6 +76,7 @@ class BaseTest(BaseModel): _operation_mode: OpMode | None = PrivateAttr(None) _gas_optimization: int | None = PrivateAttr(None) _gas_optimization_max_gas_limit: int | None = PrivateAttr(None) + _opcode_count: OpcodeCount | None = PrivateAttr(None) expected_benchmark_gas_used: int | None = None skip_gas_used_validation: bool = False @@ -130,6 +132,7 @@ def from_test( ) new_instance._request = base_test._request new_instance._operation_mode = base_test._operation_mode + new_instance._opcode_count = base_test._opcode_count return new_instance @classmethod diff --git a/ethereum_test_specs/blockchain.py b/ethereum_test_specs/blockchain.py index 65e6e882cd..6c250a649c 100644 --- a/ethereum_test_specs/blockchain.py +++ b/ethereum_test_specs/blockchain.py @@ -531,6 +531,12 @@ def generate_block_data( slow_request=self.is_tx_gas_heavy_test(), ) + if transition_tool_output.result.opcode_count is not None: + if self._opcode_count is None: + self._opcode_count = transition_tool_output.result.opcode_count + else: + self._opcode_count += transition_tool_output.result.opcode_count + # One special case of the invalid transactions is the blob gas used, # since this value is not included in the transition tool result, but # it is included in the block header, and some clients check it before @@ -746,6 +752,9 @@ def make_fixture( ) self.check_exception_test(exception=invalid_blocks > 0) self.verify_post_state(t8n, t8n_state=alloc) + info = {} + if self._opcode_count is not None: + info["opcode_count"] = self._opcode_count.model_dump() return BlockchainFixture( fork=fork, genesis=genesis.header, @@ -760,6 +769,7 @@ def make_fixture( blob_schedule=FixtureBlobSchedule.from_blob_schedule(fork.blob_schedule()), chain_id=self.chain_id, ), + info=info, ) def make_hive_fixture( @@ -812,6 +822,9 @@ def make_hive_fixture( self.verify_post_state(t8n, t8n_state=alloc) # Create base fixture data, common to all fixture formats + info = {} + if self._opcode_count is not None: + info["opcode_count"] = self._opcode_count.model_dump() fixture_data = { "fork": fork, "genesis": genesis.header, @@ -825,6 +838,7 @@ def make_hive_fixture( chain_id=self.chain_id, blob_schedule=FixtureBlobSchedule.from_blob_schedule(fork.blob_schedule()), ), + "info": info, } # Add format-specific fields From 083244a25defa23acc75299d62864940bf1e87ef Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Wed, 8 Oct 2025 00:23:15 +0200 Subject: [PATCH 095/102] feat(cli): Blocktest builder (#2190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial commit * Some refactoring * Add batch mode * Support blob gas fields in genesis * Don't default to gasPrice=1 to not error on blob tx * Fix setcodetx translation * Parallelize * Per file progress meter * Fix auth translation * refactor(fuzzer-bridge): address PR feedback and improve architecture - Remove incorrect venv activation instructions from CLAUDE.md - Replace ASCII art with Mermaid diagram in README - Add fuzzer_bridge as CLI entry point in pyproject.toml - Create comprehensive documentation in docs/writing_tests/ - Add Pydantic models for type-safe fuzzer output parsing - Add BlockchainTest.from_fuzzer() classmethod for better integration - Simplify BlocktestBuilder to use new architecture - Fix README inconsistencies (punctuation, references, sections) This refactoring aligns the fuzzer bridge with EEST code standards and makes it more maintainable and future-proof. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * fix(fuzzer-bridge): apply linting and formatting fixes - Add ruff noqa comment for mixedCase variables in Pydantic models - Fix line length issues in performance_utils.py - Replace bare except with specific Exception handling - Apply automated formatting from ruff 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * fix: resolve CI errors for linting, formatting, and type checking - Fix markdown linting errors in fuzzer_bridge.md documentation - Apply ruff formatting to blockchain.py - Fix mypy type errors in fuzzer bridge modules: - Make orjson import optional with proper error handling - Fix TransitionTool instantiation to use GethTransitionTool - Correct EOA usage and add missing class attributes - Fix json.dump parameter usage to avoid kwargs issues - Fix docstring line lengths to comply with 79-char limit - Fix line length issues in function signatures All linting (ruff) and type checking (mypy) now pass successfully. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * Fix docs link * feat(fuzzer_bridge): add EIP-7702 and EIP-4788 support Add support for two critical Ethereum features in the fuzzer bridge: 1. EIP-7702 Authorization Lists (Prague+) - Add FuzzerAuthorization model for authorization tuples - Parse authorizationList from transactions - Translate to AuthorizationTuple in from_fuzzer() - Enables testing of SetCode transactions (tx type 0x04) 2. EIP-4788 Parent Beacon Block Root (Cancun+) - Add parentBeaconBlockRoot as top-level field in FuzzerOutput - Pass to Block during creation in from_fuzzer() - Must be 32-byte hash from consensus layer - Enables testing of beacon root contract (EIP-4788) These changes close significant coverage gaps in geth core validation: - tx_setcode.go: Authorization validation paths - block_validator.go: Beacon root handling - state_transition.go: Beacon root system contract calls The implementation follows existing patterns (similar to blob sidecar handling) and maintains backwards compatibility through optional fields. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * feat(fuzzer-bridge): add multi-block blockchain test generation Add support for splitting fuzzer transactions across multiple blocks to enable testing of state transitions and block boundaries. New CLI Options: - --num-blocks: Number of blocks to generate (default: 1) - --block-strategy: Transaction distribution strategy - "distribute": Sequential chunks preserving nonce order - "first-block": All txs in first block, rest empty - --block-time: Seconds between blocks (default: 12) Implementation: - Sequential distribution maintains nonce ordering per account - Timestamps increment by block_time for each block - Only first block receives parent_beacon_block_root - Fully backward compatible (single-block default) Example Usage: fuzzer_bridge --num-blocks 3 --block-strategy distribute \ --fork Osaka input.json output/ This enables testing multi-block scenarios like: - State evolution across blocks - Transaction dependencies spanning blocks - Block time-sensitive operations - Cross-block state transitions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * feat(fuzzer-bridge): add random block count selection Add --random-blocks flag to enable intelligent automatic selection of block counts for comprehensive testing coverage. New Feature: - --random-blocks: Randomly choose number of blocks (1 to min(num_txs, 10)) Implementation: - choose_random_num_blocks() helper with uniform distribution - Each file gets independent random selection in parallel mode - Edge case handling: empty blocks (0 txs → 1 block) - Cap at 10 blocks to prevent fixture bloat with large tx counts Algorithm Rationale: - Uniform distribution provides equal coverage for testing - Max of 10 blocks balances thoroughness with practicality - Independent per-file randomization maximizes corpus diversity Example Usage: # Random mode - each file gets random block count fuzzer_bridge --random-blocks --fork Osaka input/ output/ # Still works with fixed mode fuzzer_bridge --num-blocks 3 --fork Osaka input/ output/ Benefits: - Automated testing of various block configurations - Discovers edge cases in block boundary handling - Comprehensive multi-block scenario coverage - Zero configuration needed for random testing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * Add batch mode for improved perf * test(fuzzer-bridge): add comprehensive test suite with DTO pattern Implements complete testing infrastructure for fuzzer bridge with 25 comprehensive tests achieving 98% code coverage on core modules. Changes: - Add test_fuzzer_bridge.py with 25 tests covering DTO parsing, conversion, BlockchainTest generation, EIP features, and error handling - Refactor models.py to use DTO pattern with clean separation between external JSON-RPC format and internal EEST domain models - Create converter.py module with pure transformation functions (eliminates circular dependencies from blockchain.py) - Add 5 test vectors from real fuzzer outputs (Osaka fork, EIP-7702, EIP-4788) - Update README with comprehensive DTO architecture documentation including Mermaid diagram, field mappings, and design rationale - Simplify blocktest_builder.py by delegating conversion to converter module - Update examples with current fuzzer outputs and detailed README Architecture: - DTOs (models.py): Parse external format without side effects - Converters (converter.py): Explicit field transformations - Domain Models (EEST): Internal business logic with validation - Benefits: 98% test coverage, no circular dependencies, explicit mappings, prevents TestAddress pollution Test Coverage: - 25 tests pass in 0.46s - models.py: 100% coverage - converter.py: 97% coverage - Core modules combined: 98% coverage Key Features Tested: - EIP-7702 authorization lists - EIP-4788 parent beacon block root - Multi-block generation strategies - EOA creation from private keys - Field mapping (gas → gas_limit, from → sender) - Error handling and validation All quality checks pass: - Linting: ✓ (ruff check, format, W505) - Type checking: ✓ (mypy) - All CLI tests: ✓ (256/256 pass, no regressions) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --------- Co-authored-by: Claude --- cli/fuzzer_bridge/README.md | 301 +++++++ cli/fuzzer_bridge/__init__.py | 5 + cli/fuzzer_bridge/blocktest_builder.py | 90 +++ cli/fuzzer_bridge/cli.py | 752 ++++++++++++++++++ cli/fuzzer_bridge/converter.py | 308 +++++++ cli/fuzzer_bridge/examples/README.md | 143 ++++ .../examples/comprehensive_large.json | 421 ++++++++++ .../examples/comprehensive_largest.json | 491 ++++++++++++ .../examples/comprehensive_medium_1.json | 448 +++++++++++ .../examples/comprehensive_medium_2.json | 433 ++++++++++ .../examples/comprehensive_smallest.json | 444 +++++++++++ cli/fuzzer_bridge/models.py | 121 +++ cli/fuzzer_bridge/performance_utils.py | 153 ++++ cli/fuzzer_bridge/production_test.py | 364 +++++++++ cli/tests/test_fuzzer_bridge.py | 421 ++++++++++ cli/tests/vectors/fuzzer_test_0.json | 456 +++++++++++ cli/tests/vectors/fuzzer_test_1.json | 497 ++++++++++++ cli/tests/vectors/fuzzer_test_2.json | 440 ++++++++++ cli/tests/vectors/fuzzer_test_3.json | 451 +++++++++++ cli/tests/vectors/fuzzer_test_4.json | 427 ++++++++++ 20 files changed, 7166 insertions(+) create mode 100644 cli/fuzzer_bridge/README.md create mode 100644 cli/fuzzer_bridge/__init__.py create mode 100644 cli/fuzzer_bridge/blocktest_builder.py create mode 100644 cli/fuzzer_bridge/cli.py create mode 100644 cli/fuzzer_bridge/converter.py create mode 100644 cli/fuzzer_bridge/examples/README.md create mode 100644 cli/fuzzer_bridge/examples/comprehensive_large.json create mode 100644 cli/fuzzer_bridge/examples/comprehensive_largest.json create mode 100644 cli/fuzzer_bridge/examples/comprehensive_medium_1.json create mode 100644 cli/fuzzer_bridge/examples/comprehensive_medium_2.json create mode 100644 cli/fuzzer_bridge/examples/comprehensive_smallest.json create mode 100644 cli/fuzzer_bridge/models.py create mode 100644 cli/fuzzer_bridge/performance_utils.py create mode 100644 cli/fuzzer_bridge/production_test.py create mode 100644 cli/tests/test_fuzzer_bridge.py create mode 100644 cli/tests/vectors/fuzzer_test_0.json create mode 100644 cli/tests/vectors/fuzzer_test_1.json create mode 100644 cli/tests/vectors/fuzzer_test_2.json create mode 100644 cli/tests/vectors/fuzzer_test_3.json create mode 100644 cli/tests/vectors/fuzzer_test_4.json diff --git a/cli/fuzzer_bridge/README.md b/cli/fuzzer_bridge/README.md new file mode 100644 index 0000000000..6f54cce908 --- /dev/null +++ b/cli/fuzzer_bridge/README.md @@ -0,0 +1,301 @@ +# Fuzzer Bridge for Execution Spec Tests + +This module provides a bridge between blocktest fuzzers (like `blocktest-fuzzer`) and the Ethereum execution-spec-tests framework, enabling automatic generation of valid blockchain test fixtures from fuzzer output. + +## Overview + +The fuzzer bridge solves a critical problem: fuzzers can generate transactions and pre-state, but creating valid blockchain tests requires complex calculations (state roots, RLP encoding, block headers, etc.). This bridge leverages the execution-spec-tests framework to handle all these complexities. + +## Architecture + +```mermaid +graph LR + A[Blocktest
Fuzzer] -->|JSON
v2 format| B[Fuzzer
Bridge] + B -->|Blockchain Test
Fixtures| C[Ethereum
Clients] +``` + +## Fuzzer Output Format (v2) + +The fuzzer must output JSON in the following format: + +```json +{ + "version": "2.0", + "fork": "Prague", + "chainId": 1, + "accounts": { + "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf": { + "balance": "0x1000000000000000000", + "nonce": "0x0", + "code": "", + "storage": {}, + "privateKey": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "0x2b5ad5c4795c026514f8317c7a215e218dccd6cf": { + "balance": "0x100000000000000000", + "nonce": "0x0", + "code": "0x600160005260206000f3", + "storage": {} + } + }, + "transactions": [ + { + "from": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf", + "to": "0x2b5ad5c4795c026514f8317c7a215e218dccd6cf", + "value": "0x100", + "gas": "0x5208", + "gasPrice": "0x7", + "nonce": "0x0", + "data": "0x" + } + ], + "env": { + "currentCoinbase": "0xc014ba5e00000000000000000000000000000000", + "currentDifficulty": "0x0", + "currentGasLimit": "0x1000000", + "currentNumber": "0x1", + "currentTimestamp": "0x1000", + "currentBaseFee": "0x7", + "currentRandom": "0x0000000000000000000000000000000000000000000000000000000000000000" + } +} +``` + +### Key Requirements + +1. **Private Keys**: Any account that sends transactions MUST include a `privateKey` field. +2. **Address-Key Match**: Private keys must generate the corresponding addresses. +3. **Environment**: Describes the environment for block 1 (genesis is automatically derived). +4. **Version**: Use "2.0" for this format. + +## Architecture: DTO Pattern + +The fuzzer bridge uses a **Data Transfer Object (DTO) pattern** for clean separation between external data format and internal domain logic. + +### Design Flow + +```mermaid +graph TD + A["Fuzzer JSON Output
(JSON-RPC Format v2.0)"] + + B["DTOs (Pydantic Models)
models.py"] + B1["FuzzerAccountInput
Raw account JSON"] + B2["FuzzerTransactionInput
Raw transaction JSON (uses 'gas')"] + B3["FuzzerAuthorizationInput
Raw auth tuple (EIP-7702)"] + B4["FuzzerOutput
Complete fuzzer output"] + + C["EEST Domain Models
converter.py"] + C1["Account
With validation & defaults"] + C2["Transaction
With gas_limit, EOA sender"] + C3["AuthorizationTuple
EIP-7702 support"] + C4["EOA
Created from private keys"] + + D["BlockchainTest"] + E["Blockchain Fixture"] + + A -->|parse| B + B -.-> B1 + B -.-> B2 + B -.-> B3 + B -.-> B4 + + B -->|convert| C + C -.-> C1 + C -.-> C2 + C -.-> C3 + C -.-> C4 + + C -->|generate| D + D --> E + + style A fill:#e1f5ff + style B fill:#fff4e1 + style C fill:#e8f5e9 + style D fill:#f3e5f5 + style E fill:#fce4ec +``` + +### Why DTOs? + +1. **Separation of Concerns** + - External JSON-RPC format ≠ EEST internal representation + - Fuzzer format can change without affecting EEST domain models + +2. **No Side Effects During Parsing** + - DTOs don't trigger `model_post_init` validation logic + - Parsing is purely data extraction, no business logic + +3. **Explicit Field Mapping** + - Clear visibility: `gas` → `gas_limit`, `from` → `sender` (EOA) + - Type-safe conversions at boundary + +4. **Prevents TestAddress Pollution** + - EOA created in converter BEFORE Transaction instantiation + - Transaction.model_post_init never injects TestAddress + +### Key Field Mappings + +| Fuzzer Field (JSON-RPC) | DTO Field | EEST Domain Field | Notes | +|-------------------------|----------------------|----------------------|--------------------------------| +| `from` | `from_` | `sender` (EOA) | Creates EOA from private key | +| `gas` | `gas` | `gas_limit` | JSON-RPC vs internal naming | +| `data` | `data` | `data` | Same field, explicit mapping | +| `gasPrice` | `gas_price` | `gas_price` | CamelCase → snake_case | +| `authorizationList` | `authorization_list` | `authorization_list` | EIP-7702 support | +| `privateKey` | `private_key` | (used to create EOA) | Not stored in Account model | + +### Module Responsibilities + +#### `models.py` - Data Transfer Objects +- Pure Pydantic models for fuzzer JSON format +- No business logic, only data validation +- Accepts JSON-RPC naming conventions (camelCase) +- ~119 lines + +#### `converter.py` - Transformation Logic +- Pure functions: DTO → EEST domain models +- All field mapping logic centralized here +- Creates EOA objects from private keys +- Builds BlockchainTest from validated data +- ~305 lines + +#### `blocktest_builder.py` - CLI Integration +- Orchestrates conversion workflow +- Handles file I/O and CLI options +- Calls converter functions +- ~90 lines + +### Benefits + +✅ **Maintainability**: Changes to Account/Transaction propagate automatically +✅ **Testability**: Each layer tested independently +✅ **Type Safety**: Full type checking at DTO and domain layers +✅ **Clarity**: Field mappings are explicit and documented +✅ **No Circular Dependencies**: Clean module boundaries + +### Alternative Design: Why Not Inheritance? + +**Could have done**: +```python +class FuzzerAccount(Account): + private_key: Hash | None = None +``` + +**Why DTOs are better**: +- Inheritance couples external format to domain model +- model_post_init triggers during parsing (side effects) +- Field name mismatches require complex aliasing +- Harder to test layers independently + +The DTO pattern provides cleaner separation and explicit control. + +## Installation + +See the [EEST installation guide](https://eest.ethereum.org/main/getting_started/installation/) for setting up the execution-spec-tests framework. + +Once EEST is installed, the fuzzer bridge will be available as a command-line tool. + +## Usage + +### 1. Command Line Interface + +```bash +# Convert fuzzer output to blockchain test +uv run fuzzer_bridge --input fuzzer_output.json --output blocktest.json + +# With custom fork +uv run fuzzer_bridge --input fuzzer_output.json --output blocktest.json --fork Shanghai + +# Pretty print output +uv run fuzzer_bridge --input fuzzer_output.json --output blocktest.json --pretty +``` + +### 2. Python API + +```python +from fuzzer_bridge import FuzzerBridge + +# Load fuzzer output +with open("fuzzer_output.json") as f: + fuzzer_data = json.load(f) + +# Create bridge and convert +bridge = FuzzerBridge() +blocktest = bridge.convert(fuzzer_data) + +# Save to file +bridge.save(blocktest, "output.json") + +# Or verify with geth directly +result = bridge.verify_with_geth(blocktest, geth_path="../go-ethereum/build/bin/evm") +print(f"Test passed: {result['pass']}") +``` + +### 3. Integration with pytest + +```python +import pytest +from fuzzer_bridge import create_test_from_fuzzer + +def test_fuzzer_generated(blockchain_test): + """Test generated from fuzzer output.""" + test = create_test_from_fuzzer("fuzzer_output.json") + blockchain_test(**test) +``` + +## Key Insights + +### Genesis Block Handling +- The fuzzer describes the environment for block 1 (the block being tested) +- Genesis (block 0) environment is automatically derived: + - `number` = 0 + - `timestamp` = block1_timestamp - 12 + - Other values inherited or set to defaults + +### System Contracts +- The framework automatically adds system contracts (deposit, withdrawal, etc.) +- These are included in the state root calculation +- The fuzzer doesn't need to specify them + +### Private Key Requirements +- Every account that sends transactions needs a private key +- The private key must generate the exact address specified +- Without matching private keys, transactions cannot be signed + +## Troubleshooting + +### "Genesis block hash doesn't match" +**Cause**: Usually means the environment is set incorrectly (e.g., block number = 1 instead of 0 for genesis) +**Solution**: Ensure the fuzzer output follows the v2 format exactly + +### "No private key for sender" +**Cause**: Account sends transaction but no privateKey field provided +**Solution**: Add privateKey to the account in the accounts section + +### "Private key doesn't match address" +**Cause**: The provided private key doesn't generate the specified address +**Solution**: Use correct private key or generate address from private key + +## Testing with Ethereum Clients + +### Go-Ethereum (geth) +```bash +../go-ethereum/build/bin/evm blocktest generated_test.json +``` + +### Besu +```bash +../besu/ethereum/evmtool/build/install/evmtool/bin/evmtool block-test generated_test.json +``` + +### Nethermind +```bash +../nethermind/src/Nethermind/artifacts/bin/Nethermind.Test.Runner/release_linux-x64/nethtest -b -i generated_test.json +``` + +## Contributing + +When modifying the fuzzer bridge: +1. Add tests for new features. +2. Update this README. +3. Ensure compatibility with latest execution-spec-tests. \ No newline at end of file diff --git a/cli/fuzzer_bridge/__init__.py b/cli/fuzzer_bridge/__init__.py new file mode 100644 index 0000000000..14ef2a3cd2 --- /dev/null +++ b/cli/fuzzer_bridge/__init__.py @@ -0,0 +1,5 @@ +"""Fuzzer bridge for converting blocktest-fuzzer output to blocktests.""" + +from .blocktest_builder import BlocktestBuilder, build_blocktest_from_fuzzer + +__all__ = ["BlocktestBuilder", "build_blocktest_from_fuzzer"] diff --git a/cli/fuzzer_bridge/blocktest_builder.py b/cli/fuzzer_bridge/blocktest_builder.py new file mode 100644 index 0000000000..c2b832d09e --- /dev/null +++ b/cli/fuzzer_bridge/blocktest_builder.py @@ -0,0 +1,90 @@ +"""Build valid blocktests from fuzzer-generated transactions and pre-state.""" + +import json +import random +from pathlib import Path +from typing import Any, Dict, Optional + +from ethereum_clis import GethTransitionTool, TransitionTool +from ethereum_test_fixtures import BlockchainFixture + +from .converter import blockchain_test_from_fuzzer +from .models import FuzzerOutput + + +def choose_random_num_blocks(num_txs: int, max_blocks: int = 10) -> int: + """ + Choose random number of blocks for given transaction count. + + Selects a random number between 1 and min(num_txs, max_blocks) to enable + testing of various block configurations. + + Args: + num_txs: Number of transactions to distribute + max_blocks: Maximum number of blocks (default: 10) + + Returns: + Random integer between 1 and min(num_txs, max_blocks) + + """ + if num_txs == 0: + return 1 # Allow empty block testing + return random.randint(1, min(num_txs, max_blocks)) + + +class BlocktestBuilder: + """Build valid blocktests from fuzzer-generated transactions.""" + + def __init__(self, transition_tool: Optional[TransitionTool] = None): + """Initialize the builder with optional transition tool.""" + self.t8n = transition_tool or GethTransitionTool() + + def build_blocktest( + self, + fuzzer_output: Dict[str, Any], + num_blocks: int = 1, + block_strategy: str = "distribute", + block_time: int = 12, + ) -> Dict[str, Any]: + """Build a valid blocktest from fuzzer output.""" + # Parse and validate using Pydantic model + fuzzer_data = FuzzerOutput(**fuzzer_output) + + # Get fork + fork = fuzzer_data.fork + + # Create BlockchainTest using converter + test = blockchain_test_from_fuzzer( + fuzzer_data, + fork, + num_blocks=num_blocks, + block_strategy=block_strategy, + block_time=block_time, + ) + + # Generate fixture + fixture = test.generate( + t8n=self.t8n, + fork=fork, + fixture_format=BlockchainFixture, + ) + + return fixture.model_dump(exclude_none=True, by_alias=True, mode="json") + + def build_and_save(self, fuzzer_output: Dict[str, Any], output_path: Path) -> Path: + """Build blocktest and save to file.""" + blocktest = self.build_blocktest(fuzzer_output) + fixtures = {"fuzzer_generated_test": blocktest} + + with open(output_path, "w") as f: + json.dump(fixtures, f, indent=2) + + return output_path + + +def build_blocktest_from_fuzzer( + fuzzer_data: Dict[str, Any], t8n: Optional[TransitionTool] = None +) -> Dict[str, Any]: + """Build blocktest from fuzzer output.""" + builder = BlocktestBuilder(t8n) + return builder.build_blocktest(fuzzer_data) diff --git a/cli/fuzzer_bridge/cli.py b/cli/fuzzer_bridge/cli.py new file mode 100644 index 0000000000..37b700c7f2 --- /dev/null +++ b/cli/fuzzer_bridge/cli.py @@ -0,0 +1,752 @@ +"""Command-line interface for the fuzzer bridge.""" + +import json +import multiprocessing as mp +from concurrent.futures import ProcessPoolExecutor, as_completed +from functools import partial +from pathlib import Path +from typing import Any, Dict, Generator, Optional, Tuple + +import click +from rich.progress import BarColumn, Progress, TaskProgressColumn, TextColumn, TimeElapsedColumn + +from ethereum_clis import GethTransitionTool, TransitionTool + +from .blocktest_builder import BlocktestBuilder + + +def count_json_files(start_path: Path) -> int: + """Count JSON files in directory.""" + return sum(1 for _ in start_path.rglob("*.json")) + + +def get_input_files(input_path: Path) -> Generator[Path, None, None]: + """Generate input file paths.""" + if input_path.is_file(): + yield input_path + else: + yield from input_path.rglob("*.json") + + +def generate_test_name(file_path: Path, index: int = 0) -> str: + """Generate unique test name from file path.""" + stem = file_path.stem + if index > 0: + return f"fuzzer_{stem}_{index}" + return f"fuzzer_{stem}" + + +def process_single_file( + input_file: Path, + output_path: Path, + builder: BlocktestBuilder, + fork: Optional[str], + pretty: bool, + quiet: bool, + num_blocks: int = 1, + block_strategy: str = "distribute", + block_time: int = 12, + random_blocks: bool = False, +) -> Dict[str, Any]: + """Process a single fuzzer output file.""" + with open(input_file) as f: + fuzzer_data = json.load(f) + + # Override fork if specified + if fork: + fuzzer_data["fork"] = fork + + # Determine number of blocks + if random_blocks: + from .blocktest_builder import choose_random_num_blocks + + actual_num_blocks = choose_random_num_blocks(len(fuzzer_data.get("transactions", []))) + else: + actual_num_blocks = num_blocks + + # Build blocktest + blocktest = builder.build_blocktest( + fuzzer_data, + num_blocks=actual_num_blocks, + block_strategy=block_strategy, + block_time=block_time, + ) + test_name = generate_test_name(input_file) + fixtures = {test_name: blocktest} + + # Write output + output_file = output_path / f"{input_file.stem}.json" + with open(output_file, "w") as f: + if pretty: + json.dump(fixtures, f, indent=2) + else: + json.dump(fixtures, f) + + if not quiet: + click.echo(f"Generated: {output_file}", err=True) + + return fixtures + + +def process_single_file_worker( + file_info: Tuple[Path, Path], + fork: Optional[str], + pretty: bool, + merge: bool, + evm_bin: Optional[Path], + num_blocks: int = 1, + block_strategy: str = "distribute", + block_time: int = 12, + random_blocks: bool = False, +) -> Tuple[Optional[Tuple[Path, Dict[str, Any]]], Optional[Tuple[Path, Exception]]]: + """Process a single file in a worker process.""" + json_file_path, output_file = file_info + + # Create transition tool and builder for this worker + t8n = GethTransitionTool(binary=evm_bin) if evm_bin else GethTransitionTool() + builder = BlocktestBuilder(t8n) + + try: + with open(json_file_path) as f: + fuzzer_data = json.load(f) + + # Override fork if specified + if fork: + fuzzer_data["fork"] = fork + + # Determine number of blocks + if random_blocks: + from .blocktest_builder import choose_random_num_blocks + + actual_num_blocks = choose_random_num_blocks(len(fuzzer_data.get("transactions", []))) + else: + actual_num_blocks = num_blocks + + # Build blocktest + blocktest = builder.build_blocktest( + fuzzer_data, + num_blocks=actual_num_blocks, + block_strategy=block_strategy, + block_time=block_time, + ) + test_name = generate_test_name(json_file_path) + fixtures = {test_name: blocktest} + + if not merge: + # Write individual file preserving structure + output_file.parent.mkdir(parents=True, exist_ok=True) + with open(output_file, "w") as f: + if pretty: + json.dump(fixtures, f, indent=2) + else: + json.dump(fixtures, f) + + return (json_file_path, fixtures), None + except Exception as e: + return None, (json_file_path, e) + + +def process_file_batch( + file_batch: list[Tuple[Path, Path]], + fork: Optional[str], + pretty: bool, + merge: bool, + evm_bin: Optional[Path], + num_blocks: int = 1, + block_strategy: str = "distribute", + block_time: int = 12, + random_blocks: bool = False, +) -> Tuple[list[Tuple[Path, Dict[str, Any]]], list[Tuple[Path, Exception]]]: + """Process a batch of files in a worker process.""" + # Create transition tool per worker + t8n = GethTransitionTool(binary=evm_bin) if evm_bin else GethTransitionTool() + builder = BlocktestBuilder(t8n) + + results = [] + errors = [] + + for json_file_path, rel_path in file_batch: + try: + with open(json_file_path) as f: + fuzzer_data = json.load(f) + + # Override fork if specified + if fork: + fuzzer_data["fork"] = fork + + # Determine number of blocks + if random_blocks: + from .blocktest_builder import choose_random_num_blocks + + actual_num_blocks = choose_random_num_blocks( + len(fuzzer_data.get("transactions", [])) + ) + else: + actual_num_blocks = num_blocks + + # Build blocktest + blocktest = builder.build_blocktest( + fuzzer_data, + num_blocks=actual_num_blocks, + block_strategy=block_strategy, + block_time=block_time, + ) + test_name = generate_test_name(json_file_path) + fixtures = {test_name: blocktest} + + if not merge: + # Write individual file preserving structure + output_file = rel_path.with_suffix(".json") + output_file.parent.mkdir(parents=True, exist_ok=True) + with open(output_file, "w") as f: + if pretty: + json.dump(fixtures, f, indent=2) + else: + json.dump(fixtures, f) + + results.append((json_file_path, fixtures)) + except Exception as e: + errors.append((json_file_path, e)) + + return results, errors + + +def process_directory_parallel( + input_dir: Path, + output_dir: Path, + fork: Optional[str], + pretty: bool, + merge: bool, + quiet: bool, + evm_bin: Optional[Path], + num_workers: Optional[int] = None, + num_blocks: int = 1, + block_strategy: str = "distribute", + block_time: int = 12, + random_blocks: bool = False, +): + """Process directory of fuzzer output files with parallel processing.""" + all_fixtures = {} + + # Collect all files to process + files_to_process = [] + for json_file_path in get_input_files(input_dir): + rel_path = json_file_path.relative_to(input_dir) + output_file = output_dir / rel_path + files_to_process.append((json_file_path, output_file)) + + file_count = len(files_to_process) + if file_count == 0: + if not quiet: + click.echo("No JSON files found to process.", err=True) + return + + # Determine optimal number of workers + if num_workers is None: + num_workers = min(mp.cpu_count(), max(1, file_count // 10)) + + success_count = 0 + error_count = 0 + + with Progress( + TextColumn("[bold cyan]{task.fields[filename]}", justify="left"), + BarColumn(bar_width=None, complete_style="green3", finished_style="bold green3"), + TaskProgressColumn(), + TextColumn("[dim]({task.fields[workers]} workers)[/dim]"), + TimeElapsedColumn(), + expand=True, + disable=quiet, + ) as progress: + task_id = progress.add_task( + "Processing", total=file_count, filename="Starting...", workers=num_workers + ) + + # Process files individually in parallel (better progress tracking) + process_func = partial( + process_single_file_worker, + fork=fork, + pretty=pretty, + merge=merge, + evm_bin=evm_bin, + num_blocks=num_blocks, + block_strategy=block_strategy, + block_time=block_time, + random_blocks=random_blocks, + ) + + with ProcessPoolExecutor(max_workers=num_workers) as executor: + # Submit all files to the pool + futures_to_files = { + executor.submit(process_func, file_info): file_info[0] + for file_info in files_to_process + } + + # Process completions as they happen for real-time progress + for future in as_completed(futures_to_files): + file_path = futures_to_files[future] + + # Update progress with current file + rel_path = file_path.relative_to(input_dir) + display_name = str(rel_path) + if len(display_name) > 40: + display_name = "..." + display_name[-37:] + + try: + result, error = future.result() + + if result: + success_count += 1 + _, fixtures = result + if merge: + all_fixtures.update(fixtures) + elif error: + error_count += 1 + error_file, exception = error + if not quiet: + progress.console.print( + f"[red]Error processing {error_file}: {exception}[/red]" + ) + + # Update progress bar + progress.update(task_id, advance=1, filename=display_name, workers=num_workers) + + except Exception as e: + error_count += 1 + if not quiet: + progress.console.print(f"[red]Worker error for {file_path}: {e}[/red]") + progress.update(task_id, advance=1, filename=display_name) + + # Write merged file if requested + if merge and all_fixtures: + merged_file = output_dir / "merged_fixtures.json" + with open(merged_file, "w") as f: + if pretty: + json.dump(all_fixtures, f, indent=2) + else: + json.dump(all_fixtures, f) + if not quiet: + progress.console.print(f"[green]Merged fixtures written to: {merged_file}[/green]") + + # Final status + if not quiet: + emoji = "✅" if error_count == 0 else "⚠️" + progress.update( + task_id, + completed=file_count, + filename=f"Done! {success_count} succeeded, {error_count} failed {emoji}", + workers=num_workers, + ) + + +def process_directory( + input_dir: Path, + output_dir: Path, + builder: BlocktestBuilder, + fork: Optional[str], + pretty: bool, + merge: bool, + quiet: bool, + num_blocks: int = 1, + block_strategy: str = "distribute", + block_time: int = 12, + random_blocks: bool = False, +): + """Process directory of fuzzer output files.""" + all_fixtures = {} + file_count = count_json_files(input_dir) if not quiet else 0 + success_count = 0 + error_count = 0 + + with Progress( + TextColumn("[bold cyan]{task.fields[filename]}", justify="left"), + BarColumn(bar_width=None, complete_style="green3", finished_style="bold green3"), + TaskProgressColumn(), + TimeElapsedColumn(), + expand=True, + disable=quiet, + ) as progress: + task_id = progress.add_task("Processing", total=file_count, filename="...") + + for json_file_path in get_input_files(input_dir): + # Preserve directory structure + rel_path = json_file_path.relative_to(input_dir) + display_name = str(rel_path) + if len(display_name) > 40: + display_name = "..." + display_name[-37:] + + progress.update(task_id, advance=1, filename=display_name) + + try: + with open(json_file_path) as f: + fuzzer_data = json.load(f) + + # Override fork if specified + if fork: + fuzzer_data["fork"] = fork + + # Determine number of blocks + if random_blocks: + from .blocktest_builder import choose_random_num_blocks + + actual_num_blocks = choose_random_num_blocks( + len(fuzzer_data.get("transactions", [])) + ) + else: + actual_num_blocks = num_blocks + + # Build blocktest + blocktest = builder.build_blocktest( + fuzzer_data, + num_blocks=actual_num_blocks, + block_strategy=block_strategy, + block_time=block_time, + ) + test_name = generate_test_name(json_file_path) + + if merge: + # Add to merged fixtures + all_fixtures[test_name] = blocktest + else: + # Write individual file preserving structure + output_file = output_dir / rel_path.with_suffix(".json") + output_file.parent.mkdir(parents=True, exist_ok=True) + fixtures = {test_name: blocktest} + with open(output_file, "w") as f: + if pretty: + json.dump(fixtures, f, indent=2) + else: + json.dump(fixtures, f) + + success_count += 1 + + except Exception as e: + error_count += 1 + if not quiet: + progress.console.print(f"[red]Error processing {json_file_path}: {e}[/red]") + + # Write merged file if requested + if merge and all_fixtures: + merged_file = output_dir / "merged_fixtures.json" + with open(merged_file, "w") as f: + if pretty: + json.dump(all_fixtures, f, indent=2) + else: + json.dump(all_fixtures, f) + if not quiet: + progress.console.print(f"[green]Merged fixtures written to: {merged_file}[/green]") + + # Final status + if not quiet: + emoji = "✅" if error_count == 0 else "⚠️" + progress.update( + task_id, + completed=file_count, + filename=f"Done! {success_count} succeeded, {error_count} failed {emoji}", + ) + + +def batch_mode( + fork: Optional[str], + evm_bin: Optional[Path], + pretty: bool, + num_blocks: int, + block_strategy: str, + block_time: int, + random_blocks: bool, +) -> None: + """ + Persistent batch processing mode. + + Reads input/output pairs from stdin, processes each, and outputs status + to stdout. Protocol: + - INPUT (stdin): + - OUTPUT (stdout): DONE or ERROR + """ + import sys + import traceback + + # Pre-initialize transition tool and builder once for performance + t8n: TransitionTool + if evm_bin: + t8n = GethTransitionTool(binary=evm_bin) + else: + t8n = GethTransitionTool() + + builder = BlocktestBuilder(t8n) + + # Write ready signal to stderr for debugging + print("Batch mode initialized. Ready to process files.", file=sys.stderr, flush=True) + + while True: + try: + # Read line from stdin + line = sys.stdin.readline() + if not line: # EOF + break + + line = line.strip() + if not line: + continue + + # Parse input/output paths + parts = line.split() + if len(parts) != 2: + print(f"ERROR: invalid input format: {line}", flush=True) + continue + + input_path_str, output_dir_str = parts + input_path = Path(input_path_str) + output_dir = Path(output_dir_str) + + # Process the file + try: + # Read fuzzer input + if not input_path.exists(): + print(f"ERROR: file not found: {input_path}", flush=True) + continue + + with open(input_path) as f: + fuzzer_data = json.load(f) + + # Override fork if specified + if fork: + fuzzer_data["fork"] = fork + + # Determine number of blocks + if random_blocks: + from .blocktest_builder import choose_random_num_blocks + + actual_num_blocks = choose_random_num_blocks( + len(fuzzer_data.get("transactions", [])) + ) + else: + actual_num_blocks = num_blocks + + # Build blocktest (existing logic) + blocktest = builder.build_blocktest( + fuzzer_data, + num_blocks=actual_num_blocks, + block_strategy=block_strategy, + block_time=block_time, + ) + + # Generate test name + test_name = generate_test_name(input_path) + fixtures = {test_name: blocktest} + + # Write output + output_dir.mkdir(parents=True, exist_ok=True) + input_stem = input_path.stem + output_file = output_dir / f"{input_stem}.json" + + with open(output_file, "w") as f: + if pretty: + json.dump(fixtures, f, indent=2) + else: + json.dump(fixtures, f) + + # Report success (CRITICAL: must flush) + print(f"DONE {output_file}", flush=True) + + except FileNotFoundError: + print(f"ERROR: file not found: {input_path}", flush=True) + except json.JSONDecodeError as e: + print(f"ERROR: invalid JSON in {input_path}: {e}", flush=True) + # Log full traceback to stderr for debugging + traceback.print_exc(file=sys.stderr) + except Exception as e: + print(f"ERROR: conversion failed for {input_path}: {e}", flush=True) + # Log full traceback to stderr for debugging + traceback.print_exc(file=sys.stderr) + + except KeyboardInterrupt: + break + except Exception as e: + # Catch-all for unexpected errors in the main loop + print(f"ERROR: unexpected error in batch loop: {e}", flush=True) + traceback.print_exc(file=sys.stderr) + + +@click.command() +@click.argument( + "input_path", + type=click.Path(exists=True, dir_okay=True, file_okay=True, path_type=Path), + required=False, +) +@click.argument( + "output_path", + type=click.Path(dir_okay=True, file_okay=False, path_type=Path), + required=False, +) +@click.option( + "--fork", + default=None, + help="Override fork specified in fuzzer output", +) +@click.option( + "--evm-bin", + type=click.Path(exists=True, path_type=Path), + help="Path to evm binary for transition tool", +) +@click.option( + "--pretty", + is_flag=True, + help="Pretty-print JSON output", +) +@click.option( + "--merge", + is_flag=True, + help="Merge all tests into a single output file", +) +@click.option( + "--quiet", + is_flag=True, + help="Suppress progress output", +) +@click.option( + "--parallel/--no-parallel", + default=True, + help="Enable/disable parallel processing (default: enabled)", +) +@click.option( + "-n", + "--workers", + type=int, + default=None, + help="Number of parallel workers (default: auto-detect based on CPU count)", +) +@click.option( + "-b", + "--num-blocks", + type=int, + default=1, + help="Number of blocks to generate from fuzzer input (default: 1)", +) +@click.option( + "--block-strategy", + type=click.Choice(["distribute", "first-block"]), + default="distribute", + help="Transaction distribution strategy: 'distribute' splits txs evenly, " + "'first-block' puts all txs in first block (default: distribute)", +) +@click.option( + "--block-time", + type=int, + default=12, + help="Seconds between blocks (default: 12)", +) +@click.option( + "--random-blocks", + is_flag=True, + help="Randomly choose number of blocks (1 to min(num_txs, 10))", +) +@click.option( + "--batch", + is_flag=True, + help="Persistent batch mode: read file paths from stdin, output to stdout", +) +def main( + input_path: Optional[Path], + output_path: Optional[Path], + fork: Optional[str], + evm_bin: Optional[Path], + pretty: bool, + merge: bool, + quiet: bool, + parallel: bool, + workers: Optional[int], + num_blocks: int, + block_strategy: str, + block_time: int, + random_blocks: bool, + batch: bool, +): + """ + Convert fuzzer output to valid blocktest fixtures. + + INPUT_PATH: Input JSON file or directory (not required in --batch mode) + OUTPUT_PATH: Output directory for fixtures (not required in --batch mode) + + In batch mode (--batch), reads input/output pairs from stdin. + """ + # Batch mode: persistent stdin/stdout processing + if batch: + batch_mode( + fork=fork, + evm_bin=evm_bin, + pretty=pretty, + num_blocks=num_blocks, + block_strategy=block_strategy, + block_time=block_time, + random_blocks=random_blocks, + ) + return + + # Standard mode: require input_path and output_path + if input_path is None or output_path is None: + raise click.UsageError( + "INPUT_PATH and OUTPUT_PATH are required when not using --batch mode" + ) + # Create transition tool + t8n: TransitionTool + if evm_bin: + t8n = GethTransitionTool(binary=evm_bin) + else: + t8n = GethTransitionTool() + + # Create builder + builder = BlocktestBuilder(t8n) + + # Ensure output directory exists + output_path.mkdir(parents=True, exist_ok=True) + + # Process input + if input_path.is_file(): + # Single file processing + process_single_file( + input_path, + output_path, + builder, + fork, + pretty, + quiet, + num_blocks, + block_strategy, + block_time, + random_blocks, + ) + else: + # Directory processing with optional parallel mode + if parallel: + process_directory_parallel( + input_path, + output_path, + fork, + pretty, + merge, + quiet, + evm_bin, + workers, + num_blocks, + block_strategy, + block_time, + random_blocks, + ) + else: + process_directory( + input_path, + output_path, + builder, + fork, + pretty, + merge, + quiet, + num_blocks, + block_strategy, + block_time, + random_blocks, + ) + + +if __name__ == "__main__": + main() diff --git a/cli/fuzzer_bridge/converter.py b/cli/fuzzer_bridge/converter.py new file mode 100644 index 0000000000..62affb7839 --- /dev/null +++ b/cli/fuzzer_bridge/converter.py @@ -0,0 +1,308 @@ +""" +Converter module for transforming fuzzer DTOs to EEST domain models. + +This module performs explicit transformation from fuzzer's +JSON-RPC format (captured in DTOs) to EEST's internal domain +models (Transaction, Account, etc.). + +Key Responsibilities: +1. Field mapping (gas → gas_limit, from → sender, etc.) +2. Creating EOA objects from private keys +3. Building proper EEST domain models with all required context +4. Preventing TestAddress pollution by setting sender + BEFORE model_post_init +""" + +from typing import Dict + +from ethereum_test_base_types import Address, Hash, HexNumber +from ethereum_test_forks import Fork +from ethereum_test_specs import BlockchainTest +from ethereum_test_tools import Account, AuthorizationTuple, Block, Transaction +from ethereum_test_types import Alloc, Environment +from ethereum_test_types.account_types import EOA + +from .models import ( + FuzzerAccountInput, + FuzzerAuthorizationInput, + FuzzerOutput, + FuzzerTransactionInput, +) + + +def fuzzer_account_to_eest_account(fuzzer_account: FuzzerAccountInput) -> Account: + """ + Convert fuzzer account DTO to EEST Account domain model. + + Args: + fuzzer_account: Raw account data from fuzzer + + Returns: + EEST Account ready for pre-state + + """ + return Account( + balance=fuzzer_account.balance, + nonce=fuzzer_account.nonce, + code=fuzzer_account.code, + storage=fuzzer_account.storage, + ) + + +def fuzzer_authorization_to_eest( + fuzzer_auth: FuzzerAuthorizationInput, +) -> AuthorizationTuple: + """ + Convert fuzzer authorization DTO to EEST AuthorizationTuple. + + Args: + fuzzer_auth: Raw authorization data from fuzzer + + Returns: + EEST AuthorizationTuple for EIP-7702 transactions + + """ + return AuthorizationTuple( + chain_id=fuzzer_auth.chain_id, + address=fuzzer_auth.address, + nonce=fuzzer_auth.nonce, + v=fuzzer_auth.v, + r=fuzzer_auth.r, + s=fuzzer_auth.s, + ) + + +def fuzzer_transaction_to_eest_transaction( + fuzzer_tx: FuzzerTransactionInput, + sender_eoa: EOA, +) -> Transaction: + """ + Convert fuzzer transaction DTO to EEST Transaction domain model. + + This function performs explicit field mapping and MUST set sender BEFORE + calling Transaction constructor to prevent TestAddress injection. + + Key Mappings: + - fuzzer_tx.gas → transaction.gas_limit (JSON-RPC → EEST naming) + - fuzzer_tx.from_ → sender_eoa (Address → EOA with private key) + - fuzzer_tx.data → transaction.data (same field, explicit for clarity) + + Args: + fuzzer_tx: Raw transaction data from fuzzer + sender_eoa: EOA object created from private key (prevents TestAddress) + + Returns: + EEST Transaction ready for block generation + + """ + # Build authorization list if present + auth_list = None + if fuzzer_tx.authorization_list: + auth_list = [fuzzer_authorization_to_eest(auth) for auth in fuzzer_tx.authorization_list] + + # Create Transaction with sender set BEFORE model_post_init runs + # This prevents Transaction.model_post_init from injecting TestAddress + return Transaction( + sender=sender_eoa, # ✓ Set explicitly to prevent TestAddress + to=fuzzer_tx.to, + gas_limit=fuzzer_tx.gas, # ✓ Explicit mapping: gas → gas_limit + gas_price=fuzzer_tx.gas_price, + max_fee_per_gas=fuzzer_tx.max_fee_per_gas, + max_priority_fee_per_gas=fuzzer_tx.max_priority_fee_per_gas, + nonce=fuzzer_tx.nonce, + data=fuzzer_tx.data, + value=fuzzer_tx.value, + access_list=fuzzer_tx.access_list, + blob_versioned_hashes=fuzzer_tx.blob_versioned_hashes, + max_fee_per_blob_gas=fuzzer_tx.max_fee_per_blob_gas, + authorization_list=auth_list, + ) + + +def create_sender_eoa_map(accounts: Dict[Address, FuzzerAccountInput]) -> Dict[Address, EOA]: + """ + Create map of addresses to EOA objects from accounts with private keys. + + Args: + accounts: Dictionary of address to fuzzer account data + + Returns: + Dictionary mapping addresses to EOA objects for transaction signing + + Raises: + AssertionError: If private key doesn't match the account address + + """ + senders: Dict[Address, EOA] = {} + + for addr, account in accounts.items(): + if account.private_key is None: + continue + + # Create EOA from private key + sender = EOA(key=account.private_key) + + # Verify private key matches address (safety check) + assert Address(sender) == addr, ( + f"Private key for account {addr} does not match derived address {sender}" + ) + + senders[addr] = sender + + return senders + + +def blockchain_test_from_fuzzer( + fuzzer_output: FuzzerOutput, + fork: Fork, + num_blocks: int = 1, + block_strategy: str = "distribute", + block_time: int = 12, +) -> BlockchainTest: + """ + Convert fuzzer output to BlockchainTest instance. + + This is the main entry point for fuzzer-to-EEST conversion. + It orchestrates: + 1. Parsing and validation (already done by FuzzerOutput DTO) + 2. Creating EOA objects from private keys + 3. Converting DTOs to domain models + 4. Building blocks and test structure + + Args: + fuzzer_output: Parsed and validated fuzzer output (DTO) + fork: Fork to use for the test + num_blocks: Number of blocks to generate + block_strategy: How to distribute transactions across blocks + - "distribute": Split evenly maintaining + nonce order + - "first-block": All transactions in first + block + block_time: Seconds between block timestamps + + Returns: + BlockchainTest instance ready for fixture generation + + Raises: + AssertionError: If invariants are violated + (sender validation, etc.) + + """ + # Step 1: Convert accounts to EEST Account domain models + pre_dict: Dict[Address, Account | None] = {} + for addr, fuzzer_account in fuzzer_output.accounts.items(): + pre_dict[addr] = fuzzer_account_to_eest_account(fuzzer_account) + pre = Alloc(pre_dict) + + # Step 2: Create EOA map for transaction signing + sender_eoa_map = create_sender_eoa_map(fuzzer_output.accounts) + + # Step 3: Convert transactions to EEST Transaction domain models + eest_transactions: list[Transaction] = [] + for fuzzer_tx in fuzzer_output.transactions: + # Verify sender has private key + assert fuzzer_tx.from_ in sender_eoa_map, ( + f"Sender {fuzzer_tx.from_} not found in accounts with private keys" + ) + + # Convert with explicit sender (prevents TestAddress injection) + eest_tx = fuzzer_transaction_to_eest_transaction( + fuzzer_tx, + sender_eoa=sender_eoa_map[fuzzer_tx.from_], + ) + eest_transactions.append(eest_tx) + + # Step 4: Build genesis environment + env = fuzzer_output.env + genesis_env = Environment( + fee_recipient=env.fee_recipient, + difficulty=0, # Post-merge + gas_limit=int(env.gas_limit), + number=0, + timestamp=HexNumber(int(env.timestamp) - 12), + prev_randao=env.prev_randao or Hash(0), + base_fee_per_gas=env.base_fee_per_gas if env.base_fee_per_gas else None, + excess_blob_gas=env.excess_blob_gas if env.excess_blob_gas else None, + blob_gas_used=env.blob_gas_used if env.blob_gas_used else None, + ).set_fork_requirements(fork) + + # Step 5: Distribute transactions across blocks + blocks = _distribute_transactions_to_blocks( + eest_transactions, + num_blocks, + block_strategy, + block_time, + env, + fuzzer_output.parent_beacon_block_root, + ) + + return BlockchainTest( + pre=pre, + blocks=blocks, + post={}, # Post-state verification can be added later + genesis_environment=genesis_env, + chain_id=fuzzer_output.chain_id, + ) + + +def _distribute_transactions_to_blocks( + transactions: list[Transaction], + num_blocks: int, + strategy: str, + block_time: int, + base_env: Environment, + parent_beacon_block_root: Hash | None, +) -> list[Block]: + """ + Distribute transactions across multiple blocks. + + Args: + transactions: List of EEST Transaction objects (ready for execution) + num_blocks: Number of blocks to create + strategy: Distribution strategy ("distribute" or "first-block") + block_time: Seconds between blocks + base_env: Base environment for first block + parent_beacon_block_root: Beacon root (only for first block) + + Returns: + List of Block objects + + """ + if strategy == "first-block": + # All transactions in first block, rest empty + tx_distribution = [transactions] + [[] for _ in range(num_blocks - 1)] + elif strategy == "distribute": + # Split transactions evenly maintaining nonce order + if not transactions: + tx_distribution = [[] for _ in range(num_blocks)] + else: + result = [] + chunk_size = len(transactions) // num_blocks + remainder = len(transactions) % num_blocks + + start = 0 + for i in range(num_blocks): + # Distribute remainder across first blocks + current_chunk_size = chunk_size + (1 if i < remainder else 0) + end = start + current_chunk_size + result.append(transactions[start:end]) + start = end + + tx_distribution = result + else: + raise ValueError(f"Unknown block strategy: {strategy}") + + # Create blocks with incrementing timestamps + base_timestamp = int(base_env.timestamp) + blocks = [] + for i, block_txs in enumerate(tx_distribution): + blocks.append( + Block( + txs=block_txs, + timestamp=base_timestamp + (i * block_time), + fee_recipient=base_env.fee_recipient, + parent_beacon_block_root=parent_beacon_block_root if i == 0 else None, + ) + ) + + return blocks diff --git a/cli/fuzzer_bridge/examples/README.md b/cli/fuzzer_bridge/examples/README.md new file mode 100644 index 0000000000..95b6f912fe --- /dev/null +++ b/cli/fuzzer_bridge/examples/README.md @@ -0,0 +1,143 @@ +# Fuzzer Bridge Examples + +This directory contains example fuzzer outputs in the v2.0 JSON format. These examples demonstrate the comprehensive transaction coverage generated by the fuzzer and serve as test cases for the fuzzer bridge implementation. + +## Format Overview + +All examples use fuzzer output format v2.0 with the following structure: + +```json +{ + "version": "2.0", + "fork": "Osaka", + "chainId": "0x01", + "accounts": { ... }, + "transactions": [ ... ], + "env": { ... }, + "parentBeaconBlockRoot": "0x..." +} +``` + +## Example Files + +### comprehensive_smallest.json (56K) +- **Size**: Smallest example (56K) +- **Transactions**: 17 transactions +- **Accounts**: 25-26 accounts with private keys +- **Transaction Types**: Legacy, EIP-1559, EIP-4844 (blobs), EIP-7702 (authorization lists) +- **Features**: Parent beacon block root (EIP-4788) +- **Use Case**: Minimal comprehensive example for quick testing + +### comprehensive_medium_1.json (62K) +- **Size**: Medium-sized example (62K) +- **Transactions**: 17 transactions +- **Accounts**: 25-26 accounts +- **Transaction Types**: Full spectrum including blob transactions (6 blob hashes per tx) +- **Authorization Lists**: 5 authorization tuples per EIP-7702 transaction +- **Use Case**: Balanced example with typical transaction data sizes + +### comprehensive_medium_2.json (66K) +- **Size**: Medium-sized example (66K) +- **Transactions**: 17 transactions +- **Accounts**: 25-26 accounts +- **Transaction Types**: All major transaction types +- **Features**: Variety of calldata sizes (2-400 bytes) +- **Use Case**: Testing different data payload sizes + +### comprehensive_large.json (70K) +- **Size**: Large example (70K) +- **Transactions**: 17 transactions +- **Accounts**: 25-26 accounts +- **Transaction Types**: Complete coverage +- **Features**: Larger calldata payloads (up to 600 bytes) +- **Use Case**: Testing with substantial transaction data + +### comprehensive_largest.json (74K) +- **Size**: Largest example (74K) +- **Transactions**: 17 transactions +- **Accounts**: 25-26 accounts +- **Transaction Types**: All types including largest blob transactions +- **Features**: Maximum calldata sizes (up to 690 bytes) +- **Use Case**: Stress testing with largest transaction payloads + +## Common Features Across All Examples + +All examples include: + +1. **EIP-1559 Transactions**: Dynamic fee transactions with `maxFeePerGas` and `maxPriorityFeePerGas` +2. **EIP-4844 Blob Transactions**: Transactions with `blobVersionedHashes` and `maxFeePerBlobGas` +3. **EIP-7702 Set-Code Transactions**: Transactions with `authorizationList` containing signed authorization tuples +4. **Legacy Transactions**: Traditional transactions with `gasPrice` +5. **EIP-4788 Support**: `parentBeaconBlockRoot` set in environment +6. **Private Keys**: All sender accounts include `privateKey` field for transaction signing +7. **Storage**: Accounts with non-empty storage mappings +8. **Code**: Accounts with deployed bytecode + +## Field Mappings (Fuzzer JSON-RPC → EEST) + +The fuzzer uses standard Ethereum JSON-RPC transaction format: + +| Fuzzer Field | EEST Field | Description | +|-------------|-----------|-------------| +| `gas` | `gas_limit` | Gas limit for transaction | +| `data` | `data` | Transaction calldata | +| `from` | `sender` | Transaction sender (mapped to EOA) | +| `gasPrice` | `gas_price` | Gas price (legacy transactions) | +| `maxFeePerGas` | `max_fee_per_gas` | Max fee per gas (EIP-1559) | +| `maxPriorityFeePerGas` | `max_priority_fee_per_gas` | Max priority fee (EIP-1559) | +| `blobVersionedHashes` | `blob_versioned_hashes` | Blob hashes (EIP-4844) | +| `maxFeePerBlobGas` | `max_fee_per_blob_gas` | Max blob fee (EIP-4844) | +| `authorizationList` | `authorization_list` | Authorization tuples (EIP-7702) | + +## Usage + +These examples can be used with the fuzzer bridge CLI: + +```bash +# Convert a single example to blockchain test +uv run python -m cli.fuzzer_bridge.cli \ + --input src/cli/fuzzer_bridge/examples/comprehensive_medium_1.json \ + --output /tmp/blocktest_output + +# Batch convert all examples +for example in src/cli/fuzzer_bridge/examples/*.json; do + uv run python -m cli.fuzzer_bridge.cli \ + --input "$example" \ + --output "/tmp/$(basename "$example" .json)" +done +``` + +## Old Examples + +Previous examples (before format evolution and bug fixes) are preserved in the `old_examples/` subdirectory for reference. + +## Generation + +These examples were generated using the fuzzer with comprehensive transaction coverage enabled. The fuzzer automatically generates: + +- Multiple transaction types per test +- Accounts with various states (empty, funded, with code, with storage) +- Realistic transaction ordering and nonce sequences +- Private keys for all sender accounts +- Post-merge environment (PoS consensus) + +## Testing Coverage + +Each example provides test coverage for: + +- ✅ Transaction parsing (all field types) +- ✅ Account state initialization +- ✅ EOA creation from private keys +- ✅ Gas limit calculations +- ✅ Blob transaction handling +- ✅ Authorization list processing +- ✅ Environment setup (including beacon root) +- ✅ Multi-transaction block generation + +## Notes + +- All examples use Osaka fork +- All examples use chain ID 1 (mainnet) +- All transactions have sufficient gas (16,000,000 gas limit) +- All sender accounts have private keys for signing +- Environment includes realistic post-merge values (difficulty=0, prevRandao set) diff --git a/cli/fuzzer_bridge/examples/comprehensive_large.json b/cli/fuzzer_bridge/examples/comprehensive_large.json new file mode 100644 index 0000000000..02207cb840 --- /dev/null +++ b/cli/fuzzer_bridge/examples/comprehensive_large.json @@ -0,0 +1,421 @@ +{ + "accounts": { + "0x000000000000000000000000000000000000000d": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x6517fa85aafd83a02f88fe864d93249c357cce975bd1f35d0b0430a901613f76", + "storage": {} + }, + "0x18665208d71eAF07c959cB6d2b263aCE3eF24042": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xaf09231cd0ab58828b41ee0ba14866d944b955fbc80243a5bf0bc8c86c664552", + "storage": {} + }, + "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": { + "balance": "0x989680", + "code": "0x6f19fa3b5cbcf160be11cbc1ccfa69a3a86000527f9f374ddd4b02789440d795b6a2fcfda039b83d18945750af9cee8ebacc1c27716020526f014a651f7ac467a9f4f1041275a058386040527f03088f4d23e2585886dd9918f916bd25f3a9f62b6bff62fc04a5770726fdfea16060526f19f7092f2954ea173b6f38c95f4ab8f96080527f871c73b32e1e1c5da7ba9025c14e5ba83e0c6762b66e433f8f9046629488f2b860a0526f0c1303e46eb6b78c665ea65f470ac64660c0527fa6f6149c0b9505c50046c6de2883a22579de92b151f5ab7938e9c5c269a09e3960e0526080600061010060006046600b7ffe95b06b0f681723791f4161b4947e090dbfd8783baf00b3a24bc8853dcf0196f26000556000516001556020516002556040516003556060516004556f0fb6f07b2eab53e6d95b3eea7c5f15256000527f9ff4e6b8f9784adec046dea1be26fd44754d6a27c6a2b1a1d9e44930cbd311306020526f03c0d62e127d7ca9f051646a2c401ede6040527ff683bbc13510e88c04488ced8f6b688a79584ba6dbe3debed06ec8de8a23f54c6060527f85594d4af90ecf8adb547e8c0e1f2022770dbab52d41e5d7209033a36c7b9f8d6080526f158333a1f76f866236773aa642362ad060a0527e5c4adc636c7f0ef15a9de64bbde05b7dc19d3d71c1828c7c56480a761d207c60c0526f102eaee88ca53422c1d961278654cd0360e0527f0798cc38d9234d1ab9645b653fa58fef75b9bbb4fad130010abcdf8a99900f7a610100527f713197f47d0b27493f5b80e43abe59e6052e876076598c449fd315801a093b59610120526f0bb2d551f91290b5b9fce1e398dbc4cb610140527ff6cca7cc4e69b5da29f4fa52c6581aed6fc44bb1f3c0536eb504b7d221a06447610160526f061d80c19532c14099c7c684e2ccb174610180527f57228c4901d5528ebbf0c4f47dae28c3d280068e31c107be7b4e6eda8f4ddc586101a0527f1affd06170d301f6ebafc685f05a67ba51aa136ef86f6146ea179898a8dabd546101c052608060006101e06000600c7ffd0e4ef71bd81883826cfc6172ac1a2331705d36e13ad54044fbbd2f7509d1f7f46005556000516006556020516007556040516008556060516009556f08ba8a0468fb1e41a77dc4760a4973ee6000527fe6f8dd14f7ffe63b258b76ba3945fc3212dd597342360542875ef842e0b0b2196020526f0fd65a1aed9d10788788f8c8116f56af6040527f3e4297c9aeb8329e8f90cb0afef8148320439f16ebdf6680516f5d27928a1a086060526f145d501508e98e9fdc70d4076213d6146080527f14d82b1819adbaed7aa9a6ed3877d698e515829d121b61a40d224480af7a667b60a0526f1460669ebf2d0c5804bfc4ea1e662a3a60c0527fa675412270d299cdcc4fb1af786e51bde0f9c7f2fa5a48dcd7770aa3086ca85660e0526f0bd37d392b9da52284890146de3e897d610100527f9b414b75b7fbb851dfbba872378f09666e83e15c4039cb9dd41a65ecf610234c610120526f07f750deef22c9b32314fcfd4d541929610140527f2a89d9e69169ce89d55caae0d5bfb34bae1bfdd51fdead179761953c3d68488d610160526f1d1becb9ed60428375c9cba1b1e5deda610180527f6694879571ee1b0ac9e12d815b34f005639cd4214d10865159dd2a14459ea1c56101a0526f0fff5920c6dca137b60970bb9c2cbbca6101c0527fab9d343b23a24d09491af51286c567ea4e0d802d0d17da14605dd0629ef3d11c6101e05261010060006102006000600d7f8ec3983a330a1d6443ba3a96ad13eb742da259f98b422751e4d83c507eb9a495fa600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f19da63d9ed7d5028bc4ec2241e0f64d66000527f9c2a418eca251abceb9c6ceea156ab119fa41c5d817c64b5d27e378b3666fe616020526f02b6cfb26b2a957b6cea0ced22f7da976040527fbd85f4f1cf860c6b0a4cd896da77568cb92265cb47653c0d42fa17de27204b9b6060526f134e239014bc00715daa075776787a4c6080527fc3f6e58a7ccc8761817397ee792a6a5c06ac2b8c0532465909312c3f73a0411460a0526f08015e9f29388301d30ec2275593144160c0527fe781b11a8189a11b6ca94a5a75320893f20a6d24a9a5d89f403aa9e7b2b1082460e0527f3c6c108f25654670f797333386644dc2266da7009d2379ae6b1a713b1d4f1f5e610100526f0f1f81e63fb80a8c424825c4c63fecd7610120527fa9e2c7a00edb5595ac51369c4e06cb0d327c4a2bcb9540bbc071f89d5afd930e610140526f15f887c809744b267d34ea14996f9c19610160527f4a6e3e76a9560eac9ab9302f09ae45ba8390f505f9b76aa7e095d4c06731c6da610180526e781d148227c64e9e6171737a9f90676101a0527f4da46bda7b6fc8735861079c8c5190fe2452068274e77d646be4efd9824c084f6101c0526f08709c66878c65bf4b6fe916c2994c1d6101e0527fc7ada675b682bb217386e5f3e271a9afddb98dc41ac2e620c4bfcf7cd386a80c610200527f08ee20e405693fd12009d735195f7a9f0151f0073f16c63cde49582d2ee6da7961022052610100600061024060006036600e7f89e0e03253b5683c3350f95eeea40ab73353141f0d329060d6b4bb2b67b6d5f5f260135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f0f1ff58cafe856bb0c96b8cc8e84a15f6000527f4aa828579e886669fe73006f7e0eeffb46e8774f0fc9476fe9ef7eb45ee87bb96020526f0ca2fcfc114a285353488f60b0cb27be6040527f096dc37d10d6178f1acb136e37937d67acdfcfcc479ac055f69a9d3127abffb46060526f0d334f79d96f58a39b36cb539250a5516080527f6f3fb98e2e86cfe69a80955b99fbd5159bd75b68a1170ed2a2f4d39d9f54897060a0526f19b11403a23f5806db3da4e23c11898d60c0527f7e89c85d9c5951eacc54b878539d49603b85611512db65364053e9105282505860e0526f140342b31fd4daf8752074a17957a58c610100527f03a5d0d261b7693c3c3b9465bb7580ac64ab687520c5a0a792ac014ddc760458610120526f0e1834c2250017d2a88333e20b0a51dc610140527f5ea2cd2d856b17c7a1d4f5f148d4ec0a2089219d520b672e32b439c14ea1b85f610160526f1316f2bff6c70b109dad2d28a6404881610180527f3151789d6ca1019ea82ccfe4c806673dff2d9332637b20c4e6a9cb44faa2c28e6101a0526f128e3988a581fb6fe92de2e1c48f14986101c0527f4155e4151df5492a44ae4ec360c675705b8f2aea0a2831d7e9f664aa009b4dd06101e0526f024aa2b2f08f0a91260805272dc51051610200527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610220526f13e02b6052719f607dacd3a088274f65610240527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610260526f0ce5d527727d6e118cc9cdc6da2e351a610280527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016102a0526f0606c4a02ea734cc32acd2b02bc28b996102c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6102e05260206000610300600060b5600f7f26e0179e1ab64336316965140721c1c91b4c6311479bfb37b4049e57d689e429f1601c55600051601d557e40000000000000000000000000000005368347f453af419c09e3c17d5a07b16000527fcec1b822de11b01fe0b30cc1f6e431c7d6aa6297592bb9a08255062903a43a19602052608060006040600060107f75031a4a93d2ee1164a2f48228e140897995ea0e845683c90a60af8d03ac65defa601e55600051601f556020516020556040516021556060516022556f0fd5ef3e0dc0490f4dbff5e349456cc76000527fc0a883554216d95059f28016c8d8c4880eafaac915ae37e0daa01ded35c024c16020526f0392768dd75f8e50ad0c7a67d9c819fa6040527fe551075a654737e08d0f021eb117eb6b68267334b9110a1fe2e2edb67572cc9b606052610100600060806000601160f2f460235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55", + "nonce": "0x0", + "storage": {} + }, + "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": { + "balance": "0x0", + "code": "0x607660db600b602360e6604260bd1d8164a1f4329a161d8c31f11568550b5546591c4348526c53313f04452087315456197882415f647a72956540556f94460507891a053a600036306b1858421005179170995100928d5c153f92071977a137095258425e5a0a7114005e554a086e75135b0120203c15798f157837f5807e3145197d186e09161a77705c17526f37130286621945183e3e783030080616703b1e9978348a0388121879327d546079785b7c561d5e69947c927e611016347a1b6ea0358065186c7f8476507239180619137643491d72107b59186c8b8d79009909736bfe087b5f596534169d3ea4160a555f5134676890346a5c583f5bfd66598075983267519b10468e794664653f7c9f155b77047f0a721b921914067d7218868f7079781b1104173a437275f37948383f6f8e387fa2611c74455a99fa448b65460b5f1153f335143e07717e348f3173639819686c51789204386b82721a1394975a08597876618310176d30575e0168564962842097793f796d7e00953b465c410a3c775e1e79673f167448307088777057960257519752757a5e6a313e585dfe081dfd0361055cf58d8230725d5a5831891a36701842f5015b6511125b32373015f470871c465118093a59634302396447395252398603694af4185360180033141620845647391a11347a463df410779d7b030b0170163b1a15529e563f48590a420a14067f793e8f699d8f8c5780119c587a4291127a0167783d6f576012a354f21c7874315714384578346c9b7e5569961d55566f6bfd0b1851307e013899166f1683208c615c206b48076e7503fa3344a04955f5577209046d92a48474069b516b6135209146701e886e7c7b5f7796325a40848d6b519d609e1b03110b695a8b14399c6494a4361b163b3284667c8e743a023f1a7494021b9efd01fa09075912829f729f6402021a6f311740113b3c7a811808170519763d7405570953a00406ff1020536d09a0396095a17b5a456742353d10565969761439165d63101bf1598865958d375239046630516f6a1863903a497a3e6b07129a4758571d7d56051a80675914793295793f5d131a37149b5a6e3ba20b1e5341578b6571a494022065556798115648745f550398719f696d79f03e20ff429b34f3780a5e5c5077a35a6c433f77951a4059905f96371468a4025455713251591a3014fe1a557e6549395d165467915d9b63481b03531449521979068461533758f05839733205538d5e304109079c4a036d9d42f03565376418323697066b755c02a3fff1545711798d71490462101a3344591512187298565c058e1a0377f1853ff2fa095f5655466399483e69477f6e10465c3840f3413b7275906174a17c0348341d321153355563543f9d5b12fd806a20093d6100a109107e78656fa243025b067ef515", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000000000000000000000000000000000000000000d", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000006" + } + }, + "0x2837fE6BCdADEa40e14E73df3101847267659772": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2bc9eb16f330b5d3764d1e508af3bcbb84786071e249bad6f91ac38553464bf4", + "storage": {} + }, + "0x35F694E45962Ab9eD665971FdF51A45A3b109c62": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2ac7d0629b3a39ccca4afd80b787edeccd0f9ceb5a83595c0f6a0e1cff0ebc7e", + "storage": {} + }, + "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xd5b187a1488a0211288f3d420de324151455a6fa819850303f62bd25582b7cf6", + "storage": {} + }, + "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": { + "balance": "0x0", + "code": "0x863419417b6000600055fa6de18a449c010a7f8e9660d84a21b87dbc056763006df3b8e66035a6f5fa4f42111ec56669067f796000527f9c2a7f3804dce503d7dff8e8801825fcdbd42a90e3f308ba21073ded827269296020527ff1b14bba86f2a6dd52b5d305e67bce80b579773ed881c8b9d8ce642f5638e1176040527f5e84ef7b9dc7e340641494d24498f08e7e37c9a6b3c8c03d09233a8e4af955dc6060527fce75d7e5d40ae69e572cbc0acdf3ef1eda7986dae8c69c09ab0c6f147b39268b6080527f7102b83fa59b8625e1cf6135605774b5f0a4d1bf373ac442b586a734ea8d21a560a0527fd4734a6bf23aa02d6286e928ed2edb7de8f5cedf05ecd2414ae0b4b9b11f6ab660c0527f7aee11b5432ab2a83f63841375a8f0ae8793233f2ede14d8f438f0dbb071534360e0527fb6a898321c875fee9103f3e25ab43d83cdf69aa1272812df955436426dda111e610100527f9ef2f7a07ef9168eef5eb78e995ea5792ec9b54d26c84c2b3b293f2c75e7989b610120527fb927e00951b4d24c112987f39916cee2300c7b8daca535a96ec9ae5cfaad7945610140527f78bb0fbfc44d5382300475f28e1f1f2e18708879ea8782b491d347901fe53e23610160527f7c6d85c86a9519a7852b269fa8f73f567731325f725a7286e6c01dbfd830397b610180527fcb9090f9a3bf1b0f3eb6dc9b03d0f339b6485d5b238ed7f9d0f1d4495d7b979a6101a052604060006101c0600060017f7735e2b1ad3cdfeae4afb25583920b30da69c9092974cdea990241f743cb3a5bfa600155600051600255602051600355", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000d", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x000000000000000000000000000000000000000000000000000000000000000c" + } + }, + "0x538A8474EeaB43d5a960164c554A20400151D479": { + "balance": "0x989680", + "code": "0x7fa4fc4c261945511eb0a7f9289ce44ddf8c9a5f4f7945a874976ea999c00f203c6000527f848fd24256f25171129d300596cdb3b87acac92dd320fd135b469ffb3649b0e86020527f47c102713e24fc4063948a1ada6d8df826b84b4737456cb9299ee0ddd772b8436040527fa839afcab7c931f82fc7153e8c264aba55b8a32448b9ad7568d4ca274cf0f6066060527f1addfa3a484743f66c64ca09ff38394128a899b80ecaff420a4d4a24bf44ff0e6080527f152e8f081e35367b5111bf26d890c6411c2fad393021ec60f6245c542193ffd960a0527f2f6f851250f72062da28ca7528fd1ecdac47295206aee44bb04ae8c1569d159560c0527f63616e5e3b3f1a7a4de50bae2b9628d600dc21fe02e8b000d48b229dc81959a360e0527faa2d809b67023928be7c23a9e3a6436258d51a8ee50e34c95a144cf9cf2d9e31610100527f4dbb9f316420b4b6f0a903f88704b734ee1c9b08a84949ca3c8f8c1701da909761012052608060006101406000601a600b7f0bce7192ca8c2cee8f6a4969de315bf7818617316247de5551ee9bca9f98a5b1f1600055600051600155602051600255604051600355606051600455", + "nonce": "0x0", + "storage": {} + }, + "0x641602bAD4A323C49629d45338d79A2bb984A3fb": { + "balance": "0x989680", + "code": "0x60d4600053600560006102403960ff610245526008600061026582819290913920600c5560196019610100376080600060a082819290913e20600d5560ed610320536102455161ffff60808091905251600e556005610240fd", + "nonce": "0x0", + "storage": {} + }, + "0x66bBEf07B980c8b5de6F3DB0d5CA7A0389C7f386": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x6888bf43c6b0a7bd72d3d4f360efc2fcf781b746e6de54a559882e71c4ac43a2", + "storage": {} + }, + "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": { + "balance": "0x0", + "code": "0x60f5ff91600aff60066000557f6133b9711c679b508736ed2f2a68fca7d4b1b912835742fb9dd74077c69c99ee6000527f2a08abae5a77926728c6ab0cbc4f81597dbf381b9162c36917ef9f42c63b99fc6020527f9abc7b34abd5117c02c1608a0397c757b19dd8644719be525176d7c9611db13f6040527f4e274ca06f8679a44b6c7d66f165c0c86aa94c5ea5653d359509dc6e8a4805bd6060527f4070778074d300ac50e862e4fc06c4149396762f44c15b6fd90917391f88e2996080527f881b5e6a55ab149fbe5a0ddfdd2cb487b9de8a1d29a61575afdcd2eb5a92345f60a0527f5c2e6bf54da29f38a89da143ea0c4e91d6c801eef8d9c0e267838ac85f71f0be60c0526040600060e06000600f7f67fcb88c6827df95a5c4a5f2547e65254ecb1b4d9a7ac77cf40b820e999e1f7ffa600155600051600255602051600355", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000011" + } + }, + "0x7564105E977516C53bE337314c7E53838967bDaC": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": { + "balance": "0x989680", + "code": "0x7d059b496042f5250099eca0bd057a7162d05a02ce37330a5b536cd2e4c0186000527fee48cb9ff2f9b10445a8becfeb58e5119a8a83e7dd43b101bf6e1f5dd6b3a9af6020527f476d2cfa61f20f534739aa9c1f89023a4f1fae316859138a038cdebb87a7fe066040527f6b7a7ac05061f5e8cc20a76eaafddbdb811bca541786813629824f602b88562b6060527f36dd661024742f2d3fac855c9a98a06846a1b08f9f7d281167f79f77cdc773f06080527f0566af2715eb131035e0565b67e03096d6356e168932be528a6d62a6d65c12c360a052609d60c053607160c153603160c253608460c353605860c45360b760c55360ea60c653603860c753606c60c853603360c95360ad60ca53607560cb5360b860cc5360b060cd53600960ce53602e60cf53607c60d053606160d15360a660d253604060d353600060d4536040600060d56000607f60097f2c1ed359cc60aec22438443f3489dfc9b14ff971652c6f37440f4994122fb85ff2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x87f2957b7228EC6a0dd4F2fCc669BD2ED2B14E11": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xbc501cdb0096cc68817e5b2aa2eb7e97fcf45a56dbd22b6e2de2b234b51f12d5", + "storage": {} + }, + "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": { + "balance": "0x989680", + "code": "0x7bc9700000000000000000023f00c00014ff002c0000000000002231081967d0212626262626266d01000000000000000000000000009010067e40000000fd000000db0000000000000000000040000000fd000000db0000017176767676767676767600000076767676767690061a7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff06900b19717676767676767676760000007676767676767a010900000000000000000000000000000000000000000000000000901d6000551569100000000000000000007a010900000000000000000000000000000000000000000000000000900690159014671fffffffffffffff6f8000000000000000000000000000000090077f7effffff800000000000000000000000000200004400000000000000000000017e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006847839214543589705209600155021960025560006b10000000000000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b00900919600355671fffffffffffffff15680100000000000000006780000000000000000719147702ffffffffffffffffffffffffffffffffff0000000300007ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000005901a7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a006fdac7fff9ffd9e13226262626262626000515900b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7702ffffffffffffffffffffffffffffffffff200000000000651ce97e1ab91a900860045567800000000000000067b368d219438b7f3f68210000000000000022900990076005557cc9700000000000000000023f00c00014ff00000000000000002230080568010000000000000000901c637fffffff717676767676767676760000007676767676769002127f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe760fffc000000000000767676240000000000002b0576047900390136006557ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a006a0100000000000000000000036007556101111960085560006b0100000000000000000000007d76767676767600000000007600000000000000560000000000000000000090087e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0063800000011690166f121212121212121212121212121212126780000000000000019013057f82000000000000000000000000000000000000000000000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200000363800000017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10009008900b6009557e40000000fd000000db0000000000000000000040000000fd000000db0000016a0100000000000000000000900413600a557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6f121212121212121212121212121212120a600b557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f7effffff80000000000000000000000000020000440000000000000000000001901460006000f3", + "nonce": "0x0", + "storage": {} + }, + "0x97511db90b0e141ea4cb42e3b73fe3C24c3D5676": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xe0f8e02e171a2ef7eae37783ecfa6acb82cbacaaff229a4a403134ff420cb4c4", + "storage": {} + }, + "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": { + "balance": "0x989680", + "code": "0x7f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fda62acddc27903598f1ddb505079f75a053a7fef4ccc0226f329a17de2b9b07f6060527fc2dec62772a59ab41d9b18a2c73337eaa9aa3fe8fc601987b1255f567d9d38d66080526020600060a06000610100611b04f46000556000516001557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611b2ef26002556000516003557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a060006001610100611956f16004556000516005557f57f8a6f7c3f645443cfb67321cd9c90976533d2cf4694275284018e7d00502fe6000527fc542900c2dc5f9792d3b72ff6102bd1e91f6085de62264ae37160378bcfe1b126020527f602b4b4f830c525256827f91011797701b9a95cd91a6b479634c0d8b7da6193d6040527f646afb1b2d301d0d563a1a041858c646ca0f5ad9c88933d039ca8054ae8e9fe76060527f1c805336320e07d97255daa4f56aa8f70067f661fd58e36f86bf37dceb52f4bc6080526020600060a060006000610100611c63f16006556000516007557f535cb327ee8076e255306a99e24004dc0fe803cdda5fc1b1c80cff2b2be4b4566000527f928b94b18ace4fe3705e3be1552c001258a8453a5c390ae9edc7667e6cee6e746020527fbd807c3b3183046f09199d87d5164eee161b6b65e77cd48d9e252f14fc278eb86040527f8c9b92eaa05719ff02813758277a97b44bee954d63c0baee1ed0d93a3e9aa03e6060527f342b583e2ce51c261daca46acaa8c051224903898e638c9d1ca2719c1d8d6def6080526020600060a06000610100611c1ffa6008556000516009557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c7760005265200000000000602052652000000000006040527f1e7b39a3889ab016e0104c5ab9a8ce088bb14bf824070d6927aa876a820f6f376060527fd40f3c998bbe847441d310bcf4853d094ba76414809556342a231e2fe65c63b86080526020600060a060006000610100611a8af1600a55600051600b557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f06567b1f15418bf2a6c5acd78e62159b8b682f2ef0b6f58a7fbe158943fc74d16060527fff848424bfdccf985cc7e451014000366747e559808a302682b81e678988fab86080526020600060a06000610100611a9cfa600c55600051600d557f7e47794e17a1bf02718dfec57b82b103e96d7e6f953e52385b498a5712cb7df56000527f64239ad45dc382b3eefeea8f23911594d78ca076317e9f9b7960b4f8151be81c6020527fb218b903bd81401bbf734d5a2315922f0c406ec792fab423aff997bffc0bcf526040527fe41441ed659010822b187ecb4eef5d733776c9c9526d20ad3560c87afb3d07756060527fe11cdcb149b52e6547ecacf066c0a92fbc349c3cc21d7e47eda1467ca3c1dafe6080526020600060a060006001610100611a33f1600e55600051600f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a06000610100611bd0fa6010556000516011557f4230ac0ce5216e094ef085206a48af255d3bfb7f11f1154fe86e93cc01c0540e6000527f7d6fb2a29ba4243be0d466cf073f0c91f381af4aabea1c1ab16255c03a79fb9b6020527f06e6dca6036bed2bbdd06d85cd1c256e5262d952a96d0aa5696e8cbc6fb86d486040527fe4f47823ae5cd8f8e881941248e114c9d191868f51c6ff8d4a520c2b1e619b486060527fd0be45345ec0957cc0a7ca0402c3bbadb04a8973ed59064a43342929d75167ac6080526020600060a06000610100611955f46012556000516013557fe6d744e8c84673f3796ca2ab4cac4e32ece670c0e4707639e18549b4e9dc57426000527ffccafa6cdef92ae5f09ee8dd0b500474a4363e074b1b7c1e6aa9eecc96f5c00d6020527fd4bfa61ec6a1f984eef74fcdf6e9f4baba748ac2a645492b4b9ad71045bdba466040527f58042d82f7404f2ce84e49ad7188d2ee525fe17a2d0c225521963800573d75406060527f32fbbbdd801c61ad130150f74e7b98a4ddc2f40bce85aa7e0e50de48de7eb39d6080526020600060a060006101006119d1f46014556000516015557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f02fffffffd00000002ffffffffffffffff36b4f008f546db8edb2d6048f529706020527f02fffffffd00000002ffffffffffffffff36b4f008f546db8edb2d6048f529706040527fcfe9cd9e3865d36eb93ec8c8aefe537dcefa079e55a50799d03da8403f839ae56060527f84e5ab7dc40b1bfcdb5cf45020e9f98a6557442d5792722e71d6580b5324b7256080526020600060a06000610100611c12f46016556000516017557f4ce6a314bf39f6a13a2d79f56120c5ddc884ea3dd630b091501f462b1fb1ec956000527ff74b8bf1750c490c32e2b06d4aaa7a9cf52ca9a6174b528968ec5934239d00ae6020527f8b8f147f6325c4e4bf531d0d7452f1d64102fcb5fd74338cdffee1f27dc64a9b6040527f01060c697a1b1145fe7f273366539189a56770f32f68259080022da2d03fdcf06060527f1eb393010971afde7c33346378f4ed9876480c0493093869c10e6998d5e4ade06080526020600060a06000610100611bd9f46018556000516019557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527fcadaeb5d0685aab38931aa408da708e1fc2240cfd3e692405ea590fae72a42a96060527f2fde0a17840d08b2ddd90567fb3eb219a4498af7312edabca8381bbc053f544c6080526020600060a0600061010061195cfa601a55600051601b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a060006001610100611bb6f1601c55600051601d557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f55aaaa55aaaa555555aa5555aaaaaa55aaaa5555555555aaaa5555aa5555aa556020527f55aaaa55aaaa555555aa5555aaaaaa55aaaa5555555555aaaa5555aa5555aa556040527fc9d7038f7046df28b1c52ab47bbd9e743b96259dc6c1a5aa37bd0f61859ea3996060527f7789d6c41415f62a7c6d42c4c03efbdd920a5687f062ddeb8903830b9ba59fc96080526020600060a06000610100611b81fa601e55600051601f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527010008000000000000000400000000400006020527010008000000000000000400000000400006040526f120040000000000000001000000000006060526f120040000000000000001000000000006080526020600060a06000610100611b87f46020556000516021557f88ef4ac1bd71522fb119c27ada9a3565c4c59b719ef1c5ff605d3ceb939b00c16000527f8e3123731ccaa2d15712f5427352e4f292fb6de2e48205c36b521d47903130006020527f360d418db19e848c902f3e9b0687f936a878b8aec3fc44898fcc8bed476f90886040527f8bd66669232a7307e3af41ba9e98e1c9bcc6c2cb1bcd19290d2c6d530b3806b36060527faff058330b9cd98a00323167cb85d0db1f61479c03acf5ccf081186c8913d9796080526020600060a060006000610100611916f2602255600051602355600060005260006020526000604052600060605260006080526020600060a060006000610100611bc9f16024556000516025557fca849b4c9a4205b12124c817ddcbf4847c033e130b3a0d20ed69f6b23c950bb76000527f3dca9dac712d28e081bfc4baa2adf4f8682ae2f4f4b9da7c003ac5ae8a358e646020527f55da3ebc3e6253f26fff786271effe89802c3880bbffc899f96014ca5ab0cb686040527f2f8101fcbb1bb9df8d89b1cf4d9b16cf539d2be4af0b3b593f3c3b64f15200476060527fd21c42acb6c9d34469fe759113a847175edfa8a629b9f818566f46dbbb4c38246080526020600060a060006000610100611c47f16026556000516027557f99ac9dde4f6675ca1d36afbfacf04bc463c2cfbaec70ea51c9da4de693cc2b926000527fc4796c56cf05874d9dca8ad22e242367c4eb946ef1403e0f0b31aa8a82d3462a6020527fe29fdbe9aad9dcd0bdd43f8631bafb406bfeee1928c5c95b840831d19e5672db6040527f35643c199d007509e9adb05724cac3f6375bff7be0cb8809f18432a666850cf86060527f8d623be41859ad127e15e5c841d8be44e9f745d8110b2aada89e60ceae897b876080526020600060a060006001610100611c5cf16028556000516029557fefbbd6857db26ab2faa74a46e8075a2ea1950720cb94fb676e7ca9a5ec90def76000527f9b64ec29fc397751d4baa368bf4833e82a85a6b315280fa27d1b948022547ee26020527fc4a2746dce7b72a9094289836387233b097720ad3a65622b259e71a6f28b2aa66040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b82fa602a55600051602b557feae17c0e1411fa0aed7bdfd3afc1e59f85b60e19a8f8e2fcf912481ce42c6ec86000527fb7f329f0fa26b456c94dd7728a9c795655d39144dd37fa5ab2d16badb39a9a0e6020527fc6b3b1f287e23277cb1d27608a95a428207a8ae1721a4a004653815f43e252896040527f61d358f21da2aa3a593bc15aafe7a88217556401d687cc10bdf5ee5deac2a2456060527f44bdc7b569afbecc115de3aa4f2b2b692b38c3095c830ea4b9f8a21b1cc1dc7e6080526020600060a0600060016101006119b2f1602c55600051602d557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fe6631f1c321035ee89178482078ce3428d97ef91de4f2c9fba2dfdf296eaaff86060527ff374e4cfbda2da61927aefdf99f3d38d4aedf1ea9e99b3d37505a29858a26d906080526020600060a06000610100611952fa602e55600051602f557f9fc62f83fb8c9dd1b9bd9346fa459174294f44b2aa3f6bcafe23d61ae5e1b9126000527f6133ac5a4a5a4732b24e25d0947ba4c399039d326cd81fca87102d6114a2f3f16020527f1838fa42b4ce50f86fe545cd9998b4fa08926d3fb98b1a75eab0a0c850488e1f6040527f97fb30d0bd03dfbbe22bde034b631e6c4b44981d7efff205ec83ed80c8a244886060527fd5a8987fcd6bb092b26871d3b3d7214682783e412e2d247a6ab735a59bd692046080526020600060a06000610100611b52fa6030556000516031557f2b0d74c8ad94bf9168305e77b930d7e66b1467439fcfcae9ae160cb4681abd396000527f08180ce104c5ffd56ab782f4b7a2df4255eefc0b4239f5f84335127f744fea0e6020527fa0c8527c9cc5c2221dc644e7479db9444533d56d6da5d9dc33bd8d86e2ffb99d60405260026060527f46fe64157cc965de86c8479aed407caf925052267ed6cabd25e110bdf45ecdc96080526020600060a060006101006119d1f46032556000516033557fb5bf3fda78cf36ef7037905d5210611ca0de5a749cffaceef0f98a37752c03886000527f41ba296bc996785e233b10dd0566adaeffdb62aff99637bf86b15b4dec6ebbb46020527fcbba6c16b4894b5e67d4e9a73d33a5820c94347b14db0f6c0db20b20d654a87b6040527f2a95275f9d50e9c9758b1768b718224106a7bf810d5085f7ce468ed680088e436060527f0a1a0509b915ed3d0d216cabc9617eab026dcb8c0bfc879deca2d66107020dd66080526020600060a06000610100611964fa6034556000516035557feeaceed8e997346864eb79cecb3de252aa8af678da0add3727718b7cabd681e96000527fed12432d2e8e8e5ddd5e754e444a6703503c77cb78b07ff9fcebdc8d607fd3fe6020527faff8368c4d1b501184a9f72d061237b2e80a616b88868fb16af22dfa1681dfb56040527fd01988930efebb541269070bfb6fd062aae89208ffdd7b3dc72401094bdfe39a6060527f32eb46ca28cfc45005fbd8dc3cb6ad45fa747510279a672045c4055bab2cf83c6080526020600060a060006000610100611bd3f2603655600051603755600060005260006020526000604052600060605260006080526020600060a060006000610100611c98f16038556000516039557f484f37e54c5295cf36fe10f6aff8c229bd9aa65603a5219b46c6129f33d83a906000527f789a4669c419bd471741f57ecea4239aa11fdd902e04af9e29f13ed3ec9c796c6020527f918a4029a6b2b0b14ced5c0c3038378041dc9ed86b2b62c2db603c3a381ca1136040527f966eade76bca84cb2ce407de7a840f6d19190cf918c12d9e3a99ffcf4566a2f86060527f75fa0692a5caafb1bf87d436f99e88f5c6c28a176807517f6e64e0a34b23e63c6080526020600060a06000610100611a90f4603a55600051603b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527a0200000000000000000000000000200200000000000000000000006020527a020000000000000000000000000020020000000000000000000000604052788000002000000000000000020000000000000000000000000060605278800000200000000000000002000000000000000000000000006080526020600060a06000610100611ae9f4603c55600051603d557f6b56c62902da512a9f2f6a1258155ed595a09172d2f5f45b04be21552e910f986000527fbc305a51d5165a978c2d6464030685c2d381e622c87d2ae925788ea762cda08d6020527fe2d02b525f2d094366031877ebeedd2c6016bedab9b0616283f4b86756c02c916040527f10d424688c564c78fffbf8100adea4e5df2b26b81e2d34f36b12a6debedb4a656060527f4321dc8003645b904eaaf90a5a8065693f063d8590901c68b501e6ba3bf358e96080526020600060a06000610100611b44fa603e55600051603f557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a060006000610100611a76f16040556000516041557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527f625bb93891671304e13ac8dfccd4810b590321cc0d59f12879c0dec48bdda6566060527f57a412e8fb34f5ce3705734c4bd3ef4bde25e0afa47b9da61bdf1f6cd39a00766080526020600060a060006101006119e9fa6042556000516043557f2bc778e01d771a8a4d88e33c2aebfbefe484eaf86af48a14ead2133545084a2c6000527f095960ba6bdea4f7c1f23832b6b18d34d47c06b4a6b2b71a5cf78c0cc016fe3f6020527f7cbf2333cd08c279b26b7ef66d46f671f0d80fbe95dfe456b9a81eb12bc754396040527f8a292b9ce0dd42d054f219d841a85ead3b314c92f4bc5fc2a14c2894a82723596060527f09b415cbdda55d538a4f1d4a7424727e00a03c1acc229a67a6942180503fa2106080526020600060a06000610100611c4afa6044556000516045557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527620000000000000000000000000000000000000000000006020527620000000000000000000000000000000000000000000006040527fde78cb7d6ca1833eca52dd642e9e385a572d0a13a82cfb801eb93accac19f5c06060527f2b8c37f2bf887ca80a8ba691631b072b925c5cee29092de8f0ab088c334b5e8a6080526020600060a06000610100611c3ef46046556000516047557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611bf8f1604855600051604955600060005260006020526000604052600060605260006080526020600060a0600061010061191efa604a55600051604b557f927dfee61e50c7421808524a7a90f8501e0ae985faf4ad0feda06cc7ab3ba0376000527fc911cb77f5fbcc18d1fa9a2473e882ce34eaaeb259e2e3576aa121f3ceec5a716020527f78760ebce4be5905ea0b78337e1eddd627d8a997e121c691395697b909af4b676040527f3fa97b02bdb27aa7403c6dfc2692e25923d4c079e9226030c846ed22dd4f986d6060527ff565e832ba9e1d1285b75c6eecfadbe08a5164384d40a6d42c44e9b921116f746080526020600060a060006000610100611c40f2604c55600051604d557f17d331b36f45839e05e4672575bbfdd5ce3de9ad758c5956d3c91c9f723658006000527f9e0eaefb650f77c7c2f1612e42149b83d25d130026c2990fadfd7f5f2ec321616020527f3186b54dae60571d2ee512b7083864c201a9f729a1c93e530cef6cd6dfe5743a6040527f921f646ea25327d75882e7d17671b87bfb904fb78d1c5819e4a1c582ec0e309c6060527f2d3b43bcfdeda5ed8ea601d767c7831136856a80af463726d9185b3a026e0c6c6080526020600060a06000610100611a5afa604e55600051604f55", + "nonce": "0x0", + "storage": {} + }, + "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": { + "balance": "0x989680", + "code": "0x7f0dd9ccf5a133f80f284d8119e5766fdc78abed0168e6bc910b5e0176c951e4436000527f0628c4db9f1f4f2178752223a627a0cb465ed2518827a95123c2ece65f44b4316020527f0499075786280ef4bc72e7855ff33456d8c6f125b7d1d9baaad011ea2ab9e6986040527e97cdd77deef597a2bc16d88539d254cdaa55b105a027c6ab4b83b1868370fc6060527f082be0895fb2a2e368b460cd15b64c844c38b5dc16a4b1c92e5e2798975c56926080527f1ebcfe5a688616de67316604ecdea93879b25612a3432ab4e14a26ffb53d128760a0527f1bd248bdf180ee660835d6b590c4fe6c50ccd0a060555ed2c8f37629165753a360c0527f038ba6f6510fae553b2b3ad7ed616f923858382c71b8054054746de16bf76c6060e0527f0afe62b544bd5e08f5a4d990f3989a0352495686a22f480a183823c5c0b6c3c1610100527f166f65225783504282adece0b7a23103c45a60be1b8035718589cfa007dd5bd4610120527f0636a7022c573e3bb500450a6a6781193917487a4ced2aff1a54f329a257953e610140527f1e1b2efa9cab213ae4dbff879a0610251c40ac9a41dfea3113eb5c8318c44fe3610160527f0919d4b775568b4448a2598e2aa74143d4cd29f5f94c6993cc4858c9d490b9cf610180527f2ce72450da563b7b4d652c83f0442b76d557e4eabc5519fd14d1fae51dbd10f76101a0527f0c5ddd9a6ddf253c840f29e6f1f5589039a3d31d8969dd70bc7786f7c14992fd6101c0527f0464740f9667555139ab1d405612f072c81773fa2df80237f0f30d4dd8c92c846101e0527f2c984c8a12450a4f78d13b602226bbbd93dde861fcc37f6a60ec69721d880195610200527f1356ee4dfb103fde3ed6d9a430fa55187814fb6f1688f5e5f73be48bac31d74561022052602060006102406000608660087f823050ef163d7d484e8a5a18e75335c1b282c3e3296a1e348ef6be914ec253c6f2600055600051600155", + "nonce": "0x0", + "storage": {} + }, + "0xD74CFe323387aE2fd070CD046173026716D8D649": { + "balance": "0x989680", + "code": "0x7f014578955e56f6b52f72afe95be88f8080692a1af480fc571addbbca08d5e1b26000527f6b65fe58c31529e42775db26d33a3b91d21952719de31b77b4c57f84c71e69276020527f4a78953ce832910d03e29be38626662621d587622aa95bc1aa396eb65c0fc9de6040527f9278fe0e25e1b7c612b89b3219bbe81f9a558637ee40ad3e6b4c23f00be36cd86060527f28a2e51b0fa05f2973fcedb329994bc6975e405a52336c9c1d6d7f65a3f041726080527fc4cb93a0c12afab3cf3fc961123f659e89386c086b8f8c03d651ba549d34411260a0526040600060c06000600a7f61824de34891d5dd5d68d637e3889f76a90b610e42c8d6340cad9ed9ac966da8f4600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": { + "balance": "0x989680", + "code": "0x6000600052600060205260006040526000606052602060006080600060016119fff46000556000516001557f5635d69609767cc55df05457febb80b0042d87e81eb1d22f226de79a76c708d56000527f7738ef82f2a4e2832f532706eec1556d2f325c8d5cd7930f9b3b4a409c85a71d6020527fe23a41f46cdbc28e002d9f6cc7b11c4e259671f69e9d03f4f4e45b86c9d6c5cd6040527f2531f0ec7f10dbbfff9f4b7a5d94a4f4d49ad9ef6a3de8f38ab1e6372d1e5e32606052602060006080600060006001616727f16002556000516003557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fb3bf27de565ff9a8d996e8c6f4229b90d3d785882396fc871a67df2777390a456040527f4e6497845945c0d9d7b5686784825970f0e17404398ccd269eecbd3cde93adef6060526020600060806000600161d628fa6004556000516005557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f90cfb0a7e935f0e0e195c789fbb8fd85981430909cf043ddd784e13765fea44e6040527f4788f359d9f79d7e1c54ca4d982556c9b1760282a44c6344edf82108ea60b27b6060526020600060806000600161dfdef46006556000516007557fc5c3f0ed9812b3fb0cefc109617fffd894091214ef719cb57933b24c3ff7ea166000527f34f0eb248c0ad3ce9f7420c2fc2ad0ed06cf7fb6a63a679e89e7f63806706b086020527fca6f9a3c432db550d8a783c7a39e13aa23a7ed46695c52666c858c6a85c0743d6040527f568ca38fda9afebc390205b01ffe0b32479e93802e56121bc36986b476c5bb2a606052602060006080600060016201318df46008556000516009557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f5182ddea0d6c800d464f74dd82bbae46b370e73745a2ef5be0d1cd78e8b63bcd6040527f4d8aa48e8e4aa324d6b5b0568413627f3088650584f26f7d9d230dd18bef7220606052602060006080600060016001615f50f2600a55600051600b556000600052601b602052600160405260016060526020600060806000600161323dfa600c55600051600d5560006000526000602052600060405260006060526020600060806000600161e876f4600e55600051600f557f9cd1c9e669f25ff0d75358a68b742c499dd507b1929e69211f9dcebed088d2396000527f3197fe1803571e9dcc547d0914727e57a04f413c7fe0e80df6178ba721e7391d6020527ff6f60e0b8b56deb4215aa5a8791e67cccbf67bcbf28a00ddc01aa9e2834bcba56040527f5d82dc04d961c9baa8607de329bbfc5c0fda7606fa685b8f637c96cff204986e6060526020600060806000600162015414fa6010556000516011557f48e61e67c212051774e251f4694009e70b0c8cd3e53f546bd571a89cbd5d77866000527f482558bb150d8505183572baaf7a364052737fe23c1ef7883320a2cb0353921b60205260006040527f2048679e6e96fbd4128e4da15a24443d8118cde5a019a700164135e810bd0a4a60605260206000608060006000600161e2bbf26012556000516013557f36acd9425393d15e3eb4812d51043df238ef8864cf7e0d11b59e4fabdb18cf8b6000527fb65dd238c5703c5cf7eec9884f723f689330e90cf77801118035141dd442c01c6020527f8d4eceda1b4fa1f96eafc840d34ff01e2a1dec56c33838a8141d1f9b1d4811f56040527fffff8ec6cc8d5304fff1733341f73d0448e8de858f72fe1afaa8cdcdd894416c606052602060006080600060006001615e79f26014556000516015557f16cf9ac0524c5cdee7ba74b3dd710d75cccfc885ce042fe1e95668866a1bc05d6000527f7d3dbde81de980b22866b25af9b31ad7a8f45bce7feb7bb3327b91edc5536c336020527fd28c824dcb997cdfe976e7f9e4f62c09ebf1d53e969e66f045e2cd686f3996e76040527f11e5c0bfbd64e28a8078a0d9ee926aecad8bc52d65cbcb89892a169afab5142e60605260206000608060006001600161e126f26016556000516017557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f2f63ff12ae5e48349a3cd273ecf7a16bfd325fb80c1b3601bb1c3b6958fa76416040527f4641561778dd3463d0124b1fd9432a9cf49d4e22c761e6ca5f2a88bda1bfc05b60605260206000608060006001600162018551f26018556000516019556000600052601b6020526001604052600160605260206000608060006000600162014e9bf1601a55600051601b55600060005260006020526000604052600060605260206000608060006000600161446cf1601c55600051601d557f8bf2abb1d2d1ded3bc18adf47c552ddb500f5e4936d62c2a4bbd8604e1b89b086000527f69c2dcb690ba7704bef53049a822ac4911a7eda430bf3f1919e1ccc46e05171d6020527f5ad9fc0129eccf96c24be1edbb6d90b2baff6286288c52b86544c944d778aef56040527fee6b147e5aa16966cc768773eeba18d4ca5ad8e7b1fed292547c35ada4548eb760605260206000608060006001615edef4601e55600051601f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fb3882d7cddbfb1aeb96ea275eeba65cafd3c057d53a4650c8a623dc5d90552176040527eff0997551623a79a5bc1c2e0285120219d911b571006d7178d7b70be8506ae60605260206000608060006000600161c05ef26020556000516021557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f0535a453701693dde78ff230e8ec5482f5a1087b3519b6e27f47fc871ea52c236040527f46e1c6e229537c9c25a2197a51d331418065a8a749b8c2caecfeb4138ddc661b606052602060006080600060006001620149d4f16022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f6fc20df9f44aef7af01c979f835f67e0d1426f0802d6c4697844fdb5928d46716040527f4a8986d60152dbe79028c9854f61f3bb229d465ed2296e191a59caf1e8f8196860605260206000608060006000600162011d1ef26024556000516025557f4d11001caf9bbe5571fc607b41905d585f8f1156c87c3b2a1402fc525802790c6000527fe90b1362fcba1f8347e103984f99ccfec324a2f9f4635c4776259f29f60b4a1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f1454f2b26fbdfb65f37eded4dec22e9cab0feadbd60b34913691b1d08c7b008f60605260206000608060006001600161bfbef26026556000516027556000600052601b6020526001604052600160605260206000608060006001615a0cf4602855600051602955600060005260006020526000604052600060605260206000608060006000600161f2fef1602a55600051602b557f091972bef5bee21dba19e42b89499d24001da47956025c9acdaa32f2caf1aceb6000527fce3ffe160fbd50f0c627da01036b788e8423201346a6e7ec67b8e81f69d6b41d6020527eeef5f26b4d5201c901905fca0a0a3c1f53156962becd64ce499aeac07b85086040527f024974992117a12a2c64e1b3a8e547e45418b905b5b644bca78eafefc2582ce06060526020600060806000600162018411f4602c55600051602d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f19ccd9280715e451937d27a22990dd8c7f2528581c8d0f55dd3e0c04a68adf2b6040527f3ab9a559dbac4213538275eb6df877b42992eb9f36cc3786c62684ceddb0cdbc60605260206000608060006001612800f4602e55600051602f557ff40546baf9aea56fe68bc14aaaa1e9d21509e81f21af4987b84fa5baa893cf046000527fdfd0c846d634ef20cc13379a6382995d388806421855e2c64310a6c719bea91c6020527fa5ba6c38881bf21b5a7dcfdf690975abd5e5cc39bef2af15d7f5d0d9e5e400dd6040527fffff424734ae111844e2ba4fb368be44abb4ae3505608497f5d12526ec74f8cd60605260206000608060006001600162014526f1603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": { + "balance": "0x0", + "code": "0x774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a900a637fffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0407682100000000000000227ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0901a191a7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a0067800000000000000114901d60bf55778200000000000000fe000004000000ffff000000fffff7006f800000000000000000000000000000000560c055760fffc000000000000767676240000000000002b05760477e40000000fd000000db0000000000000000000040000000fd000000db0000d37e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000096a1000000000000000000000684783921454358970521b901a60c1557f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000017f77676767676760000000000000001002e000000000000040000000e000000000901c682323232323232323237f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd901d90037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6005900760c25567b368d219438b7f3f600190140660c3556c0100000000000000000000000060051b637fffffff67b368d219438b7f3f90131c6f121212121212121212121212121212127f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd9011900a60c4556000637fffffff167bc9700000000000000000023f00c00014ff002c0000000000002231086f121212121212121212121212121212129014191d7e40000000fd000000db0000000000000000000040000000fd000000db0000d37f8000000000000000000000000000000000000000000000000000000000000002900b900b7e40000000fd000000db0000000000000000000040000000fd000000db0000d36f121212121212121212121212121212129002077fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f7effffff8000000000000000000000000000000000000000d9000000000000010760c5557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6a1000000000000000000000901d136b1000000000000000000000006c01000000000000000000000000900a900360c65576013590cab83b779e708b533b0eef3561483ddeefc841f56005177e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a006a10000000000000000000000a901c60c7557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007a010900000000000000000000000000000000000000000000000000106c10000000000000000000000000677fffffffffffffff1a901a60c8557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd197e40000000fd000000db0000000000000000000040000000fd000000db000001677fffffffffffffff1b0b7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9901660c9551969010000000000000000007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee900190066a100000000000000000000076013590cab83b779e708b533b0eef3561483ddeefc841f59011067cc9700000000000000000023f00c00014ff0000000000000000223008057e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10001090126801fffffffffffffffe6f800000000000000000000000000000001b900360ca557780000000000000008000000000000000800000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b0090047ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90107d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97a010900000000000000000000000000000000000000000000000000678000000000000001900890191619901501717676767676767676760000007676767676766c01000000000000000000000000901d900a7f7effffff800000000000000000000000000200004400000000000000000000017f82000000000000000000000000000000000000000000000000000000000000000790141560cb55717676767676767676760000007676767676767d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9077702ffffffffffffffffffffffffffffffffff000000030000651ce97e1ab91a06107e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007f800000000000000000000000000000000000000000000000000000000000000190131760cc5567ffffffffffffffff760100000000ffffffffffffffff0000000000002e0000006d010000000000000000000000000090081567fffffffffffffffe777effffff80000000000000000000000000000000000080019001900560cd55717676767676760000000000760000007600007a010900000000000000000000000000000000000000000000000000901d600767800000000000000106901b6101117bc9700000000000000000023f00c00014ff002c0000000000002231089005067fffffffffffffffff7effffff800000007effffff800000008000ff0000010000678000000000000001901d901c681000000000000000007bc9700000000000000000023f00c00014ff002c000000000000223108900290187806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a762900760076761e000200767600000000767676760000001401760fffc000000000000767676240000000000002b0576047677000000000000000117f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a57a01090000000000000000000000000000000000000000000000000068066aa0a5319bcf5cb408901960ce550a7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0610111900b60cf557cc9700000000000000000023f00c00014ff0000000000000000223008057e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000111c7bc9700000000000000000023f00c00014ff002c00000000000022310863800000000a90016847839214543589705263800000000560d0556101117f77676767676760000000000000001002e000000000000040000000e00000000090051c777effffff80000000000000000000000000000000000080016c10000000000000000000000000900760d15567d021262626262626677fffffffffffffff137f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6f12121212121212121212121212121212651ce97e1ab91a900990071463800000017d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf99017027ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff6380000000901860d2557f77676767676760000000000000001002e000000000000040000000e0000000007f40000000fd000000db0000000000000000000000000000000000000000000001901790067702ffffffffffffffffffffffffffffffffff0000000300007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0790016801fffffffffffffffe7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00181502778000000000000000800000000000000080000000000000007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb01419166823232323232323232368478392145435897052180a651ce97e1ab91a7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200000a60d3557f7effffff8000000000000000000000000000000000000000d900000000000001774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a06016a01000000000000000000007e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a001290031567b368d219438b7f3f6b010000000000000000000000079014651ce97e1ab91a7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9007760fffc000000000000767676240000000000002b05760477702ffffffffffffffffffffffffffffffffff000000030000638000000008181b7f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56801fffffffffffffffe9001191a7e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007176767676767676767600000076767676767690139002686d5adef08547abf7eb6910000000000000000000020a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f40000000fd000000db00000000000000000000000000000000000000000000011160d455151960d5556780000000000000017ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb090187ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff6f80000000000000010000000000000000901460d6557f7effffff800000000000000000000000000200004400000000000000000000017f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5901a90077e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00680100000000000000001715901d7d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9760100000000ffffffffffffffff0000000000002e0000001714712000110000000d0a300e750a000000090a0a6770000000000000007f8000000000000000000000000000000000000000000000000000000000000000900990057e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100076fffff716b61616160b0b0b2b0b230b000008010d0a2b00900490126f800000000000000000000000000000006801fffffffffffffffe9001686d5adef08547abf7eb76fffff716b61616160b0b0b2b0b230b000008010d0a2b00600190089010146a10000000000000000000006b100000000000000000000000901360d7557ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000610111149010712000110000000d0a300e750a000000090a0a63800000019007177f40000000fd000000db00000000000000000000000000000000000000000000017f7effffff8000000000000000000000000000000000000000d900000000000001141b7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb06823232323232323232306147f77676767676760000000000000001002e000000000000040000000e00000000060000b197f7effffff8000000000000000000000000000000000000000d9000000000000017f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff0000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9009901a04760fffc000000000000767676240000000000002b05760477ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9018901160d85568210000000000000022671fffffffffffffff017f8000000000000000000000000000000000000000000000000000000000000002778200000000000000fe000004000000ffff000000fffff700900b90167f8000000000000000000000000000000000000000000000000000000000000001774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a900590056a01000000000000000000007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00031667fffffffffffffffe7f800000000000000000000000000000000000000000000000000000000000000017900a197ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000068478392145435897052901060d955682100000000000000227702ffffffffffffffffffffffffffffffffff2000000000000390150a684783921454358970527e40000000fd000000db0000000000000000000040000000fd000000db000001901a900760da557806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a7f7effffff8000000000000000000000000000000000000000d90000000000000190187e40000000fd000000db0000000000000000000040000000fd000000db0000d37f820000000000000000000000000000000000000000000000000000000000000090117f7effffff80000000000000000000000000020000440000000000000000000001760fffc000000000000767676240000000000002b05760476f800000000000000100000000000000000960db55901760dc5560006000f3", + "nonce": "0x0", + "storage": { + "0x00000000000000000000000000000000000000000000000000000000000000dd": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x00000000000000000000000000000000000000000000000000000000000000de": "0x000000000000000000000000000000000000000000000000000000000000000e" + } + }, + "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": { + "balance": "0xffffffffff", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "storage": {} + }, + "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": { + "balance": "0x989680", + "code": "0x6000496000556001496001556002496002556003496003556004496004556005496005556007496006554a6007556006600855", + "nonce": "0x0", + "storage": {} + }, + "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": { + "balance": "0x989680", + "code": "0x6101296000526101296020526101296040527f69e81e3e7395914bd7a174171c2abb5872a3f74bad925e171848173397d0f4ce6060527f305d0a55de9a15923e02507df70929ce7a6e0475b4153dfda8d31734ca31a7296080527f6f40e534fd50742c50dc37c0434cd6336a9a5eb9a2e45ed8d975dbddbce661eb60a0527f1221005f45cd8a15ead74d3531129fd35a822daf4255b9cfea9dc0a2e5bef40160c0527f326aeabec0290bd67bc8c0835c9b899e66dc95ed43ce31d3580fa75ceefdc43160e0527f897c7d3a7fc2e9db1eae97afdb1cbfdae405d6093612313eb18b23781d21ec6b610100527f398f99408e87f8f74c7b2df6c46c35547884c8a3d4e9578775b11d452ed8f615610120527f7c6d97d68312ab514050a3ce3beb54356639efac32d6945047635cbe25448f74610140527f1ec847857382073929b34276a0e24b618cacc3f231dc32bc7f0e6599459c1ff6610160527fcb3707198b19ed5a4bd071c3a57a194e48a9a63c4b7de8e6954512bb6ab2cb55610180527f9cd5eb4f6f1430634f33e3d0cc775581dffc61ba1d1e3d188c9574d3e01576936101a0527f467247bd7ad3a43bd64bba6815bb51953d11ffcc1d26572d43c48e478e8c5e996101c0527f397c09d19c92b79ff9e7eff33d517220dc0ae525cc76b8bbf0407189aadbec236101e0527ffcf0525acc205a9b2f0cb0a353e5b82c0da2b68c042b8a4212682f22a1aec7c2610200527fc3d4186bf05e8a8785e0c129a5a0d951f82d409eccd3d89237fb46b530f1de4e610220527f25f22b01d268d08f7793386bcdd8a84426761cc3c231cd1eabe8eb6af296e082610240527f2efeda8ce18279934df1c2f78981298c2b1982e1460fd2d12a2cab72134f6ef1610260527ffcbeb4de92c1037e3aff1bd001b5c9d763fec0ba3c782adf56d278f055d6c67c610280527f49aef127fb8b37b2bcc87b5201325b5c5b6bccbb5a9da51b00942fa86dc143f56102a0527fdd86c4c44ef5fbca928a90b54ae77be694ea2ea2b601356817c81882979e281f6102c0527ff8e07e025ebd4a65c76f68bc9a6e50c83ead6ab102aa166d0d7a687d3590c44b6102e0527f78b0a61e9d2fcd1813363be2cf16957ce8cb1285f90b91aa32ec305a1233ce2b610300527fc69de814bd478ba07ae5167dc1686cc2dda01fbcdce97d09c16cfc6a6cab4ee5610320527f2c34769a8e26508f6d287cd1a95d355928cc5dbe0580707db6d3ac4dc31d150f610340527f49b59eb4f467447d0cc6113ab1b63ab67d27f7ae398d1d432582c2e8f6a4dff7610360527f550e23fdfa28e38ecc6b28ae82e8a26e0d8cca9e625bcf0897816de7fb8bb827610380527f6a3614910a6314bb3b7f081a174054536b82bf225bb41570f6bd385558a5c8156103a05260546103c053603d6103c153605b6103c253609b6103c35360ad6103c45360df6103c55360226103c653604f6103c75360996103c85360226103c95360156103ca5360396103cb5360326103cc53609e6103cd5360466103ce53605d6103cf5360cf6103d05360ce6103d15360fa6103d253603a6103d35360be6103d45360436103d55360ef6103d653602a6103d75360df6103d85360de6103d95360086103da5361012960006103db6000600060056301174bfff25a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e0516008556101005160095561012051600a55604260005260036020526101006040527fdf5f74a61ecca030138e6021dae95a5b368cae98b66c171812d2338bb86483e66060527fa5d7c8cfa18cda53cf98f7826fd3867d8fe9dd095e50d065de4d34d1cf88d48f6080527f0f9bdecc79c974a38d471073780296aad41362c1fda9885d9e789cab4b1ae54e60a0527f5aae2d5ef85a4d57afe48ec9d966da9ba744d517f8fad9f5502824033f94699360c0527fd55b0e001ee8a9e537e3761885d8cc05eaea065308f785bcce96f071b0853c5f60e0527f6c86b21c7df065ab5e94f5b1f69ce88c2e87fd50a9207bc9e29b2242194604ee610100527feee7d72b553031c54b89a8db874fb6946d115fae9037b30e77b8c0e39b50f4df610120527f4baa678533b3b484496b3321f1a53313d85cebada6ce98cfa7545e9b378cf193610140527f2032fd1ac0270d38f02e8432ec8d494921d7b7c706d5d5b0d7e0925ac818aeb3610160527f2835e066a94d1150ca5dd1af7b36b3105c9999b8229295830d1eee70dd73ad396101805260666101a05360fe6101a15360976101a25360c96101a353602a6101a45361010060006101a56000600561f68ffa5a01600b55600051600c55602051600d55604051600e55606051600f5560805160105560a05160115560c05160125560e051601355603a6000526103e4602052603a6040527f59cb660c0826be7706b5e062b238ad17fbf96d2eae2d89bc93e9881aea0495486060527f0339ed057e9aa557c676b245344845451ecac965862814cb13ad6a1d45e82ae26080527f4d1fd92e4000935a20b6909034d34b01b4e7ff6814f649ac3bc3dbe71eac3cad60a0527f69f3390bd3ce4afee1890e88d0e541c58019a9df73a2cd66964c2d034cfc5e5360c0527fc82d4950773b57d44e7161528597236e3614cfa5e54cafd8352a5abe115f44a460e0527f31760e86321b4347bb7823deea70704ea503067ecf4683f0ba5093d200ca45ce610100527f522e9393efbb864ffce417d0120084c0eba76f2fd2769e8cd5e71e0c927d5390610120527f030ab22e0ebc72b408291052cacc5ca32c1786a5888a527d74a72a6368a71a98610140527fe1fae46ccda64d1b1d588bc1ce80ee638626562b201e1fc23370f2b986af0f70610160527f9835a67ea548cbdd5cbc61a66a6feedf57f514d8216cfbdabc34e5fe985851c1610180527f0fd4604ceb36c7c98a58e1e3dbe176da1f0b92a858cbf7b66545cf28162057286101a0527fb8078e2a9b7fe21cc4bd3a6581c33056ed4b3031442d3c6ed9ef165634b3a15b6101c0527f29d8b959e94d587e725e5f73a69157ab9a9a60470488bbea5cb6d005066c9d726101e0527fcbf1d991de7de7a45b29f5408a8779319a21ab4f7ed873578ea84fb2f5c3a9f4610200527fcf72073db33f80ac63e9a12c825ccf52658f098e6f30a7a2398cc20519979cd3610220527f7f55da0405738fc69a98caf7a59ea205d4fa84efe99748effd6e763cc34f85fc610240527fb2aa10c82c9b0bb4bb6d916a57e70fd97d8c099af760268d684bcdec58b71417610260527f85008a08c9978857a3e7e055e7e9c86b7db8871d440806ad37bebab67b78d60d610280527f3958000361b187c50526765c4900a44261023f4c418b3e592da5e6b77f240c026102a0527f5340288abc1ad5421fc94f5e9be342f2bec6333017b1becd1912b45c4f19087c6102c0527f941d62ffbfbb047fd7b2a050757e246b197bc86e67a1ccdd85598f86e6ae6afb6102e0527f646fec060cfbc4f77e5be17fe7dd4a4082aea0a46b122a7058ea9492d96e8698610300527f4d7a189ca41c61843c598a8f197a2910a26c595be275ba67c28cf3c1c9e62fd2610320527ff287a0f088b71a6aab79a535d31111aa98a7fafa10d1ad802f6c1437a042cc36610340527fc39e979b0fdec7b5ccab8636ae3a1bf8e30b9ab564b51acc5fd767cd2cea4bde610360527f69a8f89674885b22757dd55d89dd2b5d7d72121bd318bfed01ffe7fb9fd5c351610380527fae7515a9426791b78ba37c231e6630ecdcbdfa73c9b0c293738d205bf883869f6103a0527fccc57c6c698c8a0de47c487da0244e367183967c4b3b65226ff11b6b8eeb777e6103c0527fbea49780f5480fb6ae0df0693c39b7a102df9268e4e011ca61b6dc7b51baecd56103e0527f8e9c5217aa66333950b594a2dec37f423a67bf65b9cb80a2f4d1b45c5c7dd7db610400527fbdb29ede3683d3904d533ee4df89d7db61ecfdb9b313377f1fabb76cc4955a38610420527fb10396556870f949e6c1ed83a081e425a4e5915beefd6d0d85f0643516089567610440527f1f348949c6143fceab9423d11f05656442bd666d73308e900d43ebef7bd7be0b610460527f489a7d036dabcb10f159d06a3aa2e326ca7976c5f5bc87e6f4b6d88bc9c310806104805260e26104a05360b26104a15360c66104a25360fd6104a35360aa6104a45360e26104a553603b6104a653602d6104a75360ca6104a85360056104a953602c6104aa5360156104ab5360386104ac53600d6104ad5360416104ae5360286104af5360f46104b05360af6104b15360b06104b253600a6104b353609a6104b453606c6104b55360f06104b65360886104b753603a60006104b86000600060056229a50af25a01601455600051601555602051601655", + "nonce": "0x0", + "storage": {} + } + }, + "chainId": 1, + "env": { + "currentBaseFee": "0xa", + "currentBlobGasUsed": "0x20000", + "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000", + "currentDifficulty": "0x20000", + "currentExcessBlobGas": "0x0", + "currentGasLimit": "0x11e1a300", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8" + }, + "fork": "Osaka", + "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f", + "transactions": [ + { + "data": "0x", + "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042", + "gas": "0xf42400", + "gasPrice": "0x20", + "nonce": 0, + "to": "0x538A8474EeaB43d5a960164c554A20400151D479", + "value": "0x52" + }, + { + "blobVersionedHashes": [ + "0x0132d6deb603df6639cddb11a72c84d811c0893563607dbfbdbccd7a1473f846", + "0x018e95a083430036a83e06d44d20e48c449c73887210b4fdb1754c8203e0638b", + "0x0117b08385e646dbfce1bf4e12453f47418f94c9210bd326a75c1e5f6ba466c7", + "0x010cd0225eb0ac60dcc3ea4ef75ab6bd7bffcc1a76bb55a714e12d56844e8d4e", + "0x01124668b9854fe4ecb676c9eb81b1bf469fd6e8e3bf726d1e996961958a2943", + "0x0132e4d95f2db408e3fe5a1e034a2f4782430712edbcfc1438ab49a7fc10003c" + ], + "data": "0x80e805", + "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62", + "gas": "0xf42400", + "maxFeePerBlobGas": "0x100", + "maxFeePerGas": "0x20", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "sidecar": { + "blobs": 6, + "commitments": 6, + "proofs": 6 + }, + "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89", + "type": "0x3", + "value": "0x0" + }, + { + "data": "0x25e79e54e8c02652f2565713d311d5cb168192a4d71d9a9aee1f946cdbd6e3eaa7", + "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce", + "value": "0x806742" + }, + { + "data": "0xc1a00893a8130b2ca38989576113d35462b45eecc786193b898d3eb239b6e712bb6968ed9aa996786e", + "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10", + "value": "0x56b" + }, + { + "data": "0xcda935393d196ed654f80a8b358db56e6f03ef47b2c7cbd02f981b1942af", + "from": "0x2837fE6BCdADEa40e14E73df3101847267659772", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3", + "value": "0x0" + }, + { + "data": "0x2ccc98abf7db01f4304e4590fd15868ccac4894b3e147950631ff47f5365e672b74b86bc4c34d454e28ab37da11eb194acc4957216d4f77ea6279804fea86abf0be0e98ff69c0b03df2bb4f889624ebc00d2b90dec25f6b27aa4625d29cbb5fa954dfd422dcf505eee5edc3d315ddfd4fbf1f1605fac0f2e4debf9f0c45d49b44bc6902663d567f91bd01e7a8bf300368d037c90a56a155a477262a01d2bd558dbdc", + "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb", + "value": "0x0" + }, + { + "data": "0x19a13a072bb4", + "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f", + "value": "0x402522" + }, + { + "data": "0xe2", + "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xD74CFe323387aE2fd070CD046173026716D8D649", + "value": "0x5" + }, + { + "data": "0x", + "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6", + "value": "0x0" + }, + { + "data": "0x34a9132814758b59273daa94386285ca6ec120a9d4481a23039b58152a8da551ea7308a94e7419cf89b239da0e569207cac855b71fab651a7b1738fc07791f901401b802befdd5aa04587a35", + "from": "0x2837fE6BCdADEa40e14E73df3101847267659772", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F", + "value": "0x2adf47" + }, + { + "data": "0xc16453d9244731365126c88036a7d21dc4e74b5e", + "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190", + "value": "0x21" + }, + { + "data": "0x8d80c554a0fbda8217a176413301cc3c60b0cf745f87ec393c2bff96faabf209afe5ff379b58c1a2150efd2f8ddea5668e528eb86081400aa5105ac67aed06755a5a4b5d45b83079a2fdaf7e9d90aa29756605b68d94", + "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d", + "value": "0x3213ff" + }, + { + "data": "0x50af4d2b0584036576383afba79c69f64fc2b71db10682ff80d5653cfdd52981f124f31baae8d20fff7e6aec48bf547e8c08651cad37205e8320a156f61f53f38acab75a", + "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c", + "value": "0x7b" + }, + { + "data": "0xfef68089f91a694f575e07f3f58904aafac957", + "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876", + "value": "0x4d" + }, + { + "authorizationList": [ + { + "address": "0x7564105e977516c53be337314c7e53838967bdac", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x36b7ac42eec8f5237477a6169e8c357399393f59bb26761056bbff43903482a6", + "s": "0x460efc6055f2d148029adb295d71d6df3e226d673bb716b5bf4b2521a77ccc4c", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000001", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xe6a79d6fca48ba50006d0503ccdc43c19f9f07ecaec4c496110ce6701d9789ee", + "s": "0x482ba8d2c8c39595672302abc39a714ff67de25ce1c4ce76d25e09ab86f8394d", + "v": "0x1" + } + ], + "data": "0xbfdc6d5fdd81ba0f593ea74a4a2e16aade24b578c028b7d34d5528ab79", + "from": "0x87f2957b7228EC6a0dd4F2fCc669BD2ED2B14E11", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x000000000000000000000000000000000000000d", + "type": "0x4", + "value": "0x3919" + }, + { + "data": "0x00", + "from": "0x66bBEf07B980c8b5de6F3DB0d5CA7A0389C7f386", + "gas": "0x30d40", + "maxFeePerGas": "0x1e", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "to": "0x7564105E977516C53bE337314c7E53838967bDaC", + "type": "0x2", + "value": "0x3e8" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x1", + "nonce": "0x2", + "r": "0xb69e5f919d0b7c265606ddcc668583ef819323ff6b65b9f0485cbadb495e5bae", + "s": "0x7296df3d02e403899fbe72a1676027a5216c5bf1f0891d945a992eaaf8b9b614", + "v": "0x0" + } + ], + "data": "0xbfdc6d5fdd81ba0f593ea74a4a2e16aade24b578c028b7d34d5528ab79", + "from": "0x97511db90b0e141ea4cb42e3b73fe3C24c3D5676", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x000000000000000000000000000000000000000d", + "type": "0x4", + "value": "0x3919" + } + ], + "version": "2.0" +} \ No newline at end of file diff --git a/cli/fuzzer_bridge/examples/comprehensive_largest.json b/cli/fuzzer_bridge/examples/comprehensive_largest.json new file mode 100644 index 0000000000..167efc7aad --- /dev/null +++ b/cli/fuzzer_bridge/examples/comprehensive_largest.json @@ -0,0 +1,491 @@ +{ + "accounts": { + "0x000000000000000000000000000000000000000d": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": { + "balance": "0x989680", + "code": "0x6f0a87ed7222327c89e32c494655ab7ab56000527f9edd68e08f46df176f43ab43e5cef82a0ec1e3b507236e9e1d29ee4865c3172c6020526f0407e673e011e005623138422425e3f76040527f33e8019de96821fd513cd74317d3759644eac2366ec002ff30599f23893d01a96060526f0c8ed51666fa89cc3b565d4debb1613f6080527f1b05e40e0f001cf0fd1708ed5ec0cf0848395141fad4e63c1906ef6826eb59cd60a0526f09ded88a18337c0914c78872d01d415560c0527f0968b8eb01921ab81aadf28a9d3184bca0490cbd0c34ba4bd4967f21af512ada60e052608060006101006000600b7fa4252a9216f3d0e78298c2b7c114a064716eddd0911583de04b66582d8ea311df46000556000516001556020516002556040516003556060516004556f1a419a917fc94f5634495deedf4a24016000527f048cc6b4caf2a633a5e8f2da8c0143c06d8c1936c890bdb2598545541f70d11d6020526f18e47fc371d0406e1d4db090510a8adc6040527fde2c75ec145e1c8c0c463746e7094ba17943d2c86a2bf2c6ef95c2fb431910486060527f2e2b2003141ba627ad513d8a983c48396ffad9321a55c93c2604bbfa2308a97c608052762000000000000003ea3ae275df42189c22df81e214368360a0527f8780adce6237aa9f065ec90a90954ea710e653548c7299c4530795fa29ee9d5560c0526f010cee41653204615b11ff580614bde160e0527f2b421b606c9ece327f85b1eb9cf1c824a346f190ca67c2f51a2457820cbc7b15610100527ff2c9a103bda905ed7b8b699659b9323f48a5c7bcc39089b56bdc479432ba3368610120526080600061014060007fb07bfea156dd2c6da61259f98c6acd1940635b34f57488f007f182e1c924e6e4600c7fcf18af1150328aff200c2fd8f999bcc0d5ee9391b1cba27c9881fe5df5887bc4f26005556000516006556020516007556040516008556060516009556f09b04f3d8e653b62c7982bd62d551ef46000527fa637f50de8135135d5d4fa0789fc81ff1aca0f5580ffa0aae9d3320b46eb43616020526f10f5d64a37c8c7af6fa86c43e7b04e246040527f50df08be2d64e37307e120865ddb737d40df135bf781af0cf34e643bda22fe206060526f141d734530e56cdb3b167ae3ac8df0a46080527fa4400211fd2cf3454a25257d075e59d3ba197c8840955c9a1354c2182eb04a3f60a0526f0e9be6e0e15cdb0b5bf6fbb5212abe3960c0527f87491a0cde1687660f12853fc9be9c16f6f82114c4874c4748328beec87f289860e0526f07d9ba7a0a45506cc5ce37f24472fe0b610100527ff428a69ea59c554de9cfc53f27a38281f1c264c784a645fa2d35289ce405de2c610120526f0762254fb0459e7df8563bee37c4d2f3610140527f491f360f159d69cb14c672d79d4feb00f024c4bfb3f40ae716b113faf88a9a13610160527a01000000010000000000000717a86a35e59903c132908dc7f52f62610180527f8a5cf0cf8a71f5664b402fb7810716888ecebc361881eba0ee7b505d7f16b1886101a0526e5a50ba7862cc7cda96c5dc5adf8f4c6101c0527f4331955a3d1e519f7274d3fb7d0462f1002580dee6f242c634c0089195186d3e6101e05261010060006102006000600d7fcef0c189c7d9456aaccdde7e801f01a3432106d9dcfe0446321931372442b159f4600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f024aa2b2f08f0a91260805272dc510516000527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb86020526f13e02b6052719f607dacd3a088274f656040527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e6060526f0ce5d527727d6e118cc9cdc6da2e351a6080527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b8280160a0526f0606c4a02ea734cc32acd2b02bc28b9960c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be60e0527ffee06aacd23d0a6c86c34dc19c60536cf9a6ea877a9e9eb2f6a4df3e9a353dd2610100526f1fc25c7508e84dbd1daf7961d33bfb2f610120527fe53a40dbaf0ecd8c7eb3bd54bf2168a6d7a055ec92130ba37052b423447b0a9a610140526f05e99862765b9bcd6f7cb63826fcd392610160527f848915d53314781e8877d55caf9c4f8d34c7a8b89cb8bacc90de4a29921a44a8610180526f11af9ffe6238b2de3f7dfbe19e4e0a586101a0527f4e47686ba041f9dedf748c8d126b85c8c8edb4b2797e15dbf67683b1a73a8c446101c0526f17b6657a667d398b8f13565befc2a7e56101e0527fbb993fd6c1c8a6d8b87870d5c321b47156188f585546bfbf9033a4c86be66c4f610200527f18997f86a0ce7dabec3e81f963d5481ec93f972adc070ee52a4b1e9828a1cdb1610220526f10a4258f7530a05c9baf43860413914a610240527f525ff884a38adba5cbcdb1fa8b7ed37ff38a369a0bda3f8ce5eba0a9fd23e3a4610260526f02e67a246248652e404608af51e9ebc3610280527fe9cef9e3bd785b9348c6ac8d58796c4606539f4fbf49004c85bbe2be3801b42c6102a0526f05c8bf03e4cc59c61fe7127ec8467cae6102c0527f01153b2e813177d106fce95671a92f34680a68d71a819a47a2bd88a8c1d065306102e0526f19dfecff4a83dd53c417d38d59bd3f1a610300527fecb84b85caa8935a60b706781e85e4748de3a187062175cd88589c4e1cc33d55610320527fb985b5b035764a8b63042b39ef405bc5b863eb556ac92ee9b81220fb9ec662a16103405261010060006103606000600e7f9f28453243c7169466e0d7b52d3d089cb3a5027dfe9b6346ccd3744baddef837f460135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f165c50dbe8c0a0208acb5b4f32f320906000527f17ce7e71e958a64abf31e2fc571ddddc5f47046db222374332e6e6ed6c60725d6020526f05c327bb284a00dc257c47fdee750c9c6040527fae824af6cede547411e87562748ed6dba06e401a2092e49108a1513ac54604326060526f01e753ef84d2a5461a45b2d30b0721dd6080527f911ed29cf977b2d50d92d7085099386efb72f28aaadaa7509d47ba49e2d5576660a0526f01c9507484cfc3afac23df3f40edd4e760c0527f5153fee58f641ff7ef30da0e856bb7207d5e49b0a7d803778ba2187277878b2860e0526f034eb4d81eeb63c3e0c0df223b4e7fdb610100527f676f8c98a87583947e51d405c7102382e163fb63ebe7ad836dbe58b7af5123c3610120526f09cf32bd5a983e5edf7439888f49a36c610140527f4d51e8b926c13dc5edc5bb582946bc58a3269bb45f61b3f3c8d7d1b78bf68f5b610160526f12786c6a204b05a66b3b0ec1628fa1b0610180527f1298d31fefc9c859bff378565c1f83a3ee8bf0f7ea2ef66612ba98cc908217cf6101a0526f12f75b00d7ac4480219fc66b5e4cee686101c0527f8b6820eb8cc47694ce0d910281222a281db5431258217f13b19ee22df398813d6101e0526f053a3ec469166e07e50fe90261be6c03610200527f8bfdeebc739636d4d569083c14a1dca3d1a32a736c900150dc8e231494738086610220526f0540a51dd44fb6a1bf12d3cfec1debc1610240527f50ccd16b2499c78cd00a1ef4b1cc0df6a76f7448791912fe67ec17bc38fbd0d9610260526f1792de16e20a71f569cb872f24967936610280527fd0e86308f745cca7665e2d9da1925e7b40b1c75d377d049fd0130dbb91f8d2a76102a0526f10584eb9a95dfcf214640f20dc1720626102c0527fb1ce1e2122df67c1f67cb471c1975ef95c7f3bb7ff9a0beac9a353e8a1956f036102e0526f021eff5f0e36e91a2bb867207f6be50f610300527f69c76b34f3d7519ddaf5229586a6dcb8b7916aa8c8252027408ccf6c0293b4cc610320526f06ba87408441d868c3955895247b0cc4610340527f40ae49a43bf2e94e34f7bf730588c6387d197cd1dcf8612fa896498146a54a85610360526f024aa2b2f08f0a91260805272dc51051610380527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb86103a0526f13e02b6052719f607dacd3a088274f656103c0527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e6103e0526f0ce5d527727d6e118cc9cdc6da2e351a610400527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801610420526f0606c4a02ea734cc32acd2b02bc28b99610440527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be61046052602060006104806000600f7f9a3408e92b715e6b9045c4dd6fdde08ee1a07f82f2016d98ea8017dc731ae804fa601c55600051601d556f0e66dd45ed28b50efa47ef1d4e12e1646000527f17af6eb4654a2af672d9e65ef93e7937047309dd5391b617d8c629a282008c1f6020526080600060406000607160107f08836f296e06695e07ca75a2fccb39630286f5f12e73c080324df9665ae10d32f1601e55600051601f556020516020556040516021556060516022556f12bcd39d65a32144dca96ef057a1cb2f6000527f8d9f73ba8de3281fe17b080c9ec0f08dccdfb2075f0d73d05055ccbb200296a56020526f0f8af18272344255ba2fb976696e056a6040527f4175c7145eed931d03737deb73d25c3bcb8d880ed85e03ac9a9c2c74e0bab59460605261010060006080600060117ff4f2cfddbcff68a12ebf445f82c77d68d99f8b6d8eb46723ed3ef6ed2507a37bfa60235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55", + "nonce": "0x0", + "storage": {} + }, + "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": { + "balance": "0x0", + "code": "0x608b6085604660fa600260e660c95b1870335733826958400667a041477d7f56425744fd3741659f7e12a48f835a650667f1066d7777106337fd676f7d3603521a7b418e8f62055f3f025d1d41928b75643933a4153e32a1446470013d92343c1a5c368879f5f1067b0b1b5ef4755911333e570b0a52403d647c069d97104309395a31704841655e68338f96131a473a18a01432170b1d90076e31077d78f34339653e3534481c9d771881550889a4675f376c6c135c35063863336f9e0283505059721c526d03337d467362ff8650713f123e5f89079f361d143f80587d061e5d0a52786708055a4379f188505045ff1d4138100b0b6369996a425639881c469d7a9f8838075847067865833e791537656f3f77006ba11148598e1e7f3a426a8e358d4a667808079837528009761d6c079c83754642f0333e3a0b1e7557f31ef56da45d926f1b38fa77056601699a45816b118c74a092077268451a0b9e427b9852f2639f49145501fe103a79201351598bf2406783475e80636a795165816e1c7687986e3e10753c718052997c3e16530a3d7846111e871e358a457d70537d17556215351608516a7b09328174825c79095b6cfa31183f507861621bf16e1b0bf07d368769501c8f691e1a998410191e04747f049e886a6686189757735d6f8e3769040477f5591276167c77575e9f3a57418b1e666c1a60f18187417f004750093c43583f3e56129314201b769c7f1b0a6e09075e006e63711a81547c686d6a88508e873461fe20317882fa69495f893a4637447c617a9837fa65fe1c6f061786595b925d028d085439144979187a60603e896a0a60758752796a855b73808f7b5a68803d06120a3d6875665c39105e4501a15d02940673443947824654fa4019679b05f3668b4164803c1e028e10791e5a43169744019954680688691c72855e337480339c407cf05b8a5d51641d7b056a540031419233893a7e5730053b9c098a31076efe3e41113f123d54766045677a778a7533535f757ff21814647c9b056c55163f673130a18173349252079e7742378a329f1d0b62471a51207d6a988c446c48139738770302076f3e196b11006e30839e405a167d797e1497f2141136116f886741977b5a4571597b3181207776a1976b3f3e50431ba43684151401555b421505186f588a206d1b305079f3757b5c17615b1d8a7459513d3960506c8b5619a0f533083a7859703f7a39a08f3ea3611d1c1e36621287823a204245046a1a736f7a9f3b5c727e64007c50179f3552a0201e390a7c19637e731d527978004812373379433e4702567448fd77f5139c485b483504548e4030761678395f9b1ef1761c17424aa005001b30093d8d81519f116c336e6e9765696957806c696f955c6e9d094859111a45117b48433f143c408400796894175e3a180b6218", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000000000000000000000000000000000000000000d", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + }, + "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": { + "balance": "0x0", + "code": "0xea60206000fd", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000010" + } + }, + "0x3F7d91B63d840CC7e9601d30DAd1870aE5749C1d": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x3befd359c3582c3946a564263ee77fd86f740a7c55622506c5591d61737dbda6", + "storage": {} + }, + "0x3f8A30c4E084500855A3A35b7B9Ef39cB7B90F36": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x3a650354fd40b9460e6e99f8a73f92de7aa435859e7866bdbf33c15c28575a36", + "storage": {} + }, + "0x472C5AD2732c1CFB6B4bC190Aa174656Fe3c34C5": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2944b92eeb6bcc8a67ae9ec10064b6148bb3f7a48a383559902b5c9576e70bd4", + "storage": {} + }, + "0x538A8474EeaB43d5a960164c554A20400151D479": { + "balance": "0x989680", + "code": "0x7f5d403d91784bc5a01d145ca2b3bc1126aa736b49d5b64f563dfe7aff0f5f6fa86000527f8326efe73bdcac81a56385db8739ae0dbc5e0a85a79350f9062e79f863e06cfc602052608060006040600060b460107f3533a47707127be60396663b421c89eb8b30e456501fd24af1f191416c02e125f2600055600051600155602051600255604051600355606051600455", + "nonce": "0x0", + "storage": {} + }, + "0x641602bAD4A323C49629d45338d79A2bb984A3fb": { + "balance": "0x989680", + "code": "0x600060002060cf3560206101f26103c0630ec7c0de3c60406102d061030082819290913720600455607d60fd6103e082819290915e20600555600061045d5261010061040061018082819290915e2060065560fd61034053606b6051610100630ec7c0de8382919092909193913c2060075560016066608039600160556102203961045d51607c60e05361032d3560085560326101e06103a05e60016080f3", + "nonce": "0x0", + "storage": {} + }, + "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": { + "balance": "0x0", + "code": "0x600860005560f5ff600160015d60206000fd", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000000000000d", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + }, + "0x7564105E977516C53bE337314c7E53838967bDaC": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": { + "balance": "0x989680", + "code": "0x7d0f1aca5f5617ba53a2964ce753903184ef3ddede5412b9d553a12b5e57076000527ffbb3be712806b233cb60c29db989d7ae5349630986cf360c21342ef0b4afd1586020527fa9c802a9e71442f14ee3df13a9c3835763425701b2e669defa0f9c30e902c4816040527f0ac85b8a752a7ca64e1e784236db571b228436cf99406f9420ff8b85e1cb180d6060527f782965ec2fde9394550b911b4dc2fde13170e3af8881782cc1f400d31112dd946080527ffdbca9e214ccfaad7f648f2a211cbdd3d557f26261a34da40a9b167bff12d11a60a052602060c053601060c15360ce60c253603260c353607360c453605760c55360af60c653606660c75360e960c853602c60c95360d160ca53602e60cb53601f60cc53604760cd53603960ce53603f60cf5360b460d05360fe60d153604160d253602560d353600060d4536040600060d5600060c660097f66b9f2049709614c2523935d617f2576cecdf6d4cd80e850e0a6fa189bd9c3d6f2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x837C90dc7009df3399617a7BE4f8a0cC0ED7C350": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x71a42ea3bbd6b96a66b6411dd45c75ba29bc7183fc3c007b544405b333857d17", + "storage": {} + }, + "0x872509c90c2E045B795423F9bEc01a53d6D8Cd7B": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xbb3f3eb75c641dcbe1001b459c59b97fdff8938be21771df376053aada5547e7", + "storage": {} + }, + "0x8c91B5232f6C15d412e35F7A1e10827145bdD6d4": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xba3b3739da5efe370bef502ac45ea51e77c216910dfaa0de0562c6c92a95c71c", + "storage": {} + }, + "0x918c2E9fa4fBEdf538659e6DBbcaa9cE90AAe2B9": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x876a3a4177c591bcd7c7838ab58503507cc953a049d095958fe26dc308b25059", + "storage": {} + }, + "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": { + "balance": "0x989680", + "code": "0x7f80000000000000000000000000000000000000000000000000000000000000007f8000000000000001800000000000000080000000000000008000000000000000901b7d7676767676760000000000760000000000000056000000000000000000007f80000000000000000000000000000000000000000000000000000000000000011a9006157f7effffff8000000000000000000000000002000044000000000000000000000167fffffffffffffffe1d90056a10000000000000000000007f7effffff800000000000000000000000000200004400000000000000000000010490037a0109000000000000000000000000000000000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a02901b7bc9700000000000000000023f00c00014ff002c00000000000022310868010000000000000000900b90027f77676767676760000000000000001002e000000000000040000000e0000000007e40000000fd000000db0000000000000000000040000000fd000000db0000d390186000557fffffffffffffffff7effffff800000007effffff800000008000ff00000100006fdac7fff9ffd9e1322626262626262600901d90167ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb09004901476fffff716b61616160b0b0b2b0b230b000008010d0a2b006b010000000000000000000000901b6001556c100000000000000000000000007fffffffffffffffff7effffff800000007effffff800000008000ff0000010000026002556101117f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd10901b600355777effffff800000007effffff800000008000ff0000010000777effffff800000007effffff800000008000ff0000010000056821000000000000002271767676767676767676000000767676767676900660045567fffffffffffffffe600103176005557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee762900760076761e000200767600000000767676760000007e40000000fd000000db0000000000000000000040000000fd000000db00000190096006557fffffffffffffffff7effffff800000007effffff800000008000ff000001000067b368d219438b7f3f90037f77676767676760000000000000001002e000000000000040000000e0000000007f7effffff8000000000000000000000000000000000000000d90000000000000111901b6007557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff156008557ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a006f8000000000000000000000000000000190046009557f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a57cc9700000000000000000023f00c00014ff00000000000000002230080560009009600a557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6b1000000000000000000000001b7702ffffffffffffffffffffffffffffffffff0000000300007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100090167f82000000000000000000000000000000000000000000000000000000000000006f800000000000000100000000000000006f121212121212121212121212121212129008901d600b55677fffffffffffffff637fffffff9003600c551971767676767676767676000000767676767676671fffffffffffffff9007900360017f7effffff8000000000000000000000000000000000000000d900000000000001900617682323232323232323237e40000000fd000000db0000000000000000000040000000fd000000db0000d3712000110000000d0a300e750a000000090a0a9008901c7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0076fffff716b61616160b0b0b2b0b230b000008010d0a2b00900b900b7a01090000000000000000000000000000000000000000000000000071767676767676000000000076000000760000900b600d556101117e1f0000000000000000000000000000002000000001000000000000000000001b1b67fffffffffffffffe6c100000000000000000000000001190147bc9700000000000000000023f00c00014ff002c0000000000002231087f7effffff800000000000000000000000000200004400000000000000000000010b600e557e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a007f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff00000112600f55156101116b0100000000000000000000001d60105563800000017f80000000000000000000000000000000000000000000000000000000000000021b9019136011557e1f0000000000000000000000000000002000000001000000000000000000007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100090177f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000017a010900000000000000000000000000000000000000000000000000116012557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7f80000000000000000000000000000000000000000000000000000000000000019018077ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7e1f0000000000000000000000000000002000000001000000000000000000006f8000000000000001000000000000000009900b7f7effffff80000000000000000000000000020000440000000000000000000001760fffc000000000000767676240000000000002b057604702076770000000000000006823232323232323232390071a6013557f77676767676760000000000000001002e000000000000040000000e000000000671fffffffffffffff900260145569010000000000000000006005774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a900963800000007f77676767676760000000000000001002e000000000000040000000e0000000001d90147e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100068066aa0a5319bcf5cb490029004717676767676760000000000760000007600007f7effffff800000000000000000000000000200004400000000000000000000010b027702ffffffffffffffffffffffffffffffffff000000030000760fffc000000000000767676240000000000002b0576047900390026fdac7fff9ffd9e132262626262626260067ffffffffffffffff900a9001717676767676767676760000007676767676766f800000000000000000000000000000017f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff00000190099010681000000000000000006005901c1b7f7effffff8000000000000000000000000000000000000000d900000000000001677fffffffffffffff9017037f80000000000000000000000000000000000000000000000000000000000000007e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0006901a6015557ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5901d6016557ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000156f1212121212121212121212121212121268210000000000000022161668210000000000000022760100000000ffffffffffffffff0000000000002e00000010901c7f7effffff8000000000000000000000000000000000000000d90000000000000176013590cab83b779e708b533b0eef3561483ddeefc841f5900390126017557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000901867fffffffffffffffe6847839214543589705290149019017f40000000fd000000db00000000000000000000000000000000000000000000016007900110600067ffffffffffffffff1160185569010000000000000000007fffffffffffffffff7effffff800000007effffff800000008000ff000001000090039017157f77676767676760000000000000001002e000000000000040000000e000000000678000000000000001056901000000000000000000774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a7f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff00000109901860195519717676767676767676760000007676767676767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9010106780000000000000007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90179013601a556f8000000000000000000000000000000069100000000000000000009017600768010000000000000000901a90150471767676767676767676000000767676767676717676767676760000000000760000007600000590197f7effffff800000000000000000000000000200004400000000000000000000017f8200000000000000000000000000000000000000000000000000000000000000600790089014601b55157ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb7a01090000000000000000000000000000000000000000000000000018900b778200000000000000fe000004000000ffff000000fffff700684783921454358970527f80000000000000000000000000000000000000000000000000000000000000029008900567700000000000000068010000000000000000901a10610111651ce97e1ab91a900a07601c557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7e40000000fd000000db0000000000000000000040000000fd000000db0000d3901a601d557702ffffffffffffffffffffffffffffffffff0000000300006d010000000000000000000000000011601e55682100000000000000227e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10009016760100000000ffffffffffffffff0000000000002e00000067700000000000000010901d7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001901c9019601f55712000110000000d0a300e750a000000090a0a7702ffffffffffffffffffffffffffffffffff00000003000090166c010000000000000000000000007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6770000000000000000890097fffffffffffffffff7effffff800000007effffff800000008000ff00000100007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a0090059014682323232323232323237f8000000000000000000000000000000000000000000000000000000000000001901a90127fffffffffffffffff7effffff800000007effffff800000008000ff0000010000777effffff800000007effffff800000008000ff0000010000901d901468066aa0a5319bcf5cb47f77676767676760000000000000001002e000000000000040000000e000000000900690027f8000000000000000000000000000000000000000000000000000000000000002774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a901d900767d021262626262626677fffffffffffffff900590181960056b01000000000000000000000090167f62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001777effffff80000000000000000000000000000000000080016f12121212121212121212121212121212900990056005671fffffffffffffff7f80000000000000000000000000000000000000000000000000000000000000009009901790126020557f80000000000000000000000000000000000000000000000000000000000000017702ffffffffffffffffffffffffffffffffff2000000000000b7fffffffffffffffff7effffff800000007effffff800000008000ff00000100006780000000000000011a1b6770000000000000007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee109003777effffff800000007effffff800000008000ff0000010000637fffffff10027f80000000000000000000000000000000000000000000000000000000000000026c1000000000000000000000000006901c6a10000000000000000000006c10000000000000000000000000161169010000000000000000006b01000000000000000000000090141b682100000000000000227bc9700000000000000000023f00c00014ff002c00000000000022310890050576013590cab83b779e708b533b0eef3561483ddeefc841f563800000011d6021557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006f80000000000000000000000000000001901390117f7effffff8000000000000000000000000000000000000000d9000000000000016801000000000000000090179004760100000000ffffffffffffffff0000000000002e000000760100000000ffffffffffffffff0000000000002e0000001290057f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0090187f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56770000000000000006c010000000000000000000000000990076022557f80000000000000000000000000000000000000000000000000000000000000016f80000000000000000000000000000000900460235563800000016801000000000000000010900b7806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a7f40000000fd000000db000000000000000000000000000000000000000000000107602455762900760076761e000200767600000000767676760000006801fffffffffffffffe1c60006000f3", + "nonce": "0x0", + "storage": {} + }, + "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": { + "balance": "0x989680", + "code": "0x7f2fe97199e8ba5d65d5949760aba55780db6d3e27337c12a9e2584c1aea6389366000527fc9c7815cd20d7a1591df55b3df8377d64505c5ca90911be70570f7cde3de19f56020527feb1c52cc5d5b95babc9859d69614a696a7754df4ec4513bc9af9fbd9d0944b0d6040527fb658d58f26c2302e35030999f40650e0466ee0af3b918849c2eda1d6c4fefcaf6060527fe4bd2ef5d6c1341b8e475c74757076268d6f1c5916d5bb01e70d7886019c23bd6080526020600060a060006000610100611acff26000556000516001557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffefffffffffffffffefffffffffffffffefffffffffffffffeffffffffffffff6020527ffefffffffffffffffefffffffffffffffefffffffffffffffeffffffffffffff6040527f6e28fbcffd7c03caccdd22d240b8b9ff026419e2adcdf236a36b46f43e555d0e6060527f2849144bcceeceecf83553762c7ceb27864c9f34852287bd738ec484b6f00cad6080526020600060a060006101006119b3fa6002556000516003557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fc53d059ebba0080bbcbd061e6524771ea0dc308b40f3c4ede4c8716a1eb1ec5a6060527f49237f19d71e7aaeff794817dc9f70d8a7c729a6fa39a391b5b3701d22566d586080526020600060a06000610100611935f46004556000516005557fb0c8b094b0f86fac6669fc617a9ae78274d176f28afd4133b0ff77d0f997ce966000527ffe317cbb4baf276d4432ced23f42d8c5f7d55b784db1e93057ee0fc2ea1e17786020527f4b440553855a357802be0278f1931e2e08f09691d5bea6d151656218e393092a6040527f5a91dfa926c3153f152dc0b41f6d123e4399e570bda33656750b0ffc6a7d99256060527f0b2978263b93e015de980fe4a2e55e118cf2d6c5d591977af6cf89d15631d3c86080526020600060a060006000610100611a32f26006556000516007557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a060006101006119abf46008556000516009557f7f895cb6c94965dae08dceddc4aefdeb4f7cc31e951d89545b74675c9fc8e6036000527fd34fbc0141a54ba0519984c5194ca9df72fd36885e115b38d896115fcad844116020527f55a221cabf682a678d6d7bd6cc1c9d49900274d396e26ce619d02b49a7b83e666040527fed0684f310b426c5b27d7218a0083cf6ff1beacd1156c21d6c2cd04ee12f13b96060527f3ff4da44d7964d7de1e66c4f90e7ff39f78f4cdf4f3a5270c1d722126abd91e06080526020600060a06000610100611a5bf4600a55600051600b55600060005260006020526000604052600060605260006080526020600060a060006001610100611b08f2600c55600051600d557f1e681d3a95c766757b88486b0afd7a08a6fa770a33d3701a22e430baf948b8ad6000527f99244a30ea26d6976d18c2b999724f354cf0437c6914f905b229d6456abace266020527f02de2f85c227c376b51fbeb7f912c93de8b3b8d1b719f96e3394c780fe92819d6040527f8362b3f221591571872637755ba29fccf0be8f3663fcd159c5b11acca7b83dae6060527f88e7544e2c3ce0d17afe0f1c5003d61d4a15ce6d121c9753999e920d526b61a96080526020600060a060006000610100611956f1600e55600051600f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611b04f16010556000516011557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f4556070d69d9150dde4c0c405471e1e9d6f7b187c8a48db23e436e1bf0c5a2836060527fb27460818d4e6617c7c52296366cd6160ca2141e845656c7af89e748f55051e76080526020600060a06000600061010061191bf26012556000516013557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f555555aa55aaaa55aa55aa555555aa55aaaa55aaaaaaaaaa5555aaaaaaaa55aa6020527f555555aa55aaaa55aa55aa555555aa55aaaa55aaaaaaaaaa5555aaaaaaaa55aa6040527f0691a74c0334d2c5d5f65473a379ea6f3927dfe754c742a08d391ae9e4c3a1276060527fa4c383fcbe83cce6eb2b850160756c9b9567b080d70e343074b8398346c799356080526020600060a060006000610100611c84f16014556000516015557f7514614ff040dd84409ddfc302b297d29ca8714619a4dc560aa3d4608ce954db6000527fb0c02afef69e2f48ed8f894c883394d4122f4317d1e964db799bf5da52329e7b6020527f6f65d0cbf027c882dc76923072c5d7295b43905e974ddcca2b9f18af37ccfb8c6040527f6beef3c7b6f4b8c44fd071921967d0f9be21ee44928355184ec42b1a8229edc26060527f249d6d365176c805e3d4e3c72bac6c02100a90d811311ef70ccdc495e09e6bd76080526020600060a0600060006101006119d0f16016556000516017557f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2605d6000526003602052600660405260036060527f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2605e6080526020600060a060006000610100611c2ff2601855600051601955600060005260006020526000604052600060605260006080526020600060a06000610100611aa5f4601a55600051601b557fd2d4f8d1fa6b35538f27aae222a56776a7eff0effbfd431936715b436ff451a66000527f61f79af730ffdfc7e4e96f985821c0a9dd7b5651b7b2ad75296cadf5ef8e59cf6020527fc45866c4591a45de590699e2457094b9b000856f7149ec94f8abf4670afdd7d86040527f88c77f3feeffd14bd137ff4bb3ec5b876e05180b532f10b77c0657e563c8db0c6060527fc6e572badfb5159adf1acd6d9ad3ed81da9eec85ef888e94bc6542fa2dbd08d76080526020600060a06000610100611ae5f4601c55600051601d557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6020527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6040527f393b58bcd98fe79fc2233c31884afb05d2b359bac1d264d41268621e013390036060527e70250670d4de9ed0b37629f80990116dd8270afc189249655a041d526494536080526020600060a0600060016101006119d9f2601e55600051601f557f60c6915f999a8a80a3a861f015cd24eecb142408854d05cde1b2ad1ecea053f26000527fac7f8594b93f7916770e6e5126f31801ae95ff40ae5bd478b4a1b797a17b71a06020527febc1fead5d1bedcb5bf6a7e631d9d1ff361385d8885430a71c33115ac3278b456040527f0ff45f5f73f9e822bec06a5ae4c5141d6eadfd0d5690bea74bd0b8fe1f7285976060527f41919529738f4f6232c5840ab04e3a2bd2ceb0e1e92ebafa6c28af53c57cd5106080526020600060a06000610100611cacfa6020556000516021557fcff94bfd0dc6ee2296752d48a0e6c896215b383550c60fd0f737252e86a3012a6000527f93581041febfd49fba501e7b67693d9dc64c73df8a4af587231037e4264f2bfb6020527f93581041febfd49fba501e7b67693d9dc64c73df8a4af587231037e4264f6bfb6040527f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2966060527f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f56080526020600060a060006000610100611b3df26022556000516023557f893506f03e0a80f79c48203ec81f871afda5fba19e1b5c85d8e9899f7f30ed156000527f59afbf58daa9d21e3a594d20165037571f0dbd2efee0cc099417cecdd4983f726020527f8322d130c68921c15265c8505cf39f26f51cfc6c814b95980cbced5b35aaa6126040527fe8fc8871cdcd283f1422e9f99c0075eb8061fa82c8a1df63af6c0a584c4f8e826060527f18bb7ed6399701c762f5cd56095bc0e0fb6207e8f6c82a6ad257a420b2cfad4d6080526020600060a06000610100611ac2f46024556000516025557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fbf93dfebd62c76ad15f114f950b3881bed08dc9fd561953cbc16b6bbbe5e567360205260006040527fa5c3b4cf9cbd67295dbcb27c699c6574e3d2ea63c15e9f8c8a2516c29d38b7cd6060527feba90b54b8208ef83b22016a18ba2a1a2594e6e5d238be0aa979a546909e95e66080526020600060a0600061010061192af46026556000516027557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fe2c5856908d15331d57ce42f6985fa476d70deea26c9eb600cd9941ba45846ec60205260006040527fe5b8f6469372d68b77c90e8d7dcac4c91de8b8240c24931e88ead9d567a6b6236060527f87d09aad6d64667247299bd593b3b188d5fbca5b23f07ad81dce3d152263e2b96080526020600060a06000610100611a59f46028556000516029557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f03fffffffc00000003fffffffffffffffef39beab69c5e7a13cee72b0bf18c956020527f03fffffffc00000003fffffffffffffffef39beab69c5e7a13cee72b0bf18c956040527fe99e6153b13f1459ce318e9294faa5e39366ad606aa919d8124168755b0fc98a6060527faff78ababea86849c7171ee1ac52c4630b75ab736bbf602387a7453e16eccc136080526020600060a06000610100611a71fa602a55600051602b557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527f417241b507b3a838299ce7825419fd5e77e3184e5630ed3e96b7fda7d6ae34ea60205260006040527f89f7c09aa4986bd3818ccbaf22fbf3c0a9ca814e50a5c68c86a9c2d68067a4eb6060527f0a1ac1cd8c5e4aba96b63b5b13f1cb0672c73ebd014d6a96821133fe200817136080526020600060a060006000610100611c56f1602c55600051602d557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a060006101006119b2fa602e55600051602f557f1f5056964e229e6d298fb8c47ac9527e6f4b8c9f3a8533227854b892233e6d976000527f481bf80e44001b0ece48327892479534e208843b2ad69314f3ceb0dc305858716020527f7384080df121c720d275226b1a11e2314c860faa7d84bffcd6a040b39d5203106040527fc41a4b5b018d1deecb157b623dbedffe1843922d0dfa9c7e62e0c69f6af3c2206060527f303d1191101730a74720bd3bd36ca47ad40d49321263bc1a4319fd289e5d97516080526020600060a060006101006119a1fa6030556000516031557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f0c3569d6f79a64e80516f0c1baa003c0dbd85f2d942104588bc05febecda34b86060527f78373f0ff62818343d05fbf9db4552cc0e3d3bc3b3080a811748c05088c4721f6080526020600060a060006000610100611940f16032556000516033557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611971f16034556000516035557f52c7f111411b6c31c4ea5148ed1404ee72dad2c4a63b5d9c07be2d57811dd9bc6000527f6045297350c3b2df194a8f520641552563b5aa981e044bcda6a33249f524f1a86020527fbff75552493d6b56fc7a65d64b61c429fc75420946bbf7f342728f45931da0456040527f335756c6c2442feb7baab1b4c00709f5f211e95276a51cdc179a1523815642856060527fad39878e95395f34586fa5c13cb8892da3d8e793c2986720c5c6d629dd895ed96080526020600060a06000610100611c67f46036556000516037557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527fffffffffffdffffdffffffffffffffffffffffdffffffffffffffffbfffdffff6020527fffffffffffdffffdffffffffffffffffffffffdffffffffffffffffbfffdffff6040527f13045e933830966b2db4c6a0cf39f06aadca0c74937af29ff7b3c6f0450bcf2e6060527f70725c9c6c35517926279c911828164c6ddc7e97081db8fe0dd4a729b803bd5b6080526020600060a060006001610100611c77f26038556000516039557f7c2a6630a079ee1363d056bda39ae134b585af806cd9727f90fe91abd5013bc96000527f539a2d2e57a51bd8f3f70003d2236d12a9d9c728934914f19adc0b325ee3bb5e6020527fafca78e072b71496c06d81e71bd6b60b754584416e5355676f03dcb617379d776040527ff1d328d7c09978884c803174445eb275c0d6fb998b98e95df4b08d840f89aec46060527ff3bbe41941839aee29d8237388953d7e3a3dd621fb3b594c2cbf0987eeff62266080526020600060a06000610100611b66fa603a55600051603b557f975f4af54c367ce00dd0dcb9c093bc6ca66db8c689e7a75c00b2a74c923e3cd26000527f7cb05b03626922246b24bc2f58eb57afd4a0318b2d326dfc15b6ba63e827e3356020527f4a0854303660569da11ea1cf19e24b5f6a8c61a2682b315c0ddb3d4f34af483a6040527fa37a086a86b4c63de4f608623a3b109bf839637e0c4adb7688d01784ab93052a6060527f99c32c7cd905550ae9f5025b8e9c96f8f1b79739ef5a7da917c3af8d57254fd36080526020600060a06000610100611a7efa603c55600051603d557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f469c3645957f81734edc5e79b5ee76faf692f010c502999fc3cfac6faebee0836060527f61c66083fc6c790d224dd7b2dcf78ae5ae6d9de7ea518daa10cce651e7fded706080526020600060a060006000610100611b23f2603e55600051603f557f183086ef5ab74e16dd3b9a9a662e247e1355399b33ad8b3e382fd7f90118128f6000527f1699eee7ae150a1333b791f118070e10b320096d9537337a6e6ab699df96250d6020527f4aa30c18c471b32295ba528c5f1913a779014f6be1366c3e096a64fc535e79516040527fa45e8ffa296f8b29cba6d3571041d76938d6e7048866a2c439aef5fe697c924f6060527f0ecddb7ec3a49789115126ebc8cebefa0f7cd0578541580c7e003aaf9df4c9db6080526020600060a06000610100611bf7f4604055600051604155600060005260006020526000604052600060605260006080526020600060a06000610100611aabfa6042556000516043557fadc5098eacdf58d42c946547737a616e805f2733b11e8217133530de1060ce086000527f3fdd1d9e9ee2a8a319768ff76ed2566a7d618b623031ee2b640b5b49e9fca4826020527f8cd2bb580fd635c34c694bcbb59895ec15efc61eb4154921973d31d47528a6df6040527f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2966060527f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f56080526020600060a06000610100611bd4f46044556000516045557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fa44b3f5d409dd6e3d25c670a74257af25a31645e5d34cf4e3a5d0da07e3efb746060527fe293774a13af9c848b513a08c0fc6f6e7cf52207895ca1463f3ebb1bc57c91c26080526020600060a060006001610100611957f26046556000516047557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527fc98a56c8e90bb85ab2c47b157a062b43ec365388a7d754ca2bbb60385f8f9d286020527fc98a56c8e90bb85ab2c47b157a062b43ec365388a7d754ca2bbb60385f8f9d286040527f02fffffffd0000000300000000000000000000000300000000000000000000006060527f02fffffffd0000000300000000000000000000000300000000000000000000006080526020600060a060006001610100611a4bf16048556000516049557f0967b7041d5609bb5e799ab23aba07f6b2b91ff4555434b4268d3e9d5d222c876000527f7c14247677c6f4001db4cd3ee38341d2ca131a61eb822dcce09287c4837674a46020527f1a7e956dcb2c7f6efee5292e863ecc2203c0b874b8b35860dbc52c8b70132dc66040527f86f2d864f73f34c4db6172f7a5a6701bec0feb97250b6e5da8140cb3c6f4da9a6060527f7c77d48ea9dcf0ab8f305ed9e04481c71327dbfad9b8f8cb6753d3881c24e1676080526020600060a060006001610100611917f1604a55600051604b557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a0860005260006020527f0efe03759e8d9dc917ffe841070ed6c4fe8de83ca95db79cc73a13bb317db20c6040527ff4ba61410a012a8b7255777cab86b2896c38c36afbf2379df99524a891c928c86060527fd98510a92c7f01cc181034406ef8fc5ccdf7a03761c2c5c7d169304063f0a9e36080526020600060a06000610100611b34fa604c55600051604d557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000526fffffffff80000000600000002fffffff6020526fffffffff80000000600000002fffffff6040526fffffffff8000000060000000300000006060526fffffffff8000000060000000300000006080526020600060a06000610100611a84f4604e55600051604f557f0fdf6115fdff593042a35352f203f84032e8ad490fb30d88ec80c27eeb59b2706000527fad3ba7a4ff393909bc4defb600d0c8941acca5ed88cf0fad0f0ddbaca4b5a0df6020527f2ccf7b3616e76306b829d32655858a5ba425c5a186c46d36d508764f9925bcbb6040527fb3acfe28d877e38a1e317ed39d64f0cc25503d7aeac467413a5e85ce947ad0206060527f76e5e1f3adf56e0ba28ef3b39d373bad671a66adf6d8636a168ad35ff8d1ac6c6080526020600060a060006101006119e3f46050556000516051557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527010000000000000000000000000000000006020527010000000000000000000000000000000006040527fe8c3ff17a1805a8186e1a9badc25b6d8a3f210f3c69f5fea1459f0abd81a48f36060527fb6751428f32b4bc303330c6b4f799a8250ee508d35084592698c1c2da48fc1546080526020600060a06000610100611c0bfa6052556000516053557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000526fffffffff80000000600000002fffffff6020526fffffffff80000000600000002fffffff6040526fffffffff8000000060000000300000006060526fffffffff8000000060000000300000006080526020600060a060006001610100611995f2605455600051605555", + "nonce": "0x0", + "storage": {} + }, + "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": { + "balance": "0x989680", + "code": "0x7f17a0e4d33fd0936c0c618d7e4b2b3c438d916a4b17d8beb84e6ac1c30c6526d96000527f0c04a87cfd4e8a1cd8a0cabb4654ecab7ac166d50758dc912bb7b0dd930251546020527f244e8bf5bd7bad6b3667d5c9e9e249b7828031e28ac02c709889a98fcc7458ae6040527f2296710c03a3206898c112df72d48e56e53313999c3a5d92586f825ec14541206060526040600060806000607760067f0ca10b062ab2a64f6d1d99bb1517e3ddf0c6fdbcff0db2921dd54f73fccb193bf2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xD74CFe323387aE2fd070CD046173026716D8D649": { + "balance": "0x989680", + "code": "0x7f01d82c69e8410b07c01ca9a882e46bf6daf024e4823d135695134901bbbd39496000527f49a70da2a6c8ac6c15b1698c13769f0bfc32955f226afb8e3adbd8fbb68119756020527f329ebbf77d0d3a915ad4d379945d05c9dce64bb851465d4ef63857614dfa9bd46040527fb5e0b4106beae532d5f5b6bf1d01a3ca43eaa4867d08c13fd77ffee2055d48ad6060527f7bf13d131f09815beb049cea332adcafb8e5ffebffa0d96ce28e37868811aebc6080527f6bb554b6ef4e9071617515950d9d0a988220280a2e6fc619c6171978769cb7a860a0526040600060c060006048600a7f8b755582dbe465616c420fb4ee69487e1469b805eacb028605cff157401affa3f1600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": { + "balance": "0x989680", + "code": "0x600060005260006020526000604052600060605260206000608060006001600162013d63f16000556000516001557ff7a7fe9e23dae84e7cf812dc695686b887ee16429b445ab6f639d00ba0f0e7216000527f637def65659e99a5b407f48fdc2539b585ba2d8f6e146f0dcd04b123e174b31d6020527fa8dd002f88937f4a4f794328b660cbb69efb2ee973b7ee99ceead3246562a6616040527feed05028ad90c4cc59e5b972063b803ff0d4b37b86914edc4f781382f46811b060605260206000608060006001616a4bf46002556000516003557fa8815f75827baf28b5644e9596bceec1afa6bd4f8b32b2719949895e4abd356f6000527f881529671c00a8c400e61d1adaac433cf1571e3067ee7db7f2cbe94089e1a21b60205260006040527fe463ab2d0df8d12bd29ec5dacc16bd6e5d7ab6a157f8ccd62d907720d31ffbe46060526020600060806000600162011adafa6004556000516005557faca9c4cba9b9c955f0c7093e000eef2860e1a26cb732db37dc0b4fe883296a486000527f140e3f090a86b98839b500e4db02f9018d7f52864a511aaeffd7a1a63903bc1c6020527f397c19feea180e19aabb56a00a3ae6e9320d882b18a9d347a9eeca5de4b6f1866040527fffff93df204a54ee623369e52cfb52683e1c054ecaf04944a112512084e62c946060526020600060806000600161777efa6006556000516007557f6e39c9b393bd2ebe4956c47cff4461d0e635da55baa39496348e1afeb933b5666000527f57afb64fe0b204ae8c5e4a815b9b4c01010954da2215d6f0d8a40309911357956020527f5d17dd5498fe5460245482e0a3f402a76c9e46088f8dc789ca9af50a513dcc396040527f637d21d68bb042f7dc33061a1c4ce6ebfd237cfb1814b76ab6dfb8d25d5ea0c360605260206000608060006000600162015b7af16008556000516009557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f5f8eb30faaeab04c609babdccbaf477edd8db97db8e55ceeceb1bb493e4426f96040527f11f2cdc4b9300b15b4d525b65182b14c4403637c6bd09bc0a2bab3761a42994e606052602060006080600060016167d1fa600a55600051600b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f71298fd701c45b7c99c45bd59f5116ba047f3a4395625d5585ff1ee798a9c4966040527f1402bbae0fb1f0a7efd300077f319fdaee635704bbd83feea8e49b8b8f8f53b26060526020600060806000600060016201711af1600c55600051600d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fef4c53c19751307dfdd763c9eba37267498210df36acb7f5a1cd12c53ebb85356040527f1c1927f218f94017780fb1aa67ea63feede4fe536e045ab71780bccb672c91aa60605260206000608060006001612330f4600e55600051600f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fe7caa87d70f4898c2911be0d6be2779c4dc9c434b67253933c86bc67ce9377e16040527f47930e2e24a75680d3856231e44ff8769b3cb6d1337b1254a0db4b87a904c73c6060526020600060806000600161dae3fa6010556000516011557f76f66c98fb4388763e1a351d25cb29ba0c680057382b3b11f77b17adb3cc8e1b6000527f2cb34eb253be8115f8d7b8d7fb54fde77d53321c0bd2e8332f07b0c0ee45f31b60205260006040527f0ffe730bb67588130d639bd1116df90328063f88254f6ba2ba9b1ba800aecc8a60605260206000608060006001600161191af26012556000516013557f8f2e7197264574f3342f322f67212913ad475ad738c17dea8375dbfcf3a6b96e6000527f36ebd50703c77fb901f8889db2e34e8756673f19874eba2520ed9a5c8218211c6020527f6f6513104b24e8956fa1f70d1aac9b5a7fe120e5a1c6126f89645bbda8435f416040527fffff27ab007ff6fc61d422ff2e5bbca31b384d5151682bc86dcd2d0f1f986e4c6060526020600060806000600161ee23f46014556000516015557f84defe2b984135c45e723c479dac5e6b89dd55d2acd6b7c60e47af4b58356ea86000527fa5e43cafd9b28c27e2892fa9fba78c493f773d541780d6f7f4208e237a992bea6020527f270819b760296108387de76395ad21bf976accaeea1587e28ee61a5cc458552b6040527f844b530b95507450de77b39b53625832ef337d0c16a5a4098a8ce9d7a0919bf860605260206000608060006001600162017481f26016556000516017557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f202f2b49fb9fa11ed602c1b85523c3d4a032730f598d258c9a8d9680690f02ce6040527f69a7c03b1b3720d0942861c62a0a3ba66646c5ff81d4812d33eb31b012aaa8e3606052602060006080600060016001620165c1f26018556000516019556000600052601b6020526001604052600160605260206000608060006001600162015bdff1601a55600051601b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fa18a04b28cf2058bdea13c327a857e9ea55184e20513c211f8634983862d6d426040527f09d86ca930e8f4af7258d4f018bb98a0064b7a04f8c9ce34014691164c650aaa6060526020600060806000600160016201443df1601c55600051601d557f977ebf64ddef39826bf3d737ce78d9b294f1f66bc0ae5de74941b5831d5570ad6000527f63d9d89fad7549937d74776969c34f744f7e879671791c47fc65fb549915c91d6020527f5e4123666a8d8c0bfa1721dc336ddd74892fef4e23113f17772b9560a19132cc6040527fdbcc5dc4802b0a60678b70b372de8488b82989c0ae119bf4ee54dcab710b359d6060526020600060806000600060016201629ef2601e55600051601f557f62e5e98b83df356490e80276d4f393f8d11c69b0f083adf5e4eab0a1c7c921616000527f0a74d423eaaa5027e4b37cff43c906c556403ae1c53a4dc71e02192026681d1b60205260006040527f312288e39895e53d633a2fd4b0b29f721c61c4486021fa897fc95593f96a120a606052602060006080600060016001614e1df26020556000516021557fc5719f87fdec204204aa70ad285629dbc2143db1dd617cd7943fe3ec7d3216326000527facab3633bdf64a7a9c546cb5d210502386ec46069c281ab81b441d74f915c11c6020527f17a20abd30262472cfacb8968a4d5760ffc0ae44d627eeaa018c97769d197af86040527fffffa3306ea6bba29fca6ba4028aa9431910e521898e1679fd49c01e3430c6ef60605260206000608060006000600162016d9af26022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f381bcc91ef1376de335677460515c3629f70d6576ff02e1fb35fd85e007301116040527f28eb299972b3a82dd3f7c947ee00db9d790800d48283f1aca4a6b0f9a81b0966606052602060006080600060016135ccf46024556000516025557fd57bf1e77bbed8ac7b2263924719b52528499babf7091eb7d0e0079df3f37bb06000527f25f64135eb85769efc877a35d80df7917f45138abc81bf61861c1519924c161b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fb8c3d79a0302038b1f61125145d15e4518c1e7079f997a76450720ae5077be70606052602060006080600060016001615feaf26026556000516027556000600052601b60205260016040526001606052602060006080600060016001613290f160285560005160295560006000526000602052600060405260006060526020600060806000600162018590f4602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fcd24a8bf0c46d83f99232640d3e8a1482888c9e65fbefacdb7bb70614087e8236040527f79cce5ee40684d76f67ba83918858707f28b4369441431e7851c6f131044ed4e6060526020600060806000600161cedefa602c55600051602d557fddbc53839af0650083dc792a3fa55ad4c85ee036b0bf5b6345a2a1eaf05a81e66000527fbd94388160d91b09b1d77c7b4963d6bd8c27768d040be765948ffbd68623881b60205260006040527fdf1f93c3f6e3568a40f29dfa769721bb0d56ecae7db187e2a2ed59bbeeee18c76060526020600060806000600161e295fa602e55600051602f557fcbda3bd6f960de2e77dc399318b20c310387489d7ad65d4b4a5c08a849ab1a2e6000527f2f5397a52ea58822ae9ace7a80e87d6064d0b72fa202fb5c9963479d137a9f1c6020527f29f7f8a130e56c85bff30453c7f6bb6ff0c3a2329aa96f881568aff7d5db57d76040527fffff356a0b0cb79c6057fdd64104f634042cebafbae748b06b976969f8240b1160605260206000608060006001620146c6f4603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": { + "balance": "0x0", + "code": "0x6770000000000000006b10000000000000000000000090107e40000000fd000000db0000000000000000000040000000fd000000db0000d37176767676767676767600000076767676767614677000000000000000778000000000000000800000000000000080000000000000007e40000000fd000000db0000000000000000000040000000fd000000db0000d308603a5590076b1000000000000000000000007f800000000000000000000000000000000000000000000000000000000000000290049011777effffff80000000000000000000000000000000000080016801fffffffffffffffe06901a6c010000000000000000000000007f7effffff800000000000000000000000000200004400000000000000000000010690177e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00677fffffffffffffff189007603b55774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a7f80000000000000000000000000000000000000000000000000000000000000029001760100000000ffffffffffffffff0000000000002e00000071767676767676767676000000767676767676901d13603c55686d5adef08547abf7eb197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff76fffff716b61616160b0b0b2b0b230b000008010d0a2b00901a901d67ffffffffffffffff67b368d219438b7f3f901a901460016810000000000000000005717676767676760000000000760000007600007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a69010000000000000000009009087f80000000000000018000000000000000800000000000000080000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9003603d55760100000000ffffffffffffffff0000000000002e000000690100000000000000000003151c603e556a01000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a9005603f556b100000000000000000000000717676767676760000000000760000007600009013637fffffff7f8000000000000000000000000000000000000000000000000000000000000000116040556f80000000000000000000000000000001774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a04136d010000000000000000000000000063800000001b6041557ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07f40000000fd000000db0000000000000000000000000000000000000000000001029019604255682323232323232323236f12121212121212121212121212121212900690147ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07702ffffffffffffffffffffffffffffffffff200000000000020115760100000000ffffffffffffffff0000000000002e00000063800000001c60435567ffffffffffffffff6780000000000000011c901b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee69010000000000000000007cc9700000000000000000023f00c00014ff0000000000000000223008050802760100000000ffffffffffffffff0000000000002e0000006b1000000000000000000000009011901c6044557a0109000000000000000000000000000000000000000000000000007f7effffff8000000000000000000000000000000000000000d9000000000000011a7f8000000000000000000000000000000000000000000000000000000000000000760fffc000000000000767676240000000000002b057604790146045551960006000f3", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000046": "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000047": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000048": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000049": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x000000000000000000000000000000000000000000000000000000000000004a": "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x000000000000000000000000000000000000000000000000000000000000004b": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000004c": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x000000000000000000000000000000000000000000000000000000000000004d": "0x0000000000000000000000000000000000000000000000000000000000000004" + } + }, + "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": { + "balance": "0xffffffffff", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "storage": {} + }, + "0xaf36d8c7408Ce8FAa1AF90AD03aF91F2Dd5cE2C8": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x824a1eeb2eb1cd2fed5f418cf700665ed57ec1f7852554a64e53ab714c96d76d", + "storage": {} + }, + "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": { + "balance": "0x989680", + "code": "0x6000496000556001496001556003496002554a6003556002600455", + "nonce": "0x0", + "storage": {} + }, + "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": { + "balance": "0x989680", + "code": "0x61012c60005261012c60205261012c6040527f28988182b9f8a7c79a0b95aed2466f87f9f425a457cc11ee4bf55852380a8a466060527fa5bfcb9e4a1d70b38662b6d44f23c7c4bddbdd1f28d2844f936fe9ed4bb118606080527fb03fcf95770df98315ef2b51af23285549d05625d6cfd5cffe0736904113e70e60a0527f1616db5b415312adbd59e505af5e855ca1d210196879519ae8b207e69088514260c0527f71b3c39a48356625db6957b969775a17925d33cf8280de4f7a561f27a5bfddf460e0527fe5e6216adc6e477b29568a1969d8507ae5cb6e381067759dcc20ddfe14aeb7fa610100527f71a707817752b9c6e171b6f3ada234115aeb6af498c33b5db0dc4fdd490ec997610120527f32d738512b4c2f00c4f6b9b485813c2cf29677cd20c6935cd86747935eae847f610140527ffb999b3053067e11a0741eeb60e87c0371dbb48b7d40b623e85bedfd98fa70e5610160527f268991f22889e661e3fabd207129abbf56759f2832345854e43ad1a71a339136610180527f430b14ab247e0bdb47276cedf11b5e44248e9727f7045fa7df2d545ce6f58cce6101a0527f4fd19c751096cdfa4be443726c53ee5b3d319dcafce4f195675294d476858aa26101c0527f530b2ab949778410a7c78814f61e9f6bb8321676533927a838b47ac5e28349ab6101e0527f31107fd6f10782792ddd849fa35c8fe7c90f02353ddde73098aa5247bb90689a610200527f5ffa1a6195456df5baa48f52ddffbfa7eda47f06593503c6f0ff0fd2e1e9c3ea610220527ffac10670adaae2b42169cfbb800bc8d0668b269be87b3ec21ec103a9a516fccf610240527fcc6d0629b07aa417a6c12ef714cd46fb61934d8b85342c17a39576d5f496c841610260527f2f92b102511e7127d6a76609f7ccefe157b66b938ec02b68f7e9607ca0f27a11610280527f66b91c44fdd498be0d4363e110425122affcf7593cb924a2b9df5de945c5671a6102a0527f61a97414718ff52dbcf0d9b09935a2af4fd3f7dca4990d4b607c96fb3bd8fb036102c0527f328b13a0d4892902e98820ee7471f1b7e9e97783de8ac12e9f41b0620b12b1046102e0527f7f785e3d855e1cefd16d05cd9e55a230e2f89bab26f074373defa8a9357f95eb610300527f25b8a44212fadb021ee1bd6087f2ab0696ded7219ac526c5f8c152d415cfdc39610320527f829314c23dfe811e13a3a0e993f8b4c21b3694992ada7a7e90c327da7e5a54c7610340527feccf6eea7aa9e48a96e428cc03418bc08655cb1afff348bcba819a905b88391c610360527f4ca4cb61f0e479eb14ee59a774d44edcc35ee195bf13eefeb0986f60842a7e99610380527fcc0882223f5772c358abe73bac7813da1e453b4691e26a7670c016afaca3e4686103a0527f8d5bc1107a4cd44ea32617ce6f7920fe1feaa11f278fee50c41083c271816ea56103c05260a56103e05360f76103e15360bc6103e253606c6103e35361012c60006103e46000600562e22c90f45a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e0516008556101005160095561012051600a556020600052600660205260306040527f398d623257e5b0f89ca25e2b0abdc45be46019a8aaa3038a92a8a4a7b493535060605279e55480c0374b2d5f8a9067f6474d5f004633d8a76ab315800e8a608052609f60a053601960a153606460a253603460a353600060a453607e60a553607b60a65360d360a75360c860a853600760a95360a560aa53608460ab53609060ac5360f360ad53604860ae53602560af53603c60b053601260b153600e60b253603e60b353607d60b453601960b5536030600060b66000600060056102adf25a01600b55600051600c55602051600d55609a600052610419602052609a6040527fa83059b5378e329797c8727a21bbaa4a5ce17616f92d360efd0b8e0e6e87da806060527face2068e180b2f589c8ec8af18afa9106ecb77dfe8804391f5ee3ba4020ed90f6080527f48498669d1d8ea97639424edc481d8c779fe88b743b65192d555d1a56ee2eb3460a0527f57e7b79db0d94440ef273372c7400f22ee2f7e5c56ac7c1b3683103753d339ed60c0527f25d0d57ff2c195bea93ad7561a1a0b28cf532746a1ea906bcde94065471b3a1960e0527facd81708c93aaec13cf93bd961a6655812acf22bc174610fd3013c119f746857610100527fc2d637609f89fe5238e89ad03e91eacdffd4c4ba4e8fbbec05d43a8aa31cff5a610120527f5dd8c032bb02bda9842e1bf592a37715a80c94f49089b7e476ba0c3c9cf555e1610140527ff794461fd019e9c9bd830afb7945a2e31d3e43c46648ba01571bb07c355b7c42610160527ff76e0318c95a675bc8455a5aa36412381ea06763e59fd7af71602a00829fa277610180527f627eecc12d38720d86e42e31af2361907e5390197b9a17392f3185579db856d86101a0527ffde9a84b91bdc18e8af1d06f3a1b37f88103369ec05b537c3be1e74b2b69ead76101c0527fb5a148b63a962d9afb9efb48937b9d60548bfa8985671a96d6829c275c976e766101e0527f70aca763727564c42fa1b898230dad822f1bfe4ac0fc0aa22e45fbded1e90b15610200527f3628fe917cf9b6b1c72d5beacf57357ed37d6887ce82d6ad51154df4951f9a0b610220527f9566f4496b2c485b22ab07c45d87d88107f97962d46b7b8fab58cc6eebb3e7ba610240527f8660583056107961d535ec1fccc43187e7208aeb9d778e52738ab27bfaf90c29610260527f13e3acd00673b6da72efd4190c969c7d34d37c2dc895139ba54eba590b7e61de610280527f40c8c5631d46295d36fc4ddb137c5a229c8d730ea78cc08547eb942183db3c726102a0527f48227b3cb22012ab7aec285f48125ea2ee143f0a39920b30cc124f8d9bbddb576102c0527fb8accb85a3c731ca0dd92f31b72f48ac7b2a21234f87a36f478736c23c8dd8776102e0527f7df9cecf0a726cd6493942ccb6c869e5236cd60c582e5370bfafb4c59783c444610300527f9534a9669973fad1b977d22e506cf8f07efb01005d3e548f547e49adfe6fef4c610320527f9aeb73e0a20b87a4c110da952b7f6daabff42479d0fb7729a5fce5949929183a610340527fb9dd655b4599faa4e8fefa7883c8200d745e59974181f3fb9710f397252c9796610360527fff8bde752a500bcd4d15351d2fa44a2058f90404372b9ffbaee1b48176e42f0c610380527f890ac58c630a8ba9338a7cd7c322f878490274a9f3c442f7e87710c489265e136103a0527f5379258d55b4f87ab59b4a3ef618c1c21d774075858c79fcf6eacc9d12b1fb716103c0527fc26d9972d19a97de02a6c6eae49f2fda2203aed2ea8f01de1423dad42db458036103e0527f773e0597bc7c984bfec573c1a4b0e5a1b4ba6d267d65c06e2a10788f1eb06dce610400527fed85e0645d6bb0809737e9f14f46a46a383632bfc938b3d12862e9617fef2d79610420527f978069fb6b915db110abf0dd59b0406f0c091dc0144af5b9fd7a231e786cf206610440527e3c49ea6db3b5abe1ca9559078cfdbc7220be3b418e7e5157c23a3cd862c311610460527f9069ea202ab2bc6277c9d2ee25effb54df9f88779051622ad91308ae29338cbe610480527f6fff93a59978e4211222679994b72b4cd102f6c5d77643daa26b9921fc0f61ed6104a0527fee3d02cc840f56adeafd7d90f916174f9db5dd0112b56d33157d9bf127007db26104c0527f8ef41eaf79c426da513126ea7431d843dbd71f318f910a2866cd706a7a013bbe6104e0527f08a9baea223276746eaffefda11d474184de3fcc2df0503febe747a6d013f919610500527fae5a022c5755ded3cbb7367e9e2ee18518d7388f538b6810afbd1cab813ea4d8610520527fe024627e8afb95775cce17a3d68fe738ba6c62b1dcfbae57a8e41c007bad09af610540527ff0827934b93c8f6043c7cbeb9feccd06a1e7949dfe85f431e41fc7bd69292f60610560527fb1cfaa94696a3cf0b151680ff0f298c4c568af8b0b4df97d835f0fc06cbc41bb61058052601f6105a05360226105a15360466105a253603b6105a353607f6105a453601d6105a55360ac6105a65360e56105a75360ad6105a85360946105a953602d6105aa5360fb6105ab5360476105ac53609a60006105ad6000600060056301288c50f25a01600e55600051600f55602051601055604051601155606051601255608051601355", + "nonce": "0x0", + "storage": {} + } + }, + "chainId": 1, + "env": { + "currentBaseFee": "0xa", + "currentBlobGasUsed": "0x40000", + "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000", + "currentDifficulty": "0x20000", + "currentExcessBlobGas": "0x40000", + "currentGasLimit": "0x11e1a300", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8" + }, + "fork": "Osaka", + "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f", + "transactions": [ + { + "data": "0x", + "from": "0x3F7d91B63d840CC7e9601d30DAd1870aE5749C1d", + "gas": "0xf42400", + "gasPrice": "0x20", + "nonce": 0, + "to": "0x538A8474EeaB43d5a960164c554A20400151D479", + "value": "0x95" + }, + { + "blobVersionedHashes": [ + "0x010bcc1bacc0b4efe2fd6c8ebcb059554b7dbfec2743cb76df3b8a7ee740a14e", + "0x01c55f079e191202edc506f42463ec1ea104100252f606cce0626b18b381665b", + "0x014931ab9bd64716f12bcc820c5dd5162932205c534f4894bd6a3b622fb34375", + "0x01cbeb6ed0b278d5f17532cbcd6ef9549122ddc71647fe02b76102e661c2a866", + "0x0154f2b83c83440d2a051a27367e291a206afc88a25d7b5370e4c30c198b3893", + "0x0110029229592fd387075d3095d47f54b3be6ca3250185fd3c6b1819a77d7436" + ], + "data": "0x5c24", + "from": "0x872509c90c2E045B795423F9bEc01a53d6D8Cd7B", + "gas": "0xf42400", + "maxFeePerBlobGas": "0x100", + "maxFeePerGas": "0x20", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "sidecar": { + "blobs": 6, + "commitments": 6, + "proofs": 6 + }, + "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89", + "type": "0x3", + "value": "0x0" + }, + { + "data": "0x2356de7a2eb61efa51548f", + "from": "0xaf36d8c7408Ce8FAa1AF90AD03aF91F2Dd5cE2C8", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce", + "value": "0xa9" + }, + { + "data": "0x196ac241c0af75099e4daac205ef967b8661f7d0ee55e80169888446cab389dd646c65e29814547a1f2bfb158ce0ae9e8ae5d568801098283650a8845d9c", + "from": "0x918c2E9fa4fBEdf538659e6DBbcaa9cE90AAe2B9", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10", + "value": "0x24" + }, + { + "data": "0x", + "from": "0x837C90dc7009df3399617a7BE4f8a0cC0ED7C350", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3", + "value": "0x7bf9" + }, + { + "data": "0xd6fc5421add1021ba7b3d0f87504500eb4567461d1602ef1ae47a2d245dd2cdee34746967a5147422e229a5c5c8778c4afefd07ef4180c00b3f0222bd94a12e8ae979dbd710ddc260addc6fbd1bce04c17c29aedea75e54333969278f780bc76498305159f3a8a078e56b5406c184d01ea", + "from": "0x3F7d91B63d840CC7e9601d30DAd1870aE5749C1d", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb", + "value": "0x1f" + }, + { + "data": "0x2ad0cd932856858872f48a3bfbca9954e1fbfdb23c2772e59f87706e1a3456030d23d542de2ebaca6fda3fcc9993b7d72a2f921318de9a21cab1ec8ce7e45465eac10df67fe16990a1550ec62a69fd5775d49d88", + "from": "0x872509c90c2E045B795423F9bEc01a53d6D8Cd7B", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f", + "value": "0x0" + }, + { + "data": "0x", + "from": "0xaf36d8c7408Ce8FAa1AF90AD03aF91F2Dd5cE2C8", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xD74CFe323387aE2fd070CD046173026716D8D649", + "value": "0x0" + }, + { + "data": "0xaa", + "from": "0x918c2E9fa4fBEdf538659e6DBbcaa9cE90AAe2B9", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6", + "value": "0x9a" + }, + { + "data": "0xeee0c1280086fdb7ac532c720e1515670341d2636959bd199c4b1100ee2e922c000ade375037f79ef80f2ae56d7abf944e", + "from": "0x837C90dc7009df3399617a7BE4f8a0cC0ED7C350", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F", + "value": "0x0" + }, + { + "data": "0x4de106835d8cfd34aaa51c34b8", + "from": "0x3F7d91B63d840CC7e9601d30DAd1870aE5749C1d", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190", + "value": "0xd2f0c0" + }, + { + "data": "0x568a42c9ada39ea4fc63eca5d076638b268135716755154cce04fa66d1c83d3b8b79a782b93c2c580acfc5f492b0a5249ef931b043ed75a2577ed64d09c01e73e7a2f27f9773f18025cbcb3a61944e558cc07e2f0cf01f38acd08b33", + "from": "0x872509c90c2E045B795423F9bEc01a53d6D8Cd7B", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d", + "value": "0xa1e8c8" + }, + { + "data": "0xba2c8f11c8a564895afd28829a476c8d367bfbb098d49098520b29a75f8f12e5bf408cce8b63124f011d4aa443dcbf2d970664c0553dc1dadf390b54da", + "from": "0xaf36d8c7408Ce8FAa1AF90AD03aF91F2Dd5cE2C8", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c", + "value": "0xa0" + }, + { + "data": "0x45b9bac971d9e365607e39211bc22ae777703c2d", + "from": "0x918c2E9fa4fBEdf538659e6DBbcaa9cE90AAe2B9", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876", + "value": "0x0" + }, + { + "authorizationList": [ + { + "address": "0x7564105e977516c53be337314c7e53838967bdac", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xb145569777677df0dd96c73eb6b4418c570eef418e7a4ba712917dd45a56411e", + "s": "0x29b42229e878d8946805d9067ed114210ae44977c12662476ff31ce3eda375b5", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000010", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x9531cc185abbefee3e6814a5cf10ce99a1e688f1d21b0740d1489dad208fb93f", + "s": "0x1f022a01dab73cddf08cee545dc2d66a1666887cc68547019f6afef79df9ba00", + "v": "0x1" + }, + { + "address": "0x000000000000000000000000000000000000000e", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x724e5fd54b886e8a3fbcbd6fa5064a01713b695653c4d95a5814a0caffaeb5f7", + "s": "0xe18af166931b4e7dd222c91430328dda46067572ea741a9d91271852ed19e4e", + "v": "0x0" + }, + { + "address": "0x00000000000000000000000000000000000000f9", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x18e2ec7135e23b538e1c0c5136cbe0c768feb1079fb10e6042a56253dff3d092", + "s": "0x29b40d8e0ff87562883833c3c9f219344eb40ad2ca43572c915c69ec77f1446d", + "v": "0x0" + }, + { + "address": "0x000000000000000000000000000000000000000c", + "chainId": "0x0", + "nonce": "0x1", + "r": "0xd0d81ee59ae8e357dc890bbabbb05fd44eedb7be353fcc1037727be613747c5", + "s": "0x4806ecb33111550cb6cccd9e1d33a06001e0a9f5a79eb23763b1a45ff5f60e5c", + "v": "0x1" + }, + { + "address": "0x00000000000000000000000000000000000000f5", + "chainId": "0xd3efce7597e30565b0dbf75a5d11130000000000000000000000000000000000", + "nonce": "0x0", + "r": "0xe51906a3e0b553c35a8ca3b27cc79430e643ca8a21b696bc475c18a37a23c32a", + "s": "0x73fcdc525e9f628eb502b6036a651ab1915a60fac9310a35ae6a517f0d433e81", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000007", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xd3ad68f14f52131b81dd73d61dc10ac1ab6ea5d66282204c1308cfee4292cc14", + "s": "0x7b02caed5b8df68d1f9864528dbdafb21532fd927d5f52caaf06c29e2358014c", + "v": "0x1" + }, + { + "address": "0x000000000000000000000000000000000000000a", + "chainId": "0x0", + "nonce": "0x1", + "r": "0x7c5495691ec38d78992b52233530e09c309e030d3364e603055192500512897f", + "s": "0xf6f846316d3b89c1c5b4594a72b6473e6879e507eb263c90b658636a2f5b7db", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000010", + "chainId": "0x0", + "nonce": "0x1", + "r": "0x7952eccadf9af9becda1646f83c0a72e6bff17969a41f9683dc9278eeae91008", + "s": "0x6731468363caa79b27a77b8fbb84f92e4518c6ab5bc2a8ecd97c2c73820c1d0d", + "v": "0x0" + } + ], + "data": "0x78d6d46b41cef61362953d9890efb78f2d2956fff5e2977bd0a513dd50b99575278878e77f89d447ab43ca0e061caff5f8193095e119d15b73da", + "from": "0x3f8A30c4E084500855A3A35b7B9Ef39cB7B90F36", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x000000000000000000000000000000000000000d", + "type": "0x4", + "value": "0xb4ca89" + }, + { + "data": "0x00", + "from": "0x8c91B5232f6C15d412e35F7A1e10827145bdD6d4", + "gas": "0x30d40", + "maxFeePerGas": "0x1e", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "to": "0x7564105E977516C53bE337314c7E53838967bDaC", + "type": "0x2", + "value": "0x3e8" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x1", + "nonce": "0x2", + "r": "0xb89760b96f0766e01403def425f9625a3e0c56f23562e28d17a395c05a152eee", + "s": "0x1dae2e82b53f07c9f38c7dbb123c7d1c2e01b10ca10abcc079bda42d65e0823c", + "v": "0x0" + } + ], + "data": "0x78d6d46b41cef61362953d9890efb78f2d2956fff5e2977bd0a513dd50b99575278878e77f89d447ab43ca0e061caff5f8193095e119d15b73da", + "from": "0x472C5AD2732c1CFB6B4bC190Aa174656Fe3c34C5", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x000000000000000000000000000000000000000d", + "type": "0x4", + "value": "0xb4ca89" + } + ], + "version": "2.0" +} \ No newline at end of file diff --git a/cli/fuzzer_bridge/examples/comprehensive_medium_1.json b/cli/fuzzer_bridge/examples/comprehensive_medium_1.json new file mode 100644 index 0000000000..007ede6e59 --- /dev/null +++ b/cli/fuzzer_bridge/examples/comprehensive_medium_1.json @@ -0,0 +1,448 @@ +{ + "accounts": { + "0x0000000000000000000000000000000000000006": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x0233362c058b2fCc8093841B1073A90D673E7F12": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x7f2c75141e16bea0fceec67f673a0a3578e66fe55a9b6405d1ce109be7593206", + "storage": {} + }, + "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2825c17712cd3e7e5240fb76fe09ec612d0337b643e5c605c3cfea77e44d0b73", + "storage": {} + }, + "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": { + "balance": "0x989680", + "code": "0x6f18d7e183350155e55a2059b6789e979c6000527f162a8843ab70a8eba655a2bb8d0607fa3746aad9927277b28d670f772ba0e42a6020526f0e0bbb27942303ba4643e6cc17b4e6e56040527f6d5ae618f9d71a50f10169b293f4377c461a1d03b52ec7af7b1ce02652e5cb1c6060526f0a6bdca5027d9caded893298277e37f76080527f56dee841072651c9146559bd2ae432e412014e577ac59e545c1b4ea3c3a7d20f60a0526f1edef94468137f636c21ec9b2c7d7cfa60c0527fc372437bac86e5773f2345daf41fd6677d2641dbeb85498c04a207e386d0dad760e0526080600061010060006000600b7fba950d3f783ad5c861b063c1611aab1788e41cf024c88bb16fbc34ddfb498ae1f16000556000516001556020516002556040516003556060516004556f1c12fa0ddd78a26322918fa47ee576e16000527fc52e67586447920d913c04cc3aa9d9b0cf74557abbceb64301f95290b5d98f5f6020526f1ace28b99aa546b60b40fc32cf4813ea6040527f8e261fb3e6584b44626b98af977134d78c268065600faeea62ceea235a1a4d4c6060527f7647a4aa67aa19fb376ac9862fa6bc2035a85ca785a46d13d99b2c8f68c04c986080526f07fb32d7910ec39a1559394484b8781d60a0527f217642f110a5e1af97908450f518e2b4c003babdada7c62b54933972248a836b60c0526f0b07856ee7b4a57aada15dee619726a260e0527fc03d008bc1a8657dba9292c41e0bc41dddab3c9d414d78c0b301ec95fa5aec7a610100527f185175042845c315ec8ddb2cc50b71a3e9597bce1d1528ba953af14071a6122861012052608060006101406000600c7f39438fb3e5ac23fa07111ed42f89ef3ef4a321915113e48407290248efa9839ef46005556000516006556020516007556040516008556060516009556f1819f4adb9c9197bc1b246c466357e3a6000527fa6cb0c9b4a375e66ae200da6e1635b6c498d9519be4d7e3434a75a714cab81c76020526f0215c8a410e3730f02d2607dfa1777bc6040527f435377896f04799a1096429c072af1bb7d067a82ba8ca5beefe153edfdb7e0dc6060526f0977d8785df7bdfedd6c96eb5d1b0ce66080527f902a5e36b6ba48e9b37ec7f392a20c6b6d30fe5598efa1458c16db0c1d8905de60a0526f03ad642aba1c3eb74fa9405b1c29574660c0527ff680cffdfa8abc14d05b8536bcaa9383b5a6a5395e7b3bec29149ccc3ac9afb260e0526f125e9092cebeebd9044a547721c723b3610100527faf64a6d1001edec3b9d0cbfc26a855568fcd0c7dd02eaa54654fc5cf8a41a17e610120526f1105acf307fd6b74c24fd0c91895d5d2610140527fd8870ad51fff134093ae274fbf80ed5092376bc3ee833ea1b3888f67551a28e4610160526f179592fdeba49a7c7c87d09d397c232e610180527f37ddeb4a4b52207dc0353cac7aef37e565e40aaf6315a7bb7047122a369ce97e6101a0526f0f9ba6e9332a408733d57c979b89dac56101c0527ffd7757808b6b5376955b1fab01964fffb149b470b18218402a7b5e9e06c040636101e052610100600061020060006000600d7fb79b32d94d9f9728fb0abaa92d188782899a631d43adff1e43fbf36017e0f5e6f1600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f12d4d9ac9d612b2e89094982ebb0dd056000527f6cb5f28780f25fcf5a7e00e969e5d39b059e7324dacfe868af3c2c6d97264efe6020526f0659b6b1f675dcff737d026a6275c6be6040527f1de5fac6d9157fcbd9f19472a9e9ab8c065856416f67960f6e41feb126c28d9c6060526f12a7858f7ff99c7ab499c2f4d52a63476080527fcd6fb54a854ece55f28a30d56cdd82e8eeb5d6068b163220cc23a48c2a6f27df60a0526f104ec55ef915b40a3b1fa5ef40871a1f60c0527fcf8911004ad329aeb9afaa479edb2484a7fb3f827175c20e7765adba071d2b5760e0527f2d6fd0a73fb22e08b7ee9928b2e629fdb39bae99d1ad9642a0dd33bec8c83a51610100526f1311944a5123ff0763dd92602c7ef4ee610120527f0f34546993528db770a0a08416a527c31f6ccf4ae2ed0fc3d42cdbf0da43f438610140526f08ac51bdd67f319fdcebf06fd3ad221d610160527f09c3f3379b1ef6438f3e93ec5d9a710c7f9a824888e6c7dd2235d161116fd8e6610180526f0ed139544b80307edf4541fd24bc72df6101a0527fefa9064b09bc16f538449338cc4f1a8cd82f7fd07c2a832ff533c191415c88f96101c0526f0f3ebc407dbad0cd2286d86b561b9a626101e0527fcdf55653f05e8ee2c2f5ccc6ad8f3eb2b8f33ff1bfb2ec9008c94003c3066a8c610200527faa0cd89a761006c7929e760d77864b7b9b38802e99b8f3ada864c205136afdfa61022052610100600061024060006048600e7fedc10d2f09c80b115e84dbb1b3e73ee442644855390baac1085016b748c56b13f260135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f0f36c4ee91f493823c45fcb1835c3c806000527fea7b2b2ea22b4de446fb739a72febc2a7a99156d212d97d1a13136f06689d5266020526f0210b2e54d4c413ea259b9b7f29a51336040527f28af4fc715a4c05bef9c30d07b263b98b3a6fd072b4f6dd16f4abc3f26df2d936060526f0eb656a6cbd02959e34fe5e93fc698b76080527f1ca37a22a5fffac75aae9fc0704858edd83a46264428769dd541255d9ed8dcde60a0526f0e55065268cdbdfc6f89c1f3a452c7f260c0527f68b9709ca49c9af06c27934493e952cb7d854cc37ea6df8558c06c77fad0bf4f60e0526f08b02b9db5015bf4965e874d7d21ee7e610100527fe2c3d5dcd2bcecc4de0cbf46726cd46408768e174930670ae1d91e4e2a9b9512610120526f12623863c9afac9aed09eb3dc12d1360610140527fe19cab5ea99227983aa3d4269a460b422fb68588cd95426896c86bf055279549610160526f1764827fb27b8401fd698170d88ffcd7610180527feb8f62fa7f06757a4066319ab99686efdd6a8dad8623c0dbc5bc1237bd593aa96101a0526f0187efd101687306a301cf3e33d8baa86101c0527f97a874fe3b03f271a832b0c9a5fde81b9d6418ea17af8fb91d424c57bbdb91286101e0526f024aa2b2f08f0a91260805272dc51051610200527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610220526f13e02b6052719f607dacd3a088274f65610240527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610260526f0ce5d527727d6e118cc9cdc6da2e351a610280527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016102a0526f0606c4a02ea734cc32acd2b02bc28b996102c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6102e0526020600061030060006034600f609cf1601c55600051601d556f02f499ae499faedcd82c997714c7d5a46000527f2a5fd4153be6e4c28059f4321a1049ae8a457737265470fe86c63b4726dcc3c6602052608060006040600060107f8a49f51ce511219504f9cc6a36aa91dc00fa02a2c0a3bd8131f89c6177d8fda6f4601e55600051601f556020516020556040516021556060516022556f14464c85b84b5df1762b9874fbaaf88e6000527f5f36783755beb33a13b2d48bd63aac0e0f5e9341e6850bea6aed77127dfd6df96020526eb6cca1087d6fb29d9cb9b48be39b616040527f6626c90fd491649070034b958a8fa2b0e21fc8bc073fc83871727d09f6e19ef260605261010060006080600060117f204423d923e464bf4026ba530dc24a2c11827699ce253883d0048d330f49e236fa60235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55", + "nonce": "0x0", + "storage": {} + }, + "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": { + "balance": "0x0", + "code": "0x6009602960256095604a609260bd54155833303b8415735142a344987d3b99958c454796335e7d3c41951c19805d1337509a12496a589a7739a2689b833e3407513d3b00031b4971a39ca24143915657f51d645b494407589af2a05076137f567d3f780a07676c4a786f7a48460930308f6b6c6c843830fa975d65a431346ff51a7c5954345e74301b3e9b3a33fe053619195d9e17661e151d515f41f306858a7a6e183e74006b68033478f2156244719262160443025f316e1e3b78008606a14647ff7c201a6f6c3070864a3008185a0a03185d04a33af508337b353ca23b3515563d7e8646803ba0751c9d480613765216187371097af43a436a53633bf5460052599c123f3c06086b0b75785c72700a0b1b8a33158a9d3b6f60476255656c370402336b03068d05037f79536d619c966d4a171b17991a6e56091c55146d5b53643d51741d399f7f62485887745a908f57766a50111cff0b6d687c80ff770a60fe6f423437407d543c325a89125a3a57315b0a6a7034fd5a58201c5341653f919c72fe633c6f147a30375f8e30486c141210773a6609130a601a799c503847171d37175e17011646765d0bf51c95188b74314316150076707049610a1080fa8d680a53204275905091175f6e516a5a67063698fd8a5f3b610237696f41466d7f331aa39d09f101897a4132916d9b1b015674885a4a55065a5770335bf58808f1a47f9288133e445671453481048e7956345a364072866b024613100ba45c321e983258058974106e69998d1b611a0b38306c156e7c683e593a7d3a3a5f91635a02453a7f6264966d40985e883d720359823a57063e6c340b5f5e10351890ff003a66755215373073097d4a97610a124566687853015d165c8f50690017197e917a523f77390b6712611df5f157657368369646160702746579033a1e6b6f5d104979609a72035d975436779b067705775880048d6f1d3e7c387052f43a9a580a006c6b63f3ffa1171892ff8a79553f406c4a046614a0638c465b58407574309e05597b5d573b05031135423c9d195262010008113d6e5e92353a4643029b9a736b8a76877a0a050a457a3541a111617b1a3e8643205e4aa4086c8a9c3a5d1a5217489b10a37d77040608651e3a343e1890406b7e8e7443349e377e57196e7478076151313e08879d19583697928989900b447a31653a040b51356962760268057b8d3136035b37585001f20776195d71a085556ef4736c338f6cfe995a7d5d12f03a5d9b681a6457053c7795761283109a81771cf24a3e71174833f253866d0b6c0138f17e7b461a441bff7f9c43376b480a45367a62193c1b581e5816327f473670f402473f1348663b9e517b0100820b56fe7e7e9b386e04f5935a8a4738090307649419173a3188ff601076511d6f473d519152323b703af0f31c016157", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000000000000c" + } + }, + "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": { + "balance": "0x0", + "code": "0x6000ff7f1f4eaf54315c8fae4e6d3a941db177e3868769ee85c9e234085f7093ff2440626000527f9d7af2156eaac085792d574cbf73ac0b224620fba31f374ec0d4531cd6f4f7386020527f1950b494d7aeb286ce51c460d4c512946c26af7b169c969e7da114ce7adc8d766040527f909210f7f694e2ca6c1d60f6dced44d9c18e9093e026d102f8d5339046e0c1d16060527fe368c0e9c5cb0492305455ab0a1c0f37501c901b404a1c027eff554fe35a07296080527f6ad5803c0a0838d2da46ec60842496d768b7075d698cc666480038ff29e05ad760a0527ff7f742ea0d73c844228ee63b620810759f3bc275f790c8e0bfda754479b5f0e460c0527f9ee360a58a352ebb2853bc95a9181e6da00f0bd105993384d12533e7abfd46b060e0527ffa992bb9e68c423a8a3c834bb541d8986e66b1bf2eac3281420bfc1d08434219610100527f6c5b212321f86af0ac903c35f370673f0d3ca1994da43a6bad6439b610260319610120527faa3378aced9bbf492423e078b82103d33f3ae4caebe93e76a342e745fcdc9726610140527f05014092cefffeac2583a70145acf06b8d379f9a6c4eb1e2663da51a3ed400fc6101605260406000610180600060af60067f6e26585d5fd0a6ddee33d39117e99f8ae9f67d8185c13f8fed674ae80c121c74f2600055600051600155602051600255", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000006" + } + }, + "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xaa07ea6d7ebb90738862bff26aa53633e9a6a4c2732f31c270f5a02687a06eb2", + "storage": {} + }, + "0x535863dA03bc1834eeA10eeab8FF498565F33f2d": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xb214f8d7a564be547e6de1404f829b88b9c5f1bfc42a708554e97423e49a9def", + "storage": {} + }, + "0x538A8474EeaB43d5a960164c554A20400151D479": { + "balance": "0x989680", + "code": "0x7f96e27046ed622a1ac747d68654f22e78d72ebd5dde5cfe5244e8a04d8c59307f6000527f0cdf327d2d3b444f88d3e2dd89f5def6e143135120384cd4cda73cdfe8cfb6556020527f73c2af4f9cff559dc5e76c1c8c1074891ff284df755d54c990bcfd89410efa8d6040527f7d870f436757bec47394f2c6fd4ebca744cb39659dc9759dd20a0934b93449a66060527f254171faae8c94052703883b5cc818dc8d4f0a182583388abcda9d7d3b98885a6080527f0298db5babc9b6915fd16c9d77e9a9b0d5698dcd7c6798d4406082516ff92f6460a0527fdd3fd1b61ab3f616b967192b48d6846d5eb669b8191ab24030bc5c322016ee5a60c0527f6f9f9a9dd0f96c49b9a1dd4ec33c20556baee81ee0a6dbac1027bbcbd2d78ecc60e0527f35c2c76473ef7fab214d4094ccc9fb10be83173276dddf1769cfbf1fa4fa0869610100527f084b1303321eb6708e861622f0e697a6f7bb6b28924cbff65561dc68c4d70789610120527fb38665a80c68ec7c4c5926675b598c8e2c559664f2de200ee44fe4c79c691a8b610140527fe35f61a689d051e2ef0e84c0d36c1a7deb4fec99447762591c6f6096530bbc66610160527f24589df6f317949386b8986b6a659899bb0c0b0ef1fd412a0b885921ad867201610180527f419906d725ad3628677528d9735308ef7b51c8aff282640658ee31f1e0ea04836101a052608060006101c0600060ae60107fdec1d9215e7dca700a09dcb57f9076e9d92bf98b71253c9f8aa0c2f7bf0e8c58f1600055600051600155602051600255604051600355606051600455", + "nonce": "0x0", + "storage": {} + }, + "0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x641602bAD4A323C49629d45338d79A2bb984A3fb": { + "balance": "0x989680", + "code": "0x6102e051608060006103c082819290913e20606d5560606103206102f05e600c3560606102f0fd", + "nonce": "0x0", + "storage": {} + }, + "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": { + "balance": "0x0", + "code": "0x600bff286001600055600660045d7f6001600155600060005d7f600054507fe4014fdbc93a0c052fd4d7fe3b1827156000527f906b6af91af7e5189c91966000527f5d9f7c1dd36000526040600060206000606020527ffa7f115422365081605f82110ba02d6020527f8f3f386c56309ddfcc0d9555be6040527f0ff1eb52b5a7f46002556000516003556020516040526060606053600460615360605260606080536055608153606060825360626083536053608453606060855360636086536060608753600060885360f36089537f1a2488a7583830e08a2d3d95491bc5cc8a8bd4324a308e2ae656ab355a6a7cee60a0527f202459f3ea19d89fdf452056ecb75bbedbf440c26cab6fc613700b334ce193d560c0527feb871f1876b0658470874f9ff9209b1d958f9002365e0aba7e9acbea7e98632960e0527f5d88dde4a225dadc9eb6444cfc690c047831a9d0d65d4f73a4432b8749ced7fb610100527f45b0ebf658bcae7bc00f675b825aa5749016393917c06e56554f646f20e0528c610120527f87e743b4b23c3a75cf536ed88c258677a578cc76b164b77955e5cab4bb0e3e8d610140527f37d9a1d4409d48965ceaf0bdf64f54f49194aeef28c06bbe1f1e7c0054248147610160527f039deaacdf4659d9d892b472b67a4642a5a605326275bdf953aaa76d4950706961018052608a60006000f06040600061010060a06000855af1600555600051600655602051600755600855", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x000000000000000000000000000000000000000000000000000000000000000d", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000010": "0x000000000000000000000000000000000000000000000000000000000000000d", + "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000012": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000014": "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000015": "0x0000000000000000000000000000000000000000000000000000000000000012" + } + }, + "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": { + "balance": "0x989680", + "code": "0x7c1810006947494e06de82ec6c913c636d201144aabea6c44cdd285c84106000527f833f564ca3bf6dc32bd8ac866434694f71293812e07d12849bc05213c23691646020527f6d33a0b53d3df1a6de97147b5157cae198686cf1533f6bb9833007bc7fb3e61e6040527f6c91e941fdb2af7b0b19db801767c3e87460dac3906a9075367654892b622a426060527f52769125e5c0d9dc254d06af85a9a45919df1ac386697f81f5c4ca9b3d0eaab96080527fa6d3cf4af84dec80aa879b35bcdbf309d777663fc6b92942e34191503b3ad03260a05260cc60c053606b60c15360f260c253609f60c353603a60c453603e60c55360cc60c65360cb60c753606860c85360e560c953601a60ca53607a60cb53602460cc53608a60cd53609060ce5360e460cf5360ff60d053609060d15360c760d253608660d353600160d4536040600060d56000603260096008f2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x79cca006f0792Bf40a6d4E011c2884eD862A52DF": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xada9e915b45b3f9f3f335fe00a484308905ec68a78d49750e1a47ec4f9c17d23", + "storage": {} + }, + "0x862B38c425EF5544d0127449A12c89C46dd3E050": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x35c0e7a818e7367e6218647e77752b4b0d92f50362a7eff324915762586509ba", + "storage": {} + }, + "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": { + "balance": "0x989680", + "code": "0x7f80000000000000000000000000000000000000000000000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a056c100000000000000000000000007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb005900b6f800000000000000000000000000000007e40000000fd000000db0000000000000000000040000000fd000000db0000d305901363800000007f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001712000110000000d0a300e750a000000090a0a9009901a6b0100000000000000000000006d01000000000000000000000000001d177f80000000000000018000000000000000800000000000000080000000000000007d76767676767600000000007600000000000000560000000000000000000090036000556f800000000000000100000000000000006c10000000000000000000000000126001557d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97f7effffff80000000000000000000000000020000440000000000000000000001016002557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd637fffffff1d7f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff00000167800000000000000168210000000000000022099011151c6a01000000000000000000006380000001901d186b1000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb1d6003557e40000000fd000000db0000000000000000000040000000fd000000db0000d36fdac7fff9ffd9e132262626262626260006600455762900760076761e000200767600000000767676760000006901000000000000000000900717197ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb7f8000000000000000000000000000000000000000000000000000000000000002901d6005556780000000000000016f8000000000000000000000000000000016056006557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6a0100000000000000000000900760075567b368d219438b7f3f7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00901768066aa0a5319bcf5cb47f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6c100000000000000000000000000805684783921454358970526f8000000000000000000000000000000190071b6008557d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf967fffffffffffffffe1b60095567b368d219438b7f3f778200000000000000fe000004000000ffff000000fffff7007702ffffffffffffffffffffffffffffffffff20000000000009686d5adef08547abf7eb686d5adef08547abf7eb1d600a557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff677fffffffffffffff05901015600b556f121212121212121212121212121212127702ffffffffffffffffffffffffffffffffff20000000000090136fdac7fff9ffd9e1322626262626262600777effffff800000007effffff800000008000ff000001000012600c55680100000000000000007e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a009006600d557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee681000000000000000009001137e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000651ce97e1ab91a02600e557e1f0000000000000000000000000000002000000001000000000000000000006a01000000000000000000007f77676767676760000000000000001002e000000000000040000000e0000000009009712000110000000d0a300e750a000000090a0a63800000006c10000000000000000000000000090760006000f3", + "nonce": "0x0", + "storage": {} + }, + "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": { + "balance": "0x989680", + "code": "0x7fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffffffffefffffffffedffffffffffffffffffffffffffffffffffbfeffffffff6020527ffffffffefffffffffedffffffffffffffffffffffffffffffffffbfeffffffff6040527ffc3a2f02de65712b945c08d0980ad749b92bd7d38f1b3e470deed91662736a1a6060527f3da9b83f28fb59f39d695d836c4595213f2e68b3b8a5bb83a114df3734f673d96080526020600060a060006000610100611bb0f16000556000516001557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527faaeec1df015b2c79efd02a48950975617f8513d1f23dd02cb37cef70a1a76e9660205260006040527f6b25db539f5946185cbe132e22ad09e1c01fab7afcc9c52d5b940d7c87a9ebab6060527fd5a90ce8b987b05942d0d6cefa2a5c864bb377c4e876dd42453992055b4a50c56080526020600060a060006001610100611ca3f16002556000516003557fbe490cd43a8c01bf6a07ed9ffc82d88dc8661980f11412e953a32768132ef2366000527f7b952eeb664746755c081599cf42620b39a630439719b17a0dfd8beed77ccb2e6020527f01c1e19eec67f278e72a7c65b8a304172eb1290a81324a8921ae362f3a20068b6040527fff9c58a91b2e2d65525c7cc313c4d9e806efebe2b25f94e970f253fa14b78d016060527f5361d075c7705e054d8aaaf2e2bae692828827eecb21697a0e50f594dc6ec8bc6080526020600060a0600060006101006119fcf16004556000516005557f4ad81e14a688ea777d58214ecb6214763735abbd317e3ae7f789254666a873766000527fb5979f0161380baf7720bf616da397578eb9f5c54750a8bdd7b06de7d549e0f26020527f765171a147b702a79decb6174bbc322f9a5faa5737d08efa04d8ef8b2c7e355d6040527f41b63405d22ee996112005b48fe252bd767d60147a83a579003db8c80e88f4726060527fd8eadb1ad524deafd2791cba205e43ae1416040133e84075639184b180e7ae4f6080526020600060a060006001610100611ce4f26006556000516007557f95454173cfdc225fb21debd06f84ed70994e98e634852bc59122192795a562706000527f7097bc46cc19a70bea1e2122383ef1dd87ede22020e8c90232b086923d624b1b6020527f5248d32f23121577145b806de74c030e2e26052f8024092d6b7ffdf08529f6836040527f3a471768c788e80a9e0c79c6514e91e244544d18d91c5e6d647d8dbf469b13926060527fab397df44745e87f5cb6fd5c279c4456bdae8d5ab21cd0b476c802047be6aebf6080526020600060a060006000610100611b1ff26008556000516009557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a06000610100611cd4fa600a55600051600b557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f0985caae0f3ee3530d6ac3e401171f1dcdd87cd77137192312c65c16a0e230e56060527fbc539f7392385647f381799037936d0f8460d9aa16928f192f085d32ca60fac26080526020600060a060006000610100611b2af1600c55600051600d557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611caaf4600e55600051600f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611bb2f26010556000516011557fd95a8a726d8b94500f2b1da117e9b1720c4f0f4ffacab4ef82ce69e5bf0f837e6000527f18ca11386098e3bbb69f2295e67a3d92c225402224f32926597894fb0a1c338d6020527ffeafe36c9b3c6426c2f5cccb21b765f489f7a549f1b94d0fba5c5f2150a53f5f6040527f97dbd752f38179710604ba60b84b2b43c8360dcfb58a7f99bc2e4d73aaf2c0d26060527f1a6d57f85b6654b3d246f7399fc0491529acf9baf253229e1cfea1f652d56aa26080526020600060a06000610100611a58f46012556000516013557fc9423f1212150d2f42d3d65735ec98a59f0fa7cfee9851efa0da6477383f84106000527fb3f71f3eb2437c230de62fce1f175b724c23adfc6fdff1863b73e71b17a0a3416020527f47341a2c30078fc15c2d9ff0fe33dc54a2f79ec53367d6e1bab8d48fbf265bbb6040527ff9459daf8d64f0765c546c4ee8099fab2bbfa31fd8cb21df9780c31a7ed7a2f26060527faa0a9a0f8a06c5385411f2efb5791de6750fc711805044550e2883846b817d9b6080526020600060a060006001610100611afbf16014556000516015557f8ac0f7691fb4629af96eb4b962e7e557b3928b47a38f452a1cf24df0c0ce2b1a6000527f97c6bddb1a11e1e223c3008c4b5bdc48c998b30c151734a5e48acb62f7041e096020527f9ac61545dcf4cb6a47cd983e9538919611d8228a028962787ea750505cc323b76040527fcee4c729d8bf46d0e1aa5c2924b70a2e1458ac9b082a21c7fa5c8c91000a1d326060527f669d02080b01b70b086bd2a25d204c7cfdecc5a68e8aae5eeecc24df23f7d4316080526020600060a060006001610100611c4df16016556000516017557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a06000610100611b30fa6018556000516019557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6020527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6040527f37cec76d1f3bbfec96d5feb30a095d8bccaf8e3b3fd246563d44876c7e023a816060527f2a5a699c56efb1b8cce8066db3ea053eca2f92fdf27d978e9d043b296dad7a376080526020600060a06000610100611c1df4601a55600051601b557fc598d1bc7b8deaad833597c6065bf2c5e39c14fbf6857d24017a9a52a783be5c6000527f1e52f24e498515f78270588cb3cdc1dad2256baf7b4350223143a9696a36574c6020527f3bbfae4facdffbb18c8f3d5df6fecda9339decc06c8d43652c73b2ba43f5773a6040527fb6a9068ce72b7e6724d70493a8e28c656aa8058a47ea010a95d73905b25bdd716060527fb674f6b897dfed1e24cd7825b4d7c25396a4b84840fe9d99201c5c5e833d96946080526020600060a060006001610100611b2cf1601c55600051601d557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f7421a12359bf7f411da04037c4168a24aebdf951546d203d7f52c1d9a083086a6060527f844fa38b8e9588a8a8a6a8ecc77de074e4b104edd2ce74d0cdadd2674ba28cca6080526020600060a06000610100611a39fa601e55600051601f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006101006119fcfa6020556000516021557f9d121cc301f8aa0b6c410c09755c16006410ef563790acd435ef44521f31444b6000527f6018d9327b3eb5c170a4b5ce7177734f914c0d42d6b8706ff4cf775ed56bfe5c6020527f1216f7a990c04237f0e44a6705030d84cae4ec8d797b9373cb8afe7771824f2f6040527f83b03bf29b9090a15ce7a7cbddc2b937b10bbb71c988cefda85a0fbbe31bdf376060527f220cb57b3bae8643a825a585ffd2982ec3e5227784ff9dbd113e3c71faf998d06080526020600060a06000610100611924f46022556000516023557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611955f26024556000516025557f911aa27b36f7d952dfa15589fa0acdd4353d802f9e646a27cf515b3b0c6ad9f26000527f9870e87a88d959d124a98b897a79732bd613d9363888769490327ccfbc8c85606020527f85bf05a8f523b212d5a38da5f7494760ea94f79717fb401cc31c0b52012d89c56040527f151cdc310d1c0fb068193dd9995cf6d33e21f4c543b1420b28b60e264cf438366060527fc02016e4f0a388500dda3f644c0a0a8369243df9efb5db3d08ac8d1911eb149a6080526020600060a0600060006101006119f3f16026556000516027557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006101006119bcf46028556000516029557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527f99ee9c85744518a641fb86485494690139f717ae93817a0f56ae938040e2064f60205260006040527fffc0f614ee1e3eb711183f058772b9b99f3d17ff31a7de44ea279b86e659ce506060527ffa558b6d6b4b9fb6fb28c55bce8acb4d4f437d3615dcbbc0a5cbfd8807833bce6080526020600060a060006001610100611a12f2602a55600051602b557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f37b7a14518d8e8c2c425b7a5fcb2e377296874a15dd38945013a81877a07c8946020527f37b7a14518d8e8c2c425b7a5fcb2e377296874a15dd38945013a81877a07c8946040527f04fffffffb0000000500000000000000000000000500000000000000000000006060527f04fffffffb0000000500000000000000000000000500000000000000000000006080526020600060a060006001610100611909f2602c55600051602d557f9add50aecb2590beabb40a73e52cb7d25eee639a881c53aec8229c3c89b147c56000527f22773d54fd753a32afb62abe1bc9edfa1bd447242925928b498311022a4088046020527fb4be5a59e02f6c6fdb331753e275322d60b3b6ae41886cecb24b6a0fa38b482b6040527ff9195e00fff88c599a6b5616733f28fabb45c11a93092c035562396e523a7fbc6060527ff338d766aa5b91918b6e29c80eeb8d6b912a0961e2974ec5e3d86a75e06218556080526020600060a06000610100611c62fa602e55600051602f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611c83fa6030556000516031557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b9afa6032556000516033557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fc37c841d078259954317bfdcfa432ecfb86253f87270028f023bafa2dd25924f6060527f0bb4264610afcd1aaa8c08467a307f396f8de2b77a0ebdab2b2870563909da5a6080526020600060a060006000610100611aeef16034556000516035557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f02fffffffd00000002ffffffffffffffff36b4f008f546db8edb2d6048f529706020527f02fffffffd00000002ffffffffffffffff36b4f008f546db8edb2d6048f529706040527f7c6f7895747231ac77d562339b36a17666dac663ed5e15f8ae40cadf411cee2b6060527f5dde658d2a1b8ec9ae16d52ba9d04e5c0387810a562775dced140eeb21b29e926080526020600060a06000610100611b38f46036556000516037557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f20385e628215070814ecf86812295e71fcd8a943aa03877f57f7868979eb6c6c6020527f20385e628215070814ecf86812295e71fcd8a943aa03877f57f7868979eb6c6c6040527f03fffffffc0000000400000000000000000000000400000000000000000000006060527f03fffffffc0000000400000000000000000000000400000000000000000000006080526020600060a060006000610100611a13f16038556000516039557f0d387666d4a50b0794b35a1e676f95921ab4a9a0418d6d90dd7dc279bfaf05c16000527f85053f55f125a5458f9ec4dbd99392a5e913eddfa113b37a8c6fb531e07d36726020527f93a478228437246e849746a0cf48fcd25bd8ba790ea446217d227ed1fde8b8276040527feaea26fbd043f12db289b0745b8c77395a68a6c96cbe4ad6137bbe1a7e5edc546060527f7c5406ac087ca551dad122d9088dd93360a7ad33c3c7b92d7e56887e0f61f3946080526020600060a06000600161010061199cf2603a55600051603b557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b0bf4603c55600051603d557f75a4be67ccbf899fbde0dd16b3c3f6ac6278bfe397ccff21857d15da866bcc4b6000527f1256f1fb4828792144fbf30fd0f9bd3315e64786bee2fd21f264bc2dcde845516020527f2c5723112c82d6c1f80000ce4a6ffa343377307ae58c5f2f704133bdaa9ae3c76040527fa574345be4ff67553c7bc71701665077ee4b6e3e11a15eac13770fde5b233ca46060527f3572978e4e046c9fd18ca0b5582f2a7ad14d7838aa452a18680ae3a429bc510f6080526020600060a0600060016101006119e2f1603e55600051603f557f2dd2fc34631156074982459867a4a96ed1b1e8f752e7b7a49a11780986d2d02b6000527fff057f2ddea4367d67200ac15efabad425bd7e5ee028854c6ec3b19bc8895ea36020527ff060d2a1739e51e785ef0ee757cd97560d7fc13501cb4e1c39d762a309fb841e6040527f0379e4cd9a4824cbde4686ebd16df416fba39fae4b714c5d0d24625d084469666060527fbc3e9f5e3e90c98795007800d6c0ca9cc3d7560c89c36068332792cbe4e0357f6080526020600060a060006000610100611b73f26040556000516041557f10021ad946641eef1055d665d7030c60dcf39a4b5b4eb19a18037c0097afdb246000527faee82d13e528762e433dfd89373588f00f5a3ab03acbbfaad357fb33a5fcd5b06020527f571d96ac94c21a38f85de4546e48ab2e4a579cc366def7eaf03fa803b0d0d9b66040527f2f02d0377759d89eb38a99b761a7b796495493acfe161d4634608210c551575e6060527f769332a3b848b8bd69b4129911d2d5a8d3b9548cbdf6bbb6d4b285e4fd8357d56080526020600060a06000610100611bdcf46042556000516043557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a06000610100611a76f46044556000516045557fc3df4030e15dc0d030692656dfa055d2b3ab7d1f1f157db691597fa809dcb3376000527f66234c39bc3363275b52c3fd44c90f98897803ec12458bd84c26d005391f3fbf6020527f9c942bc9c73cf249f3764587e3aa0f5d3f292bb38ccd0c9b4cc8f08ee0cb7c956040527fd97dce720557d57791a7aab11f659d3c3cc27f3212add2c8434faeb04e8340bb6060527f46ed59c543d1f37e8612a2e11f99882f5b5ded8ed733465b63059e7c394f47f86080526020600060a0600060016101006119aef2604655600051604755", + "nonce": "0x0", + "storage": {} + }, + "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": { + "balance": "0x989680", + "code": "0x6030600053600e600153603f600253609160035360056004536071600553609e60065360cf600753602060085360e0600953607a600a5360c5600b536053600c5360fe600d536044600e53608b600f5360c56010536061601153608e601253609e601353603760145360c3601553606960165360876017536083601853605460195360e6601a5360f4601b5360e8601c53608c601d5360ea601e5360406000601f600060077f9f914c6b08e682a081d2d8fd682c8093f8ed74ebb3ec8711598863921e79de7afa600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xC192f888ADA47142Ef2c856FC2C35197eea9E718": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xc14a8497cfed2168f05952f5437042184f962496ae2ad8f389cf588ae6ae5426", + "storage": {} + }, + "0xD74CFe323387aE2fd070CD046173026716D8D649": { + "balance": "0x989680", + "code": "0x7f01de0d4bedf35144d5022ea8f807f68bc79f19abe604e3c4f9774f21517e0e886000527f2e91565c9e29fd6b1406b4dd148bfe805723651567cd013e1a5ff05553f1fc266020527f28d05f9ee49d9caf10a86175605981e86d9c9ae128158dcac272a1df69f7dc516040527fafad4e9799b8ab2e1f7d598ba9ab82cdef410a3f560a2f4fb300081766e9969a6060527ff4e68ee6102e13059303259b7d880ec183869e0aa85c187c3264cb3f297920d26080527fb5623bd151376ae749a02af6b642819f64a5a8d7abe46052adcfb3b44c8431af60a0526040600060c0600060e7600a7fb915f367d70f2d7ed301673fc7f9d93dc9e7df385991376505ecfd946d36de30f2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": { + "balance": "0x989680", + "code": "0x600060005260006020526000604052600060605260206000608060006001600161a321f16000556000516001557fa5621ec461df934885df87c577f28066b8c6bf7ae936471ac0ac7d1e37d176786000527fe08ef3afe4073e521f5a89f4a9188ba00a226983ccf1e46a2ebbb8109f88ea1d6020527f85f5fa439c5a885b49aa392774f346e618393818225f34cad265fac1e54563036040527fff3c4d8ff92c311289a7e7ebdb4f3be590344eba725d97f59cd048aa33828b93606052602060006080600060016201081ef46002556000516003557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fda1398e40e42e008964af3aa5f0a343e6cfcbe5305d3660334b2bbc383f262ca6040527f1d7be1825822fd58a48cb43a9760ad86a468321d843ded67848e3980fa2a79366060526020600060806000600161480df46004556000516005557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527ffdae382eaa2470305db5d4fda8d1179a5183f034a042b46f19f63c933b33619a6040527f3add5cd52644881226f6d3e255d611f39ac802730d9da8b7fd8e2ef695463bb0606052602060006080600060016133f3f46006556000516007557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fa68af8eefb8844f05b0fa80aca01755e35fe788d83a7630aa0982af5e171ce1d6040527f2e7232c272df81f99c4cfb13daec393a6f68152fb69515b92b3658f2be928454606052602060006080600060016001610c89f26008556000516009557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f335075861c51f15a8180e465e33a79393b322bfd54649f1d09feb50eb18153476040527f78f516fb6cd1b8b03c91b15103321b4678a8a06e5c4767cb4fa8236116fe8a5d6060526020600060806000600161c761f4600a55600051600b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f304cf9115472b9acbe808ea11428ae5c6048a5573aa3e719b6c196922128a99b6040527f4bbae5da7b7fdcecb397082b83653a63763935c3bf619d9bf3ea978c8e0a47b860605260206000608060006001600161d3c5f1600c55600051600d556000600052600060205260006040526000606052602060006080600060016140a4f4600e55600051600f557ff32eec09a93567be48ce35b712a1b16539a8f3e797ab55cdea5bb1ef90dff3956000527fa827922f078f505525baacb818b6a15ad6b9c506a09018c68999e28a4d426a1d6020527f87a26e26ca9dd9735d1022cde00bf777924bb4f9128df846b469cab30db65c866040527f4e2c1908e8a6519aa6e9a482a1d7b45f587462bd15c06321e23dafe8c05289236060526020600060806000600161a12af46010556000516011557faab0530c99524dcafa571c784f17a37638e4c40b02df4f097a599b1ce3daf2f06000527f367819afeffb4d5e691be1a305d95e090811c8de47e3e2179b5a0880f874e81b60205260006040527fc629d9b24dc66c52fd1adfd9de1e7e5e867cc153d34e622cea630d02d24ac93b6060526020600060806000600161d41ff46012556000516013557f1275e3f62fe4f663581b8f1920a2056ef61ef6d24d3cf93b6b9300d5d1da3b0c6000527fc38af617f098d9bbf3179194a8d6536261f71ce5247d4b179de050139e25ad1c6020527fb045db9878135c9e2253636b40c2bfdd218563082adb35d1c6aa68a2666ebdc96040527fffffeb93395e132a2546d82a9bc9ec8ed63e7cc62da9f537b386ceadbbba02896060526020600060806000600162013ed8f46014556000516015557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f1bfc3594d3ea16195343c7959726c0e90a5aafc0e307e8199324a24b6d85796b6040527f7372342c5e04794a0d434073d73e0d86acba73476cfd417e32212619344983a76060526020600060806000600161589ef46016556000516017557fdfa21b05ce02e03b7f42f3385eecf8614701e057154f04b75c4edec10b0ce7cc6000527f7b01e6b04bf4f7e9f5e19592b60217fe14ab8978c0795fabec8cae297fe6591b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fc11e69a1e07329747f6042217206556668a8fbe73cd46a1552ad20cb31d7e3a0606052602060006080600060016177b7f46018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fe99324cdaaa32e6994bc8accfc797329b8a3031fb424da18bdbe7ae1ce5432cd6040527f5578556da337789cf53638e58da42301606dfe2db467cc482f282f70ee25494060605260206000608060006001600161a881f1601a55600051601b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f71d3f0efa306fe4a489287be4bf731ba59008b5578a0575e86df979c01fa2d136040527f010fa20e9b9b26ab399bd34a5caafd8210d2c3d5b20a084287932272622fd3ac60605260206000608060006001600162014694f1601c55600051601d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f47ef410eef537ae6685e76a65fafbd768707f22cd7a3208e92e75553b64afc246040527f4633d74dc13137a982ad969e99f3e34ddf4043b7f71d17768d1e5d44917afdd060605260206000608060006001600161fb0df2601e55600051601f557fdd7795cb9181c1840841e9f7c35aca534a161267ca048cf99b9bde4141adda576000527f23a510455929c3747acfdbc10ef5b5a1ad79266004ee1c2e0e9726c4e172dd1b60205260006040527f714e3836b80a7055dace8298885f24695d369e7a39f528f4a3910be50d174f436060526020600060806000600161d02ffa6020556000516021557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f0efe8fa94ff50316b3ec97b5f23e9a03a24f422a379860076c44d31b3a2fc2336040527f421dddebe35bb7bee2ffa96ab41122596fd92c8775123eaa7fdad753825c696b60605260206000608060006001615faffa6022556000516023557f2d013c5e51d0be3dcb6f506d18a69bc4747be02d00b4184194926067291c796f6000527f361f0ed0ac73e41bc6bfdaf5abb874da420e3eed9e2e74b35de46d271a9717596020527f651cd1bd399e2b59860ec16f3a9280a7d35f97e3490d7829e1085dd809f77e636040527faf4abbbc5ea9968b423dbb69dde46adb9388f463e97063aedefba0b60e7082a16060526020600060806000600162010951f46024556000516025557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fe9b95a12c340897c063ac3cfd1b7acbe4a0da0bfc81ec062f09675b048ef2ccd6040527f52807eb804a4fc3e794e24d1808a4f809a55a5c6c8a23b89c34f833726e2d92a606052602060006080600060016001620157baf16026556000516027556000600052601b6020526001604052600160605260206000608060006000600161f380f160285560005160295560006000526000602052600060405260006060526020600060806000600161e86cfa602a55600051602b557f73eccdeff1a8150ef8d9cf7157b51d12c07b0494ef7ae4568cac21c33bfa92c46000527f892abad06cd4a2e33e363309fc1ece4d12c3a4553617680ceeeae747a9cea81d6020527f5b7b5dc85b34de6ca00bfc58341126c699bf992b7a1ca7a6faed21ccd9ebd04d6040527fe63beea996e785a07b35f7cac66899fdb4746fe3803751fe66ee99a6bb2cae49606052602060006080600060016201793dfa602c55600051602d557f2a50c17a6e67a09ffed7c20e9d938cae76db03fc54a6547862700f1f3c146ceb6000527f4635b8a742eb226c4310ba261bfc3dd4971517130e37c539c5b948fbb7e55f1b60205260006040527fb898935f3b968fbec7fcd5efe9e2f63b1b876b0b3fb76cabaf1ed606051b288e6060526020600060806000600162013ac9f4602e55600051602f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527ff509be065ef1b1b177524ae119671796044d4b45cc30c9f36f71e737ae96c6f26040527f6b198d17a16c8f7bc38af6549c4b0f597d39c558045393137989fd22a653d8ed60605260206000608060006001600161b3d4f1603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": { + "balance": "0x0", + "code": "0x6b0100000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a0267d0212626262626266f121212121212121212121212121212126380000001900960005519778200000000000000fe000004000000ffff000000fffff700600501600155778000000000000000800000000000000080000000000000006a01000000000000000000001c6002557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6a1000000000000000000000901a1590147ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6c10000000000000000000000000900569010000000000000000007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7e40000000fd000000db0000000000000000000040000000fd000000db000001900960035590027a0109000000000000000000000000000000000000000000000000007f80000000000000018000000000000000800000000000000080000000000000009007600455677fffffffffffffff7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a001c0519760fffc000000000000767676240000000000002b057604768210000000000000022109018777effffff80000000000000000000000000000000000080017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1b1b6005778000000000000000800000000000000080000000000000009011901d6005557f7effffff800000000000000000000000000200004400000000000000000000017cc9700000000000000000023f00c00014ff000000000000000022300805026006557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff901b6007557176767676767676767600000076767676767667800000000000000090187f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a576fffff716b61616160b0b0b2b0b230b000008010d0a2b00901c60085515157e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0b6009557e40000000fd000000db0000000000000000000040000000fd000000db0000017f8000000000000000000000000000000000000000000000000000000000000001651ce97e1ab91a0890047e40000000fd000000db0000000000000000000040000000fd000000db0000017f800000000000000000000000000000000000000000000000000000000000000012137702ffffffffffffffffffffffffffffffffff00000003000060011a9003600a557f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56f1212121212121212121212121212121201600b55637fffffff600190177f82000000000000000000000000000000000000000000000000000000000000007f7effffff800000000000000000000000000200004400000000000000000000011d15900260017f7effffff8000000000000000000000000000000000000000d90000000000000190110219600c55638000000163800000010a197176767676767676767600000076767676767667fffffffffffffffe90039019127ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a59014147f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff0000017f8000000000000000000000000000000000000000000000000000000000000001901d600d5560006000f3", + "nonce": "0x0", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000010": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000012": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000014": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000015": "0x000000000000000000000000000000000000000000000000000000000000000e" + } + }, + "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": { + "balance": "0xffffffffff", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "storage": {} + }, + "0xd5A8353a487e0749707fee138b741aeb2061C14C": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x4b5f705c5993deaa35a6d4e991c09c52f1d54151048b241126aa7c780cd2723d", + "storage": {} + }, + "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": { + "balance": "0x989680", + "code": "0x6000496000556002496001554a6002556001600355", + "nonce": "0x0", + "storage": {} + }, + "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": { + "balance": "0x989680", + "code": "0x60e360005261020060205260e36040527f17064e08aafc17bc922849c8372926c6a434f083594f6a07a8a45c764d5f32746060527f1f6959a22ac38f4842df68feb8894add1446f1f2b5eee105a531d9bab03dfdd96080527f95ec80853752d76fd53b9f3b5ee9028646da199627e7229bb1fdf4cce004c90760a0527f3b646cde24009c8a34bbd09080385a9aa6faa3c56360cdd8f1f6981dab2876b960c0527fbbc5ad8a8ef7dc0af7260ba09ecaa44972667a2995b572460c55e5a6bc5a54fe60e0527fd0b9e187dc2a1423bd2c32ffc276266366f4b8c23f6d9db52a800f7075e8ad7e610100527f9d0d8bc9c71ef1815e1f247afe1ddfde106adffd054ff9d0e1aa05a421d70db4610120527f4b6d6fb048e531dcfaa8d04551c0e9477487e1f42dfe6b078683edce88d707a4610140527f636d013bde3777c7d61819db32eb615638a717cd059f2b8ad9954706c98770cb610160527fa219a4f1ef80c84ba5f49f32398f3f92d2d325856dd70dba5a85b32f96cdbd96610180527f467edabf6a79713c6f62fdb7680ff03452a41bc91c2abcecc72e736e62c59d3f6101a0527fd8c7a5b6d35332bb32716638e5afc3dc11e15fdf251f301fc0b30c64e2accdd86101c0527fb65b83a80c856b89e597084abcc78eabb3a1c77561ca466f62ee699e334571c36101e0527f8e90fcd0ff032e05e75b51d9dec47825830251dc35616413af21313736dda353610200527f6fe1d91e54ab0713be14458c91ba5d750d4496890c25452adbff6d154efe2253610220527f6a50e684a75187e31a5866370cfb737ff50cd49b2303a43f466b6eb621193c21610240527f6c4b5f56d956912d88f44fb605dab278667f51189d4e3375d89b02ee40ff0efa610260527fc3503a6dbec74bdcdb811e1c648183980f4efb71f6ab7f632b416a5c8d2e7c9c610280527f02b2f7383198636bcab2bd027039c66ccec0d1bc0a9b066e4bdc871c22e527c26102a0527fae9a79a076c724db7dbf49a2d6610673568da9af9d551bba1a0c36944d1554626102c0527fe0d0ff83459d9d4a1401b8684f532643ce5d5c85e6c7194ec4726be2f3e9aa9f6102e0527f654e210bbc2793c4ceada7c42c8cdc784ff08014c941dd5123f5edd5ccedaab6610300527f0eb0abfb04c0bfefc6903c8eff6834a397b347248a5b8f09d6b053b4929cb7d2610320527fe77c26e53f9d388aeddedd75a91aec3694862f4a2bc2c704afbf0824c5997359610340527f5a6382f831c09b9ea1713902fcd17e9238e374c2a9fa49b55e344a21ab2ad0e6610360527fffc47ec16d2055eced751b3cd2ba7f4370247dbcf13a1ca513ffc09dcded5539610380527f6424b6fabee6424573a0f47c8b29c0a32bc810e559f8eab0cbb48453bb2322806103a0527f4dacfafe68f1a203c122ac379232368b3c44e6c3ea571c9690eea2288726d1d86103c0527f81dcb18b456fb670e67b800f82718896d03244459dab3fa9d6e963f4e6b0d2906103e0527f98c2300ecce35fdf2d465fb2bd595934fd16de5d0b4250dde3807d3d39d62b8061040052602d6104205360e06104215360be61042253607061042353606e61042453606c6104255360e3600061042660006005630121304ffa5a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e051600855602960005261039360205260296040527f5b18ef532970f673409e96991eedb6c6c5ebd58355c4bf48036cd4965402df856060527fb22b05c1af879b519c134bcd9cd1717c8174c23fd50323cb498d984d87e644c16080527fecfb996069bbe4b810cb2003cb46d20298de618dded8b126a207c12b8fce9a2c60a0527f431df67d39976f0e0ec3e4d34dc258b9b8ca8a0ac73bb1ae76999f3508336c5b60c0527ff83d846bb720d6a7309b5a8c66bda94fd71dfcee1071ce91829dfc7371cf45ca60e0527fecf245a33c7b2542a013ba70d04038f3a6b38444b4891098f1db09f22811244d610100527fd7240d71eefbfad870c0178707c0e73ec010aab35cefc6167b170a1fc9a03c83610120527f3b5b9e03ab8ec164160cb7e4088a16282e543d717bdfe9460d4b8e4df73ce26d610140527f802318619d643531c4b6600f4f8bd35736b0efc13b38ee9462388bdc678aa142610160527f0ae40df6f91a2a88ccf46be9638cc3703db018bfa34e93ba8fee0503c0faf437610180527f9e7ffc5727f562e636d6929bbdc801b60747e7d40a29b02d184e334983a1c2926101a0527f9e76a473cd4152669e3870d79f78c171609be04a54d52caffb6e2ff3d2c637c16101c0527fce59ed6693397cf2665136b7c2f62db543dcff91cb5871e2bbfbc0e7ff8768e96101e0527f63c2c85e54a93f234a35662c4eeb6e3cc00f3cb656bf221fcc2433fb89424dc4610200527f961f4318b87886e6a097045ff77802be19c5e730a91f6c1f5f668f71d91fde6f610220527fd74dc4216664b0a8e343a7cbc4f2f1318d1adce27cad161029d9d24ab2dc0fb3610240527f0bf743c02e0288c9c5a5a46fd92f2d3b149872c242a14ccc061269791944252f610260527f2826cb8d035823fb79638057ab32227859186d9775d1586f629de389e4be131b610280527fb766eea382e8630072c0d97b83afff7ac79f9bb44e83e00dd033659e261aca6a6102a0527fb9258ec4494918bc425e0ce55939d831a06fdd54306a316aab3555d0e14e43276102c0527fb74725c4e0a5b5f57bc966f0b8bcd19aa40b0e49fb9bf71a1469dbe07a81022c6102e0527f129dafdeb706c0f01aabda2eab3571596b70760ad4f3c96c1fa67605505b2bf0610300527f87cf9a097aa5e2d615ae37cbc44d21b5ef4a912e0872e47fd2dbc8082b3e0c24610320527fb1d99403f8e1ac532376dcdf630f8ed09ee0409771253f8a92bdd758b2f38889610340527fcfa1012d22ed9230e688fbb1ac059b3aba749813862407b76334d94ab0931c6d610360527fe5f8768375e384107bcce47c4191446b201783e221cca47c115ed6371067d8a0610380527f2197cdd8f09a558bed2656b42d4187681c870aa404f2b82422a0eca0c70f89a96103a0527fd5d0f60e764c43053ad591aad788e11d8f3d19fff798c40c9ec20830b3c37e856103c0527f1eea42a3a5b9fa7a3a67d41779badeabe3fdc1ed55a08109311d9331cf1386e86103e0527f2d10ff66d8a0dccc13b738acaa5857f9edca207c55857e0d80ac7494a125ffec610400527f629ceecf5e664b489500bfee7effd6ee1be437f9e92966e206399c92446b04906104205260c46104405360bd61044153606661044253609161044353600761044453602960006104456000600562150304fa5a01600955600051600a55602051600b55", + "nonce": "0x0", + "storage": {} + } + }, + "chainId": 1, + "env": { + "currentBaseFee": "0xa", + "currentBlobGasUsed": "0x40000", + "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000", + "currentDifficulty": "0x20000", + "currentExcessBlobGas": "0x20000", + "currentGasLimit": "0x11e1a300", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8" + }, + "fork": "Osaka", + "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f", + "transactions": [ + { + "data": "0x", + "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C", + "gas": "0xf42400", + "gasPrice": "0x20", + "nonce": 0, + "to": "0x538A8474EeaB43d5a960164c554A20400151D479", + "value": "0x0" + }, + { + "blobVersionedHashes": [ + "0x0163265b8324a04c9ed8d0edb85a0d7a2007818cade0ac8688c74a99044cbc33", + "0x01bfc2990aab016818a9020657c03a92ad639bfe0fb95e25e62399bcbdcb2053", + "0x010c5d0a87a926c9f5a527b6d21ac1f3b93f47b3e0b391c5bdb0bf305d786a54", + "0x0147ff69e28cdd0e51fd8ae75bf49cb1c6ec900462fa181d7f3ebf63040b5013", + "0x018526f9e485f72923a91721812baa0527c6b93be7d5ee22a0ea78fb5b401ef0", + "0x0158a07bc9b0d275edb3bcdf3fb9e36830662edecd32ee1fe9839f2ea7e87527" + ], + "data": "0x8c", + "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46", + "gas": "0xf42400", + "maxFeePerBlobGas": "0x100", + "maxFeePerGas": "0x20", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "sidecar": { + "blobs": 6, + "commitments": 6, + "proofs": 6 + }, + "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89", + "type": "0x3", + "value": "0x0" + }, + { + "data": "0x82", + "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce", + "value": "0x83" + }, + { + "data": "0x946ce4e9e90aab59992f710210704de54caacbb3f144f6341c47f79f9be9dd9cb3d57b7d2fa3e26835c614f015952f0e8e079170f6ee3fad", + "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10", + "value": "0x2a" + }, + { + "data": "0xd16fec5d8628da397d96ce91dcf8f35ed0971782f4a9f0cdaa464464eaea86", + "from": "0xC192f888ADA47142Ef2c856FC2C35197eea9E718", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3", + "value": "0x903b4b" + }, + { + "data": "0x49cf894cc9899f782fa6ced5aa78a40f5d1f25115ac517de3a6dc1e439fc28d40f87b47b98e8da27413d69c86ab9243cd5bb0a5667e8c024effa2e012ea2290e48722b8003f1d55f2fe170de82328b58e0715d8d1ffefc5a3708200066a2cbc13145cda01e89853d78a5385f4f71aef7ce3690a81fa9e5200302a94c517022654f4d3fae178b211256dd479d34facd5352491ef61c72dda752f2b78c9330b63dd90326c1cf41cad9955d7f575d56d275f4f2aa3a365e23aaa8f3caefed894b6a", + "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb", + "value": "0xdc" + }, + { + "data": "0x473883564bf6baab586b369a707020adb4dd9002da0da251a44de3c83d9478379bde8cc6cf20fc05e703883d561055cff8f1eb68e74a918e58af54e82b3c96fbcc9fd100e69dc06dc035ee8d1731", + "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f", + "value": "0xd8" + }, + { + "data": "0x57", + "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xD74CFe323387aE2fd070CD046173026716D8D649", + "value": "0x0" + }, + { + "data": "0xdf", + "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6", + "value": "0x59" + }, + { + "data": "0x6663067150ece19358b8213b58", + "from": "0xC192f888ADA47142Ef2c856FC2C35197eea9E718", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F", + "value": "0x0" + }, + { + "data": "0xca644bc4782a166a7f1414746cdf88f780576ffb77c1a1a81d80", + "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190", + "value": "0x0" + }, + { + "data": "0xe1a8835b8666127d66b8b00bc97db84e33a19c6e7b7e57b4b00aebd3d883384b6ff6aab51feedf2fa847e8f67a26e5935fc857a1", + "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d", + "value": "0xf706f7" + }, + { + "data": "0x3bf30a40cdcc2baef21d17c6a32a4cef206f6f3c508696fc6980689f018f3ddf38c4b2", + "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c", + "value": "0xce36f1" + }, + { + "data": "0xccf3fe51190f8fb88f69ac18da750c2e5e43f2205ba3288b7593f9dca020331e1602184dff78216b6752124c2b7ae740d0a98a98d0c85876a9419f75ad86361d48371fc59154a3836b3ed9899bbc", + "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876", + "value": "0xc9" + }, + { + "authorizationList": [ + { + "address": "0x5cbdd86a2fa8dc4bddd8a8f69dba48572eec07fb", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x3ed20ae1548d1fd9d90a1eca4f987f64219a8b416ad20454a5cf43825750cae8", + "s": "0x2cf38759a4ca00d224a711398e8dbd8844596dc29e14601fef012659d6207fc0", + "v": "0x0" + }, + { + "address": "0x00000000000000000000000000000000000000f3", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x6d2226c5a987fd92af6e5041ab9aedc1c14cfa4b8729945d3e2658ef82618a54", + "s": "0x568ea8ee65ce67292e114515be368d64f76e6f32502031aab4852c127928d57e", + "v": "0x0" + }, + { + "address": "0x00000000000000000000000000000000000000f8", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x93b6d4c7f0b540e53a042a79ec312616116c2597cb52feb27b77668793b8e5a0", + "s": "0x209057b5fa3c5387592c33993e4ada764dce62b97e6a9303f819019772ec6df6", + "v": "0x0" + }, + { + "address": "0x0000000000000000000000000000000000000004", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x431784db736d7a7b32afa2a06f9b2dd9b7947510fcfe270ea15c2ae08af9c7fc", + "s": "0x780ae64313ba535e023075c4b6ba0b292377005a380b83e0483cb71d70cdf9d1", + "v": "0x1" + }, + { + "address": "0xdb2430b4e9ac14be6554d3942822be74811a1af9", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xd7b62ccc7a7a187ab2a16675f305830774b4d337043a2a0419e1e87fc30a5157", + "s": "0xa46b6d701549aef8b29ba9a6ef7c3c6366b748ea1294b88df5a8cd91edecb40", + "v": "0x0" + } + ], + "data": "0x08d056a6464dfaa052593f5547603f5143d1fc601858fc8e45aecea245c1a56cbcf28f73", + "from": "0x862B38c425EF5544d0127449A12c89C46dd3E050", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x0000000000000000000000000000000000000006", + "type": "0x4", + "value": "0x3e" + }, + { + "data": "0x00", + "from": "0x0233362c058b2fCc8093841B1073A90D673E7F12", + "gas": "0x30d40", + "maxFeePerGas": "0x1e", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "to": "0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB", + "type": "0x2", + "value": "0x3e8" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x1", + "nonce": "0x2", + "r": "0xdd95902a4746dbf0cb38778983b6a5061c9784572e18492bab91b69a04315a29", + "s": "0x115d234e528f56cac392831ef418acb2db384b9b92749f4174e4e2ca2b2878a3", + "v": "0x0" + } + ], + "data": "0x08d056a6464dfaa052593f5547603f5143d1fc601858fc8e45aecea245c1a56cbcf28f73", + "from": "0x79cca006f0792Bf40a6d4E011c2884eD862A52DF", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x0000000000000000000000000000000000000006", + "type": "0x4", + "value": "0x3e" + } + ], + "version": "2.0" +} \ No newline at end of file diff --git a/cli/fuzzer_bridge/examples/comprehensive_medium_2.json b/cli/fuzzer_bridge/examples/comprehensive_medium_2.json new file mode 100644 index 0000000000..d73d2b2112 --- /dev/null +++ b/cli/fuzzer_bridge/examples/comprehensive_medium_2.json @@ -0,0 +1,433 @@ +{ + "accounts": { + "0x000000000000000000000000000000000000000d": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x1028f1F4b946800E1b6D7528C4699Cc3df844fBf": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xffe5a49189ac8e319cbc7e1e0e1a40f1fd261f8706e9f8d4529fa55a2dc2d4f3", + "storage": {} + }, + "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": { + "balance": "0x989680", + "code": "0x600060005260006020526f12da46b729d5fe99597845a4964902366040527f7bdb3a71550f71fa7f7942107297241e78338eb3604c21c1b885c35c48acd88c6060526f16de46d5414dffad552eb6f59ecfbb586080527f34fc0621617564ee4c92ac95929675eb9835e334e4976df845359c5f73e8dd5360a0526f12c09fa734e3f0289e4ed0ebfed3f86d60c0527f8baf34656290909d3369d5ee4b87ca47eafa338e78286cbc013e8cef8bda961e60e05260806000610100600060aa600b7feac041227fcee37f9758d873e36bc136c2c92a797ef826edfba231397c53359cf16000556000516001556020516002556040516003556060516004556f04556c12c0112472d3ad7764fcc242526000527f700a4b4c7c60a9e0d4a17ed4f5d0910687cd3bdcddc93caf65cd75aca3467c236020526f17838af83584d739cd9d3bfb9e7c96e06040527facf7eeaf93a5b5b862cd741e66deaab818c5bbc0e133c12a7023ec5984181fdd6060527f624abd858aabcca57ec88d91cfdadb3653c8ef629561e03091cee41549f9c35c6080526f05a13e7604c27d4f5a6f9ddc508f3ec760a0527f17b3f77520bc5dd88f7c56fadede2f6dd5fb773f97a39e4d7d86ac2b899ce16860c0526f0528b78253febdead3d353d2cf4b691560e0527fcf4ce6b18f44bd19ceaccde8ca10ac15bf5d89cc89740d4a5e96ddc380638e2d610100527f3d1708e4b25fddd12bf6c5e2b5c07dfbd20983bac930289e6996c910bc0130f7610120526f1c9a01fa112f6d22a27d3fe125ade109610140527f0242653dda65fdca5b1e80f28e2360fb3195ad1cb6d914e1c9a5342485c21dec610160526f1fabe90a7d6da23a062c0d63bc0e6c80610180527fa5afbb640e2530dc5c7db4f21e2c1d1ef3fcbf8ce5fbdc8c8fc019ffbc2bcdd46101a0527f35aa1c2ad23c66d610a5374c259610eaa6669cde15e79354b9bedca1bddedca86101c052608060006101e060006041600c7fc7264066f1cabf74058d2ced3ace5e80281c49a3c498eb80d085ad1c9703c7edf26005556000516006556020516007556040516008556060516009556f15043153691079ff8b800801a519a8996000527f49e6674f1209d211ceda5f887a519cfb173344e8638e7cb1695e83bbfb4020076020526f1592374a4fdaaab67b883dbfad398ddb6040527fe8cb651ef24f0055e31a0aaed60027f66cc7e39291c2e99c58b8f370b667496e6060526f16723a2fd291491fa598d675d7732f8f6080527fae239956720f09bc7812c2cb24341f74e93f278d7b9cf1669a0c09d444b527d260a0526f0a6bd72d6e614e15c74478c1c738feab60c0527f2aded243d43c944e4fc1a76346d4f8ca7690109b066acf4925879a8b0a1333a960e0526f018bce8a78cd8f3b7030358875f5ae27610100527f99a85cae15e756f5f4d05ffb400670ae7176229dd7ac5303c9a1c534d1ca5557610120526f11e8395922b79ac4e7e1c8a861bcc225610140527fa62c2d8665daebbbf41d4efa4ac8c5b50f1f1328f7486bead3691d18090d06b5610160526f199c667464a2b2ce3bf8804917adce69610180527f866f6a894a6b280753a2f8160b9f96835f7d531c7d7f18eb3db6e72df005bed16101a0526f120c518d3494cded818bd7059d008b146101c0527f9529f3df954cb1b0707022156b934a5bcfea7ea17a49c493162fa22b1f9688396101e05261010060006102006000600d7fefb999ff2151cd3b487bdc950acff68275a427314d465b97c59157af861690a1f4600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f14cec51b5b967401b0a49786056323826000527fd1605a4f4dbb0327cf158208972c7297c7a480af8f57418db26fb9d8a57ec42a6020526f0a308a73497553ea2558f44c64a4da396040527fffcfac4fd59b6d58bc20165648d211fea03cf367a9335f567406b64dd29a6d756060526f04b58fc3f267e4e6b60dd110ba61a05e6080527f7e23fa9b3538858c2563347ca5ae3dc8345fb24b57d27bd7a1d9f101dbcecf8260a0526f19811cf90edb6826a4402bf55576069860c0527f1a8266b64e9927d372eb06284402e65f05fd750dbf62fdf9c575737ba8b695a460e0527f420e4630658c2419983969c302e1cba7496a1565cad4194ea35eb92ea6671d65610100526f10c51b3ecb9cdd339c30853998639902610120527f7640d27ccbf15be36a1b1edf9a7badab3d0b843d897d86e4f11d15b2d859a226610140526f058f95d8cd109abd3cebb68a4b5028f3610160527f581903e67af5ffb33bd524e96b5ea825d7015eb997d6d5ca7bbd29d489cfe741610180526f04da4aaa0bce3c2cf00ae6041613c62f6101a0527f261103d196247d4933d641a4fccebf58454037c1555012471ea6b0f2cddfedc66101c0526f1d901f3512c8641e3bd1e6c7cf23a0a66101e0527f3c5b40381b8cf73c39ddf391caed85641eb08ae5dcdf326d3554d72103fe0741610200527fc98ba1c875128d3c1407895a214423daa888cc29623d7df67e50f9acc52bb0446102205261010060006102406000600e7f730b6b0a81e1c498a48c1b55a7f30f4e2acc5ec19392edcb81b9037ee5d4a1e1fa60135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f087e790c45fa839f3fd183f65550ae906000527fd2d71dc1cf38b5ae688434dd6992ef5f2dd0d49660b7f365272e095439c6e3126020526f11b1426059eceed225f12fede8a7437c6040527f7bce7fa6d834ce84a657d64a968640121cc492bec9c8399a2073dbbfadffcd2f6060526f130a9b9736cadec87b5f67b649ab56786080527f7ffac8dc16b072f277a3a2248b955fa63d8a8bc68cb08bce0c0097e0f44880fe60a0526f14696e3c6e19d213e52ce80486f4361b60c0527f6a68cf37a154f56b8512cd1148d78eaf1d81d4079548c73d1b41bea2202ae13560e0526e5f79ecbbafb9cebcd604ae004523f5610100527fed2e2ada166d6bd877079b525144dec82e05b65d9424e5ff7d8cbc553360f23d610120526f0f901a221e5deb6d9b439fe259c0f290610140527f9f25ef61f83f8ce4f8766da70ab62ed53e46ddafb36acf280fd692e67f55440c610160526f099260ba4a9a5a3fac51565b1fcbd380610180527fe76af01600cbc075cac5d4fe75c305d2a70414f5b7b9539d91b05bef357b00f26101a0526f0647d541df6837c0047e390106df15926101c0527f525a15bf78542328efc960cfc5d5aa6e13d7a94d0e02a18d5dd3072b3fece0326101e0526ed9a2d531ecb0273ab936749bf2389c610200527f555945ce7ed1820f168148bf98e19e80b4624c37ea3ad3430b9fa7f7289d1888610220526f07c4ba9468409af2a87e772f8c2a7e2c610240527f738e75af54c95a4af93aaa720d5ca5e63b0dc683a45f2e6049793c906dbe58b4610260526f0da82f6193a31129fd1db9a1a86954fd610280527f64c98561cc043565c7dd8ccae5afc2901bc161c42b198763427fb568f9a77be66102a0526f0ced91c8bf442cdc34bf8713070b2e1f6102c0527ff5cf7367396ad1d06abb1bf3f05169024c882cedef70ae1d24628999dbfa85f16102e0526f0a4185c9e4d0baaa2a0e1498605414e9610300527fb2db2d033e084ee25b27dc5686c2b4fed9915481f4a8c6aba3e56199611bf19d610320526f022c32176f46809429aa7a6e94b0a541610340527f8b89c2eca6ad64a1d08f9e56aaf1879f1287a781bd38e944ce7de7fb2aa224b5610360526f0e29ef6ebe99e7f4f12b94b147294b10610380527f33eb7d7314e330b5c75d0e40b1faaffe5dffef1818414c15f47c372ff6fd53306103a0526f0992e8892988a7e207d03807b96495f76103c0527fe0c118af357b36cc6de661f4c3cffb8123fed50bf39926482279de5446075c586103e0526f15a1a4fe36d43d536fd227be3de90662610400527f882c8d76f346af89f2897e47fb03e1cff01f154376ba731fd67a0c5e004ea5f5610420526f0544ff26b18dbdba97e63b5e83b0639d610440527f32091000f391c2dfbf525518d4b2e4313702d936c9a365b2176629b3573d18fa610460526f03787c467ee560d77adc1e5c51a2008c610480527f01407eb311f4eddf4b89d697b5a9085c746931ffb4415e2bb11588db88edfc966104a0526f05b37347124fe87949be342f69fe0d3d6104c0527fb6c98ea7386b0666e55dd7c69ff494462a22b380edc524c220d7a19edf48bf776104e0526f024aa2b2f08f0a91260805272dc51051610500527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610520526f13e02b6052719f607dacd3a088274f65610540527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610560526f0ce5d527727d6e118cc9cdc6da2e351a610580527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016105a0526f0606c4a02ea734cc32acd2b02bc28b996105c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6105e05260206000610600600060de600f7f42fe45fa84e8928ada6733b78e40be4e28a744ea3bf60c69eb808fd2b6b00f65f1601c55600051601d556f19f0ff5cf765f8191a92dd7333f115636000527fd41f77c7b6ad482a8a42dceab06c0cc2d518223fb5ca70d288410bbc931a3147602052608060006040600060fd60107fa10d7d88e8e6ceb23cb75c8268d2abee7e2f4f843ea76f5cbb4cdc17cae5133df1601e55600051601f556020516020556040516021556060516022556f0bb44118f452e8d6256a535940c2f83f6000527febf8909f76ab23b0fe6972a6f41d32316d3483c2ba33e550d5c325f0fb1c1d776020526f01acf293ca3d4b46d36596ebc63a46246040527f6bc9d5064757af806470c48d23afa99bde4a2a31715e1b2117783f7ffa06044360605261010060006080600060e160117fe6589a52f39e3deaaed3749e845bfc9549711b79a7903754446e251342879f54f160235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55", + "nonce": "0x0", + "storage": {} + }, + "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": { + "balance": "0x0", + "code": "0x60a160eb60ad60ff60cb606160aa1a0778385a5c5e3298ff9cf0004477401c360b411c8d8dff123196f05f97556d153f18f09b6e125b4973559c097b1518381b738b5707575f53f34430139f4a1078396a6e10f11e13f4014165173c017a657a188118693e303efd1972111a5a3bf1636d026e0003514a699a315c1b60417e110805f23913626f12744a7a3e671973415f1b3820f4674754083e531ca4f05c6687915077097e90a10a36137f5c3f47466904470a7e5f0b1076067c1b0b55583c13094a7685171d59177602487f1a209f7e445c903e95476f349f8f5a124a3511723c15415b704660440803151c75761c495841626b496c3e9f898a021155205bfe9753f4068356845e44503a3b409c4a62370078586254159453673551055f5889655613fd437504866e5f163065339e1c3112347a190630323e500147543e121a6140434363440a8579747b475b576b15465c19784a90031e390805106c365519699f6b8576801b1c03436c8ba260335b535c0071000507336d49a390423d7dfe773c7a14601d5554208164016a81f2f5615a42fe35337739081e983c361d65516a136f189e958e1a6f181d97ff0a566e8208f197691e776d8964a274323c80ff001c657b474475705cf47954945b73855a1633699d3c62a41e321c9a487652406a596e876b59085e7e0b511449646d70468f3307067e567e1c4a367831619c51726f8898697e621972045e3035798e13f41c493d514941185a7a109b909a3001905072313613935c6857314545517a855a8e0a15523d95a2424a557418539a6e45646e676a6442f3fef31b307d77514912fe70331141317c495f58406e3c624866a46b11735b078e44ff77f24691863e707f5268743e675233551e04f55454486719446191687c876e48051357fe55681231073f34671e586358736d5f8c57834756087e748f415213663e5a6d2034195d786063685a495a9d6c6f09336b5173396b345d6c7561653948470509908d1d9b8255678b4389081a357749778d3943569f9299145e1733376c33041c7f02091d8148fd170612127a06771979fd7c617c7d00458d1e7f6144f19a534a8136160865616c77703e326303fd656c8042163219fe4534333a4055f1366b0506541e7549699d5f1a3a9f70081c347d0b7b7b3e5f3b5a679b3e405a7b9043475751a188167677938a5e53673f6a867b8933fd7e6c5938509a02446ba455616744424a711477356618035e8b313a7dff4a47a47311496e5a48609d137b1e691488915b54397f43343580455220a15394766c823f02727b7f356d611b69373e96741950a380150609181d5c8314011e3820323b388699039e84375c68521b725b3787448c743b1e3c5a76817f736856721bff1006f59d597a5c0918836b0382104072146d9b016061f1463c857d368981583c", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000002" + } + }, + "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": { + "balance": "0x0", + "code": "0x7fac24561d9f5035ce04d964a68037cd14dbff7091ef59d77299bedb0b38c6ad556000527f2a0169a823df60688109dfb0d02ceb695fd6299c0c7df33756f060e3499a097e6020527f84adb74ea377c7cf23bb8d05ec376b6955da1dffdb831726512dc92c71ad5f436040527f6dcd32102f6a81d419ccd009b5d3a4b266dc1049edbc5e307525a2b2bda040bd6060527fc6995d1048cec095a29569af28b61a5f38dc61586062eeb401efeecf1151d7316080527f70e2858125805f578d2deb5a6d9c20170e352c20417a194c6e5035403963772660a0527f801b6949c072d646a2caf58f33ff5f8e69728a830da82da55a43a6e43c39013c60c0527f1cf0dfa518395721c04b8c6b368370acec11e662342c7c356a59255de4dee03860e0527fba75a6bb2de967e948458ce598f13431acb43b082926b3a2a330e0960b9bd2b0610100527ffa67efe960985744944789e237312835d725acf28b21557d4e6673428e36b86a610120527fe0d4c9b0112dab6624a912a175b89297731e9dd9a59112519ca0087f5bea30c5610140527f85384aa36ec17a29241fa8a2870634d2cbabf3cb0e959a607073bf591e5d733e61016052604060006101806000608760f960e7f1600055600051600155602051600255", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000007" + } + }, + "0x3fD261193d23d8a73a4fdfe7735892c6Ebb4f2Ac": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xe32520991692770350e0a6c3acde9b20b7ccf11ddd1d1e86cbf91ed98e2d8451", + "storage": {} + }, + "0x48Ed5D2f29e6CF27031A62C9e4826d56B4536a36": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xcf9e2e355349971fa5c9c1774fb5ea58f30310b283b6b14d6dc779faa5499770", + "storage": {} + }, + "0x538A8474EeaB43d5a960164c554A20400151D479": { + "balance": "0x989680", + "code": "0x7faabb9137e7492c9f26c298cd433b7e0318c3876d2f5ec0a905a1ca164efd28a16000527f70b020e11c1bc897b7c2b210d69a0adc3684f818c739cbf9680a11f4c7f75b186020527fff98638a49a81dd7fbb111626efcc4428a2567adcef3aa2f321381c030625f1760405260c560605360436061536068606253605f60635360266064536099606553606460665360dc606753605c606853604f606953603d606a536089606b5360ea606c5360206000606d600060087f7a615e760c7a1993a13a60cbd25477ce8f96290789500f791bbd997d0086e6f5f4600055600051600155", + "nonce": "0x0", + "storage": {} + }, + "0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x641602bAD4A323C49629d45338d79A2bb984A3fb": { + "balance": "0x989680", + "code": "0x60406103602061010061034960a05e608b60a0f3", + "nonce": "0x0", + "storage": {} + }, + "0x677B3ccc29f7c2293364fEec7F51907756f0124E": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x83011199ca2c83c9f2275cc32037543a5c54321011ec6e342bf9e00710e5c20f", + "storage": {} + }, + "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": { + "balance": "0x0", + "code": "0x7fd861f3a6d05dc0b79ac2bc4d2f6ba1d52f11ad2817ab5db8af0c48ceab5773b06000527f1e0a1dd7b3b806ac4bc3fea18a4a4bc66071ae29ea60cfe9bffd7f39bec4e9506020527f3155c44ae2cb923a1f9664fa462c7c71975c57706987231a8b3ee5d04b5fe5306040527fad7d2f50e5a57baf9916e251cdcb680035a9d37f08ae7ee52b9026af284639416060527f17d5aa5a02e8859b7d7fba8338a1d07d8beabbb32c02effc5e475be4e7c3daa66080527f505c30ab6738d740e6a0fb2dc2ac162a219d72ec70fdedd81ff86150d7a067f360a0527f85712bd79e2937184e738b74b26a7f486b37903d9aae6c99a203896117d757c960c0527fbe6ee428ff22d6bfcb5832852cba8c9ab765df85938186f67b3d3400da3a3f9c60e0527f3939dc2b739558813adf772aa4b15c7eb7a7bf1409dfa479cba20297fc43ca5c610100527f6b35a7cfb1a6534523db9eb3242394caae95bf9bc31dc008342b761ad30de09f610120527f854144dc711fe375a7c065a2cd136956440e1adf2705de37bf972223c4f003ad610140527f91bc4ee89625507337e9aab34ea2cde3f18b96f18b0a27cc5e8ad661f0123021610160527f664faf22c3e905bae00c2d54a010aefafc10d74c1a000decd3467859105f114661018052604060006101a06000602460087f9b83a54ae8b5af5197c75d7a815c8bb11e81161cb04d4f7aa59b9aa578f4ef1ef2600055600051600155602051600255", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000e" + } + }, + "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": { + "balance": "0x989680", + "code": "0x7c9a60c23b9313f62b01b29e4eb8d423b58410678d89810ba3fcbf9b86766000527f33484703223612690945d74b3b595973ede4fdfbd022c31967190f52f9710d9d6020527f4e50abf59452e7caec6f35757bd59dddf76032ef813ebe914034c6a6515f8b1c6040527fc61f52d194f07d882f72a998cd4bd51b8857cd0a2e8663e0a665917ad2b53b686060527f5ebf56e91c6fd2c8db25b04dba00ca3457181a104af1b15f5fa560c2f388477e6080527f788179f76e7f546578d5b889305cb7fbe18e406b9979a6129fca8c7487cb3e5a60a052604f60c05360f760c15360cc60c253605460c353609760c453609a60c553608f60c65360e860c75360d160c853607e60c95360a960ca53602160cb53600160cc5360ed60cd5360c660ce53604e60cf5360bb60d05360de60d153608760d253606160d353600160d4536040600060d5600060097fe61ef44776e880511e5e8b7872c121ad30beb910665e6be4ef98603a772cc0a7fa600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x91C6Dd1A685cAE33B044370252727B57f688e5c7": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x89032b3329df88503c25a42c79eb3d5628c802530d8ee347881aeeebaf5ffdfd", + "storage": {} + }, + "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": { + "balance": "0x989680", + "code": "0x6380000000197ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb067d02126262626262604077ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f7effffff8000000000000000000000000000000000000000d900000000000001146000556a01000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9018901a7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb6801fffffffffffffffe901a600155156002556c010000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1a7bc9700000000000000000023f00c00014ff002c0000000000002231087bc9700000000000000000023f00c00014ff002c0000000000002231080590166b1000000000000000000000007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a001c90147f80000000000000000000000000000000000000000000000000000000000000007f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901818157cc9700000000000000000023f00c00014ff0000000000000000223008056823232323232323232390180a600768066aa0a5319bcf5cb4181c60035568232323232323232323712000110000000d0a300e750a000000090a0a90056a0100000000000000000000686d5adef08547abf7eb139007678000000000000001600790067f77676767676760000000000000001002e000000000000040000000e0000000006b1000000000000000000000006a0100000000000000000000080867b368d219438b7f3f7f7effffff8000000000000000000000000000000000000000d900000000000001140460045571767676767676000000000076000000760000197702ffffffffffffffffffffffffffffffffff000000030000638000000090111d6005557f40000000fd000000db00000000000000000000000000000000000000000000017ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200001d7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6b01000000000000000000000090046006557f80000000000000000000000000000000000000000000000000000000000000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9001686d5adef08547abf7eb7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00677fffffffffffffff089011600755638000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b00901d136008557d7676767676760000000000760000000000000056000000000000000000007d767676767676000000000076000000000000005600000000000000000000017f82000000000000000000000000000000000000000000000000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe90136009556f8000000000000000000000000000000168478392145435897052762900760076761e0002007676000000007676767600000009600a55777effffff800000000000000000000000000000000000800168066aa0a5319bcf5cb41314600b5567d02126262626262668478392145435897052067fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff760fffc000000000000767676240000000000002b05760471c9012777effffff800000000000000000000000000000000000800167ffffffffffffffff90039010600c557f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff760100000000ffffffffffffffff0000000000002e0000001c678000000000000001778200000000000000fe000004000000ffff000000fffff70017901b60017e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006a01000000000000000000009008600d557f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a567ffffffffffffffff9004600e557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd67b368d219438b7f3f1b037e1f0000000000000000000000000000002000000001000000000000000000006a0100000000000000000000901d7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00600090089008600f557d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97f8200000000000000000000000000000000000000000000000000000000000000901c7f7effffff8000000000000000000000000002000044000000000000000000000168010000000000000000901790137ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a0071767676767676767676000000767676767676900511777effffff8000000000000000000000000000000000008001760fffc000000000000767676240000000000002b0576047610111900817774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a7176767676767676767600000076767676767603900a6f800000000000000100000000000000007f80000000000000018000000000000000800000000000000080000000000000006f800000000000000000000000000000000890159010601055600515196011556f8000000000000000000000000000000167fffffffffffffffe901871767676767676767676000000767676767676762900760076761e000200767600000000767676760000000b1869100000000000000000007cc9700000000000000000023f00c00014ff000000000000000022300805026012557f800000000000000180000000000000008000000000000000800000000000000063800000011a601355157f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a567d02126262626262676013590cab83b779e708b533b0eef3561483ddeefc841f59008151415601455760100000000ffffffffffffffff0000000000002e0000007a01090000000000000000000000000000000000000000000000000014637fffffff67ffffffffffffffff03067f77676767676760000000000000001002e000000000000040000000e0000000006fdac7fff9ffd9e13226262626262626009007900519637fffffff7f7effffff8000000000000000000000000000000000000000d9000000000000017d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9086015556780000000000000016801000000000000000090116f800000000000000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200006a010000000000000000000008601655901060057176767676767676767600000076767676767601901590076017557cc9700000000000000000023f00c00014ff00000000000000002230080567ffffffffffffffff1b7f8000000000000000000000000000000000000000000000000000000000000001760100000000ffffffffffffffff0000000000002e000000901260185563800000016007900260195577800000000000000080000000000000008000000000000000680100000000000000007e40000000fd000000db0000000000000000000040000000fd000000db0000019009900a7e40000000fd000000db0000000000000000000040000000fd000000db0000017ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00900b601a557ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff6780000000000000010b90047ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff0000019018026f80000000000000000000000000000000637fffffff189004712000110000000d0a300e750a000000090a0a7f80000000000000000000000000000000000000000000000000000000000000029011901a7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101119011601b557e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a006f8000000000000000000000000000000005900b651ce97e1ab91a71767676767676000000000076000000760000900b9010157e40000000fd000000db0000000000000000000040000000fd000000db0000d3638000000002037f77676767676760000000000000001002e000000000000040000000e00000000068010000000000000000129011156770000000000000007e40000000fd000000db0000000000000000000040000000fd000000db00000190131019678000000000000001712000110000000d0a300e750a000000090a0a9018036c010000000000000000000000007e40000000fd000000db0000000000000000000040000000fd000000db000001141590127f40000000fd000000db00000000000000000000000000000000000000000000017bc9700000000000000000023f00c00014ff002c00000000000022310890121667b368d219438b7f3f6fdac7fff9ffd9e13226262626262626007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a091b762900760076761e00020076760000000076767676000000774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a0603601c55777effffff800000007effffff800000008000ff00000100006780000000000000011167d0212626262626267806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a1067800000000000000167fffffffffffffffe7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd900890086f800000000000000000000000000000017f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1b601d55677000000000000000778200000000000000fe000004000000ffff000000fffff70010017f7effffff800000000000000000000000000200004400000000000000000000016910000000000000000000901112601e557ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07f77676767676760000000000000001002e000000000000040000000e000000000901c6801fffffffffffffffe774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a1d90047e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100069010000000000000000000505601f557ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb067b368d219438b7f3f9010197f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000016801fffffffffffffffe06901c68478392145435897052717676767676760000000000760000007600007702ffffffffffffffffffffffffffffffffff20000000000090086020557702ffffffffffffffffffffffffffffffffff200000000000600116177d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff90116021557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7e1f000000000000000000000000000000200000000100000000000000000000901390126022556d0100000000000000000000000000686d5adef08547abf7eb03686d5adef08547abf7eb6910000000000000000000900690076023556f8000000000000000000000000000000067700000000000000090167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0090116024556b1000000000000000000000007f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0218602555690100000000000000000015760fffc000000000000767676240000000000002b05760477a01090000000000000000000000000000000000000000000000000001116026557f7effffff8000000000000000000000000000000000000000d9000000000000016f800000000000000100000000000000001d67d0212626262626267f80000000000000000000000000000000000000000000000000000000000000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb900890046027557f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001157f7effffff800000000000000000000000000200004400000000000000000000016f800000000000000000000000000000010a19191763800000007cc9700000000000000000023f00c00014ff0000000000000000223008059001017f8000000000000000000000000000000000000000000000000000000000000000760fffc000000000000767676240000000000002b05760476d010000000000000000000000000090081768210000000000000022684783921454358970520a167f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd717676767676760000000000760000007600001b90187e1f0000000000000000000000000000002000000001000000000000000000007f7effffff8000000000000000000000000002000044000000000000000000000112900b196028557ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07e40000000fd000000db0000000000000000000040000000fd000000db00000111671fffffffffffffff7e1f000000000000000000000000000000200000000100000000000000000000901c7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6770000000000000007f82000000000000000000000000000000000000000000000000000000000000000990086780000000000000007e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00901c1b60007f820000000000000000000000000000000000000000000000000000000000000002900b7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000017ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a0008901660295560006000f3", + "nonce": "0x0", + "storage": {} + }, + "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": { + "balance": "0x989680", + "code": "0x7f2d48fef6d6dbc72cbd48b0915fa033ffa7d4a361118c537ed2d7edd66d78e7c96000527ffcdd0f1f8c09b3d29c80926527694e969a9ba25d383e3ba54aef34d24bd497cb6020527fe1d7cf96007291dd8c1eb2d1081963c991a1d6dea4658779516c6a7274017c806040527f66bdafcf782baea58cc2eb1141b2632df0d2f55926d787efa5412396958e25fb6060527fdf352be9237b127f7d05d548b7407b9c30207ade11fbd720718c9c5ee9d0fd376080526020600060a06000610100611916f4600055600051600155600060005260006020526000604052600060605260006080526020600060a060006001610100611c58f26002556000516003557f460591a824574b95cc69076bb607cef8d40a0c0b4c847c7dd99f0dbcb69615056000527f742e579fe0f7e725f6fdaed587cf572f5cb07e738dcb5c980e0e96bad4dda3536020527f5e824e64a8a098aead190a98c096eee9468efd48a851080108b8393dd5fe3c726040527f278fb56ae5fe76e5eb5a8a478d378e8eb6fc0a149ce9300f322cd7b91a6d4f1a6060527ff141171951bf218ff95ff9d70c99355db248dfc52db1d551a0a93b2b78c4df276080526020600060a060006001610100611989f26004556000516005557f48ec01c0e1871403bb3ca3a08fbcddadcc99a469e4a7305b81f23bc7b53193896000527f9925d5cf12ca591180ab2e8461dc882ef7e83de5b155e09a986576c23b2900de6020527f94b0e6be6afe4521f65b0d946074f1f23d5393ef2dd7da2978b0f2086a76ff2f6040527f78b4f1c71ad536b3d04db6fe5b6000e437359573fff6f11a3be9baeacba2cdfe6060527fd0859ce0e95ca9c4d981a67d181b08ada3884ae5cf6ec584d93d21c27ea2d8496080526020600060a060006001610100611c24f16006556000516007557f7e7405fe9def216c90e9e92b81e64defe43995d088898179e64c81573501ffc96000527f5feb47f2139e0858713da463e2d6e8e50248633757004714cd7720b3d7fe45bd6020527f604a2ffa598e68971c856cefd048c75305de2ad9549e9802830b4c0786e836906040527f7f57c80bc07f2580f08c7d1d69cfaed1c294761d9338c6f2ddb41fd86428ae266060527f129c44035429199b8f6e1d71295ab48df4b41f9bf0e566080908d293ce3d28736080526020600060a06000610100611cc0f46008556000516009557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fa8f7dbc25e8c7cca554fcf1f8d2ab12eb45bbc4fa90d51971281f4b413bcb9776060527f8dc09b13292575a077fb4629b0c3a3ba5fe7557de3c70246662d7be1fa768f3c6080526020600060a06000610100611c66f4600a55600051600b557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a0860005260006020527fd72bb6e19026029599b5f099d83684d02890bc6fc0cf8ac7ed234498516a43f86040527faace2731c2f9766302293f90947e01c4739475ed7f6e72f5ba57627c805423de6060527fb676d1036dab813d9fa8172cdd0b522309cac452e775f65bd7c10e3565bc1f9b6080526020600060a06000610100611a49fa600c55600051600d557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a0860005260006020527f5809acbfb7d1d265d77fad581f331327df9e2e1b8e09be2c60ffe6e1bd9ae7526040527f795acf93e6d163e6d1ffadd6cacd3744af8758c8142b2ef2b06a491cb517b3486060527f31c0407c043a0d3579017bdacf960b1be3d95235253045518f02b6afa9a4b0d56080526020600060a06000610100611b08f4600e55600051600f557f1f578153149420497e676cd6d5eced6ad7043396f1b476698d8982d5f82d51156000527f47a758179ab51312779d4529b0c4d24c59cd3c082ed5fa0024a52a2ee26ee8a46020527f068c672385b1a7d8730ccad44ea08f9bae8b8c48b15636ee8d218b2ef9a202db6040527f9823ae0e11e65fabb51477fc42c46bd9a8026bca26fe815a67a3c2f2133da64b6060527f16e38ad5ce001771fe1ee92e2ea2c17e158e8d26faf1967ba6b9726d93190f7b6080526020600060a060006000610100611b9df16010556000516011557fadd5246b8fe95262b5c92e34b66460e9fe6846fc80c0d0143ad0a7b36e6b71826000527f1f01817d03674644755b5302064fb4d951ead6492a12d1194ddda94d859fee836020527fd796ec850f4397801b66dbe752a4ec9d3cdc06c63f384b8db9cb393400dfa79c6040527f53bb06fb0a450f211e84d0d65a1bdaf5404dc24923bbab3874a17f833cdc31c66060527fd1db726c8e0dfa245af9fa7d9516999e05bfe7405e12b9c4d4b80f6278ba65006080526020600060a060006001610100611cb4f26012556000516013557f7e5f992155422239ce99f246ef28398cd19efd4945bdbcfd0906cf295f0acf9a6000527f23486150ca3798a368f956840331487ee7aae2b4c41bb3c5d06dde0bd5a8319d6020527f7262fc33081844bc6fe1324f77d816fab0596e0aa4a80911d5de1ec1065c3a966040527ff60b76f958d30c87f1f4cea06a0511e14cdcfff27f9ef7300380843e70f69a156060527fb5a22958693bdd0453d5c4c7dc392ba265a81b1a6ec356c7a0d71a2f1733933e6080526020600060a060006000610100611910f16014556000516015557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611c99fa6016556000516017557f3dd166a0d3b1651ed856c109b45cc195a240a2fab23183accf87757b64d3b30f6000527f7c96ef833b5e75bd4d69819a6a13377ed249b800798e1f58fb48a3a47f0d04376020527f0285012e51e1ccd423b89be32135bc22bd266a3c66aa8e2a6d375a0a3edd93d56040527fddb9a2c3c25ff7fc7438521df5159d379cf4242e9d72c126a24deeace97d01406060527f0bd8aa57cadb8ec6ad4c294ac9fd5f2033f876b305b70da837a2e47759a83daa6080526020600060a06000610100611c70fa6018556000516019557fe723ca68f12a5176750652de172ea07516f031fc69df3e4d3f4db7991ec7f4956000527f1ea11655451f9fa1a6ebee3cf000d22d6feb8c82718cbb8ddb12dab77d1fe2256020527f5545cbac5769033d164c67144735e7fb4e5f5b778b89659318cbb40cce98fb366040527f9a8d1e5e35392b97f14359da3e744bcd711f673ffd7a101711876fcc329b4bfb6060527f8eb0802a3a39bd992fc1919de73ca1a41e627bd9d448ddd43df1a1ed9e13a3dd6080526020600060a06000610100611b0ef4601a55600051601b557f781f41bce25afe583069c7570abf9f17a52c59c73276dec66742b55a91a22c316000527f5276b48e3889087f1d05c469fcebb4b6acb88da49c7718fa3fe678a8e420627e6020527fa026f5b97a918119b4ef452550ec36faa0f2757c922c13e3aec9a82373219bcb6040527fca070f9cb46904d7e3cbf6dd138653fe8f1a1756d472d82ec6d5f7bb813a71226060527f8dac32f60ea0d00b8c67638175086178d77232c404736267b3021b5db6e72ba76080526020600060a0600060016101006119dcf2601c55600051601d557f28ecc5cfc546424311627c988e9cbe9c434fc5e2ceb5182ff18bb8485da8457d6000527f394f722770e2b9a2631399cc5916c8d1b6c87bf5a6f3138da5ec52137167a53f6020527f4fe27e8baffc4c94f1a803b14262c24588a41035455ef46ca2f68cbda15a32b96040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fa9a1d51ba3df24dbc7c9afb53437ca15d46d6dece751957fe2b24f87204a23bd6080526020600060a06000610100611bbcf4601e55600051601f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb5600052600960205260096040527f2f1a6ce97909c9947e8b05e181f97c0a0a4b142b7eec35215ba499d057ea23b96060527f157a3a06678067b0697843853539281f9caf2c41ec378bbaca088500748194db6080526020600060a0600060016101006119c3f16020556000516021557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000526fffffffff80000000600000002fffffff6020526fffffffff80000000600000002fffffff6040526fffffffff8000000060000000300000006060526fffffffff8000000060000000300000006080526020600060a060006001610100611a37f16022556000516023557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ff7ffffffffbfffffffffffffffffefffffffffffffffffffffffffffffffffff6020527ff7ffffffffbfffffffffffffffffefffffffffffffffffffffffffffffffffff6040527f559d4c984a71993ba2299eedf7dbf226f692c1c329b899b4a29490e31f55cf326060527febf7a5aff69e762b1e871db04864e65e35e75995c68adca0154d1d925e93703e6080526020600060a060006000610100611931f16024556000516025557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6020527faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6040527f8f7bbf81d570991c1dc5a300654032769d4a6dba81ee23e470bd7b6749b048d26060527f6fba636686ecf2906bb10decf2ea18ede20a5313a6bd2755b68e1c8eaba91c826080526020600060a06000610100611a5bf46026556000516027557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611c13fa6028556000516029557f92dcf6a29fe268ccbfad7d1241b0d570b0490e793a871cbe3993d65f8c7631956000527fa69ce0f86c885b497070631c6763d1cc9b5a288b2c2a436f79e2816fb4b9526a6020527f7f125a6da806dd90960fec9d3a916e6b5b1e16fe518e5ce7fcae454b649dcf6a6040527f3f3c52730247cfb14ff4045b32ec699ca52cc02586a3b3db47f012772e7b53516060527fac7a5635ad3c1eb29393792efcb90c1908ce7ab9d80459a42dda216e912d65306080526020600060a060006001610100611a16f2602a55600051602b557fd0a6aae6c767f393aa8969e191293a4c502f4a7d9865373463dc8eaea20ae8866000527ff20b041a964c5e6a8a54e64e3a83e6c194317a88e88d5f0c99d03d4ed586e0b16020527f4e8f68a34e68a36828a90e7f7021495a5fd5555cc38e3cc394c1dca6b59017a66040527f2a6fa2088e0d26db96dc6ab441c3a60048ab953bd53a52c4fdf17e5239f2fe3b6060527faa09203b7edd9840fe7bfc098dfca22fb18aeffcce0179a252dc3528172e1fe26080526020600060a060006101006119f9fa602c55600051602d55600060005260006020526000604052600060605260006080526020600060a060006000610100611cc6f1602e55600051602f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f01000000000000000100000000000000010000000000000001000000000000006020527f01000000000000000100000000000000010000000000000001000000000000006040527f65c1110c0be74cb76965d2672cfaab66768f6273153b48499ab92620291661c96060527f28244fdb476e78a0ecb14370154db3a3cf0eab01383dd5996c52775760d448e46080526020600060a06000610100611c1afa603055600051603155600060005260006020526000604052600060605260006080526020600060a060006101006119a5fa603255600051603355", + "nonce": "0x0", + "storage": {} + }, + "0xA9A42c08023d1a23a61dA0cAEd0106A7C48b7120": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xfade6018c180bd1cd998447d92b262af3473cfdbbd4c3b901b6f1b189c53e7fe", + "storage": {} + }, + "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": { + "balance": "0x989680", + "code": "0x602f6000536038600153606f60025360e5600353607e600453608560055360cb6006536072600753608b600853604060006009600060bb60067f3e1f7155c0651aec04b04c5c8bc70f2c07a70c9372276c8b438cff34ea5b6e60f2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xC4AA0D75736f14fb4971bBDe8CE49Fa1E25217bd": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x9327cce81f1cac3ff6a060f8ccd3b81f543fb0332849fa43c6c26683cadd52fd", + "storage": {} + }, + "0xD74CFe323387aE2fd070CD046173026716D8D649": { + "balance": "0x989680", + "code": "0x7f0193f3b4d1bd34cc620b76788c1b0b7efa494a6a3b9b30afe63dcc0add0bf1286000527f7030eb85fc3a20e4208718167e80e0d80be0b29311eace6c92f4fb8466ddeefb6020527f52830b627d58510f8f2672ea2b9ac2b2deaadfc7a476774581844b2e6aa5c4a06040527fadc18db5ec80ce6f7ac02e7e823aca5ce50c0b6d80edf88cc50eb6ada1273b046060527fb5b6bbd639bc86335d476a042fe0760ab6a944f65e1c716602aeefb17f6329fd6080527f317ddc040b0dbe36d428cd49f9be1cb0e35527fef9bafb63f0604ac6fcdc5f6e60a0526040600060c06000600a7f9c2fc66c6fb11903613fd8b83c51568eb684932cae21637977215ab21c31f001f4600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": { + "balance": "0x989680", + "code": "0x6000600052600060205260006040526000606052602060006080600060016194e3f46000556000516001557fcc931ae91d1ae57ee1ae991be2dc667e43cd1dc8ff19fc5ccec78bd4ebab19df6000527f9783a52c81da9f990d466b3a1e3f67197145f4c8a3696bb62611a66384fdf51d6020527f43c4bfa434bd3b91f5e79a1815c15fe2ac602508e4998fa6b283c280a415db926040527fd96c2b30519212ae3b0d24d7e96f2b1dccc96e5e928d6c62622534da108219b960605260206000608060006001600162014147f26002556000516003557fe0617947124e86583d06ccd8e934e8195ef7c763f8e784e16dbc8ee0bcb086666000527fa6d80bb7f4815e2722b9ca09e6f4512fa46ee459f5a28781f330dd12cff3961b60205260006040527fa4d8b749791a8539cb4af58f9b5243fed693d8e31d82da71abf56f6165c6b7f560605260206000608060006000600162017d5bf16004556000516005557f526a7959323beb89149c76522f91558f16cbcee030ddc8fa0b22f43a237eb2596000527f959e49aed0281ac6522e27bbc28d41281dcd3716d823e7c8cfbdf748730d271c6020527f4470f60814b8689866b44fe346006f0884e1f7c7f3a32a7d94ebd08d78d32ad16040527fffffa08a0b7881fd72c1693c3dae3852a0011d8af63aff4ddd92437a3b7a4b50606052602060006080600060016201488dfa6006556000516007557fcf96f626e87a60a687ea394b316955428eb10d42e1e4f4239698fd6c00d08cb36000527f5c1757376584c0674f7709621fa64a2078ea08000a18403b11664b70ca52d6026020527f21cce01d37a32278d253ca812f41c4c5c44e99eab20167aefade6a82ff28aa346040527f3499e9f20a655e68ff6aac3baf378aef196dfcf602498704643ebf1e17da55c6606052602060006080600060016110fdfa6008556000516009557fc2180a992da54ed7bcc3b66cc7ab15181a1986294c9675692459164f15cae08a6000527f65b49bc2356d42810531fa25681d2e5cddf2a23830f2721935ee942a794d601b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f90fa6156adc938830646bf56550d29a7ab6c07808d4c917fb907e327098e12e8606052602060006080600060016151f6f4600a55600051600b556000600052601b6020526001604052600160605260206000608060006001618beffa600c55600051600d5560006000526000602052600060405260006060526020600060806000600162015743fa600e55600051600f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f2286250ac79bbf13291e28d79da99adb427d9dcc5d9d210305cb8db7bc9e61fc6040527f7e22a7f0e2a324800b0cd4025aa51e3c32a13a6c60b468a214e9845a9b0527256060526020600060806000600161ec65f46010556000516011557f707c2c24eebf2dec569acbb9360b6059f29fdb785678db078d525d68197b41e96000527f872ba55696a0dfdd467dd9bb428da400c8a35ef846e497cb2b3427df6a304d1b60205260006040527f8936a997dcaae3ca6613577406824f2d9afc2b78599fc062df4198c02f14a103606052602060006080600060016121f5fa6012556000516013557f1741794b464ca914bfe3d72ab2166a284bab4512f1cf1ac5fa7585dbefa0d6d46000527f064a505fc85000dd0e064c7d38e3b3fcd61bdf4f5d44802afd3ff17ca78b101c6020527f6768b2f44970599cdc4d42de36d5ff39a10f1cd4fa0894f54bd06611aa24bf8a6040527fffff19f3d2af03a26a93a71940e0e74db00f903040c25e5b15519eac6fcd0f986060526020600060806000600162015b40fa6014556000516015557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fffd93fd2822906f26edbeba1bff10ed9aaaaa2d78eaa224433446639d341d13d6040527f422c26054c09af7cc00fcacd0bc46071b3c21726043dca5334fa9647288c7fba6060526020600060806000600162011c24fa6016556000516017557fa90ffaa963c65a3c654bf00cf6ac34f86c3a17f8029c05c5244b23d96b2916976000527fdfa7100ab09a5db4abcccbf45e6aa4a0be1d2dbc129cdc930280b985609c111b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f5a153b43cf49358856de90daf0d33fad42a42c6e5ab8a6c8cced6438af664a7f60605260206000608060006000600162013aa6f16018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f2ab58abb36d14f8bc721eac991a26b8eb73efa3baddc31647d7da807ea3f6b146040527f5c66b60ffe1f3aae3f62a9c12a205d6b7d6c5ffe631d53a766b4bfea67f5573560605260206000608060006001600161e558f2601a55600051601b556000600052600060205260006040526000606052602060006080600060006001620184adf1601c55600051601d557fb908e0e234371730aeeb6793a86770a3e13390f5c8354db1d08c5a14c381aab06000527f724b9d656c076ecf5ccce4090b19986980e01c61fb74cd5f0a00f183f9772b1d6020527f61c243042f4c03a0292b98fda438efb44f6316d818b31e8821f09c5909474dee6040527fee36d3a720ff6f90c2ef947b206516a085da82674bd935afd7c6160c7d51c70960605260206000608060006001600161be54f1601e55600051601f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527ff2e8bf9a85882292bde75beda7bac92bc8a1325b9e28697699a7af4f415e913d6040527f560737dad06caf1302db510e5182e3986a6ab0798c04b7c55a1e88ad8b41f36e6060526020600060806000600160016133b7f26020556000516021557fc6212c3f5648d0e9a77343ccc80ce36daa100704ed7282871c2ccc629342a3826000527f549e53ba450f964ed2cb30b7eb094d3da8b53b9cef467661f81a0ffc4e5a3a1c6020527ff05e25052bab68bdb535c86e03a2fab5c8f8549c4b954551cfec37a7978f366d6040527fffff4f207c79659b7c1fda0afc2b8b775837677495a1c09bdf82620a5b35aeeb60605260206000608060006000600162013816f16022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fc311f0f33ab412d1f6c16c80b672109e2f6f67add81efae206c3c7113a6144826040527f7d21de99c9ff97207312a5fdc060506fd6a1b5b01a3a404d77e4ac0314a5db576060526020600060806000600160016118c2f26024556000516025557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fceb2f025bf374596293fc0b0b5f4b8454cdf8ed8c69f00a5f1205c0b9c21a1f26040527f23dbf65535a35a8a20e5596fa4eb0672389c7f9679da632cbb6afa0ee049aa7860605260206000608060006001617c71fa6026556000516027556000600052601b6020526001604052600160605260206000608060006001617692fa60285560005160295560006000526000602052600060405260006060526020600060806000600161e2f6f4602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f52b1f8b72565696f923a2a3c1c02884cf7715739d62da47be768787c5f6e4ea26040527f5ac903ceb935cdfb43b0456e4caea9ee634a7bdb7553a85d3f2d0673cc32fbf860605260206000608060006001613f13fa602c55600051602d557fcd3ab31c082129f8094b149405055f73cf34becb36f8dbb1a483ef9350a546d36000527fdc35f0f8f80bd27f84ce0f46ce2eda49694fe87e60398584a313db6ecbef5c1b60205260006040527f5decf45ca977b833255baa1326af0258c91ed3eb8e9d47b5fae45a9c19fdbba060605260206000608060006001600162015542f1602e55600051602f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fe0f55acbcebbfaffeea778fbd1f0651b2329d467759a5a20b528c940a7744f256040527f320b92b20a863ca1648ae7ed73f3b5a9350c78a5acba2bc82f9de2e6a6caa4716060526020600060806000600161c172fa603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": { + "balance": "0x0", + "code": "0x7f800000000000000000000000000000000000000000000000000000000000000069010000000000000000009007197ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe67ffffffffffffffff021660077f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a59003166036557d7676767676760000000000760000000000000056000000000000000000007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90116770000000000000006001677000000000000000087feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe68100000000000000000081d6037557ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb90057e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006fdac7fff9ffd9e13226262626262626006f121212121212121212121212121212129009603855901c7d7676767676760000000000760000000000000056000000000000000000007f8000000000000000000000000000000000000000000000000000000000000002900360395563800000016000901b901d6f800000000000000000000000000000016f8000000000000000000000000000000090059014712000110000000d0a300e750a000000090a0a677000000000000000120163800000017fffffffffffffffff7effffff800000007effffff800000008000ff00000100000590176f121212121212121212121212121212127f8200000000000000000000000000000000000000000000000000000000000000110b677000000000000000684783921454358970527f80000000000000000000000000000000000000000000000000000000000000009009774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a7f80000000000000000000000000000000000000000000000000000000000000026901000000000000000000900990087fffffffffffffffff7effffff800000007effffff800000008000ff0000010000686d5adef08547abf7eb1c603a557ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000067b368d219438b7f3f059012603b556a01000000000000000000007f40000000fd000000db00000000000000000000000000000000000000000000011760057f80000000000000000000000000000000000000000000000000000000000000029011126823232323232323232367ffffffffffffffff0a9017778000000000000000800000000000000080000000000000007702ffffffffffffffffffffffffffffffffff0000000300000505603c5567d02126262626262669010000000000000000009012603d556a10000000000000000000007d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf990167f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001777effffff800000007effffff800000008000ff0000010000901c603e557f80000000000000000000000000000000000000000000000000000000000000026801fffffffffffffffe1c7f80000000000000000000000000000000000000000000000000000000000000017f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe900816077ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb7a01090000000000000000000000000000000000000000000000000007603f55671fffffffffffffff6a10000000000000000000009013901d7f82000000000000000000000000000000000000000000000000000000000000006b0100000000000000000000001760006000f3", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000040": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000041": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000042": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000043": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000044": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000045": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000046": "0x000000000000000000000000000000000000000000000000000000000000000b" + } + }, + "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": { + "balance": "0xffffffffff", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "storage": {} + }, + "0xeBcdc7CF9233a11AFCD5B8283E89D951d41283cc": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2cc060ba5fe78470210f46455ffac3d00df319717eaa79d4593afa9062a57837", + "storage": {} + }, + "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": { + "balance": "0x989680", + "code": "0x6000496000556001496001556003496002554a6003556002600455", + "nonce": "0x0", + "storage": {} + }, + "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": { + "balance": "0x989680", + "code": "0x61018060005260206020526101806040527fc88bc00e3537574b69732b2a238d0126e3184313f737d07192139a447f56d7846060527fff6785753ee39984ecb7c9b84dc11b47fb781b88da28b6000d1b90235325fa606080527f616ff98d7ec4ff8502c4a86f709ed1a33b93c96da73d7a86be20636c3c75bee960a0527f7c7ca862cf1136b0f0171218255509196e9b8ddcc25109cb94602a88ddd46ea960c0527f8dcba5aefb18ed2c3e7cf3be3f39d83570fd524e00ab3d6cde1814ae51a4619260e0527f6bb3d76c05f73ba8cec9fd7ab35f6b5ddac7543ec6499dd66e5ce46ebf400811610100527f72699a293323eedcb8aed63f7c2d0c3c52ff40d9e806fa8570a5c9b988e35a5e610120527f3b3a032e24a3a4698ac5e059494b7e743a0e2bef3be48dd09d9bf9d77333235d610140527f54875e49a40d0ae2b81ffce06b2d68ade92272e9a21c94a5e8216c7203e1ee4c610160527fff3ecb58315b139cb07c5d93f439b2dfe4507c726a2c73c8c2234884f6b43262610180527f282ae62f4fefaf921b85b6f53bb4dada949167b3204e1673f6571046d7a6ab2a6101a0527f5d91178ce041f76cffeba58ba5a066ce9241e5d057819c097bedbf0fe2ff65606101c0527f8682ace22d5cafe24a2f58aa0eb97d825d40c0ac7c1887db376d161f582e95716101e0527fa90692dea0fcbd11600c0ded9ae428e70002b856db4baa70c981e521fa1cc536610200527ffdac109928200fa9e36aef37a751ee48870ca924f31263ae10005a79602c409a610220527f3e376542b55a21ab18a68af8a667360675b2151f12f5e3c99e8a752cfe8789aa610240527fd9900f9479d8d4e3f89dff1b4dba1ac05832d950dcd766873c9161220fbf8f21610260527fbbcaf4cf7f9c67a0705c5ea2c90c6a5dfb87fcab41cca51811966ceb30e3f76d610280527f7c71ae2db271bffe3fade5bc7111976f871bc5746a0b2f303b91ab2f9c1f651a6102a0527f582d401c25f461c28c30c79527b0091fecc7827c0614be2c554764138604e75b6102c0527fce97c8bac4249c6a637508446ba207b88aebc045620d3c9dbae6f0915bd865c26102e0527fe52c3e61df670e390fccf242c0cdd51e72c5c0410b8a1f5e73d69bca2c23627f610300527f7748ceee680bc41377a5692e7de9cc4867407fa4573faa8238fba994a3f42f12610320527fe0e1f522a003a43de6797d3f94ffef6919865113a9419e409290f38c6281e7c6610340527f97ee141220dcbb5fb338f60dba3eec7dc475c6e119333adc7a4afd1a386952e0610360526101806000610380600060056216c54cfa5a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e0516008556101005160095561012051600a5561014051600b5561016051600c5560916000526103e160205260916040527f4b41fcf56e9c946f221b309933258452445555591de517a9d26f0d2a1b7c64016060527f808ea269768820a6dadabe52e6133f5bd510e1f70b00a53b9031774cc05af46b6080527f2ed65039bf4d7065e580fcb6a194637e2a8d07d938348bf4578df9844e1d146660a0527f5a67614ca53c1c119320c25af763316f78d9e6688946ee0784b00b8a803bb65460c0527fc6a8d6003b582da6bd7b1c84a15e8c43a4a75d1c151d36ebe3cb78139859c31260e0527fc1989579155f746b12ab9e4b483b4bc29866d83e683d65045e97e858957751a8610100527f23cf01a1b3b3bcf7ead3ec22e3b11c57e0936834f52474e889877ce3472506aa610120527fdf326bb9973addd5d70d7e40b3eb3e5118dba8ca848e08f9f55a84d6e7191a95610140527f64f0c5f152f6091ae72a50ca260323f5bf2b749e62ddcc6509663f0da5e6ea90610160527fcc7357dbde438cfb92eb3743bbb037da16aa7f44e14c6323b182c5de3f4ff188610180527f723a5d4e993d6f86a7c571e66adac53fa4bbc2dcd39947a29529dd2abfd9c75c6101a0527ff77cb4a60d4f5077f47d5cc2a99ed7cb8aeeee6d833de8cb9315ebcdd8bb32a86101c0527f759f01af36d502525fadb44f95066c7d115300a821d5c0db18f240f39f8c6eb26101e0527f6159732f3661df236710bfe60dd52e537b2703be72e05968781c7ec03ccabeb7610200527f5c9b851808d0b3849215278846a0a842bf2371cd003fe4d234713560dc2dcbc5610220527fd0210caaee72c4cafeac5ac7a9755c7cf0e62949c7bb69f2dd0def8dba3fec6e610240527ff5eb49654493600bc393b6b6f385b9513e4a0cd31412b08fa823d4401b9c55c6610260527f47c14f97fc0441f35445a943311fea3df2078b948229ff9a5d148e4558020e3f610280527fbe9d6d2a17318753f8adb7a6f7cac1ca07a456c835387cbf9cc3323bd0f83de26102a0527ff0575265a924887002e2e529ac61047909bcf3c576b83ee31bff3bf51d7adc956102c0527f9b080bcdb51091fa112a4b91064192330d9f7147acf8714da54cfeefbf82773b6102e0527fcc314277713bd0973ccef3db913dd38d1c0e6161d153c18a4afc9bf4d030502e610300527f154f005cf084d1aaedf71ea3e4df05d8b05b79a9e151071ceb50c39d84da78b8610320527f732b512522d4ca4f24f28e10872426408958a1c377356e3252364ec0488d36e7610340527f3c3090846254680cc9b483192b2c4870b3ab1776f50edfa98ce6ac9b04db7d3f610360527f83543676a190cad63ace2543b3063db4d7d865d81c155b77abba99cc9fa7215c610380527f7f3fe9056fc7c7d0f15f3f3c104535f6c4fc8933924160657f61646a5b7951c76103a0527fba17efe8c8ac88c63c9d12deac81dba0e3bf6663423ac7efa9f8da4c026d1bc06103c0527ff076d0cc7876097233b55072853059c5ff9776e862c9aa122346d2eaa182c3266103e0527f1fab28f57939024c7fc5e577fa2df7c34c60160fe9682bf64ad00f6e09a8daf0610400527fe6b9006b8be0626c3dceb0b5b319c14fc2d82be90cae680512995edcec093d30610420527f1da09d7671dd174e33437697541d05cb1cc29820ad59fa9b77ebe3d43f277fd3610440527f5e2c68b3ebca51422679c03e0bc3931a94ce4ca83bfe472d3661179b1a14b5d5610460527f1b011af773258ed38942bfc665962c227ea111ebbee3f7fb3d2cecdb82f3bd41610480527f303546afd8d878903066fff3419493884ff13cef00810dd261738ed9830f809a6104a0527ff298a2147d740c127c77726f4c7c32c073c7f1adc5ae6a25440a5fd0f740aeff6104c0527fee789daa860dca3e563238995adbf06c55064d6aa91ef3d721334cc272554f0e6104e0527fdbf41f32e8cdedc0930deb033f3d792bf0c0e4856c48f322c1a905e1022a1735610500527f5ca4f685f726f478922a225ffb97c3c52ccd2765b82552e56eeb73b5b081dc32610520527f87ab723d86e1167b5944ec34e727413f9cdab9783fdc856dc8ca2ecdcf1b5efc6105405260ec61056053608461056153600261056253609160006105636000600562c97aa2f45a01600d55600051600e55602051600f55604051601055606051601155608051601255605560005260ef60205260556040527fc794b2d8e2eaf072f7fef7d41ccd9915d7489b568d0aec5b331c5033092b5f5d6060527f6cf56ab9dfefcb156c3d2d3b2d98e82e5bcdfb49ed92e4489fa3717f709feb4b6080527f2b1cef471d90b89a969ba196bf62a9b0eaa02fb93b000000000000000000000060a0526b02000000000000000000000060c052600060e0526000610100526000610120526000610140526000610160526000610180527be1744d1fa7b3eb20d74c603d45de1a77e200b9368bbc81dcfba262a56101a0527f71ab2b1d08ea3e6be5a5c4ff7f294621e1f38fe76c2642fc6ae03ca909b5db406101c05260b66101e05360f96101e15360796101e25360326101e35360c16101e453604e6101e55360da6101e653606a6101e75360916101e85360c96101e95360ec6101ea5360de6101eb5360246101ec5360a36101ed5360f76101ee53607d6101ef5360896101f05360a06101f153604e6101f25360596101f35360b86101f45360db6101f55360d16101f653605d6101f75360e36101f853605560006101f96000600060056210c298f25a01601355600051601455602051601555604051601655", + "nonce": "0x0", + "storage": {} + } + }, + "chainId": 1, + "env": { + "currentBaseFee": "0xa", + "currentBlobGasUsed": "0x60000", + "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000", + "currentDifficulty": "0x20000", + "currentExcessBlobGas": "0xe0000", + "currentGasLimit": "0x11e1a300", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8" + }, + "fork": "Osaka", + "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f", + "transactions": [ + { + "data": "0x", + "from": "0x677B3ccc29f7c2293364fEec7F51907756f0124E", + "gas": "0xf42400", + "gasPrice": "0x20", + "nonce": 0, + "to": "0x538A8474EeaB43d5a960164c554A20400151D479", + "value": "0x0" + }, + { + "blobVersionedHashes": [ + "0x01d389829e7c0e709e1989ec5305e8e731df7d9881b56e8a74b0a3ff6257c139", + "0x01ad0d7a10bd7f499e177998ee602ed0f57bffa973614c8412f178db3af2cab8", + "0x01400983c44bac7d4d6f52d98ce77eb2ea6935ad5938dc3cffbf3ebe5d7ad2c9", + "0x01fbccc493401424e414b91cec5d6c4bebdf8be74a8f818597a0ea97f9a69347", + "0x01bb6fff1f1c2f113286a6ca12c99baed80fc252499beacf63cab5e4d0dc0dfe", + "0x015369aaeb26bfdfb0eeecbdd298cc41ed5202adf8b0c997aba93a6d6d5f971c" + ], + "data": "0xb28f", + "from": "0xeBcdc7CF9233a11AFCD5B8283E89D951d41283cc", + "gas": "0xf42400", + "maxFeePerBlobGas": "0x100", + "maxFeePerGas": "0x20", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "sidecar": { + "blobs": 6, + "commitments": 6, + "proofs": 6 + }, + "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89", + "type": "0x3", + "value": "0x0" + }, + { + "data": "0x3df575b295e707c07dc1df", + "from": "0x91C6Dd1A685cAE33B044370252727B57f688e5c7", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce", + "value": "0x8b" + }, + { + "data": "0xd4ce11f99d2bc3795165375c1c08364f5bfdc5f051857969990d67468d55ec7df0f8937ce6f8024a0e9c4a44a957eeefe0f5382fa9f30b0f567236f67a9db10e671c2758c3731c91a72261", + "from": "0xA9A42c08023d1a23a61dA0cAEd0106A7C48b7120", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10", + "value": "0x50" + }, + { + "data": "0xa30735fdab09bb096ff451ad3d528f3307732d98c9874070c1a606c846fbcd8d8334532b56d8ba63234af9dd6c1f8f514395241fa19ecda6e195a24b3ad55e689e5ad800b0ac7406ae428d", + "from": "0x3fD261193d23d8a73a4fdfe7735892c6Ebb4f2Ac", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3", + "value": "0xa4e5" + }, + { + "data": "0x58b0f9739971e35ce10fee000eda2c1ed6ee9c0d253988fc965825e5935919840cf3fdbaa3f2274310d0006a3cd03514e790bc849f6f02467a08026835d916c636deb68b7ff2cf49295cfafa02a2b2bf743dceacd8a070070f0444d9ebc35151b4566a5239f2ef577d9fdaf29e951d5b3eac10282df33d7e6d1198ed63e5e1070480d045313411021984807664507f9eb29710e354a96f167ed5234de54d0250be5bedfe38182d3348c48d9c57d6681ce5c68875bbd9de06baeb369b0efec41164cfc2ab8bc2220fdba8f29c5ece41648a537466166e411352d5cf02428852026e8e64ea60605467fd463ff4346872cfee0300083f5cfcdb50a93a33396fb4895bd6bac23656dbab2ad22fcd3754730913dbfb7e8f828c72d21bcd05245117c69519275804de80667cde09f0b2cb4ef6e7cfe7076efc78734c08336016fd36d04e79ca6f0a8e7f0dc486557b883092203358e76999a92e83", + "from": "0x677B3ccc29f7c2293364fEec7F51907756f0124E", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb", + "value": "0x263651" + }, + { + "data": "0x4a99b4", + "from": "0xeBcdc7CF9233a11AFCD5B8283E89D951d41283cc", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f", + "value": "0xc" + }, + { + "data": "0x", + "from": "0x91C6Dd1A685cAE33B044370252727B57f688e5c7", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xD74CFe323387aE2fd070CD046173026716D8D649", + "value": "0x0" + }, + { + "data": "0x3e", + "from": "0xA9A42c08023d1a23a61dA0cAEd0106A7C48b7120", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6", + "value": "0x0" + }, + { + "data": "0xcaf367a2c043521580bf2ded9a8e1b0b8ff4c77e9109ad4a78b35e6df5ec8a93af16705a1ff1740b05bf2b2d08eefcbf53b54ec3b6bfe1cb842f0f0e249d6cb6bcfd6fafd83b55ec40b1bdf17f62917ea408fcc4a3800a2e", + "from": "0x3fD261193d23d8a73a4fdfe7735892c6Ebb4f2Ac", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F", + "value": "0xfb285d" + }, + { + "data": "0xbe89f155f782357bf7038a34b224dd184c0045a929d8edd5fea33ffb3131a832686096521b6bce6d74d53fd9e907c442975a094a7cca03f2c9f4fc6af7724a80e7", + "from": "0x677B3ccc29f7c2293364fEec7F51907756f0124E", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190", + "value": "0xb6918e" + }, + { + "data": "0x2c9c0082bbe5e68dfc726e41fab672674cb60b19ec0aaacd2efe958cb1c08b8ede492c702a99ef5acd704e55ace7aca4f209c59f9151e04405d4a396fc05e50c97d125878775dee202f269a9e038ceee92aa5ed607a8b0462afe", + "from": "0xeBcdc7CF9233a11AFCD5B8283E89D951d41283cc", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d", + "value": "0x9ca7e9" + }, + { + "data": "0x5d3a30b3be577899e7e228d7ae0561981cd3e887", + "from": "0x91C6Dd1A685cAE33B044370252727B57f688e5c7", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c", + "value": "0x0" + }, + { + "data": "0x44cf53c635525fc3", + "from": "0xA9A42c08023d1a23a61dA0cAEd0106A7C48b7120", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876", + "value": "0x0" + }, + { + "authorizationList": [ + { + "address": "0x000000000000000000000000000000000000000d", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xbfe7211c0c349339a3e3634ad737c2d33e232f89fb39d664d328afd5ea2603d4", + "s": "0x6b1d940a4be6b4b75d4b285ebfc1f63b599d780ea66348d3210522d155cc7716", + "v": "0x0" + }, + { + "address": "0x00000000000000000000000000000000000000f2", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x44aef284b3b8fb0360a3550efdf9e4876503da8a3f0b14f56d27ff1d2f1e6a72", + "s": "0x2ce2b6ff7121d90053f7f56595f335d6e5bcd1e55b075ec10e0bc04e97650ccb", + "v": "0x0" + }, + { + "address": "0x0000000000000000000000000000000000000007", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xeef59efbbb9cc6b8bcca0384ddaf3ae96bc7e761ed0ff13d48ed531251a32a56", + "s": "0x1d270521363ccd1bbb726f908d863acfde6dcff0347885d3e6df7dc786415d39", + "v": "0x0" + }, + { + "address": "0x0000000000000000000000000000000000000007", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xe8c243c5128186444a344b011d78b24cbe52e9bffb3bf4959b986834d93214d3", + "s": "0x3c629a82eebf4be563712ec562627be11e9d50b2cf1e6dab4aa4dde638e29ce8", + "v": "0x1" + } + ], + "data": "0x3115c7839ee8f609514b277b51b9f9f190d191513422a143d5186d5c4dea9bda8b4f13a9592dfc025773fc03ca013c", + "from": "0xC4AA0D75736f14fb4971bBDe8CE49Fa1E25217bd", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB", + "type": "0x4", + "value": "0x0" + }, + { + "data": "0x00", + "from": "0x48Ed5D2f29e6CF27031A62C9e4826d56B4536a36", + "gas": "0x30d40", + "maxFeePerGas": "0x1e", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "to": "0x000000000000000000000000000000000000000d", + "type": "0x2", + "value": "0x3e8" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x1", + "nonce": "0x2", + "r": "0xdafdcae05424d2ae0fa456ad45e0707710e5e4e3c7b1af8f5997f8a464477a5e", + "s": "0x20eb4f7e18471a0060ebcc24066b256591e6f5a6d5b5b9adff14d3c9fe41ae96", + "v": "0x1" + } + ], + "data": "0x3115c7839ee8f609514b277b51b9f9f190d191513422a143d5186d5c4dea9bda8b4f13a9592dfc025773fc03ca013c", + "from": "0x1028f1F4b946800E1b6D7528C4699Cc3df844fBf", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x5CbDd86a2FA8Dc4bDdd8a8f69dBa48572EeC07FB", + "type": "0x4", + "value": "0x0" + } + ], + "version": "2.0" +} \ No newline at end of file diff --git a/cli/fuzzer_bridge/examples/comprehensive_smallest.json b/cli/fuzzer_bridge/examples/comprehensive_smallest.json new file mode 100644 index 0000000000..2825bec976 --- /dev/null +++ b/cli/fuzzer_bridge/examples/comprehensive_smallest.json @@ -0,0 +1,444 @@ +{ + "accounts": { + "0x0000000000000000000000000000000000000010": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x00000000000000000000000000000000000000f6": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": { + "balance": "0x989680", + "code": "0x6f06fcff69196a393d4ca702feba344df26000527fe442438ab1b839640ec7742d77053df806abed423ae6a498dc093103382749206020526f022f0c5673eddb443409f509edcab2aa6040527f9abe26305ddce240cddb9d26556bd4b9555e14d029eb88a867702b43c75375e46060526f151a683af814b7b843ef0914d5b656966080527fc6f0e3c21eacda1ed058c181dea5c54edecefe3c22d09f1b70fc504ccee0270760a0526f10fe871f92678911745d6a5791dd721460c0527fb0cf887504450cbe272528c86a6fcc368b036f7627f2b503147e788dd92fb2d860e05260806000610100600060e5600b7fad00de6676d949b2879235fbfb19b0f975c79dde8b90f395b4b322156e4b0a76f26000556000516001556020516002556040516003556060516004556f1430217071dcf4a05f9b69af6dedba006000527f47092bf14ec9d7f19ff07c710fd652c2bf72945a93b820b4d80b594801db4cec6020526f169208513a417a1e8e61bec2838a72a36040527f950dc6303e7d9b6735f1883b2d10a7219bd467187bfcbb6da18eafb8f78d3ab76060527fb2d7154982a36a940a4a09c6533e417af13231e08b223f9f07c3e7a537fa0a7c6080526080600060a0600060ff600c7f6be1e0cef74f639ff740aa84eb986d22098505fac3c26e495d8bb5e4388908fff16005556000516006556020516007556040516008556060516009556f02780635f54e105d88e2940d22d4d2f36000527fd8e8a4208f388a09b5dcd814920701343f527374169559101e60fcd4f636b0416020526f0de0e61d06d1a9cd1a6033acecd196516040527fbbf9aa91fe99f07b86314ce0c4773f41664bf03ceff26a5b3bbc11046b7426336060526f0ce031599c822d4cda00bba3b0621fd76080527fe9c08c8aecc9facb8d88e18dab0335adca4950d09292316b3c375540100d49d360a0526f104fbff0ad9fc644bb6bd13b6ace02e460c0527f96d62ee342495614596f56fe5ddc10a5bb1f162797396b9d75f1d840c8a79ad960e0526f07007d1fe6363f7bad8fe120e3c68a44610100527f7c92ee323f405f938e2e02484c62f2facbfc43cb0d28ff3f16178bd0fcaec335610120526f13768ffdcdf366e9ee63cc23475e8595610140527f26a575e5544f22c3e064dac3d495eb6b2b594fe846073026db1695ffed066018610160526f147ce84581777751a3704f7d43b119ae610180527f6aa4376abd93d8112f31876e7b337350b6a17946adc9616877967cee76d974a76101a0526f1198913a5b19ba3457b36d25d593fbf56101c0527f752b3ed53a63bb73c4ddefe4082933e93a0103780b21db8980c117f10637e9c66101e05261010060006102006000600d7f4a1b51e507433a9bd45b51429637710682598c3a5087b26ea136ee017aa52e44fa600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556e4f08014da76e7b1aa3302e2241f8736000527f8d10abc569925647915ebb5ab88486679288a9dbbf5f481f182da264ab34a4bd6020526f06d5881b1e939fc02875eae54bd32f2e6040527faaea60b13abe552a5d5350d84df14cbff41bc4bfac9e9e503df34f79993387fc6060526f0216413b0addfbb5ca4ae26c9bf45ebf6080527f86fb951e8d918cd399777392ae695a393f9411394a71295409713785105fdc9460a0526f126cdd8c9ebc88a54fa5539c5902074060c0527f6fc52da24a2337cf2fca7d6e2fee1a27a029a0ab80479d64152789fdc1465f4260e0527faa80d757ada2ee24f6fbe189479805f7061b1186cb063a550bb96d88fa418b11610100526f0c243dfde08ddddfa8949c2ecee26f14610120527f0cf1870266b91b5dad84ae43af0c6c02fa3f81f8245e5074af73afb381e48d2a610140526f124d3efb3d621c83c682e1759fbeff13610160527f87ac0dce1bd0ef742565c79c2d84f58a99ce3c1334dbdf1adbb87d9b317add3a610180526f1549d53c5544278fef820b936a0b9da56101a0527f1f765ca450e5cf7f5e1ea309d3db585d9f1fc47ec6fbceea63e9c31ae58bcfab6101c0526f0ac911e323fddc70e0dd973ec59da7526101e0527f66b33b62e4769dcc3f2173d8b4e6c207a1511c40b9e337f8b04dbf08c7e68df5610200527fa94a87066f4ae7ceca92defa2fb336767cf1ee575035d3a3a462b8adddd262056102205261010060006102406000600e7f93d23edbd187f33f27c1739cac18e93f6cd1bfc5c81828a1b3cb4814a00285bafa60135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f0745441fdbad4dc5a236412bf6ea07b26000527f207d89aea5a9a925d32b8007ea0c44c6e88a06fe3dc88ef32801cb9873b65b2e6020526f13402186bb791b3ee693abcbe0dee89c6040527f36e4ef4ad8c6abea65d3fd94f43fee9d40d65edf597dd2de64a8fd647f1e0ede6060526f043d2a388ccf087d3ca888a2d72d51466080527f0e1c0926a3e74772c807ed86d32169540c7de35b90db097f020ec825f81a5e9f60a0526f0d3bd03f6ec3dceed892b4cbed1a047160c0527fb8ea4b0f0e3c14bc6540f327571a1dc7245387434c6260ea8545c3a3f43f52ae60e0526f053e1e81dc8a4f0d68d0a0c23e2603c8610100527f65a9b0a2444d15e77339587e109f20caa38c7352304baadb57925cb4713e760e610120526f02abce8b992a833ecafddd3218eae49c610140527ff73bb4507c7fd63d1eaa6c29887203b04d95ea0b44c7d13c6b4ecb8533234bb0610160526e3aa8288491bd367dea58c58c500c9d610180527fc213d583c73602aa92808cb213aed86247865a978709cc5371970b15b9ad527c6101a0526f0fcd23237589ff2f23073c8417f31be16101c0527fa1634d060e1bcf6efe039ef5a11a41d90bbb05c22a595ce63103fe08960464d66101e0526f0711b1af2d891054dd6f374d2465e7e1610200527fa2c46d4e6b6235f105cd0ebfbd0293057ed0c38a4fe43d86d90eac8adcbd6b58610220526f16253bf3d1b7aba9a88abff5fd797e42610240527facd45ad966cae5da033fba84d2b954b265f9aabfcdde8ff90242beadccf09a2c610260526f19b6a239f990178d2a5f5ec618d1bb40610280527f53280e61e0bd7199af0108355ea94099ab1b61b3616d70d87c5e8c5c720ddc886102a0526f0c7f8411a266d2c99fd03f900fa0a8906102c0527f70f9b3c407c52fe2dd8965b56db2381a7d10ce2e93f52cc51d420fbd11ee13e76102e0526f10fc7f5161a560db1d3167f858f43bff610300527ff474f46440009367463cb9b447e03db4fa8e1c79a414e79e6270e6637f116d80610320526f07bc163101bc29f18e42064275adec4c610340527f5e7bfd20d8eb12d3e5d1cbfbfc15bce7a24f1eff82f8206979980ac56b0fbad0610360526f024aa2b2f08f0a91260805272dc51051610380527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb86103a0526f13e02b6052719f607dacd3a088274f656103c0527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e6103e0526f0ce5d527727d6e118cc9cdc6da2e351a610400527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801610420526f0606c4a02ea734cc32acd2b02bc28b99610440527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be61046052602060006104806000600f7f25e0a9449d9aa98ab896355983bd0dca54badbfe493862625ea8cabf7caf79d2f4601c55600051601d556f0dee3561b6f871f4550f22e15c3768796000527f2921b8637f9982d39db18d2d3999a8f6067fe7e48f56f3ea4e21def7679afd226020526080600060406000603060107f9d94c372e3e4486685ee8485a7486537efef6ef03d31f110b4d9756aa40fe142f2601e55600051601f556020516020556040516021556060516022556f0916c557668c9c2db6a6b6869d92d80a6000527f53efcc2a81d2672df3b335817985c423e104ef4e228c5402823930a8ffab490b6020526f12793c650781ed6cf7c127628edf18eb6040527f50ae0145e33bdddd7150b6834b309712248a3e91d2b629ed7955af38864c3a2560605261010060006080600060117f66602b2002036afe8d1f22e7a4028da230c39328019419cc67bef352f4e833adfa60235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55", + "nonce": "0x0", + "storage": {} + }, + "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": { + "balance": "0x0", + "code": "0x609d606660e560af60d3602560b3690b483c7050464a301c02315b3da461503a6e569c5f7d756717647d711c73303974760817747057567d035548030342816c7e35587f9c5e59f15a620a8d684805768f58909e6b107f716c167e454407688974805245698d12415e420b7c563d95876a161b74479355685451706c50165a748917324117306c156d7314048c6350731837f3fa44167f597873f46d527e7a403d01068407019f13019b191c34891004701604128c590b907309656319817e7d343d47860318677a5f68a47457151a543781faa170751d395779fef06e37193e5d11045b3e4a63618085845b547a1d1a365d615a613210f5835c5f7a915258630b345d806a9c821bf1339651755d201384f04136348604395a575f786141683d7755137b5b6612645d63883dfe6658fe14937f5d147a656f706554021e6ef38b855a44484a947a99417333053d67753b6e67a03494193f19483362503f4443783920075a5381010404a2611e349f39321335763f9a6e983670f0785c9776517558805f419914086d5c09545b80f43b439535803d515c95376d058b86f41a334530746135025f3942f187869e6a035250006f07117a8c1d399895165849fd569337a25263f05c51a06b0430771e8317881a8f5d9c0631603537588066774537017e98646b9781a07c5bfe695180f15c469e511a4451486e107d030a6a3d60593c633736f16d3867666577471d430b32063864648186165f16f533516c0407077f61711c389d9c681ea480574045367967841b41075a76636e1a484908311112176a8a3b841a66496168755c027b6888050af58933f015895e1375340143567f37743b5085904a6277474a19337b33816a3b7441411392435783497f423d10816f797253729c6a085a05803051f5324109855e108c5a3a736537618a7a7f7b755c3b3d1e517cf37105708b806b143e686e7c6755416a9f778044542055406605766b018e731e6f5d603116303b466c78753e40127a846a731783a16c3e177b545b096d0359450b9a171e31525bf0447502776c9e5566108803973a805b5c41436570840a587cf1867e3d7f1e3b31713f775c917858951b4a5b6c669e75737665736460867c6a421a16060341f05b6c5254075d793e090a05891e493068388b94677605016d5d9f5e0b3a080a891c6d187cfd1483988f953779f5569169f47a3c528156189d41138f605238037d6c796a65789f5133f36e1a828b615975929979626da0757030911581858d11143a3b6a4066095257a4453c0795fe6d6d5a6662125c601091553c4613390b0614656f9a6bf20b65435705041773fe446761876e5a5219431d333e5544f08f19453e9808455735a17252019377073e613f52587a5640387a9541127b0219368c539061630a684a77f4543035611e9c17863b54305a", + "nonce": "0x0", + "storage": {} + }, + "0x23957dB27fD43F125fee8eB0a2Be85F1FC39Fa74": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2d16ef33a23df66bb3a4c85e596df85ef7c524808ae7eeea57475353676882fb", + "storage": {} + }, + "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": { + "balance": "0x0", + "code": "0x600054507f1bc37322bd8795aa5c0d765bb9d786a2c2ef34a695ec27232ea0ed8509cba6986000527fa18a0ad7e91a1cba90a04235dfbda77cf0549c58790669e09f88b509d33815096020527f63b6f74c4a5c6cb40ae6de0408689fcbc400291b3da160ed5a4e975415305f8e6040527f8108b2ecdb883a794c1152e92632e0a64f6a8a5d55bd29b90f7d51b3a4953f976060527f581e32c2704f32e72cd7e6ad7cb1071b92f237895e588adc7ab993aedfe2afd36080527f5aa1c972ecb9eb74528c16d451c9aa9ca317df0a4450636b4034468d39d36bb960a0527fde65e94ef04338d6ce09ac96d0ff2ec58982a6d1bf305ae6c855276fcceaf0b460c0527f8d43c21ac3785bb7cca350d44fdbe19966227e30c6b16bae02fc147c57ef402460e0527f8437286b7c84a04fdabf6afe1e0875d72be8d4fde1a3d4051478b1b20b3206ac610100527fb1a464581de2466781a0c72f1dcc93b941760f217e5a88aff6763dd525ea59f3610120527f8309b7732f9ccb14f135e34091a095196abc4dd8c3dc7bf32aa78b67afce944b610140527f52ed661a19b5c516db7c24a0782956e725fa01b61f9c8fdf9d92d0bb258d98b0610160527f92aa99ffdb4a178eb0f265d347b9358d0c2fb2fc72e0ffe189275942c409343b610180527f887bf88b7bf9d2f1da02e89e11790f03fc3a6f45cef57aedfba36a79273322906101a0527fada6af26406987cf79280e837f83cb9cdd89d26806ae700e62fd603e30283f366101c0527f2ddfb3f5e3bafa1910e8e57c7c3d45fef5024c8d298309640fdd6d771eedb7586101e052604060006102006000606a60077fd2a2dc91b7adfff42174a98e0770f27dbde9545997a551e20b2824a74bcf7708f1600055600051600155602051600255", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000a" + } + }, + "0x538A8474EeaB43d5a960164c554A20400151D479": { + "balance": "0x989680", + "code": "0x7f063b9d3462f2d80599492ec1750090cfb49edd47f3bef1a1d5957a77033f9d3d6000527ff849a2ffa8a3461a482f3a22613ed0bf62a0ffb9bd07ae10c23eccb926f837cd6020527e684149fb4557de661e5a06f306db0ef1a74ea674d299798a296735cbeeaeb96040527f585531de2fe977bf410e4b688e209d146281c4e3462321851ed413b2a0686f306060527f5f1b5a92ce191927ef8a99675520ad450f127080f9b344ab13bb64eb1f92c83e6080527fb42fb286f11a883b5b335e5ef2d5477569aa8a4d8430496d2d5109c40d6436ce60a0527f075e55f44883857cac5e60f122e4d3c635b99507a3a06941c0cab3564984bd8660c0527f4d35d25f52d6ca0bc2f7ab9b9b39b14e646e9e45e333bab86231e6d3dd923c8260e0527f337fc2b6a185f66f133b7f02d43de1c294e96db2bd41b446d367c9cd93f888b0610100527f65aa838654bb90480d83fa2e3077ff6054cdc5f35e5758c74769f5cd642cd643610120527fe852da9bae2aba92623982d69a62052d0de78a796ee1f0079fdf3eef27645b87610140527f583309beb4dece1ca64314d7119a948bd0bd9250a16aa2a367a080aa5c96ec3d610160527f742878009f403251a96de70c5813de6710ee4036b04b589ea5354778cd843650610180527f1cb588dae2ed495d5025e814a1cfe05f629abf0a7e89ffd6f70158219a42c04f6101a0527f1aaea7750e284228ac6dd044545a90ab4f063bb266721afb0503d980a4762ee16101c052602060006101e0600060886101007f47d7e060bd3dd5829e781863df7b5ac9b170d37543f1740059c8e0d89eaa5a4ef2600055600051600155", + "nonce": "0x0", + "storage": {} + }, + "0x641602bAD4A323C49629d45338d79A2bb984A3fb": { + "balance": "0x989680", + "code": "0x60005160016060f3", + "nonce": "0x0", + "storage": {} + }, + "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": { + "balance": "0x0", + "code": "0x7f0ba0370907b7d6bcf961e381f77377af06df0572990c889c82b7c74f1e90f8de6000527f9826a8d0a9e3d00cb36c029caffaac161013bada23a90db9e8c9094de47cfa3c6020527f3c377edc4581270e7bfe23963fde77a95dce4e1958f673e76ecd1002488df8cc6040527f92ab51e33a39f0d13d88d8289ab18894b3ac7c2ea89a5bff9def6250dea461106060527f93c199a032e468ec45dd11b7827ea994289c6ac47c45f3dfb3f54c987255c3bf6080527f4d562b0308a2434ff7868a0702561923970abad32ac03f5a58ca902b7ded758160a0527fc584e1ac59d9d6416adc32d759f72e78ce7cdfad0128b477f96924147f66cb4b60c0527ffbb8d840baf881780dad88f8243aa46ca65214725bb4da5dd82242513fca909560e0527fb7f9b70fc4f2a0809a524d3fe329bd25015b1b5bff94225815eff18acc2ab46e610100527f5a3ce6d41a8eaeebab2d0fb1c78741ec5749b1fb23fdbfd2ee37d9e3a115527c610120527f28171e9dfa097d3e025060a1a7dce9eeeccb0562450a5f0fbbc8637302ca40e9610140527fb35e30b4c8f5070eb1120979c1a82336118624c8138e2ca026a0dd0ecd531b32610160527feaf23bed9d70590d96e25b2f9c1dcccb04e0cb94221e6728bb8c1f250ec744af610180527f1c2e979f28cdc255c646859306139ea4111fce459c056b760439ce2cf68b18a26101a0527f463df923aadb23509b5a813bccee78cc68873d42ed8712225341f89f4972b3ae6101c052604060006101e06000600e7f51c346e9c8ee8b23f64efc42ce303b46b7a555d3ec49a8f2922c3bc20740a256f4600055600051600155602051600255", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000012" + } + }, + "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": { + "balance": "0x989680", + "code": "0x7d02886c65c9baacdc167c99d8d4b203ca59c9c5eaac2647906bb8c5619ba96000527f7d653106964d182963c381adc6ef7caa35be72a76cf8837e854e28ebc20b67f06020527f5844d18a6ce56f0d2e63c6cdcc1f27f51e936bf6190ca2ad94718d29e5f0db1d6040527f44d2715a6b6e3a3df172f36ce09cdca3a48a1b5e5ff40de302f3895fd32a734a6060527fbbec99a8077daa3775d4e1e47a920a5a9035f1bde0378b33b70becb47af43c8a6080527f956302c42f2686070942a30c4a27d37d7fab7a1dc94194d2b8fe80ac7fc0b70d60a052606a60c05360c860c153600060c253601960c35360dd60c45360b060c553602760c653600060c753601b60c853604a60c953605360ca5360f660cb53602460cc5360cc60cd53609060ce5360f760cf53604860d053602960d15360f160d253604f60d353600060d4536040600060d5600060097f2c798e304e82a8acba8a9b9936ffa652a6ef6a118272cd1f71c32c61d15ce085fa600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x8b632B705a6Ab4ee30e08eD21A0AEE1C3b6583B8": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45d548a69d16dbb51608188756e9b4e2125431bfc7c8900afd1cd15a45df5689", + "storage": {} + }, + "0x91D1D8f382B0EE7F1c8E2a19934487D80A469695": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x3af15a0aa381091abf31af1f4363ccda85c9e17ea76d6743a55cb18ef1aca326", + "storage": {} + }, + "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": { + "balance": "0x989680", + "code": "0x60017f77676767676760000000000000001002e000000000000040000000e0000000009007197e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a007e1f00000000000000000000000000000020000000010000000000000000000004900763800000007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10001b90186fdac7fff9ffd9e13226262626262626007176767676767676767600000076767676767602077f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f7effffff8000000000000000000000000000000000000000d900000000000001901b177ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000777effffff800000007effffff800000008000ff0000010000901d106b010000000000000000000000712000110000000d0a300e750a000000090a0a901c076f800000000000000100000000000000007e40000000fd000000db0000000000000000000040000000fd000000db0000d310116101117f62d8fffffffffffffffffffffffffffffc18000000000000000000ca0000000110901c760fffc000000000000767676240000000000002b05760477e1f0000000000000000000000000000002000000001000000000000000000000b901867800000000000000060051d90066a10000000000000000000007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a0004901d7e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007e40000000fd000000db0000000000000000000040000000fd000000db000001901a6000557f7effffff8000000000000000000000000000000000000000d9000000000000016b100000000000000000000000186001556005600103600255712000110000000d0a300e750a000000090a0a6000901214197f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56b10000000000000000000000012600355637fffffff6801fffffffffffffffe9017187f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7f40000000fd000000db0000000000000000000000000000000000000000000001111476013590cab83b779e708b533b0eef3561483ddeefc841f5678000000000000000901390117f80000000000000000000000000000000000000000000000000000000000000027f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0081590126004557f40000000fd000000db0000000000000000000000000000000000000000000001157f7effffff8000000000000000000000000000000000000000d9000000000000017d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9901c900267800000000000000076013590cab83b779e708b533b0eef3561483ddeefc841f590057e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007e1f00000000000000000000000000000020000000010000000000000000000067b368d219438b7f3f0902901367fffffffffffffffe6b010000000000000000000000046005557fffffffffffffffff7effffff800000007effffff800000008000ff0000010000682323232323232323239013901460006000f3", + "nonce": "0x0", + "storage": {} + }, + "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": { + "balance": "0x989680", + "code": "0x7f1ad252f41f24a4e47e3b30cd077e62ec5e97a21593b08ecf63ad797c845aa7b86000527f6fbc7de1246b5c82e32038eef1c50b793f80ff9ffd5d94ba0201758921e895756020527fe96280d9bf66a984d8429554eeee5d66f13b77754eea60b5914cb1c70d88da1c6040527f8aaf6944e59f427beb0d6335a9403e372a2a8db59ee99e352b7db426f88ba8c46060527ffdd5139e421a516cc016174ae8fe299812e0afcd0dea30757f1f68d1d5b3b7396080526020600060a060006000610100611ce3f1600055600051600155600060005260006020526000604052600060605260006080526020600060a06000610100611b56f46002556000516003557f03c5e492839c5c2a6b19faa426486d273e5df7df0532a9f9d383c91cd9bbf7936000527f20e0282db9e31ae6b468087fcf52aa711f00a9dbf73b175409070c9ae273822c6020527fe447e297c6692bf0e8e2cb8d719eeb6f9f5ea25df880fc9905033106d25d318e6040527f09815f1b92071b6bb2fd09dbca9fa959781493ac972d9589fab850a11a088ae26060527f4ad5492f2514adec949add6efa491707a9e123aad36c8765c6ffa0e2cb17d27c6080526020600060a060006001610100611aabf26004556000516005557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f61ed34369e8bae5efec15bc2180448deb0300cf1b070a5a26a46011a920110216020527f61ed34369e8bae5efec15bc2180448deb0300cf1b070a5a26a46011a920110216040527fffffffff000000010000000000000000000000010000000000000000000000546060527fffffffff000000010000000000000000000000010000000000000000000000546080526020600060a060006001610100611ac0f2600655600051600755600060005260006020526000604052600060605260006080526020600060a060006001610100611ce5f26008556000516009557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527f73a36436fa98c0fc51a987b95addff4fc9c75bb81bebe4de704dff46e505fb576060527f38e1d909e72e3aa17fbaae010c05f983cf22bc32e8185e753dfaea1ad1ab90ef6080526020600060a06000600161010061197af2600a55600051600b557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527f01fffffffe00000002000000000000000000000001ffffffffffffffffffffff6020527f01fffffffe00000002000000000000000000000001ffffffffffffffffffffff6040527f33564af2e42df9370e250b21edd1008473a5b1949296e746d3748b2bc41003c06060527f5b9c6cf0c4700189db47f7b04d8797e0e081455ddc17dc4a138bfe67932356186080526020600060a0600061010061197ffa600c55600051600d557f8d4159e7e3803d936acee7d4612c733ac930b2fb51f6174ac35de8f39ee534036000527f9f6469e303a270c1cf5086bdb94ffa1302bdcba38e064aa3ec68172b6cdd81a66020527fe5370d64927b00b5108dd7dca14a43ba347ef449ddb21817a3c11a8bed8088436040527f45522722aa893c41562916d31cc615d400da709ef10584642286833ce28ef7cb6060527ff2ffbe167212bf8d3259f185ace7398c2ac93afef5afb18d6b54adfcbc6f42116080526020600060a06000610100611c0efa600e55600051600f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611c52f26010556000516011557f1171c00fee29e1938e2a6b6f34e9197442dd80d7199a6c10d35237168f36c3506000527fc2402ac2e231e03da69f462f2e5e6be072787a8991672df9ff14679bdd0700ec6020527f63a862c6560c083a6d23336744366d42c66ca9a4b4190cc5d71eb3b666ebdbad6040527fd05f4d1319607b3d6b7a3312a68dd20f137cde4cae15d980c17633597984ef086060527fc325a6b95842461aa3b5c3498d64193ed54e02f57f0be0537242a66a68b5ab646080526020600060a060006000610100611a4bf16012556000516013557fbda6b6b71c43a35a2143ed305ef881ff6517885a2b2bdb3f552af2367f692a846000527f76db0519ff4b38d2dc0d66547b4108b9048cf323d4dd0eb0abcd6fb83e21b56f6020527f204ca45c158b1eccdb890e200e477755770d4b8f1e3b8a36cb8a7357befb64f36040527f457db2bda9a5ca9b5593e485b1f4bfd82dd3a951c4b63b517151fe491589afa16060527f7b14407d90693d5b3e7b7b7cb0b64d372190d7a66ae8b0b513355c330717923f6080526020600060a06000610100611a12f46014556000516015557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000526fffffffff80000000600000002fffffff6020526fffffffff80000000600000002fffffff6040526fffffffff8000000060000000300000006060526fffffffff8000000060000000300000006080526020600060a060006000610100611cdef26016556000516017557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fcd3fc77ee4012b5c4a1b53c5505eb714ee8ed5cd87dd8b73eb6f0d49dcaf4e7c6060527fbc3dc47c6bd4ef0ef3884db62acd5869593b03b899a242f1c6d7cb9735da242d6080526020600060a060006101006119b2f46018556000516019557ffc4aa970a0e7b17c095b40b850ceded317761a1a16147e214ccaa96d9ee14f266000527fcb00f4ebd745a67a7c4a55a4bef1454967bd2de0d81c83c834c6731e8e317b126020527f972603641d77617c5b93acf08c51db4c7b4422d0819ff38df9cc3d0c21e949636040527f882de2caeb49647cab0bcc63f06360c7f8b0ebb146e7cf9d6eaf103f65c825c56060527ff286e0e711e69166f764ddc113afa12d7161be84a40f80c0e6089b96c606f3526080526020600060a06000610100611c87f4601a55600051601b557f6d6682250096f33214278016bb1b507795293e4e0dd283f3ab83b795c4a9bd396000527fe100ec27eb368f3463b3a786e77984d1acf9840e4e092fac95b0a34a588a55de6020527f770fe499ff9ece0cd34a38b1b0689749b64e3f5cac291131ac7da89609b182b76040527f4bb791d72d7eb44f291d53f70d52231fd15f5bb4870e21b0c4f6b67c314ea2716060527f0960e09df623eaf10d78118c9a145cf266d44c838c02fbf28b223593b9c7baba6080526020600060a060006101006119c1fa601c55600051601d55600060005260006020526000604052600060605260006080526020600060a0600061010061196ffa601e55600051601f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a06000610100611bd2f46020556000516021557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fd2afb235f5597e2aee0408594b854a67f0e4975710114a3f5496ef4d96f9b5006060527f75c614dd29c2c3803c76e5a6de4c63139668f8e380a4ffb98fe2e1a6654a9e786080526020600060a06000610100611ce0f46022556000516023557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b91fa6024556000516025557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f89c6d5fdbbaa7c407fa80fb9cdac80a029fcb4f8ee2304f1312ecccdbb1e41ea6060527fca4ecc2889086480a754452c08cec711cd805c63200655f021bc418da89eb71b6080526020600060a06000610100611b48fa6026556000516027557f8e9dc16c462acf426681e70f761fea49dfef131264f9b0669577fcfdd70f2ba76000527f751dfbc62bd426e8511df1a12bbac73d5de7dedea04fd75cac1a59e948b323ae6020527f5414ab14f228830c07a2c7ce94922fa4c78a43bd7a45d74f15fee7d8836211536040527f175d1de0e00e6f26f7b487d3ffaf8fff9fc6df7839dae9e6e70c708fb692bbf76060527f86c7248ef0667b8977a8bd67594ae4dcd371541d2091567f7d84a7d4bb99b9266080526020600060a06000600061010061197af16028556000516029557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f0f4ba6ac4a0370f9c52d177f52e5fed8f8e0732b342b804596904879dc2220946060527f58ecd351bc27ca231233fb4412e1cf7023886e2b97e1e983459f3ff6da79479e6080526020600060a06000610100611b4bf4602a55600051602b557fbda369cd0602201df26b907dcb52b6a024645f509dd784cc175defdf009ee2936000527f9e5f40b672050788563557bb58931bdd7144f959a52ee1b58d36934825c50e5f6020527ffc4dbd3dee137e5e000cee5fa85efaa40a924b04465d0cdd0c289b472df6502d6040527feb63f70b39bb575552c38831324f4b8694b9b2d3340e39eb3136e12b94d251e16060527f4d3d300f9b1904f1482fcce852285fd861108b67d5eca18993a2c009e08e98fa6080526020600060a060006001610100611ba9f2602c55600051602d557f9094a45689e1f3cfd0bc968b521cd96d091f0d224e0a5fbae7bdab98c16c65276000527f932998a71fbe19159a57f33ab2d599721cb95deab14045707752698d700631156020527f6aabdd3f95e53a8066b3ece600ca962e57c12da74850196abc0ef9eeda6d11e26040527f1a6f7d6c7fb2ffb638b0d851de935c20cd472fef92327ff6205c903b426592186060527f0fb87b1c13bb67755816f4b4b02a7a39137878dc92b9ee676df9e13da2e853fd6080526020600060a06000610100611c84f4602e55600051602f557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f0537ccb278355352e685946c9163e32ac76c72dce7ea05da8e4078dc6589393d6020527f0537ccb278355352e685946c9163e32ac76c72dce7ea05da8e4078dc6589393d6040527f01fffffffe0000000200000000000000000000000200000000000000000000006060527f01fffffffe0000000200000000000000000000000200000000000000000000006080526020600060a060006000610100611a32f2603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xAC364Fe8a53B3B06E4ffc43a61e6b6aE111F8B60": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x1a99c1ffc59d50b72111e84f5d61d63204cd7d7e8b6ce298d4a90852322615e2", + "storage": {} + }, + "0xB02727BF3c9593eb8eDF26697507d3d02ADf188d": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xabe2b602ab377c7797019f012a0e5eac45892762493a745125435d1f1969fc8d", + "storage": {} + }, + "0xB9f155f6BD269F51899d0fd3Fc7457195caAC6d4": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xd8202e39fbc64c17d1fdd7dfde35c6ac6a6048407cca837f85cf3a92a054b6ee", + "storage": {} + }, + "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": { + "balance": "0x989680", + "code": "0x7f1e3ec63b030c7721b195943c9e930fd54a2243b19a6b8f02ccb4d36de4f51cfa6000527f0846ca5cee09fdaa635a885d1bfbdb0fbb95c8ea3b5cc13a480c18459f58ea466020527f07ed8d82547c81a477a07ce6e3c2ab2f2fe9e4722f5605a1dd11b1d9decc37586040527f0c171f4c23860fcf50b25e53dac759e220cf16285be0f41d823131f2d0cc59f9606052604060006080600060067f1deffa299c37fcd9de705bd75c6ae69fd020d9a1b71ffca3a342363f85644ef7f4600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xD57b4cd1835F4e135762235a065aA1F4EEE18fB2": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xbe7e199e4f874aec32866370704d58651fd0b7254c5df2d0cd5e3482475a47c0", + "storage": {} + }, + "0xD74CFe323387aE2fd070CD046173026716D8D649": { + "balance": "0x989680", + "code": "0x7f011d81e0f48f2e0a4ec52fbd74772f1d3ffd13e39941dc2be3734bc8120495646000527f09328d03a44d267cbd550663d7ef3ebd8e8eba55e9e08165066890393d6b7aa86020527f13a01bed25f2ebc06b2cbdc4ccbebaf1f8baf4eeb7dc09a92ff5a4bbe25b29a76040527f90cb218380878d54b59a327fba1dc57c9554fa98a51a67c00acd773b2a7aa3aa6060527fce7c256d67b551be7e15626d7c2b8af5b40a61ecafbdce9a1ac030e5ce7c4d0f6080527fef6e10a89e0b4a03ac19f1f3dfaed522841d37e427e7478d598bb60a7ac53f0a60a0526040600060c060006000600a7fb72daca576fbf03d76c0b31da23b0686ca502ef473f7257e68b9612642f56eb1f1600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": { + "balance": "0x989680", + "code": "0x60006000526000602052600060405260006060526020600060806000600161cd15f46000556000516001557f43d1c02f84f79ae1492e9d2b89ab0fc9c103b392014bc60e1f173dc2a0d1fcd16000527fd414fa0aa72304bb922aa543cad14c25d2e4628cc5dd8d4cf81654e930c1551d6020527f6a3e96376126e8d3213e473f976810ff99a400fb7dced848459d5819a2ee6c3d6040527f1b3d6f19413e4bdef71bf5e03f0f25f47e6a7cf4fed7c2e89c4e5c01b486530160605260206000608060006000600162013eabf16002556000516003557f9906fc552d3ec01e0b96f107dd7dbcc884d10916865d2b483dbc35bb38fe0e996000527fd0b61eabc3c8fdfb793f5637eda97b84fad76f65dfdb26fdecefef2b65c5241b60205260006040527f1bc98b07747845577aea1c943af100df8b2d6917ecb9a1900d366713e6dc21fb6060526020600060806000600161ce70f46004556000516005557f180bf3f60fbc13743779da4dbee67b9fb0a63a819247264d1e961c12072f883a6000527fbb7b0b8c1ba91b810339f399b0740d77465bedeb824ab54f3fc47c579960ba1c6020527f64bf56ba321a655d7303c3cd42f07d3690bb7f70fe3fe04da89e4a617314dbe16040527fffff5f62bbe5ce1a329e700125d900cc88904616ec42ed8c92402ac49a7e97ae6060526020600060806000600161b052f46006556000516007557f8e19a52298f25ab5e498d779c824d5e5f9a82349543ae1775f3f19cd9e7dddaa6000527fb1336383b66a81ccf29284e94cd334f2d2af7c15295f540d2b3179178c05bde86020527f13444f6f7c48837047f68dfde90b784979d5c6a48e811f99552df2cc59f5d29c6040527f704cec5b3329e7229764e23af1de861f1a21e9c7a7aa1f4d79061a05d36a0c4160605260206000608060006001619dd4f46008556000516009557f5ea7f56c36e9e4c0522b1f5a2431991a21e4bbb6b577e907304a3d2391fef00c6000527f6ca40332b424d7bb466b25be0125685eecccad4fc76a32f36177e52a94f7741b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f12e8c58a0d25d7d3b8e54a1d2351692154176fb53aa675696145892159127671606052602060006080600060016132f8f4600a55600051600b556000600052601b6020526001604052600160605260206000608060006000600162013010f1600c55600051600d55600060005260006020526000604052600060605260206000608060006001600161c800f1600e55600051600f557f5eed20e4b3ced00fddb6ae28295dd9f327c822b92d48c8317ab258f7354890ea6000527fba5b5f2f20638cc0ed85c2bf7d5dbef69c7ad41fc63fa2dd95d055133d59631d6020527ff1aa8fe91f95559c861bb9f62234f1f730eee73ad5e5b9414eaec78e4b0911406040527fc33d84f13d192b77c8a6c072207b9a3e212100df63f56cdbbb28e3b8548c870660605260206000608060006000600161b0e2f26010556000516011557f0370ec4cd113a16faa25fb1be5ad2ebb4953a67250f780e0412495c039f004e46000527f5963b02c2c91e0247518a1941341b22e70a27e252ea45dccc4b8c0eb407b581b60205260006040527f33938ddbb7182f02f24dfd6745b0c329cd20da3212b2e3bdac7921a49bc55481606052602060006080600060016170edfa6012556000516013557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f85c283986bc3d889d40819dc1d1b54cd73407be4818d72e52a104b738fdb91fc6040527f7fa53c21bc99e7af078dc6f035377ea7bbdc87559f5940189979693b16822676606052602060006080600060006001611736f16014556000516015557fc56302c5e8354a195485e3071c0fd415eae836ea0b31a43b7a92f20446d8f5b46000527fe4aaabc67a48efd62a65b3bfaa602d36ae5be5bfd89975b00f6e543c81a8a92d6020527fa0fdc4680e1a90dabd5dedde26d1abc0f0682ae7d009b7ff897d5e4022ff6f866040527fcdcc7fb3739c6c85bef9d8ccc82a4d121a3cee7ac43ae9e760f3fa9e8b9583fb606052602060006080600060006001613b6cf16016556000516017557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f4ec33bf7c871488fdce24f7ecf0a8fc010b739ec785fcd3638dca6a377219c5d6040527f14da99b4e79b4645e98051cc3146991dc08a4ae3eaac621a1e40208cf6df710860605260206000608060006000600161c5e4f26018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fab21f62421bb4acf9d252d6da285819ce6bb336f395872f89ebf744435f0c7f56040527f4aa5fa48a4f383446987fbdc957f643e384894228b080d54c1a7cb5c045749856060526020600060806000600161a3dcf4601a55600051601b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f912066e90ec6d7677e6fd8649cbdec3d4055d45dc3dd902745d835200f2a5f826040527f321aeb012e43ef288403416873ce3ded971cdf34df79e96f736b8cf03cbe83b860605260206000608060006000600161ae9af1601c55600051601d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f0d25e1b503d26804d6f732c050c961dbdc7ecc983905a76d583f470f579286186040527f5b73f2b518477c7afe6c5a119b42ead82b47f6e9f3b1de85fde3ad0a1486f8fd6060526020600060806000600161702efa601e55600051601f557f191fee423fb7f9a733c422df7c994b5477d27864589dba7a7fc28e48b8c2b2366000527f997fef11a8a4d589d2bd5a16a377af25e5cbbe813d65809db1e7bff336dcc61b60205260006040527f0b9e657c2b3bc2373a59b95a2bf3cf2306a2cab40b1845a7b33ba8f243ce7c8760605260206000608060006001620146e8fa6020556000516021557f73fc5af59dcce95b2824cf40e1c7e9f977da9f39d54bd4a6de5e69f05eb1aa9d6000527f2c4bf0413d4ce2f0658575771d3285e9f6e3282d6555d8bc86cccdcf86fb681c6020527f07dfbd7899eee43c9c7b0845b36528cc21febe6545aed949b08de39679cae3126040527fffff1f7a9c047f143904f54fc68101d4e35b6c61d1d29b47df3b23c2c51e3eba60605260206000608060006001600161dad5f16022556000516023557f6dce7564da0f627bb73184c062700c46b5fa40e038a26c6a09eee7992e7e77046000527ffae46ed9f1946468fc654e3169a858414c39f3231022971b08a6b9dc9d6024116020527f84e739bef13197615698bdfabfc1b886287b2209d526e0b88b8f55ba85686fcd6040527f2492d934f166e91909ab699d514a7c8945a3c1b2fdfe76a00ed909de0dbc4ccc6060526020600060806000600162016754fa6024556000516025557f25dcd8208d704c68a2751182346d2332b924bfb5f43ff4bb095c84343eed888f6000527f6fe4fd7dbf2d88c709f0e59813a6f58c27e01a1897848daec12d81bc1eefae1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f8fa1ab083edbcf3b8a7de09fd4044ff3e9a11fe374d4b15c65a950e2973acc5460605260206000608060006001600161b1a3f16026556000516027557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f6caa89f589fb21ffb2b20bc89cb3d36db7d98733cc9308d9d2366bf43090091d6040527f6eb4c20a32f3ddeafec7a5bf91ec6c400addc6532ab4af4473433035465cd2b36060526020600060806000600160016139f3f2602855600051602955600060005260006020526000604052600060605260206000608060006000600162014a19f2602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fc2572296cd1fcd3374840b60d4ff9eb33c3298e4e0086147e1e5e58a5cfe504a6040527f544c1008f7d5d111dd146db87a85232dbdc8c77bad357000653fdc2861a35b0360605260206000608060006000600161a5f1f2602c55600051602d557f08fc53f403c7cd48139e619636d480ff67993d8d59b986ca81622b913e224cdc6000527ff5e0393483b02dbe4abdd1121437ea1890c8ce44770700c775411594fece3c1b60205260006040527f0e06d11efa9fc8e458187396b1e1cbcc0b5a29af8755ad270262a9d68f0606d5606052602060006080600060016001611154f2602e55600051602f557f2f8c6555338a6deb90638b65fa8d38a23ac9b5a29c3c0de86607ea580f2dc8406000527fd13d5b86d6e628e20f07808e3d8d3ea9bc09b2b87135f84a5050eba6a71c9c1c6020527f67e38b6c13a0ee8fe9df12ca0e010dab052985ac852d1f107bddf86a78e7e47e6040527fffff4145f42083b2c92ccabe7f2b3b18c183a1d89758ac508242806f53d1807160605260206000608060006001620122dcfa603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": { + "balance": "0x0", + "code": "0x717676767676760000000000760000007600006f121212121212121212121212121212127806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a90097176767676767676767600000076767676767668210000000000000022901411717676767676767676760000007676767676767f7effffff8000000000000000000000000000000000000000d900000000000001901390186085557f82000000000000000000000000000000000000000000000000000000000000007f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe027f7effffff8000000000000000000000000000000000000000d900000000000001717676767676767676760000007676767676769011046086556fdac7fff9ffd9e13226262626262626006823232323232323232390147f82000000000000000000000000000000000000000000000000000000000000007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0901090136fdac7fff9ffd9e1322626262626262600671fffffffffffffff900402682323232323232323237ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200001c1c608755681000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a9016157f40000000fd000000db00000000000000000000000000000000000000000000017f8200000000000000000000000000000000000000000000000000000000000000901b6088557702ffffffffffffffffffffffffffffffffff0000000300007a010900000000000000000000000000000000000000000000000000111868010000000000000000651ce97e1ab91a9001901b7f80000000000000000000000000000000000000000000000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a0260895567800000000000000169010000000000000000000b901c608a557176767676767600000000007600000076000060011767ffffffffffffffff67800000000000000090020360056c0100000000000000000000000007901d7f80000000000000000000000000000000000000000000000000000000000000007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00059006717676767676760000000000760000007600006000017e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007f7effffff800000000000000000000000000200004400000000000000000000017e40000000fd000000db0000000000000000000040000000fd000000db0000d309901b7f80000000000000000000000000000000000000000000000000000000000000027cc9700000000000000000023f00c00014ff00000000000000002230080560070890181a6380000001777effffff80000000000000000000000000000000000080017f80000000000000000000000000000000000000000000000000000000000000000805608b557ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe76fffff716b61616160b0b0b2b0b230b000008010d0a2b000663800000016380000000901190066f8000000000000000000000000000000068232323232323232323901c608c557e40000000fd000000db0000000000000000000040000000fd000000db0000d37ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000090056380000000600068100000000000000000089019901c11608d5560006000f3", + "nonce": "0x0", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000008e": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x000000000000000000000000000000000000000000000000000000000000008f": "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000090": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000091": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000092": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000093": "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x0000000000000000000000000000000000000000000000000000000000000094": "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000095": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000096": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000097": "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000098": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000099": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x000000000000000000000000000000000000000000000000000000000000009a": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x000000000000000000000000000000000000000000000000000000000000009b": "0x000000000000000000000000000000000000000000000000000000000000000e" + } + }, + "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": { + "balance": "0xffffffffff", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "storage": {} + }, + "0xd8C19eFeDe5AC667bcaC98d9E23A7ecDf49174Ab": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xa5d82b3ed5a4c81ecb208ed654c3afe5ff5a47f79737c75b2ca157448e545334", + "storage": {} + }, + "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": { + "balance": "0x989680", + "code": "0x6000496000556001496001556002496002556003496003556004496004556005496005556007496006554a6007556006600855", + "nonce": "0x0", + "storage": {} + }, + "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": { + "balance": "0x989680", + "code": "0x60e360005261020060205260e36040527f68ba69fd3d79033c88699f723b3ce8fc174e29617c0fdf5ca331345cfc88b3956060527f685a1289529ff6e4b8b0484285ab55b3f76dac15363842ec9b2d336b992ea10f6080527f36353ceec362a372703a5cbd12668f037d544cd7c5264f4b268658d99c9db80960a0527f67f2d2ba771a9e1d252660d4152e6b8c1ce1a15ffdc8cd107f44c9c0a7d3f31f60c0527f71a1fc485056395faeb3e337098b3eb579ecd77697bd38b7556d8c634f682e0760e0527f344453774915ee11d19d67019c1ab1cbf96284ebefdce23024b39297c3c86809610100527f0f3fc9fef99f49e7bbcb69512cb677dd0086b428baf1e45e86549109856b1f4a610120527f322173301aa0eb293c7a1a3cf35632d3e42be43b6f8a36b91810ae73fbfea52b610140527fea8823493f7e5e580c92ddd9f0b79a23cf39bb08378429ba4ff8c1c750e59dd8610160527fd83b25754b08bb09b9dad3f96e50bbaa26c21a516c7940b5a8d078e6dab85a9b610180527fceabfd9310faf929caa07eb2c16a5cf3220ad4ba347ce0fe46085d20ba75071c6101a0527f24f6d0eebee5563dbe1e9dbe7e5689c9327c1789ded8138a4be72594f913513d6101c0527fd17fb4869234da5ad1b1cfb239de0786236d865ed2cc386c97cb7fe2a692cf136101e0527f43b98da2bf7162f8e98dd6ee834e94d31db5b2a76894cc91c6f58a5143bb0036610200527f2774108405df680dce4dba7259b45a6db14c441d7804509ea5ede9dddc75223d610220527f96e7ea97d826d2439804598fc7876496be861a6ca50fda1429ee97f3c50aeae0610240527f431d4329971916f7e101455383ead34fb5abe5248acae9647a371fa6bf738cf9610260527ffe3bd91f70c14502003b140401804b9d89802c6a9fed066381650106babb9c3a610280527facccc13cdad040f47b674e9069c1626fade6322831db3e26bee1f4440770ef6e6102a0527f12d04d5e92ab3ba2bf08df17cd2e5b13e4ebfca850d995fae5b365342c16e7796102c0527f0748435c74300793195d4019c4e460346070e707a450ef6eb46c0cdaabacecd96102e0527fafb4c5e73d81081a0ed8969d16ddf0d93b2894302081351f20f428748609b85c610300527fa1136e7dca75863f6344598ba67ea78be7eede3fd603cc272682d41c55b54981610320527f77790a8dadad8b64cf67b4d1c698b3d17abc404e51ffcf26949e3708d03349af610340527f7616852f1e0314560baa48f0f80956faa938efab1743869fa0c40ed1fc187703610360527f0411af79acdc67e00252f798319ceb984f7f938fa5c477e5000deb9c87cdf7a3610380527fdfd48a4eed3f2c68bbe464b128a5692bcbe8404e85cc77067428633fe3ce77fc6103a0527fa923a6709345117ef6665b922f87b32bbddaff432fd51f1aea04c789d495a7636103c0527fbcf7aea7ffc385cf2e2694a1e44181a7106c4bd667959c6e8d3d40eca5c3d7e76103e0527ff55e9dd571ba1201b63ca49bab9e270b451bb49fc5fb30dcfd7c8d55426701636104005260396104205360526104215360556104225360d16104235360e66104245360446104255360e360006104266000600060056301253018f15a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e05160085561012c60005261012c60205261012c6040527f4c13aa7bd89ec1d2c97320c06de11439a3ef9f76f35cbef4a26bdaa531facb886060527fe936ad5a1ff2ae08e306e0675c45b5897bc54bd20ebb7401b8d0bbf7c8d740006080527f6e89c3b9088a0adc7f74bf8d5b78bebb6a608cd96c3d3ff56a2aca44cffb859760a0527f5ef8d2a654c19fd41f23d7154e6d4d39e1f7f83f350b3eeaee406db1cf882fdb60c0527f10582dc1df5ff7a13a5c4da82250077d56b4f3431de716f4140bd06a5f75e8d260e0527fad66636358287940d2e94232ea2849556b2ec8a990e15bcaf0be81232ec49ea1610100527ffdb224be211341222db5e820df4c160a3463e297f9c5dd460b4d0e0212bf25c2610120527f1de01c72fada90d9d23a7b8a3f34a01e3c5ea262f1be04457af21bebbc1b197a610140527f256e0ed7425a4a0ddcf8daabd1ee80e3a9a2b591233b7472521bb4e762e81e3c610160527fc02e02687247389cd723176ff321a468b17b0a9935ddff9fc995864eae74e129610180527f5d1c6e53c08315d8ca820b2da313676a3f607630be87d188154c529b5d98483d6101a0527f8f01e5b864f6406c46d2e6236303538d60a6326bbcd34b27736baf670e5e64906101c0527fbd11741f29b8112c2fd1bfacb8f381818b6b84c3fcc47e228dafe7622fdf5a266101e0527f0ec1be3cb9dbb1aa2ddafbd6839456c0b93ad959d9f032cc072cc4a7f67cf523610200527f7cde68df5a162da4f59c6d125fe25659a3d284949cde9f03e76142cccde98745610220527fcfb60777ffebf9e64be81d40180bea6dc4a5f6336b2b8a13c21df333baf7a2ce610240527f0226d7361c97d87324984f784e53b3494567d268d709630d595ca42f8753125d610260527f831f7f613cc4940a56d74a282a2f158f4ad6eec1b3a540cc4f2e70649eeb2ee6610280527f3f1db47e40ae8bdb42dac89e92e946d18c8dc4762e3d112d9a806f47e5749be16102a0527f30dbc5d2c3454b56123f0cefb0b8409e97d661959987129440081d476b6f6dbd6102c0527f9f959d6ed8f803e00cada84448dd3afa609dfff3b0536748ca0ec3b14be0ad936102e0527f04f126df3fe3b3f230519fce73d16706e0941891db3281f3859bc57f18c55f0e610300527fafdb95645eb77981cd68bd03e9fdb3bbb9edcb8e7995a1ab87c55c17dc7110e8610320527f38f6bc0d087f7348be687868f26e7c2ce8063f1e1785a1e8522959a21855b799610340527ff498e688264e826b3e2d34f0778b61afd62977d5e711976224a9ee3bb0cae3d9610360527f90e914d74e9d5366ef98fe6ad24437b59e9f026b8c098fbf61413149cd501b60610380527fd12b58e018d6c64acf92bcbd311784ff44446d651bd1ff78f5193da46abaa62d6103a0527fd7183b49e5f51ac4cb8d35b0bb50d90bbadbc0a91c98998fb1ad5a2b2b0a3bf96103c05260326103e05360f46103e15360826103e25360026103e35361012c60006103e460006000600563010a4374f15a01600955600051600a55602051600b55604051600c55606051600d55608051600e5560a051600f5560c05160105560e0516011556101005160125561012051601355", + "nonce": "0x0", + "storage": {} + } + }, + "chainId": 1, + "env": { + "currentBaseFee": "0xa", + "currentBlobGasUsed": "0x20000", + "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000", + "currentDifficulty": "0x20000", + "currentExcessBlobGas": "0x80000", + "currentGasLimit": "0x11e1a300", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8" + }, + "fork": "Osaka", + "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f", + "transactions": [ + { + "data": "0x", + "from": "0xD57b4cd1835F4e135762235a065aA1F4EEE18fB2", + "gas": "0xf42400", + "gasPrice": "0x20", + "nonce": 0, + "to": "0x538A8474EeaB43d5a960164c554A20400151D479", + "value": "0xeb4e32" + }, + { + "blobVersionedHashes": [ + "0x0151232cf675c935ef391b8fd558a10e093eb25d5e78fe6170c1f8ce23b06e17", + "0x01bfc9c4e99a03f3708fd387e97733f3c5b2a65e459587674598eda695b354b0", + "0x015a37c0077673cf8aeaa690fefed9714b00490c5c45dc43ad4990256f744250", + "0x017effe0e39459c4c2c9e96b0e1ccc963179783ba07f37e28c9ea3588c24b80a", + "0x015051974a4f040fa74fde7e1f10a3caa0958210540822e965dca0cc089421de", + "0x0136aab88a6300af782af468b9dbd33a5e7f09dd88c940c7e8bc9696351a2396" + ], + "data": "0xb8a1", + "from": "0x91D1D8f382B0EE7F1c8E2a19934487D80A469695", + "gas": "0xf42400", + "maxFeePerBlobGas": "0x100", + "maxFeePerGas": "0x20", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "sidecar": { + "blobs": 6, + "commitments": 6, + "proofs": 6 + }, + "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89", + "type": "0x3", + "value": "0x0" + }, + { + "data": "0x979ef803f86d8da0b051f1c1978a54f1f249e777afe349bde7784af3af3736a1cf6427992bf070b8b3237445a46c46c0", + "from": "0xB9f155f6BD269F51899d0fd3Fc7457195caAC6d4", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce", + "value": "0xf6d8" + }, + { + "data": "0x234f36b00b899acd82ee47db9ee3eacb23dfa61b9692c8fa886079a4cc27a4ec89c56555cdcbb295e6aaf676bb35a74e2660bca16010", + "from": "0xB02727BF3c9593eb8eDF26697507d3d02ADf188d", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10", + "value": "0x57" + }, + { + "data": "0xa16b5f3897ee5da10daf1d2482cd3d61f3acd4e947b01f8e646aecd279", + "from": "0x8b632B705a6Ab4ee30e08eD21A0AEE1C3b6583B8", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3", + "value": "0x9993" + }, + { + "data": "0x5c1f04f49b87fba351403d18f62492f20fa63c360685451c204c39496b48757ccd9e4b286bf9150936c0107298861c5f87343a0c638efcfd30d06b69906fa2a572d9fb3b019659ddc85daa806cd5f9a9bde5889720800a7d1ad910c9d5c08be332af0816a2f03512f0e4af7338eea9409a415c9a92a310cd70dbdebc32bc590642bc5437f9bed555c5afa58252ef0433", + "from": "0xD57b4cd1835F4e135762235a065aA1F4EEE18fB2", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb", + "value": "0xe4" + }, + { + "data": "0x02a401377e008d7264913d4b8f133df0bf2fe023635467aff9b5b2b7fb87ee092248f6e94051377206c0ac69fb01ea0662e1f8642d017a58d0", + "from": "0x91D1D8f382B0EE7F1c8E2a19934487D80A469695", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f", + "value": "0x6e6593" + }, + { + "data": "0x6c", + "from": "0xB9f155f6BD269F51899d0fd3Fc7457195caAC6d4", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xD74CFe323387aE2fd070CD046173026716D8D649", + "value": "0x0" + }, + { + "data": "0x", + "from": "0xB02727BF3c9593eb8eDF26697507d3d02ADf188d", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6", + "value": "0x0" + }, + { + "data": "0x8c8c7d9be0d21bb7e20e11cdf09d9bab1f7afb0acbe01c2c7208d5d61975c330918b75aa79b0bd7ada434555a16755e14cbcf4bae04220c84caf7a01cad4856a", + "from": "0x8b632B705a6Ab4ee30e08eD21A0AEE1C3b6583B8", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F", + "value": "0x34" + }, + { + "data": "0xa1a576ba71d1586c137ffbf26a64a0f08839c904930a3ccdd5fb49a22bfdeae09fd83fe4205d3d81f6d5347a416e9dbe1a01845aaebf4bfd54f441d02d1245", + "from": "0xD57b4cd1835F4e135762235a065aA1F4EEE18fB2", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190", + "value": "0xb6" + }, + { + "data": "0xeb4d46c8676782f9a0e27952006dade15be39bfcd5e93b473bec8286c82129e97a95df024b8ac429c3a12675fa5d33f5bd0368ee51954e118f45bbe0d5c75e0f14511626e3cec36f8a0fea34debb42f4ad3b", + "from": "0x91D1D8f382B0EE7F1c8E2a19934487D80A469695", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d", + "value": "0x2586" + }, + { + "data": "0x37fbd9d422a2d3b07bdd02651e16a09771aed6a8afadded3fe3554b8e93812ee89bc1934160eb425798dfb23a67a07d6253bf4ef552a8047a43e6c0afcfc0d59611e445f59284029ea0185197b1b68c34695af3ae1596bb7260ab1f9ffcbda973774c9", + "from": "0xB9f155f6BD269F51899d0fd3Fc7457195caAC6d4", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c", + "value": "0x0" + }, + { + "data": "0xf079043fb1e333119c9f37c0da1e7c37afaa7bd4f0a48cc4c13dfa7b0f1fdad73b5b9e0693640d461ef391412d33458c44b23b59ebf9209b43fe85fdbedb04e99fa64b", + "from": "0xB02727BF3c9593eb8eDF26697507d3d02ADf188d", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876", + "value": "0x2a25" + }, + { + "authorizationList": [ + { + "address": "0x00000000000000000000000000000000000000f6", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x7c48536e23d335550aeafe4c1a83a723d065f2e5b3a5ee92a511407047864475", + "s": "0x205759410d303ec597e2dc6393fd16b9fdc3822b291964ffc8ce0b38d37443ff", + "v": "0x1" + }, + { + "address": "0x00000000000000000000000000000000000000f4", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x54c674400688f718ee9e00c2c3a55d381086f0b5c02a1c4f858a7163fe894f00", + "s": "0x4cfd634ceaa675a52cb1d7ca3ad14ca67c6655e807fb31b4a4594ba92878a697", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000008", + "chainId": "0x0", + "nonce": "0x1", + "r": "0xc6956404e7cf31ffbeeb302279839736467b40fb83017c2b2541dac5e31f691a", + "s": "0x4d92016e2691de9b91edb8b4164b729d285e88d1189b9fb7cac1a100464a4d94", + "v": "0x0" + }, + { + "address": "0x1563915e194d8cfba1943570603f7606a3115508", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x9f7853fc3910422af738e43f0cdfca99e563e26c8191674ff73e451bdb76f920", + "s": "0x74296c8652d2063bdc5babf2f29d407eecbd33cbbc64039487c464d48b0be33a", + "v": "0x0" + }, + { + "address": "0x0000000000000000000000000000000000000002", + "chainId": "0x0", + "nonce": "0x2", + "r": "0x661803e8303b235dd6c107384ea9de0b00bc66c64ebce4eb656a4f5b2c9d18f1", + "s": "0x2b034a6129d8e3a6e719bd58cc085c355e8cb14ce9c77566bd430c4fa56b6877", + "v": "0x0" + }, + { + "address": "0x8fd379246834eac74b8419ffda202cf8051f7a03", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x66dccffe43cd270b38a7e7f384e73e48f305ff9eb08795b67b0a98760321116a", + "s": "0x6a55044bdaea2aa0b6231b536dff7844907538f69cebaa0fd94c50702f883c58", + "v": "0x0" + } + ], + "data": "0xc159", + "from": "0xd8C19eFeDe5AC667bcaC98d9E23A7ecDf49174Ab", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x0000000000000000000000000000000000000010", + "type": "0x4", + "value": "0x8e" + }, + { + "data": "0x00", + "from": "0x23957dB27fD43F125fee8eB0a2Be85F1FC39Fa74", + "gas": "0x30d40", + "maxFeePerGas": "0x1e", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "to": "0x00000000000000000000000000000000000000f6", + "type": "0x2", + "value": "0x3e8" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x1", + "nonce": "0x2", + "r": "0xb8ddf540ae2c650211ff9615477d69061db710b2b73a527a8f5d3e9cebfee5e7", + "s": "0x77a01c72961d20542f9ebfb2169fd30fb798f730e95636dd0d904cc62b93de80", + "v": "0x0" + } + ], + "data": "0xc159", + "from": "0xAC364Fe8a53B3B06E4ffc43a61e6b6aE111F8B60", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x0000000000000000000000000000000000000010", + "type": "0x4", + "value": "0x8e" + } + ], + "version": "2.0" +} \ No newline at end of file diff --git a/cli/fuzzer_bridge/models.py b/cli/fuzzer_bridge/models.py new file mode 100644 index 0000000000..925d24edac --- /dev/null +++ b/cli/fuzzer_bridge/models.py @@ -0,0 +1,121 @@ +""" +Pydantic models for fuzzer output format v2. + +This module defines Data Transfer Objects (DTOs) for parsing +fuzzer output. These DTOs are intentionally separate from EEST +domain models (Transaction, Account) to maintain clean separation +between external data format and internal representation. + +Design Principle: +- DTOs (this file): Parse external JSON-RPC standard format +- Domain Models (EEST): Internal test generation logic +- Converter (converter.py): Explicit transformation between the two +""" + +from typing import Dict, List + +from pydantic import BaseModel, Field + +from ethereum_test_base_types import AccessList, Address, Bytes, CamelModel, Hash, HexNumber +from ethereum_test_forks import Fork +from ethereum_test_types import Environment + + +class FuzzerAccountInput(BaseModel): + """ + Raw account data from fuzzer output. + + This is a DTO that accepts fuzzer's JSON format without triggering + EEST's Account validation logic or defaults. + """ + + balance: HexNumber + nonce: HexNumber = HexNumber(0) + code: Bytes = Bytes(b"") + storage: Dict[HexNumber, HexNumber] = Field(default_factory=dict) + private_key: Hash | None = Field(None, alias="privateKey") + + class Config: + """Pydantic configuration.""" + + populate_by_name = True + + +class FuzzerAuthorizationInput(BaseModel): + """ + Raw authorization tuple from fuzzer output (EIP-7702). + + Accepts fuzzer's camelCase JSON format. + """ + + chain_id: HexNumber = Field(..., alias="chainId") + address: Address + nonce: HexNumber + v: HexNumber # yParity + r: HexNumber + s: HexNumber + + class Config: + """Pydantic configuration.""" + + populate_by_name = True + + +class FuzzerTransactionInput(BaseModel): + """ + Raw transaction data from fuzzer output. + + This is a DTO that accepts standard Ethereum JSON-RPC transaction format + without triggering EEST's Transaction.model_post_init logic. + + Key differences from EEST Transaction: + - Uses "gas" not "gas_limit" (JSON-RPC standard) + - Uses "data" not "input" (JSON-RPC standard) + - Uses "from" not "sender" (JSON-RPC standard) + - No automatic TestAddress injection + - No automatic transaction type detection + - No automatic signature handling + """ + + from_: Address = Field(..., alias="from") + to: Address | None = None + gas: HexNumber # Will be mapped to gas_limit in converter + gas_price: HexNumber | None = Field(None, alias="gasPrice") + max_fee_per_gas: HexNumber | None = Field(None, alias="maxFeePerGas") + max_priority_fee_per_gas: HexNumber | None = Field(None, alias="maxPriorityFeePerGas") + nonce: HexNumber + data: Bytes = Bytes(b"") # Will be mapped to data/input in converter + value: HexNumber = HexNumber(0) + access_list: List[AccessList] | None = Field(None, alias="accessList") + blob_versioned_hashes: List[Hash] | None = Field(None, alias="blobVersionedHashes") + max_fee_per_blob_gas: HexNumber | None = Field(None, alias="maxFeePerBlobGas") + authorization_list: List[FuzzerAuthorizationInput] | None = Field( + None, alias="authorizationList" + ) + + class Config: + """Pydantic configuration.""" + + populate_by_name = True + + +class FuzzerOutput(CamelModel): + """ + Main fuzzer output format v2. + + This is the top-level DTO that parses the complete fuzzer + output JSON. It uses pure DTOs (FuzzerAccountInput, + FuzzerTransactionInput) to avoid triggering EEST domain + model logic during parsing. + + After parsing, the converter will transform these DTOs into + EEST domain models. + """ + + version: str = Field(..., pattern="^2\\.0$") + fork: Fork + chain_id: HexNumber = Field(HexNumber(1)) + accounts: Dict[Address, FuzzerAccountInput] + transactions: List[FuzzerTransactionInput] + env: Environment + parent_beacon_block_root: Hash | None = None diff --git a/cli/fuzzer_bridge/performance_utils.py b/cli/fuzzer_bridge/performance_utils.py new file mode 100644 index 0000000000..e64e44921a --- /dev/null +++ b/cli/fuzzer_bridge/performance_utils.py @@ -0,0 +1,153 @@ +"""Performance utilities for fuzzer bridge processing.""" + +import json +import mmap +import os +from functools import lru_cache +from pathlib import Path +from typing import Any, Dict, List, Optional + +try: + import orjson # type: ignore # Fast JSON library (optional dependency) + + HAS_ORJSON = True +except ImportError: + HAS_ORJSON = False + + +class FastJSONHandler: + """Fast JSON operations using memory-mapped files and optimized parsing.""" + + @staticmethod + def load_json_mmap(file_path: Path) -> Dict[str, Any]: + """Load JSON using memory-mapped file for better I/O performance.""" + with open(file_path, "r+b") as f: + # Memory-map the file + with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mmapped_file: + # Read the entire content at once + content = mmapped_file.read() + if HAS_ORJSON: + return orjson.loads(content) + else: + # Fallback to standard json + return json.loads(content.decode("utf-8")) + + @staticmethod + def dump_json_fast(data: Dict[str, Any], file_path: Path, pretty: bool = False) -> None: + """Dump JSON using optimized serialization.""" + if HAS_ORJSON: + # Use orjson for faster serialization + if pretty: + content = orjson.dumps(data, option=orjson.OPT_INDENT_2) + else: + content = orjson.dumps(data) + with open(file_path, "wb") as f: + f.write(content) + else: + # Fallback to standard json + with open(file_path, "w") as f: + if pretty: + json.dump(data, f, indent=2) + else: + json.dump(data, f) + + +class BatchProcessor: + """Optimized batch processing utilities.""" + + @staticmethod + def calculate_optimal_batch_size(file_count: int, num_workers: int) -> int: + """Calculate optimal batch size based on file count and workers.""" + # Aim for at least 4 batches per worker for better load balancing + # But not too small to avoid overhead + min_batch_size = 5 + ideal_batches_per_worker = 4 + + ideal_batch_size = max( + min_batch_size, file_count // (num_workers * ideal_batches_per_worker) + ) + + # Adjust for very large file counts + if file_count > 10000: + # Larger batches for many files to reduce overhead + ideal_batch_size = max(50, ideal_batch_size) + elif file_count < 100: + # Smaller batches for few files to maximize parallelism + ideal_batch_size = max(1, file_count // (num_workers * 2)) + + return ideal_batch_size + + @staticmethod + def calculate_optimal_workers(file_count: int) -> int: + """Calculate optimal number of workers for processing.""" + cpu_count = os.cpu_count() or 4 + + # Scale workers based on file count + if file_count < 10: + return 1 # Sequential for very small workloads + elif file_count < 50: + return min(2, cpu_count) + elif file_count < 200: + return min(4, cpu_count) + elif file_count < 1000: + return min(cpu_count, 8) + else: + # For large file counts, use all available CPUs but cap at 16 + return min(cpu_count, 16) + + +@lru_cache(maxsize=128) +def cached_fork_lookup(fork_name: str) -> Optional[Any]: + """Cache fork lookups to avoid repeated module imports.""" + try: + import ethereum_test_forks + + return getattr(ethereum_test_forks, fork_name, None) + except (ImportError, AttributeError): + return None + + +class ParallelProgressTracker: + """Thread-safe progress tracking for parallel processing.""" + + def __init__(self, total: int): + """Initialize progress tracker.""" + from threading import Lock + + self.total = total + self.completed = 0 + self.errors = 0 + self.lock = Lock() + + def update(self, success: int = 0, error: int = 0) -> tuple[int, int]: + """Update progress counters thread-safely.""" + with self.lock: + self.completed += success + self.errors += error + return self.completed, self.errors + + def get_stats(self) -> tuple[int, int, int]: + """Get current statistics.""" + with self.lock: + return self.completed, self.errors, self.total + + +# Memory pool for reusing buffers +class BufferPool: + """Reusable buffer pool to reduce memory allocations.""" + + def __init__(self, buffer_size: int = 1024 * 1024): # 1MB default + """Initialize buffer pool.""" + self.buffer_size = buffer_size + self.buffers: List[bytearray] = [] + + def get_buffer(self) -> bytearray: + """Get a buffer from pool or create new one.""" + if self.buffers: + return self.buffers.pop() + return bytearray(self.buffer_size) + + def return_buffer(self, buffer: bytearray) -> None: + """Return buffer to pool for reuse.""" + if len(buffer) == self.buffer_size: + self.buffers.append(buffer) diff --git a/cli/fuzzer_bridge/production_test.py b/cli/fuzzer_bridge/production_test.py new file mode 100644 index 0000000000..d2d2a416f5 --- /dev/null +++ b/cli/fuzzer_bridge/production_test.py @@ -0,0 +1,364 @@ +#!/usr/bin/env python +""" +Production-ready test suite for fuzzer bridge with geth verification. + +This script: +1. Loads fuzzer output +2. Converts to blockchain test +3. Generates fixtures +4. Verifies with go-ethereum +5. Reports comprehensive results +""" + +import argparse +import json +import subprocess +import sys +import tempfile +import time +from pathlib import Path +from typing import Any, Dict, List, Optional + +# Add parent directory to path for imports +sys.path.insert(0, str(Path(__file__).parent.parent.parent)) + +from ethereum_clis import GethTransitionTool +from ethereum_test_fixtures.blockchain import BlockchainFixture +from ethereum_test_specs.blockchain import BlockchainTest +from ethereum_test_tools import ( + Account, + Address, + Alloc, + Block, + Environment, + Transaction, +) + + +class FuzzerBridge: + """Production-ready fuzzer bridge with validation and verification.""" + + def __init__( + self, t8n_path: Optional[str] = None, verbose: bool = False, keep_fixtures: bool = False + ): + """Initialize bridge with optional transition tool path.""" + self.t8n = GethTransitionTool(binary=Path(t8n_path) if t8n_path else None) + self.verbose = verbose + self.keep_fixtures = keep_fixtures + self.stats: Dict[str, Any] = { + "tests_generated": 0, + "tests_passed": 0, + "tests_failed": 0, + "validation_errors": [], + } + + def validate_fuzzer_output(self, data: Dict[str, Any]) -> List[str]: + """Validate fuzzer output format and return list of errors.""" + errors = [] + + # Check version + version = data.get("version", "1.0") + if version != "2.0": + errors.append(f"Unsupported version {version}, expected 2.0") + + # Check required fields + required_fields = ["accounts", "transactions", "env", "fork", "chainId"] + for field in required_fields: + if field not in data: + errors.append(f"Missing required field: {field}") + + # Validate accounts with transactions have private keys + if "accounts" in data and "transactions" in data: + senders = set() + for tx in data["transactions"]: + sender = tx.get("from") or tx.get("sender") + if sender: + senders.add(sender) + + for sender in senders: + if sender not in data["accounts"]: + errors.append(f"Sender {sender} not in accounts") + elif "privateKey" not in data["accounts"][sender]: + errors.append(f"No private key for sender {sender}") + else: + # Validate private key matches address + if not self._validate_key_address( + data["accounts"][sender]["privateKey"], sender + ): + errors.append(f"Private key doesn't match address {sender}") + + return errors + + def _validate_key_address(self, private_key: str, expected_address: str) -> bool: + """Validate that private key generates expected address.""" + try: + from ethereum_test_types import EOA + + eoa = EOA(key=private_key) + # EOA class returns the address directly via str() + return str(eoa).lower() == expected_address.lower() + except Exception: + return False + + def convert_to_test(self, fuzzer_data: Dict[str, Any]) -> Dict[str, Any]: + """Convert fuzzer output to test parameters.""" + # Validate first + errors = self.validate_fuzzer_output(fuzzer_data) + if errors: + raise ValueError("Validation failed:\n" + "\n".join(errors)) + + # Build pre-state + pre_state = Alloc() + private_keys = {} + + for addr_str, account_data in fuzzer_data["accounts"].items(): + addr = Address(addr_str) + + if "privateKey" in account_data: + private_keys[addr_str] = account_data["privateKey"] + + pre_state[addr] = Account( + balance=int(account_data.get("balance", "0x0"), 16), + nonce=int(account_data.get("nonce", "0x0"), 16), + code=account_data.get("code", ""), + storage=account_data.get("storage", {}), + ) + + # Create genesis environment (block 0) + env_data = fuzzer_data["env"] + genesis_env = Environment( + fee_recipient=Address(env_data.get("currentCoinbase")), + difficulty=0, # Post-merge + gas_limit=int(env_data.get("currentGasLimit", "0x1000000"), 16), + number=0, # Genesis is block 0 + timestamp=int(env_data.get("currentTimestamp", "0x1000"), 16) - 12, + base_fee_per_gas=int(env_data.get("currentBaseFee", "0x7"), 16), + ) + + # Block 1 environment overrides + block1_env = { + "timestamp": int(env_data.get("currentTimestamp", "0x1000"), 16), + "fee_recipient": Address(env_data.get("currentCoinbase")), + } + + # Create transactions + txs = [] + for tx_data in fuzzer_data["transactions"]: + sender_addr = tx_data.get("from") or tx_data.get("sender") + secret_key = private_keys[sender_addr] + + txs.append( + Transaction( + to=Address(tx_data["to"]) if tx_data.get("to") else None, + value=int(tx_data.get("value", "0x0"), 16), + gas_limit=int(tx_data.get("gas", "0x5208"), 16), + gas_price=int(tx_data.get("gasPrice", "0x1"), 16), + nonce=int(tx_data.get("nonce", "0x0"), 16), + data=bytes.fromhex(tx_data.get("data", "0x")[2:]) + if tx_data.get("data", "0x") != "0x" + else b"", + secret_key=secret_key, + ) + ) + + # Create block + block = Block(txs=txs, **block1_env) + + return { + "genesis_environment": genesis_env, + "pre": pre_state, + "post": {}, + "blocks": [block], + "chain_id": fuzzer_data.get("chainId", 1), + "fork": fuzzer_data.get("fork", "Prague"), + } + + def generate_fixture(self, test_params: Dict[str, Any]) -> Dict[str, Any]: + """Generate blockchain test fixture.""" + # Get fork + from ethereum_test_forks import Cancun, Osaka, Prague, Shanghai + + fork_map = {"Osaka": Osaka, "Prague": Prague, "Shanghai": Shanghai, "Cancun": Cancun} + fork = fork_map.get(test_params["fork"], Prague) + + # Create test + test = BlockchainTest( + genesis_environment=test_params["genesis_environment"], + pre=test_params["pre"], + post=test_params["post"], + blocks=test_params["blocks"], + chain_id=test_params["chain_id"], + ) + + # Generate fixture + fixture = test.generate( + t8n=self.t8n, + fork=fork, + fixture_format=BlockchainFixture, + ) + + self.stats["tests_generated"] += 1 + + return fixture.model_dump(exclude_none=True, by_alias=True) + + def verify_with_geth( + self, fixture: Dict[str, Any], geth_path: str, test_name: str = "test" + ) -> Dict[str, Any]: + """Verify fixture with go-ethereum evm tool.""" + # Write fixture to temp file + with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f: + json.dump({test_name: fixture}, f, indent=2) + fixture_path = f.name + + try: + # Run geth blocktest + result = subprocess.run( + [geth_path, "blocktest", fixture_path], capture_output=True, text=True, timeout=30 + ) + + # Parse output + output = result.stdout + result.stderr + + # Check if test passed + if result.returncode == 0 and '"pass": true' in output: + self.stats["tests_passed"] += 1 + return {"pass": True, "output": output, "fixture_path": fixture_path} + else: + self.stats["tests_failed"] += 1 + # Extract error message + error = "Unknown error" + if '"error":' in output: + import re + + match = re.search(r'"error":\s*"([^"]+)"', output) + if match: + error = match.group(1) + + return { + "pass": False, + "error": error, + "output": output, + "fixture_path": fixture_path, + } + + except subprocess.TimeoutExpired: + self.stats["tests_failed"] += 1 + return {"pass": False, "error": "Timeout", "fixture_path": fixture_path} + except Exception as e: + self.stats["tests_failed"] += 1 + return {"pass": False, "error": str(e), "fixture_path": fixture_path} + finally: + # Optionally clean up + # Note: args is not defined here - should be passed as parameter + pass + + def run_full_test(self, fuzzer_file: str, geth_path: str) -> bool: + """Run full test pipeline from fuzzer output to geth verification.""" + print(f"🔧 Loading fuzzer output from {fuzzer_file}") + with open(fuzzer_file) as f: + fuzzer_data = json.load(f) + + print("📋 Fuzzer Output Summary:") + print(f" Version: {fuzzer_data.get('version', 'unknown')}") + print(f" Fork: {fuzzer_data.get('fork', 'unknown')}") + print(f" Accounts: {len(fuzzer_data.get('accounts', {}))}") + print(f" Transactions: {len(fuzzer_data.get('transactions', []))}") + + # Validate + print("\n✓ Validating fuzzer output...") + errors = self.validate_fuzzer_output(fuzzer_data) + if errors: + print("❌ Validation failed:") + for error in errors: + print(f" - {error}") + return False + + # Convert + print("✓ Converting to test parameters...") + try: + test_params = self.convert_to_test(fuzzer_data) + except Exception as e: + print(f"❌ Conversion failed: {e}") + return False + + # Generate fixture + print("✓ Generating blockchain test fixture...") + try: + fixture = self.generate_fixture(test_params) + except Exception as e: + print(f"❌ Fixture generation failed: {e}") + import traceback + + traceback.print_exc() + return False + + # Extract test info + genesis_hash = fixture.get("genesisBlockHeader", {}).get("hash", "unknown") + pre_count = len(fixture.get("pre", {})) + print(f" Genesis hash: {genesis_hash[:16]}...") + print(f" Pre-state accounts: {pre_count}") + + # Verify with geth + print("\n🔍 Verifying with go-ethereum...") + result = self.verify_with_geth(fixture, geth_path, "fuzzer_test") + + if result["pass"]: + print("✅ Test PASSED!") + if self.verbose: + print(f" Fixture: {result.get('fixture_path', 'N/A')}") + else: + print("❌ Test FAILED!") + print(f" Error: {result.get('error', 'Unknown')}") + if self.verbose: + print(f" Output:\n{result.get('output', '')}") + if self.keep_fixtures: + print(f" Fixture saved: {result.get('fixture_path', 'N/A')}") + + # Print statistics + print("\n📊 Statistics:") + print(f" Tests generated: {self.stats['tests_generated']}") + print(f" Tests passed: {self.stats['tests_passed']}") + print(f" Tests failed: {self.stats['tests_failed']}") + + return result["pass"] + + +def main(): + """Main entry point for production test.""" + parser = argparse.ArgumentParser( + description="Production test for fuzzer bridge with geth verification" + ) + parser.add_argument("--fuzzer-output", required=True, help="Path to fuzzer output JSON file") + parser.add_argument("--geth-path", required=True, help="Path to go-ethereum evm binary") + parser.add_argument("--t8n-path", help="Path to transition tool binary (optional)") + parser.add_argument( + "--keep-fixtures", action="store_true", help="Keep generated fixture files for debugging" + ) + parser.add_argument("--verbose", action="store_true", help="Verbose output") + + global args + args = parser.parse_args() + + # Check paths exist + if not Path(args.fuzzer_output).exists(): + print(f"❌ Fuzzer output not found: {args.fuzzer_output}") + return 1 + + if not Path(args.geth_path).exists(): + print(f"❌ Geth binary not found: {args.geth_path}") + return 1 + + # Run test + bridge = FuzzerBridge(t8n_path=args.t8n_path) + + start_time = time.time() + success = bridge.run_full_test(args.fuzzer_output, args.geth_path) + elapsed = time.time() - start_time + + print(f"\n⏱️ Completed in {elapsed:.2f} seconds") + + return 0 if success else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/cli/tests/test_fuzzer_bridge.py b/cli/tests/test_fuzzer_bridge.py new file mode 100644 index 0000000000..46815e7b05 --- /dev/null +++ b/cli/tests/test_fuzzer_bridge.py @@ -0,0 +1,421 @@ +"""Test suite for fuzzer bridge DTO parsing and conversion.""" + +import json +from pathlib import Path +from typing import Any, Dict + +import pytest +from pydantic import ValidationError + +from ethereum_test_base_types import Address, HexNumber +from ethereum_test_forks import Osaka +from ethereum_test_tools import Account, AuthorizationTuple, Transaction +from ethereum_test_types import Alloc, Environment + +from ..fuzzer_bridge.converter import ( + blockchain_test_from_fuzzer, + create_sender_eoa_map, + fuzzer_account_to_eest_account, + fuzzer_authorization_to_eest, + fuzzer_transaction_to_eest_transaction, +) +from ..fuzzer_bridge.models import ( + FuzzerAccountInput, + FuzzerAuthorizationInput, + FuzzerOutput, + FuzzerTransactionInput, +) + + +def load_fuzzer_vector(filename: str) -> Dict[str, Any]: + """ + Load fuzzer test vector from vectors/ directory. + + Follows the pattern from + tests/prague/eip2537_bls_12_381_precompiles/helpers.py + """ + vector_path = Path(__file__).parent / "vectors" / filename + with open(vector_path) as f: + return json.load(f) + + +class TestFuzzerOutputParsing: + """Test parsing of fuzzer output JSON into DTOs.""" + + @pytest.fixture + def fuzzer_data(self) -> Dict[str, Any]: + """Load test vector.""" + return load_fuzzer_vector("fuzzer_test_0.json") + + def test_parse_fuzzer_output(self, fuzzer_data): + """Test parsing complete fuzzer output.""" + fuzzer_output = FuzzerOutput(**fuzzer_data) + + assert fuzzer_output.version == "2.0" + assert fuzzer_output.fork == Osaka + assert fuzzer_output.chain_id == HexNumber(1) + assert len(fuzzer_output.transactions) == 17 + assert len(fuzzer_output.accounts) > 0 + assert fuzzer_output.parent_beacon_block_root is not None # EIP-4788 + + def test_parse_account_with_private_key(self, fuzzer_data): + """Test parsing account with private key.""" + account_data = next(acc for acc in fuzzer_data["accounts"].values() if "privateKey" in acc) + + account = FuzzerAccountInput(**account_data) + + assert account.private_key is not None + assert isinstance(account.balance, HexNumber) + assert isinstance(account.nonce, HexNumber) + + def test_parse_account_without_private_key(self, fuzzer_data): + """Test parsing contract account (no private key).""" + account_data = next( + (acc for acc in fuzzer_data["accounts"].values() if "privateKey" not in acc), + None, + ) + + if account_data: + account = FuzzerAccountInput(**account_data) + assert account.private_key is None + + def test_parse_transaction_with_authorization_list(self, fuzzer_data): + """Test parsing EIP-7702 transaction with authorization list.""" + tx_data = next( + ( + tx + for tx in fuzzer_data["transactions"] + if "authorizationList" in tx and tx["authorizationList"] + ), + None, + ) + + if tx_data: + tx = FuzzerTransactionInput(**tx_data) + + assert tx.authorization_list is not None + assert len(tx.authorization_list) > 0 + assert isinstance(tx.authorization_list[0], FuzzerAuthorizationInput) + + # Verify authorization fields + auth = tx.authorization_list[0] + assert isinstance(auth.chain_id, HexNumber) + assert isinstance(auth.address, Address) + assert isinstance(auth.nonce, HexNumber) + + def test_parse_authorization_tuple(self, fuzzer_data): + """Test parsing individual authorization tuple.""" + tx_with_auth = next( + ( + tx + for tx in fuzzer_data["transactions"] + if "authorizationList" in tx and tx["authorizationList"] + ), + None, + ) + + if tx_with_auth: + auth_data = tx_with_auth["authorizationList"][0] + auth = FuzzerAuthorizationInput(**auth_data) + + assert auth.chain_id is not None + assert auth.address is not None + assert auth.v is not None + assert auth.r is not None + assert auth.s is not None + + def test_parse_environment(self, fuzzer_data): + """Test Environment parsing (using EEST Environment directly).""" + env = Environment(**fuzzer_data["env"]) + + assert env.fee_recipient is not None + assert env.gas_limit is not None + assert env.number is not None + assert env.timestamp is not None + + +class TestDTOConversion: + """Test conversion from DTOs to EEST domain models.""" + + @pytest.fixture + def fuzzer_output(self) -> FuzzerOutput: + """Parsed fuzzer output.""" + data = load_fuzzer_vector("fuzzer_test_0.json") + return FuzzerOutput(**data) + + def test_fuzzer_account_to_eest_account(self, fuzzer_output): + """Test account DTO to EEST Account conversion.""" + fuzzer_account = next(iter(fuzzer_output.accounts.values())) + + eest_account = fuzzer_account_to_eest_account(fuzzer_account) + + assert isinstance(eest_account, Account) + assert eest_account.balance == fuzzer_account.balance + assert eest_account.nonce == fuzzer_account.nonce + assert eest_account.code == fuzzer_account.code + + def test_fuzzer_authorization_to_eest(self, fuzzer_output): + """Test authorization DTO to EEST AuthorizationTuple conversion.""" + tx_with_auth = next( + (tx for tx in fuzzer_output.transactions if tx.authorization_list), None + ) + + if tx_with_auth: + fuzzer_auth = tx_with_auth.authorization_list[0] + + eest_auth = fuzzer_authorization_to_eest(fuzzer_auth) + + assert isinstance(eest_auth, AuthorizationTuple) + assert eest_auth.chain_id == fuzzer_auth.chain_id + assert eest_auth.address == fuzzer_auth.address + assert eest_auth.nonce == fuzzer_auth.nonce + + def test_create_sender_eoa_map(self, fuzzer_output): + """Test EOA map creation from accounts.""" + sender_map = create_sender_eoa_map(fuzzer_output.accounts) + + # Verify all senders are valid + assert len(sender_map) > 0 + + for addr, eoa in sender_map.items(): + # Verify private key matches address + assert Address(eoa) == addr + + def test_sender_eoa_map_validates_address(self, fuzzer_output): + """Test that EOA map validates private key matches address.""" + # This test verifies the assertion in create_sender_eoa_map + sender_map = create_sender_eoa_map(fuzzer_output.accounts) + + # All created EOAs should pass validation + assert all(Address(eoa) == addr for addr, eoa in sender_map.items()) + + def test_fuzzer_transaction_to_eest_transaction(self, fuzzer_output): + """Test transaction DTO to EEST Transaction conversion.""" + fuzzer_tx = fuzzer_output.transactions[0] + sender_map = create_sender_eoa_map(fuzzer_output.accounts) + sender_eoa = sender_map[fuzzer_tx.from_] + + eest_tx = fuzzer_transaction_to_eest_transaction(fuzzer_tx, sender_eoa) + + assert isinstance(eest_tx, Transaction) + assert eest_tx.sender == sender_eoa + assert eest_tx.to == fuzzer_tx.to + assert eest_tx.gas_limit == fuzzer_tx.gas # Key mapping! + assert eest_tx.data == fuzzer_tx.data + + def test_transaction_gas_field_mapping(self, fuzzer_output): + """Test critical field mapping: gas → gas_limit.""" + fuzzer_tx = fuzzer_output.transactions[0] + sender_map = create_sender_eoa_map(fuzzer_output.accounts) + sender_eoa = sender_map[fuzzer_tx.from_] + + eest_tx = fuzzer_transaction_to_eest_transaction(fuzzer_tx, sender_eoa) + + # Fuzzer uses 'gas' (JSON-RPC), EEST uses 'gas_limit' + assert eest_tx.gas_limit == fuzzer_tx.gas + + def test_transaction_authorization_list_conversion(self, fuzzer_output): + """Test authorization list conversion in transaction.""" + tx_with_auth = next( + (tx for tx in fuzzer_output.transactions if tx.authorization_list), None + ) + + if tx_with_auth: + sender_map = create_sender_eoa_map(fuzzer_output.accounts) + sender_eoa = sender_map[tx_with_auth.from_] + + eest_tx = fuzzer_transaction_to_eest_transaction(tx_with_auth, sender_eoa) + + assert eest_tx.authorization_list is not None + assert len(eest_tx.authorization_list) == len(tx_with_auth.authorization_list) + assert all(isinstance(auth, AuthorizationTuple) for auth in eest_tx.authorization_list) + + +class TestBlockchainTestGeneration: + """Test end-to-end conversion to BlockchainTest.""" + + @pytest.fixture + def fuzzer_output(self) -> FuzzerOutput: + """Parsed fuzzer output.""" + data = load_fuzzer_vector("fuzzer_test_0.json") + return FuzzerOutput(**data) + + def test_blockchain_test_from_fuzzer_single_block(self, fuzzer_output): + """Test single-block blockchain test generation.""" + blockchain_test = blockchain_test_from_fuzzer( + fuzzer_output, + fork=Osaka, + num_blocks=1, + ) + + assert blockchain_test.pre is not None + assert len(blockchain_test.blocks) == 1 + assert len(blockchain_test.blocks[0].txs) == 17 + assert blockchain_test.genesis_environment is not None + + def test_blockchain_test_multi_block_distribute(self, fuzzer_output): + """Test multi-block generation with distribute strategy.""" + blockchain_test = blockchain_test_from_fuzzer( + fuzzer_output, + fork=Osaka, + num_blocks=3, + block_strategy="distribute", + ) + + assert len(blockchain_test.blocks) == 3 + + # Verify all transactions distributed + total_txs = sum(len(block.txs) for block in blockchain_test.blocks) + assert total_txs == 17 + + # Verify transactions maintain nonce order + assert len(blockchain_test.blocks[0].txs) > 0 + + def test_blockchain_test_multi_block_first_block(self, fuzzer_output): + """Test multi-block generation with first-block strategy.""" + blockchain_test = blockchain_test_from_fuzzer( + fuzzer_output, + fork=Osaka, + num_blocks=3, + block_strategy="first-block", + ) + + assert len(blockchain_test.blocks) == 3 + assert len(blockchain_test.blocks[0].txs) == 17 + assert len(blockchain_test.blocks[1].txs) == 0 + assert len(blockchain_test.blocks[2].txs) == 0 + + def test_blockchain_test_pre_state(self, fuzzer_output): + """Test pre-state (Alloc) generation.""" + blockchain_test = blockchain_test_from_fuzzer( + fuzzer_output, + fork=Osaka, + ) + + assert isinstance(blockchain_test.pre, Alloc) + # Verify all accounts are in pre-state + for addr in fuzzer_output.accounts: + assert addr in blockchain_test.pre + + def test_blockchain_test_genesis_environment(self, fuzzer_output): + """Test genesis environment derivation.""" + blockchain_test = blockchain_test_from_fuzzer( + fuzzer_output, + fork=Osaka, + ) + + genesis_env = blockchain_test.genesis_environment + + assert genesis_env.number == 0 + # Genesis timestamp should be 12 seconds before block 1 + assert int(genesis_env.timestamp) == int(fuzzer_output.env.timestamp) - 12 + + def test_blockchain_test_block_timestamps(self, fuzzer_output): + """Test block timestamp incrementing.""" + blockchain_test = blockchain_test_from_fuzzer( + fuzzer_output, + fork=Osaka, + num_blocks=3, + block_time=12, + ) + + # Check timestamps increment correctly + base_ts = int(fuzzer_output.env.timestamp) + assert blockchain_test.blocks[0].timestamp == base_ts + assert blockchain_test.blocks[1].timestamp == base_ts + 12 + assert blockchain_test.blocks[2].timestamp == base_ts + 24 + + def test_blockchain_test_beacon_root_first_block_only(self, fuzzer_output): + """Test parent beacon block root only in first block (EIP-4788).""" + blockchain_test = blockchain_test_from_fuzzer( + fuzzer_output, + fork=Osaka, + num_blocks=3, + ) + + # First block should have beacon root + assert blockchain_test.blocks[0].parent_beacon_block_root is not None + + # Subsequent blocks should NOT have beacon root + assert blockchain_test.blocks[1].parent_beacon_block_root is None + assert blockchain_test.blocks[2].parent_beacon_block_root is None + + +class TestEIPFeatures: + """Test EIP-specific feature handling.""" + + @pytest.fixture + def fuzzer_output(self) -> FuzzerOutput: + """Parsed fuzzer output.""" + data = load_fuzzer_vector("fuzzer_test_0.json") + return FuzzerOutput(**data) + + def test_eip7702_authorization_lists(self, fuzzer_output): + """Test EIP-7702 authorization list handling.""" + blockchain_test = blockchain_test_from_fuzzer( + fuzzer_output, + fork=Osaka, + ) + + # Find transactions with authorization lists + txs_with_auth = [ + tx for block in blockchain_test.blocks for tx in block.txs if tx.authorization_list + ] + + assert len(txs_with_auth) > 0 + + for tx in txs_with_auth: + assert all(isinstance(auth, AuthorizationTuple) for auth in tx.authorization_list) + + def test_eip4788_parent_beacon_block_root(self, fuzzer_output): + """Test EIP-4788 parent beacon block root handling.""" + blockchain_test = blockchain_test_from_fuzzer( + fuzzer_output, + fork=Osaka, + ) + + # Beacon root should match fuzzer output + assert ( + blockchain_test.blocks[0].parent_beacon_block_root + == fuzzer_output.parent_beacon_block_root + ) + + def test_sender_is_eoa_not_test_address(self, fuzzer_output): + """Test that transaction senders are EOAs, not TestAddress.""" + blockchain_test = blockchain_test_from_fuzzer( + fuzzer_output, + fork=Osaka, + ) + + for block in blockchain_test.blocks: + for tx in block.txs: + # Verify sender is EOA with private key + assert hasattr(tx.sender, "key") + assert tx.sender.key is not None + + +class TestErrorHandling: + """Test error handling and validation.""" + + def test_invalid_version_fails(self): + """Test that invalid version is rejected.""" + data = load_fuzzer_vector("fuzzer_test_0.json") + data["version"] = "1.0" # Invalid version + + with pytest.raises(ValidationError): + FuzzerOutput(**data) + + def test_missing_private_key_fails(self): + """Test that transaction without sender private key fails.""" + data = load_fuzzer_vector("fuzzer_test_0.json") + + # Remove all private keys + for account in data["accounts"].values(): + if "privateKey" in account: + del account["privateKey"] + + fuzzer_output = FuzzerOutput(**data) + + # Conversion should fail due to missing sender keys + with pytest.raises(AssertionError): + blockchain_test_from_fuzzer(fuzzer_output, fork=Osaka) diff --git a/cli/tests/vectors/fuzzer_test_0.json b/cli/tests/vectors/fuzzer_test_0.json new file mode 100644 index 0000000000..2525655832 --- /dev/null +++ b/cli/tests/vectors/fuzzer_test_0.json @@ -0,0 +1,456 @@ +{ + "accounts": { + "0x000000000000000000000000000000000000000F": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x0233362c058b2fCc8093841B1073A90D673E7F12": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x7f2c75141e16bea0fceec67f673a0a3578e66fe55a9b6405d1ce109be7593206", + "storage": {} + }, + "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2825c17712cd3e7e5240fb76fe09ec612d0337b643e5c605c3cfea77e44d0b73", + "storage": {} + }, + "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": { + "balance": "0x989680", + "code": "0x6f0304bb487cf38ca47fa3bdb2fcd17f446000527fbce853b19c5e1fa4e21a75f5c633b19093d16e4225a1e18f93e6b0280d553f456020526f12907f8e8e33612bb1cd28222515089f6040527ff9ccd6deac82230464c9a0b6b46ae6cdd7488cbcb2701e4ae34128fbc7278be66060526f0f648013c07e63d91b12e235737d86626080527f152b1247f61c53a7c05b6282599a5a565624a120e3884ee2cf02e267fe10be1e60a0526f0ca29f1d84c20b8318dfc76159fa754560c0527f8730ae6c1b52728688bb33a14d5e57c18fe660ff55431c5fcc749dfbfd027a2060e052608060006101006000608c600b7fb2a9d981edef956e7c15a8f00819612f341891f265ea91e2d1bf0c9ddf17706bf16000556000516001556020516002556040516003556060516004556f0a1d7979d389cc17fa6234b538473d336000527fabda0c5fb1790d0da3b62020c61a9e0d09bf34d7299d048a86be80fd34ecc4a86020526f0560d9b5c15fec8dff6be987c92016df6040527fa66b5477a91ae92db1582bd62fffc0a3b6bafc39ad9636987f953f1acd6011036060527f6eb221e467bd443a6fd33fcac3eec22e63e51613f05df0310c0ecab2124210386080526f089358667ca389db7562f52f881de51e60a0527fa3b281e831d4286f5cdaebb3161f352f9f5cbed6b20674ad02b7606c56d675a860c0526f17f1263e3a15d93c02a8f6557c73bc0160e0527faeda0be01631b7b34d0fed1325f69b428679a30b79321b4ee50a7a382da092b5610100527f8f53d4aa5331cb3dad00de83c80191ebccf46fb3f1527416ebb22311d8cdf5ca61012052608060006101406000600c7fd4fc806c73fce35b7910639bcd5e440f3240dbba1f1db35ffd40ac39bd9ed326fa6005556000516006556020516007556040516008556060516009556f0e98e9c5a0ce1800ea000f728c792ebd6000527fc62c5196c7362c18572f8150745dbd193236def47b700cfd019f6a63c232e7726020526f17305bfbf895a75a1b4e0374fe26d8f96040527fb6dfed3e090fc8b5952d6ed6d4722f9d0d12419a9dac52386160f712bbcaf1fb6060526f03cd0052fd56e53a9904f76c29b4f6e76080527f62c168176691eb3f0c43f3263ebbfae78287a9110f2e7210f8615b4c0deedc9560a0526f0d99d442b87f10626da56ae4efc4557660c0527f5b87b2d664e585438fc0e5c2529f960b8421293bc9e64cf73c3681315c67cceb60e05278100000000000000000142f2b61de3fd9f5fae7f30f9a200465610100527f69a2fa1a70f398346b86baf9a1caf04c81261ce8120d073e480c017d1072ea86610120526f16367e551460bdf8b55514e5fbc98336610140527f4e41aa34f39059f6b645f11adc22a135c4cac0f8073c4a48dc3e326dd64570da610160526f1559a897fe4d9101750cf0c50d759307610180527fc6f2b0bbf73d7f6e7397777e2839216f0636957d997b14fa1dc9183d10ef4d806101a0526f10d05bbe32b66859d000015085fc6fb36101c0527ffd839495def4a7a0217ae1194b79e4e4a929cec96eea279ca635aa528718c5e16101e052610100600061020060006087600d7f4997fb8662809f846cccb8072b5a665549bced5ba0babf36c900744358ed4715f2600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f0a80f16dec66305836d93b07b6a14b746000527fd694453efa14cf142cc5b48cd8e49e5fa6d52f6b904f3c51a1e99be6ebeebc626020526f17ec12f7a83252673a562e934ae83c7d6040527fd980e2a6787fe55b5d6250b8c8c909f4c5fa906b7ae1e359fa84225966b4585e6060526f0201c07465f5a818868d265f2b9d3a5a6080527f4382a23b79074ccec8e1ad21c580fc1fe95213d4798af4aaa22855bd021050c360a0526f170d94a3398fd8fe44b7ff548fe6d93160c0527f726ae0d035252f5ec681388307703619e6198ba67ce8e3380cb576edb1a871f160e0527f1f4158e9331a61d7f6666fa0bbfea04cf804c27cc8b8ac749176fd7ea110a2016101005261010060006101206000600e7f903dbfde19bbf5a150cce310c94c5fde73f13db285135e8fa471e112a500dbb2fa60135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f060500d8f2788f675515321a657ec91d6000527f2f68c11e9812c09c2d1ea3667837f81666de01b7136237cd59d0e4fdd23f03496020526f1029733bf268a8dfa83ebd6870b9c5b36040527f8f3731515fdfb60678ef7e109ad680738e1c20e6e7ac6c1daa02e3fbca9ff4526060526000608052600060a052600060c052721000000000000000000000000000000000000060e0526000610100526000610120526000610140526000610160526f0671a07ffe971a913c8e718e1f8aff72610180527fddad0b334b7407fc1fec9eb7273da17aaaff013426274ab1f61cd0f04ee188c36101a0526f123c38b43dec7cb6345624c5f8b403c06101c0527fff208bbb12cc604d5cdd3ed163805d0bae5d8c8ec7b5bacd6a0ec529327c719a6101e0526f181cce65e82fd9347b1b66b4bdcade50610200527f71ea0bbfc0be2f5d930fdb39907aac0765d1e38b4b10cc44d4e8b89bf0848a12610220526f19669ebdbfec5754e13c61595fb28b72610240527f47795a1822a6b61169b1fdf8c13a66993bc9a0a9b03b236d1ae9619f80274c7c610260526f0bee714d419295547b26ad30f3f6d265610280527f0c5cc9a7d2a9d234cfbae47ccc7b753fb83ba16ea7b8c9100fc4ab9664b34ae76102a0526f01c0c352f3bb92ccfc65ba09ce10e2bf6102c0527fff7b95a9a3502e998e571f6b14a95669015c4065160fe57862c56ba26dc223e86102e0526f0a5027e9bff89a14938cce229b6608ed610300527f0f15b6977401680f5eac13988d4d5223190b3ead586a370df633fed4e2c2fbdc610320526f05fd50e2ac95e4d5ee6f46f492485ef0610340527f11c90229dd700ca24d7560d6318ac814c8f2cf0fdcdb6734ba88088a82c78b48610360526f0a9cddc7b8e0a02a9d05efeb7135a08a610380527f1edf3ccff9518b554a7169b9664ecbbae8e1fb5712d6eb21e507e91b58e0f1726103a0526f071f0b7f899b0ecc684373f03693e3f26103c0527f0973056eab4f7cd509c36304f21d5685d7bf3adfbcae30b1543c2b360af306e66103e0526f08780fd2546a36beb1ca303e02af7b14610400527f8252ab31a0707573563e183b8cfcf36dd3b166e6303a79d9787cbeb04bad0b99610420526f055bc48aa14fb1c46c09ea909afd6bfe610440527f25acb1249e874468f4e3b73366b400bc6bfe4f542a412bc91c9c83615f3501ab610460526e6fce599f3edafd3ec2cf034379f3ed610480527fb7bc1878c6b16a4c036f54f228c5fd735c10975d62caaaf0e9624900efddd6b66104a0526f16287deaced22aeece826750d5f96d0d6104c0527f493b5d3ddb685f425f5b727a5b85a82ebeef92615ee32877afc243908bd50d2c6104e0526f024aa2b2f08f0a91260805272dc51051610500527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610520526f13e02b6052719f607dacd3a088274f65610540527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610560526f0ce5d527727d6e118cc9cdc6da2e351a610580527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016105a0526f0606c4a02ea734cc32acd2b02bc28b996105c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6105e052602060006106006000600f7fd4124f75d9f67bb9297799198175ef8987c66e6c7afad5fc75719adbe2e89dc9f4601c55600051601d556f048ecddc27cb7b231e2079d5c96adb456000527f549123f3e3c3d28ff640bc3a1adb125dad75897d889e48d44f0f77ac28f020ed602052608060006040600060107f01298de28edfc331e1c52caa4e4d9601b30e5980bd635744a17225c5168975d7fa601e55600051601f556020516020556040516021556060516022556f13eba7cc9982c91920252877d0c114016000527f7c2cd98b0a402e7d0d5d015f9412eb553a9c306edf04e6dfebb84be9fd306cff6020526f12eade4a55567c4180d389eab65e95626040527f0eaf9b6cee65d9ac1233d2143011bdde7a2a2ed1306214f985d48cd255e4166f60605261010060006080600060117f3f0844a363566ce2919046fe2ab2946fc4152e80ec32229cb032f73b21f4c162fa60235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55", + "nonce": "0x0", + "storage": {} + }, + "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": { + "balance": "0x0", + "code": "0x60d360fe60286079600f60ec60b12008326f52059b3f3d528a53656d668c36445c1899f01a4a466151845c61368ca35c8005048e95193f551d209510615502414a3c77104309044a6d45570968789058f53749193e817f5f807d9e025f793d755575028b5d3c8f9e3a91097d5f6cf39a4768798a66111c0a3979807ff37e0b31f3188f8a0856006464fa818b75140096629833556e1e59607b9c53ff5f056105f53a8a5416160b533c54317514638106616607936f3c00023716095a69437e52411d59437b751c8a46573e595f671c8af203341c6e7c741017705f126a56727ef08f515a461a5e506d18126f72506b0638434537024009074081a163f0f002135857107698446917376d506379643b07431a20ff681c3e091049410516418a0353458b5aff685c6f977114578fa47531771d5e00536e1959605e733b147e72356bfa194291556d1069007f1d811e563d12863a7b336d51093266788d74451a197916f4764801630bf11cf242f032f30217445a3d6a57900751876b4930606b483161047432743a3a333a88787548797a4206467e33955269959f1c5865556b1b51194a446f023808a27c3d475e133d686937f0656c46780a33004a503e188f5c16597d69a20517466a5e6615474769540081050606631b605b7c7a37496cf58d8207f56e085b986f6f7d467762861940f17b3f3a661d401d6d46681c050a3d3d501d49653903561a406b483b7e38679336a363505fff736120516a6934818a5b556a3a0a12ff6f9b71841184763b077c8d106809861b881c9e405e3e388672081b727a77817b7a83a26c16560770794a703a6904684800786d00198130fa32074a6b5f07881d3d5659843f3d56735d5b31a0050083381609190539a002360a424538430b3e748173433d726d83416d497f153e440231fd1384396e5a9361045795613a87991e54ff1c6a701b05540a6103718d56718a536c85a0313853569781873754413861336e72975a47503e55a25b02a336361a6542a4708736839846fd316766933d567a3e718e537d1576414694588a609b1531366d0b19080a6435703c73027a3d32591e6a723305156a1991603204380b486a619b6b83083e7390807d5d8a7f57f05a78024a511ca20b360292543f660436676f5a1b03f473667d07545300f36a96974a56358e8f653e3b38005393671a47121802583e191172461214ff87176f9f51fe99071d68065565810a03865c8857723e09618181900b3775515a51461c7249503d403403f5161b6b5e5740604a55758b6a7180fd63721c9b5801047e9e68a33176015e095b380737799a45015e6c3a8796a08f5916110978f2454a570335504a7e335c3a166d520a53627678325245745338727b7df309a1830a74374a6d325d58f3711e7f6ffe684271363b325c5d00979b8c15561e8a42", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000012" + } + }, + "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": { + "balance": "0x0", + "code": "0x6000545004121e6f7f56198c1e35957e3f1771fc736167d061e5a3771e4ea7b6224c5795c0bfb9e27d6000527f073b1b146e22e2cbc33be43483ed67045cde7dfc18abfbc072e3007d1759a6436020527f25a5d983835b0a0a8ddda9e973ca774131d07a607a50fff393e8eb4cc1f26c6c6040527f9c248c3c71446e447ce71a16117be91eeb6887774ecc073bf3687f333852154c6060527fea9d67c047c8937ae33e470ae93ab841543e412d7fad66143778f8bc924fa5d46080527fd5b2f67b2063905d37d496c15a25d758c22b2b44cc1236b0ed5b7984e779d46360a0527f0a2e60472c4944e9fe2c9cb40ee4ef6d4664a0b3a11b5385c4b7e0bbff14540660c0527f2f523606c6d7ecf0fa8698a50b184183e745a9fc62ac210b2c697b0990eef9c960e0527f76eb16a60b21c1f33f72b6fba934a49df31cc33495c2a5448c52c4678fd235f4610100527f7eec64c80233121f38717239977ee9780a8bd90f8503cbafad56b1d154a42fc6610120527f7587ae46cbb70adcab17b5b0de3acb3145a7c274822643a1f60445b25869683b610140527f2b379af570b1ecd121b6a8fa57f5b95070dfc6f568bf5fcd6463325a70dfeabe610160527fcab611c6fce59eb2d48e25746327158cbe1e56043270425b912c395a481140d7610180527fb278bfc525b03b0bdc36704d4f33402e419bf94220a962778732dee8df0701af6101a0527ff31a16cecd89cbbe248c1180cbe3ab9d47f0608191ebae06c8ca65da94a6cf0e6101c0527fdab48b0443e2f74491047cb5043ec3ab52a64c3cd9207829e01c0c7db9767e4c6101e0527f48fe70c2e6614d7a443a9e349eab5d084c38b49a7915188567b9fed7bb303205610200527f4cd71e66c5664a1f0cb150d3c620b349dd38c1cc760aff91f76927665de296a6610220527f4fa12b0350149110fa8a0c12251cd216f5ef2a6933dd28cb7ab6de9f613097e2610240527f0f4c3ea9097e42038e26855e750999a40ab7f90ea69d1a2a2c1fd97fa79a0613610260527fe7faeb6bccf6487cf16aa52814ebdc29fb624527e80805b08a504d1598dd7831610280527fa445a986e95b0f4e0378e18b97819ff5f3c5c534d436d4b648c297b91568a10c6102a0527f8c4eda6372fd44629eba2c9d2dcd470136c712ab976abb3396c1da6f4ddcb6826102c0527fda48bafb7e3ff88251bb85a28ee3fbfea120a23150a8d2d725989f9c4502a5286102e0527f47a217e00683fa23ecf58f04b7663a46be40a80bdbc7910d7a7a6ea7528c24326103005260ce6103205360cd6103215360266103225360b66103235360db61032453604060006103256000609660f47f80dd5cba9287bdc9d8484da6db0c443bcf39f18dc9a3b877daa4b47b152f695af1600055600051600155602051600255", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x000000000000000000000000000000000000000000000000000000000000000f": "0x000000000000000000000000000000000000000000000000000000000000000d" + } + }, + "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xaa07ea6d7ebb90738862bff26aa53633e9a6a4c2732f31c270f5a02687a06eb2", + "storage": {} + }, + "0x535863dA03bc1834eeA10eeab8FF498565F33f2d": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xb214f8d7a564be547e6de1404f829b88b9c5f1bfc42a708554e97423e49a9def", + "storage": {} + }, + "0x538A8474EeaB43d5a960164c554A20400151D479": { + "balance": "0x989680", + "code": "0x7fb858c07c2fb9fb447c54bdf506edb58f631476bed129929800bdb8049510aa7e6000527f3a410073dc03e299ea3618ffb2e7292ecd57563edff75605855ca16c9cb158e66020527fc3ac92c70cc33b79c43ed311142981018abce5f5cbc322fb4d4cc081031ec1ce6040527f73d594fd80189ea82db6754b27de68050a84ba50ed82afefe5b900ff19a00aac6060527ff1a8e519f5aa98550f849cff101dee44b99100c44eac7a7f2cde3610cd54656e6080527ffd7b744a4d233ee11b0b11f746f2d48a6563968ccf0b8a2f3f99d60ab16b146460a0527f756af369bcf3131ecc8d276e72b38074f3f02a253f611208f70b72661c27458f60c0527f3078b132f36721702d0b4ee6c4c30fb87f4860d76c267f1a3fc1a3e56901fbe160e0527fb903e43f3659db206c8e26d8f3276f2696926e86f82ba6cb69639480bb9e85b5610100527fa0225a93a51f5cf08e2829018fc694fc8dbfe36ee19d9c33e8f6cd0918a823076101205260206000610140600060027f3d5fcc6dc637aa0a00e46f5c03d83b8b4476d9fbaab5d9688c67e13eceaa005bf4600055600051600155", + "nonce": "0x0", + "storage": {} + }, + "0x641602bAD4A323C49629d45338d79A2bb984A3fb": { + "balance": "0x989680", + "code": "0x6008610400fd", + "nonce": "0x0", + "storage": {} + }, + "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": { + "balance": "0x0", + "code": "0x600054506003fff87f9dfbc28738b4aa81098db57872f5db652fb31e6563a7e0444aef68ed160a85c5600052604060006020600060b660077f6b0476a7d3e48eaca4fb3595c2ad7657f4da9552ffaebcd13068b1c91fad8d6bf1600055600051600155602051600255", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000f" + } + }, + "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": { + "balance": "0x989680", + "code": "0x7d08361ee866d39c2fb444e88ff7ee2a8e023c8c049aae8a67f7f686951abb6000527f2884635f8539e311ae790c2a42ca96eb6a850235a6ab1e3de3ab9106f17f69806020527f9c3330a9d409a3128e5da585e8d90364692c33c7b156330f7a9d0466b958016c6040527fbe4b1c709bb0327f1bc07d29da9e49dbc164adef56992936f18fef5d9bea45086060527f861e3e31afb13f20925a2ef9718e14add535afc482c88a4429ddd65c050491926080527f054efe1978cffd5b49f3791f5c168bf912146245ba05b3425577697c24436d8d60a052601f60c053602a60c153601260c253602960c353609c60c453605f60c553604660c653609c60c753608d60c853601a60c95360b860ca53609260cb53601c60cc53602060cd53602660ce53602860cf53608560d053604660d153609760d253602160d353600060d4536040600060d56000604d60097f67a046b0dcdd07f5640269c0b1d159c2f87bc5cab9c9cbcbfa19613952b719d0f1600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x79cca006f0792Bf40a6d4E011c2884eD862A52DF": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xada9e915b45b3f9f3f335fe00a484308905ec68a78d49750e1a47ec4f9c17d23", + "storage": {} + }, + "0x862B38c425EF5544d0127449A12c89C46dd3E050": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x35c0e7a818e7367e6218647e77752b4b0d92f50362a7eff324915762586509ba", + "storage": {} + }, + "0x88f9B82462f6C4bf4a0Fb15e5c3971559a316e7f": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": { + "balance": "0x989680", + "code": "0x777effffff80000000000000000000000000000000000080017a01090000000000000000000000000000000000000000000000000090176000557f800000000000000000000000000000000000000000000000000000000000000276013590cab83b779e708b533b0eef3561483ddeefc841f5136001556780000000000000017e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000901d7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5901d9007678000000000000000690100000000000000000006760fffc000000000000767676240000000000002b05760476007717676767676760000000000760000007600000909760fffc000000000000767676240000000000002b05760477f800000000000000180000000000000008000000000000000800000000000000090050b197702ffffffffffffffffffffffffffffffffff2000000000006801fffffffffffffffe90109017197ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000677fffffffffffffff7e40000000fd000000db0000000000000000000040000000fd000000db0000010913682100000000000000227f80000000000000018000000000000000800000000000000080000000000000009006107ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000686d5adef08547abf7eb90066002557d767676767676000000000076000000000000005600000000000000000000637fffffff901819901b7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f800000000000000000000000000000000000000000000000000000000000000018146d010000000000000000000000000069010000000000000000001a16610111774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a1090167feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7bc9700000000000000000023f00c00014ff002c00000000000022310814177ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02901615682323232323232323237f7effffff80000000000000000000000000020000440000000000000000000001901d7a010900000000000000000000000000000000000000000000000000778200000000000000fe000004000000ffff000000fffff700637fffffff0990161b71767676767676767676000000767676767676638000000116901a682100000000000000227ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000090109005681000000000000000007f82000000000000000000000000000000000000000000000000000000000000006b100000000000000000000000080b6d0100000000000000000000000000777effffff8000000000000000000000000000000000008001051960035567d021262626262626680100000000000000001090137f80000000000000000000000000000000000000000000000000000000000000006c01000000000000000000000000774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a90081b60006000f3", + "nonce": "0x0", + "storage": {} + }, + "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": { + "balance": "0x989680", + "code": "0x7f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a06000610100611915fa6000556000516001557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527f8302763a7a03204c2f880bc82f3d38d8747211f1a910880e90004c102538f3ae6060527f7d8da52b6ebd1b2c2d84b07a8d2092e09d27777575aa939ed783a54cddd2b0c66080526020600060a0600060006101006119fff26002556000516003557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffffffffdfffffffffffffffffffffdffffffffff77ffffffffffffffffffffff6020527ffffffffdfffffffffffffffffffffdffffffffff77ffffffffffffffffffffff6040527f91dbff4fb710b1e81ce14be3bd88f06cff8428403452b064321bebeabec55f7d6060527f54c975daf7c93874c068af196208eda9c8f9ced3460ef5bffcc93b3dd8f2ff8a6080526020600060a060006001610100611a1cf16004556000516005557f86f977edffd2ddaf1c5779296743fb477fe65e68d47bb0716a1ab8157207455e6000527f43c36642eaba53487655950d16ee65b9f61ee0c605a4388cffeacc12f2b01e856020527f4aa560a8b3dec45915d077759ff76a3efaa44d25c93aa98b466e59fbf502684e6040527e9047ae74c90ca58dad54af6f18f053e27deb4632fcbf5998f269e614536b826060527fdadda5824c6bcf8a00a246be87fd739d8751107ef5ce89c85d3da736c3fc69326080526020600060a060006001610100611a77f16006556000516007557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f81f541a8a3462901f68ba711ca1e3aec670f9cc713e1972a1606fbceb2ebd2886020527f81f541a8a3462901f68ba711ca1e3aec670f9cc713e1972a1606fbceb2ebd2886040527f04fffffffb0000000500000000000000000000000500000000000000000000006060527f04fffffffb0000000500000000000000000000000500000000000000000000006080526020600060a06000610100611af4f46008556000516009557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffbffffffffffffffffffffff7fffffffffffffffffffbffffffffffffffffff6020527fffbffffffffffffffffffffff7fffffffffffffffffffbffffffffffffffffff6040527fc9e005dd1af6d82d77505fbdc1b18fd3d9741240907a510e5ddc9febe80c768f6060527fc75def9510f5aba00f7917e84ea6002991ba59604d84fe1cf2b6b4cd6ea7c6746080526020600060a06000610100611c3ffa600a55600051600b557f63b53bcdd52d82e3e5ae5108ed590a8631113f6abba1624acfd0cd5be0a0d56b6000527f890c4ce6a855ff49e201e0ed48e8274c14be1cbd115364818c32fe3cedfa7c106020527f236ad4b6d7f6ef8bb45b6d45172b950216c0738bdd2be455d33a3058d34a061260405260006060527f5a824510cc45547b0a39a6b8767f15f0ac481a630dbaac91803d3bfc6b9c6ebd6080526020600060a060006001610100611cbef2600c55600051600d557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c7760005260016020526001604052600160605260016080526020600060a060006001610100611c1ef1600e55600051600f557f6ed85366d9c82e9481594355f9b55ca5408697bca7ef1d349e6d8e37e2b4c85d6000527f7bc7b5eb03d4cd86c342c7dd8f06d8e2a952439d2e8a630919d74500a4a344496020527faacc19c91c17de70c9873189d63e0d28987290f3089e5ace18d13d5ea618439e6040527f8047db8b33c977bf4d8069f8c3715097251328b395f3cfe5c475ddf3f762e5606060527fa75ed49f31331b289b30793cefa79a7e0ccece8fdc7796f909112e53d509d3746080526020600060a0600060006101006119f1f26010556000516011557fe506e35f179221d3ed2944ac1ac29b7483a73e7adbd784c5ee7bd38b345dabf26000527fab4deaff0494294b86417f8c8d2238649f97e5c45f926a183e5cd1594c4cb07e6020527f4afb0bae902a54052d1bd6b411d165669850774bb42b8ecc73cb102c48786bd66040527fa7c4a4fb78abc4a6cd32f47ce4db416c91208a04f7ae267e8151968fc3a609646060527f89d7f7cc508073e2cc8644c5154846a74315dacbdadbadda1cafd82e386dde4b6080526020600060a0600060006101006119c6f16012556000516013557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611be3fa6014556000516015557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527f8be9b57e112a8abb6ec40524a35e864b5293159b6a77f4860f8e00ceee6348d260205260006040527f48209be5e8f0e89ee1f0d4b74645ed38280f0bc6ddafec46f395720346b12e1a6060527f5512a03479460ecd88cf83565013839e24c5a84008f6edba23f0d0b9dfcceb4c6080526020600060a06000610100611bfbfa6016556000516017557f69955cf40e14f69443bf4f8ee5432aa2b843671673ccae71a51215fba3872a426000527f8ec01f4b15fe0c755482f5e90658c5a758699386c587b3657aed859e90eb69d76020527fb5eb6c9b3994887c43c6f40747ff3494f507592761d915254a01827d7f36d10a6040527fd26cfb0cd81d2a94cd7a10a5972d6d20d1f06ccdc6cbb0f578a4bcfca45f2df06060527faad80ba35b270796c9cae745b7a027b43027d54af56540fedd8c9b73114f47156080526020600060a06000610100611b01fa6018556000516019557f500b93dd1d2a593c5a87657f32a4a7c2688fc81d9696cdcbad878cf630537a9c6000527fd78d8eeffa7139961a28191e23ec8bd01da90e63007ce5f9425fc50ec264d6f96020527f0ee4e5c1a1819348b133f191aeebecfe2f27b9be698d6ffcb5fa441ddffbd9196040527ff1db2ab546530306590bae04535c1353a7f14b8e8b3a893bd88358612774b4a16060527fab214a7af0d280dfbe046277723d67cefbdb88c22aae39f752e872c257a372556080526020600060a06000610100611b16fa601a55600051601b557f5da1d3b0edc7e8bf95cb6f26d1c264d9bdf4ea04f05a9ed1e541bacb8672f675600052603d6020526059604052600060605260006080526020600060a06000610100611b8cfa601c55600051601d557f22fdb863e2df7a57588e5cc6b8b128c8ed3e88b5ad088f1b37a2f981bf41bdc56000527f69bc3329e8cb108c84c98ceea1bd99d39a2efe8517074b1a79ffb6c8fa5d163f6020527f5d80d369a9dd69d08bb0389ff4dc31d3a179aa82f61a2543e9dd3b58326f7b216040527ffdcdaac7043a1c5a4abe5883e66744659480933d3fc6d79f388d18a72a0f11076060527fa4edfe3c45411b6d8bb1aff118ca3d1a2c56beea9a2b9778a6c093d0ff22e25e6080526020600060a060006001610100611970f2601e55600051601f557ff5c112beb21695afb638f1032170f8b4af1040fe570bf6356c74082a31bd6bb36000527f399ca9ad9f8dc34b7964f8a853550a4901e3eec73fa5604131d2e7ab2d0e6f156020527fc048cf554cbffaa48220a65412e471ed20e28bdd82ffe99589e3867ee7e9069b6040527f1a8634914abb264491eb6c117d8a3c72a74965333bedfb0494bdf448da64838d6060527f57ed3625d9e134d129cfd6a7d3fe7f6c898fc9aff54c3ae2ef0890479e5e5e8e6080526020600060a06000600161010061192cf2602055600051602155600060005260006020526000604052600060605260006080526020600060a06000610100611987f46022556000516023557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a0600060016101006119e2f16024556000516025557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f22276e0d2c74bdb35707e25acac41b33490f53b461dde80d2c6114f1698391d96060527f470aab8b0fde69b11fb96c7d20a0ca75f3654fe23a02f19e7d98eefc7ccb8c8b6080526020600060a060006000610100611b93f16026556000516027557f160e6420d863db6655fa27dd50cf8e353f9ef4a20092520f63ac63f4e0eb32556000527f343c3b8c8e2ceba457169b28ae411d0a278741b36f671feac0fea97a45cf40d26020527ff6f052ffdb97a606b3ac7009313248236b4ae112d3acfa537663d4c38452de6b6040527fa25d6665169122469ad9dceff29c3e6e871360326eb49e49e0261adf89361f016060527fef7b14d9fae44f66fc4ee9b481ca0a6ac49cf8eeb913b4efac7a064ed9ffe6946080526020600060a06000610100611b93f4602855600051602955600060005260006020526000604052600060605260006080526020600060a060006001610100611928f1602a55600051602b557ffa194dba78ee8b822744bdbcb38ec187ce7e6957ba51c87d846781edc354c2de6000527f7df9c36794bc5982da95b00d072d4de68c47c54b7764b1a445bd00c418d489c16020527f6c1d819223cb31c461c96697f336c1da899f543a61d5964258167c4b874db3dc6040527f4ce7bacbcebb07f25acb5ef88add479e12c3b0d61e4c0b8bae8d909ad260f0226060527f77c9584e2c81ff7a15790f44da433b1774037cdad4197b7f5919f3c7362439a26080526020600060a06000610100611aa7f4602c55600051602d557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f01fffffffe00000001ffffffffffffffff79cdf55b4e2f3d09e7739585f8c64a6020527f01fffffffe00000001ffffffffffffffff79cdf55b4e2f3d09e7739585f8c64a6040527f615dd4a0a844dbbc1ba9dbc9caa8a519a38e98fc4b354dbc92833c2762344bb66060527f633ba1bdcc154fe6e0c3d52306e212ae81f22910d9775e2c0b7ce8a7a88b1c896080526020600060a060006001610100611940f1602e55600051602f557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f8f9cd5d78b75c2accc5121383427522b84cb4c2a8b56c1f94eb4a0576183d3c46020527f8f9cd5d78b75c2accc5121383427522b84cb4c2a8b56c1f94eb4a0576183d3c46040527f02fffffffd0000000300000000000000000000000300000000000000000000006060527f02fffffffd0000000300000000000000000000000300000000000000000000006080526020600060a06000610100611c20fa6030556000516031557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6020527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6040527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6060527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6080526020600060a06000610100611978fa603255600051603355", + "nonce": "0x0", + "storage": {} + }, + "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": { + "balance": "0x989680", + "code": "0x7f20aef1c1f12d6a92cb52c4715a73e8c2614607f6ac041e6430cab9fe7fcdc1f66000527f1c939c4275bf050dfd34fa9b8f3f385d8aceeea459e4da4d6f5be4bf21c30c4e6020527f041d957b0f7cd04de520dbdfb6caf3b7e2c93f15dfb83ee4964259dc3a71010c6040527f1187ca1a59643ea4c84ebf358eb75f0197b94ccf1de9a611a8aacc67e98b81596060527f04c60f013196b55a72e324986492f7fb42bf9a29dc1eab9f3600576e609908386080527f01de910256aa0b0cf620ad54825cea02f2a010466e03f48525a844480ce7ca2b60a0527f12bd4e9e7da40cb226005e886d4157519c785583ee0b628a7e170afca0040a8360c0527f2af1146a5a0a77a33db10bb29c0e88c2f129f12da3e337e07207adc8fe35fd9360e0527f18d9d93d2709144afd90541edb4c76af2e1dc914e7b798802dbec728e8545e8e610100527f0f6c1fc929b35d345b04e7311bd92a7c4cb484f45a4a2de21d822b646ec56bb2610120527f197f6a2343a24edf4f5ca3b3bb758accb273d4d73665d6fa3162b3aa91641baf610140527f167a452ec75749fa735a9fbb78d97befc3f7728664c4addcb0685ab2f56ee7846101605260206000610180600060ec60087ffd27c6ba6a708c14c70af9ba56fa769590455ac5d595eb467381738bd373d77df2600055600051600155", + "nonce": "0x0", + "storage": {} + }, + "0xC192f888ADA47142Ef2c856FC2C35197eea9E718": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xc14a8497cfed2168f05952f5437042184f962496ae2ad8f389cf588ae6ae5426", + "storage": {} + }, + "0xD74CFe323387aE2fd070CD046173026716D8D649": { + "balance": "0x989680", + "code": "0x7f010ecc09792089d18d4479db8993c8fcdb89a002902be5ece3271bd6659d7e0b6000527f044972c01a9d6ba28efc73430f44409753c29ddbae5bff87273015f602ab1ce46020527f05843ae5b1feef147e98cfc86520ffba73ac7d193619ecffbebcb43a646bb8ce6040527fa1b37d411bf6aef0bf6fc51999378760024b9887c33d3bb81a68d3c9b75081706060527f9560b0ce42d34e540905f397216d5c5db68e507e5f426d697153eca14de27d006080527fec577da7b3b854936beb95a33eed744afad1634bb7caf1367891d297cbc7c0ed60a0526040600060c06000600a7fb3e4b6e12f51d93384e52aedcde8fdb6b014c0a3d95f3ded6e7f0d2b57dbef4efa600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": { + "balance": "0x989680", + "code": "0x60006000526000602052600060405260006060526020600060806000600161d14ff46000556000516001557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f7a716c6c3afadd1671084c199b249ab67cb13b24bda9e286436fa18f7864e4976040527f10fae069ce12132048de75c2026c733caaf588c455a968b3651f7c228fa44b246060526020600060806000600162010699fa6002556000516003557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f99f4746ad5cf85f771993c0fd69d90ba6aff84fd3b54bbfaf5f37452d1b728976040527f1b8f04ef96c64881c8e59ba85d32c031b8596e1d8902abdb28efa35741bdd6a960605260206000608060006000600161c852f16004556000516005557ff27665304201615ebfd77f43b648a3dcfafff868a7cdb9aeffd48ec1e264856c6000527f64bdcb002895982b9ce61851c1432eb49a3950047c2d7ffec0cbef0c1e64391c6020527f183664ca17e24e37d11872d0c0598d15bd9ef3b7795ccfac411d31c772a67cea6040527fffffbb016c07414c332e7c980d032465d78ecda7783ba73789fcf5d2d4d9c0c56060526020600060806000600162011c5ef46006556000516007557f41ba54f83d2c0d9b4f38d9d9d3ca20379b17295a7086a01b2abe79a8836e7e186000527f51b34b41f839df524328d27001af78a2278758e6ac46b9e370472fd52ae78ce26020527f0916b5e6f73c3cda7ba0fd79206f5dcaf3f2ac62da7223f3da4d316e6c31426a6040527fa7360ef9b3f7448986a48fdc1eb2f8d1739b2dbf1e02dbc629f01ddb0a8f5d0d60605260206000608060006001620185fcf46008556000516009557f4537e59187daada0452406912ad285677796e5f3343eaf3f6a8cc62d8da6092f6000527f0b256a3b254f8a868901f48311a481702c817405e994b48ddfad842d4058071b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f114edb3d78635682a891fa57035b3411904f8a3f346d440faf7534c7e6077ed2606052602060006080600060006001620162ccf1600a55600051600b556000600052601b60205260016040526001606052602060006080600060016001620160faf1600c55600051600d55600060005260006020526000604052600060605260206000608060006000600161f04af2600e55600051600f557fc6dc4bda4074f5f3b4e12522a9a0223053dab048a7d424e88ee966270a22eb4c6000527f94dc6447ffd64c131b25e7319daae0f199fa9166236b1548f969de00aa09641d6020527fa407f508e892c43f0dd3ac2cc0dddbd939d39bb6faba6e498fe6e97cef5be3196040527f5d615f63e658f52f872d2b7bbb4bcbdbae0b4c3df2a73bee519578b185d3e58e6060526020600060806000600160016153bff26010556000516011557f33d5feefc5519ec25cc0100957b7608d3665a475d3783bdb88ba5b53908dae916000527f36812bb46b76453c52d59b88b683c4c28ab62ee6a35e4433ad3a054d81d9971b60205260006040527fb1375053bcc1d5d98acd0f6ed39352aa4c0956210280d87cb01ff69e265234476060526020600060806000600060016201352df26012556000516013557fdce6a42b5553622247140cde69633c8b457fa610f13d087cd48fb82e2995b1a66000527ffdb503ac2d6d53bd6a5a40ed90c1c40c1e41a5486ec04ccd5f0ea21b3ef59c1c6020527fbef9c5fd0a2414d203c03893359266c7c0b935596670b0f03c9c2d71bc58a6376040527fffff827136bbf05cf1256f0c6dcc1d55f964e1e8dc8eac450b56370ed6b7c3e660605260206000608060006001600161bc37f26014556000516015557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f6eb702a6332e56b41cc0cd5235b32b1ff7c6cb9d486e2b3216f08a77433033f96040527f572979406e827f3ef2b31fc2678f1f6c7b89605ddea9106fa302fda7af29095c6060526020600060806000600160016201596df16016556000516017557fd2d2ddc40c9eba073cf7dc252b24d4b859faf5f4d76c484030bd7442f773dc9b6000527f42ceb9bfd0c82e953f894afeb9fa4bac618ac96fbcb6ad0ceb923912acfe281b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fcf55bdbc0e2471363b3ff29e3c95b4fb79c962bfddcdc25fd7687dc28ece8edc606052602060006080600060016201452cfa6018556000516019556000600052601b602052600160405260016060526020600060806000600060016201245ff1601a55600051601b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fd47dd3c1d041a555aca1b52f7198fb903eb030222fa613eef67ba627fa0640a76040527f7b5642d919eeed48663cc5f5af3c554069729e2cff8be177adf994f65f722fa560605260206000608060006000600162013c1ef1601c55600051601d557f563ac94508886a144c2c03279382fbd9ecbc8710b0527dedee83332fbaa1df176000527f08433182194af83c622691218fbe4760f097cb4d9bffe06d3db15b921eaf191d6020527f45dd3caa2bbdf31bc21b70e30dab5617e2062864ace8d7b2b0d783b08bd3274e6040527fb047a3a77f908c13d37b2763331b7a52fdbc0780d8e3b53cfa1b7df03c4f072060605260206000608060006001611793f4601e55600051601f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f743bc6098efdaf75f878572b65040cf9459e05d875e65eb140592f6a5e82e6ab6040527f765e9112299a4b18d31198eca89311fcbabc0d5b238be6f688a496e7751ef882606052602060006080600060006001615560f26020556000516021557f2e098924832cc1e3e61f37e39c0e5865e5060ed0268aeabf381558565149cf606000527f30ca5d41c93b865e912445e13e0113cbfbc76d48a59e7ca00ea304f6c1d63e1c6020527f9cb92db99c342a7a4d550f5e732dc30201822319a7aa4ee4f599c5c648bc66d76040527fffff0164291505107e496abdb5738a5cd089195b547afb043b09909da06cb13760605260206000608060006000600162014ad8f26022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fd61240180ee4ba2ac39064feba53f2f5655a3555f1ad982b68f24d46fb0abcd76040527f2833151b144a0411b05c2904e358f54bc7dcb1f23ccff4cfaa2913ec1c5fff376060526020600060806000600160016182ccf16024556000516025557fa8ad052dc706ed8513a5e200da416e7230339f1417edbc36810e6390887621af6000527f33184a5cf1dacc9891af332af34024f1aa98ba82751572cd1ea2a00ee2a84b1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f16a0fae6f494f63f176aab5f15d2b09c5da5fe43f6650c406d1432b5f5786ccb6060526020600060806000600162013a8af46026556000516027556000600052601b602052600160405260016060526020600060806000600160016201829ff2602855600051602955600060005260006020526000604052600060605260206000608060006000600162015b6df2602a55600051602b557e5013d7a5fe09b36373406442599663a125ad3f4a11bd9780c149f1f83827ff6000527fab11953158f950c085665e576ccba0a135e0ff7acf5b87417f0237b0a5d61c1d6020527f4480cc59fa0a1b3ade81cac1ea3e8a596b4966086e72948923348d7aacc52ce56040527f91a72e339775f3bc04cc1233063435de168690521311f42fe25ac55e9f4001ac60605260206000608060006001620156a9f4602c55600051602d557fac6eaac38cc30405f1571eefb890b4a4ec94ae45782d8107158c7b4f25ea8f726000527f2717660cf7c0a7a6d80ee4adc0158d9550deecf7744d959605c3754f9f9e191b60205260006040527f299f28af54efce351b5d16681e5bdd6e58427c9e0c031986d8828f9ec078ff8c60605260206000608060006001600161b3e5f2602e55600051602f557f7b931c95a91a9b1adfffe8d278110e6894ba93fd1e6300cffe0e37ba6952efc36000527f8ed55391f54fb886f4598d4d0ae7ed1fea86797718916b9c63c41fe0890aaa1c6020527fac275c5d8acc7f4bf159626eff9b88d082ef2cb85970ce49cc51bb25685c28f86040527fffff3e35ccf1ff364dd43fb8c80a5b24dc9233de11caf201c065570ad28934c060605260206000608060006001600162011234f2603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": { + "balance": "0x0", + "code": "0x6c10000000000000000000000000197f82000000000000000000000000000000000000000000000000000000000000007702ffffffffffffffffffffffffffffffffff00000003000007077702ffffffffffffffffffffffffffffffffff0000000300006780000000000000011b1a7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a006801000000000000000076013590cab83b779e708b533b0eef3561483ddeefc841f59009127cc9700000000000000000023f00c00014ff00000000000000002230080567d02126262626262616137d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007bc9700000000000000000023f00c00014ff002c0000000000002231089009677fffffffffffffff7702ffffffffffffffffffffffffffffffffff000000030000690100000000000000000090089010900b60b2557702ffffffffffffffffffffffffffffffffff2000000000006001901876013590cab83b779e708b533b0eef3561483ddeefc841f57f7effffff8000000000000000000000000000000000000000d900000000000001900b1c7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60057ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000090080460b35567d0212626262626266a100000000000000000000090167f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5717676767676767676760000007676767676761c1160b4557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7f7effffff8000000000000000000000000002000044000000000000000000000190066c100000000000000000000000007702ffffffffffffffffffffffffffffffffff200000000000900390077f80000000000000000000000000000000000000000000000000000000000000016f800000000000000000000000000000000660b555678000000000000000774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a1d901c7f80000000000000000000000000000000000000000000000000000000000000027f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901390177ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd90186101117f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd68066aa0a5319bcf5cb4090760b65569100000000000000000006000900460b75576013590cab83b779e708b533b0eef3561483ddeefc841f5680100000000000000009010900260b855760100000000ffffffffffffffff0000000000002e0000007f820000000000000000000000000000000000000000000000000000000000000090176901000000000000000000671fffffffffffffff900160b95519691000000000000000000076013590cab83b779e708b533b0eef3561483ddeefc841f507900468066aa0a5319bcf5cb46801fffffffffffffffe1290177702ffffffffffffffffffffffffffffffffff00000003000060001c6f121212121212121212121212121212127f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5777effffff800000007effffff800000008000ff00000100009008901260ba5571767676767676767676000000767676767676712000110000000d0a300e750a000000090a0a90101b677fffffffffffffff7f8000000000000001800000000000000080000000000000008000000000000000678000000000000000900990037f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6d010000000000000000000000000090109012671fffffffffffffff6a10000000000000000000001712651ce97e1ab91a7f7effffff8000000000000000000000000000000000000000d90000000000000190180676fffff716b61616160b0b0b2b0b230b000008010d0a2b0060070360bb557ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007176767676767600000000007600000076000090051469100000000000000000006810000000000000000010901d7f8200000000000000000000000000000000000000000000000000000000000000777effffff800000007effffff800000008000ff000001000090109016760fffc000000000000767676240000000000002b05760477f77676767676760000000000000001002e000000000000040000000e0000000001c60bc557f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff76013590cab83b779e708b533b0eef3561483ddeefc841f59001901d6f1212121212121212121212121212121276fffff716b61616160b0b0b2b0b230b000008010d0a2b001060017a01090000000000000000000000000000000000000000000000000068100000000000000000091a9015900467ffffffffffffffff68478392145435897052900a7f80000000000000000000000000000000000000000000000000000000000000027f7effffff800000000000000000000000000200004400000000000000000000016b10000000000000000000000008901690176a01000000000000000000006b01000000000000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b0009177e40000000fd000000db0000000000000000000040000000fd000000db0000d37702ffffffffffffffffffffffffffffffffff20000000000090079019027f77676767676760000000000000001002e000000000000040000000e00000000069100000000000000000000a901b60bd5576013590cab83b779e708b533b0eef3561483ddeefc841f5156d01000000000000000000000000006f80000000000000000000000000000001901d60be557176767676767676767600000076767676767667d021262626262626900307197176767676767676767600000076767676767667700000000000000090030415637fffffff7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd9001167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6f800000000000000000000000000000011d04156f800000000000000000000000000000016101111060bf5567d021262626262626637fffffff0790147ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb7e40000000fd000000db0000000000000000000040000000fd000000db0000019012901060c05568232323232323232323197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f8000000000000000000000000000000000000000000000000000000000000000900190047fffffffffffffffff7effffff800000007effffff800000008000ff0000010000690100000000000000000010900560c1556801fffffffffffffffe7f77676767676760000000000000001002e000000000000040000000e000000000901a7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb760fffc000000000000767676240000000000002b0576047901360c255156101117f40000000fd000000db000000000000000000000000000000000000000000000190036d01000000000000000000000000007d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf96f8000000000000000000000000000000009060a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffff7effffff800000007effffff800000008000ff0000010000677fffffffffffffff08047ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb06910000000000000000000901490187e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100063800000001613157176767676767600000000007600000076000067700000000000000090136f80000000000000000000000000000000717676767676767676760000007676767676767bc9700000000000000000023f00c00014ff002c00000000000022310890081b90137f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f8000000000000000000000000000000000000000000000000000000000000000901d900b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9007901c717676767676767676760000007676767676767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb901660c3557f80000000000000000000000000000000000000000000000000000000000000026b010000000000000000000000900a03157f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1d1460c4557ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007f62d8fffffffffffffffffffffffffffffc18000000000000000000ca0000000110671fffffffffffffff777effffff8000000000000000000000000000000000008001900216684783921454358970526c010000000000000000000000009012027f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000017e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00030b7f800000000000000000000000000000000000000000000000000000000000000068100000000000000000900160c55515760100000000ffffffffffffffff0000000000002e00000076fffff716b61616160b0b0b2b0b230b000008010d0a2b00901d90037806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe901090057e40000000fd000000db0000000000000000000040000000fd000000db0000016f80000000000000010000000000000000169015017e40000000fd000000db0000000000000000000040000000fd000000db0000d37f80000000000000018000000000000000800000000000000080000000000000009016176780000000000000006801fffffffffffffffe901867fffffffffffffffe774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a6c1000000000000000000000000008900b0b7f7effffff800000000000000000000000000200004400000000000000000000017cc9700000000000000000023f00c00014ff0000000000000000223008051d9002777effffff800000000000000000000000000000000000800169100000000000000000001612156801fffffffffffffffe691000000000000000000002147f77676767676760000000000000001002e000000000000040000000e000000000691000000000000000000005017f800000000000000000000000000000000000000000000000000000000000000068478392145435897052021a67ffffffffffffffff680100000000000000000360c65560057ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb09009027f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff0000016380000001900660c755677000000000000000690100000000000000000090171760c8557f8000000000000001800000000000000080000000000000008000000000000000682323232323232323231763800000007f800000000000000000000000000000000000000000000000000000000000000090140767d021262626262626760fffc000000000000767676240000000000002b05760476823232323232323232308036101116f80000000000000010000000000000000778200000000000000fe000004000000ffff000000fffff70008901067ffffffffffffffff600090031467b368d219438b7f3f7f800000000000000000000000000000000000000000000000000000000000000090121b777effffff8000000000000000000000000000000000008001778200000000000000fe000004000000ffff000000fffff7000690017e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0068478392145435897052901260c9557f40000000fd000000db00000000000000000000000000000000000000000000017e1f0000000000000000000000000000002000000001000000000000000000001719016801fffffffffffffffe67b368d219438b7f3f0b03157d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf96770000000000000006f8000000000000000000000000000000009056f800000000000000000000000000000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe69100000000000000000000860006000f3", + "nonce": "0x0", + "storage": { + "0x00000000000000000000000000000000000000000000000000000000000000ca": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x00000000000000000000000000000000000000000000000000000000000000cb": "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x00000000000000000000000000000000000000000000000000000000000000cc": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x00000000000000000000000000000000000000000000000000000000000000cd": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + }, + "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": { + "balance": "0xffffffffff", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "storage": {} + }, + "0xd5A8353a487e0749707fee138b741aeb2061C14C": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x4b5f705c5993deaa35a6d4e991c09c52f1d54151048b241126aa7c780cd2723d", + "storage": {} + }, + "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": { + "balance": "0x989680", + "code": "0x6000496000556001496001556003496002554a6003556002600455", + "nonce": "0x0", + "storage": {} + }, + "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": { + "balance": "0x989680", + "code": "0x61026260005260246020526102626040527ff1fec7959374ce5d274bb0a066fd25d6a7a0eda5d66247e90611eea900d93dd66060527f3261bf7f4a1354ec9c06574626a9f622a4b463d8547013098dcafb926e4736a46080527f2a2f602320d89b1d7330c8afdb044737104b3c1df434e20cecdfe27fff1d1f2760a0527f1ecad556a17a8a7bd6e68d5a04868ada5e17684e3f260e2fc8142dee9b3812e660c0527ff1f6436c628b04937be67aaf3df114fba877dcf697e789ef8f3e0d65da018b6e60e0527f5134802f76d89e54193a1efd277cb40b2fef4819b6c71803b540d35a5736fa07610100527fb82884b8ee0bdd6d160bb37981688eaf2997550bd816f22d790b68f6a613f115610120527f4b0cfb396fcd8d20c873179465d91a926b35a127da6851106e93a1c95d306531610140527f2cf297554aea5d6a9c03a2397f17e3ed672af0c83dd0250acceb68e7297b7704610160527f64f27ad759e258d9021631c63ecdc8e4586ce55237f3a4107c35975cc158def1610180527f24b24b5973e1f540c0f4120009a97e64b8184beff858d50d4ad2ffad3951ddc06101a0527f819c0f43d13523fa4ff0d19e2125a05c420517eca779beaa2a7cd38184210c476101c0527fad10b5f2259319e47bd25046de0a0b2affb1610fa4b7e3750143e9aa35c44f726101e0527f9f0ec1800e9fdc12fac4dbfeb087c50e073b95c24b68419e31aade25653ba836610200527f2aa1362bdf0f50a44625a6f6cf94471ec9e37e1362f1ae6c54bd73bc48d175f1610220527f7432b4e648de16c9ff2ccd7d0c46bde6d99f0202b94ad09effb10a3e03e82c1a610240527ffc3c493d3e7658f8de59135f4183cac601e3f940b0f269625ff68a106420ff66610260527f0581e520bada0d8aea39b5df5cc1580f3743fcf4367944cc3a777f8687c3dc6b610280527ff2d859b0ae0467db1581a1825ea8f32b041b6fb47b084986f8aa7add00e69b496102a0527f8008a31bb9d8901fdc563425ed15567fa92f3f2caac4a95b4f69986861257b3e6102c0527fa6535c9d5c6eb1fd9d1af1ffa7d9a17daff3d9f390b94cdb30adf8856754b1406102e0527f7ce7a6bbb1642d6d4497b7f29914c5ce41da9915e5b1ffc8b418226d175c7478610300527f070aa85789733ac4df0330e4dc3359ce3cfd092c7ca52fb4e7329ba9478d0a49610320527fb31b0f71a8f651c80427c925f7866f5eb09570a1c0c916bd287824b01a30a76b610340527f4596e9e1d193313e1f1404d9ce3b9f0426230c24927405a48bf4adff74e76fde610360527faeb92923019d16f8790ccc7b71e92b68924f64798ef2a9208548c15e21b4086c610380527fb99ab67cd7c8af790ab5356fe5a0e28d5df8c51dc22b83ccb2711f30965f1e616103a0527f2479fc94a5451dabd9828512b8b40f67ee0b6d8e7eb1bd866992cb058930d5116103c0527f092a2183f2c6ef97cfde4785cc1c896c8bd768bc0a870ffa104345dd7a38aa216103e0527ffb91f752acdcf005d60392fce991749582688ef75179c1e5bc302e3474fa092f610400527ff01bf4a1ca9ec98b16516dd639870c7da21822e753f618566bd4116407bfa814610420527e7b1078ef968ef0d58cefb9442b9f72a949f123d74fe9cbfbeba9d1ebaa50e9610440527fadf61176f5482726f72e521273f004ff47ca791a2d36f46ad735d8c5daa7522f610460527f6a8c8353f541becd5b975007a0cedebcf07546cadb88f89c3611c4532159b0a2610480527f6fd6ca54878a97d886a2496d88a97f39a91ed2ea43b2e287949f111b94e2bf116104a0527fa52821a5b62778a1f910b7dd380e0d35f460a71b9ea7b63e4f2b751af2911e766104c0527fa8680a459d4dc3edeb3b23251632ae8a41949552e870913ce7de2ecfccde155d6104e0527ffe15c24c187667c8910e993fb1d04570b7e0d9ac330b1a0ea68beeb755e9d7ae610500527f3d2c6bb3e5ec048336342fa09dbcffd6e3bc9db43d8d273c618328d4e312dc3f6105205260eb6105405360686105415360766105425360366105435360306105445360df6105455360ab6105465360286105475361026260006105486000600060056245d72df25a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e0516008556101005160095561012051600a5561014051600b5561016051600c5561018051600d556101a051600e556101c051600f556101e05160105561020051601155610220516012556102405160135561026051601455601c6000526003602052600b6040527fae8cb809085836c6461fd847d701b558c26c51eb89ded0e4ff921ede82f27af66060526060608053600760815360456082536058608353609460845360806085536072608653606560875360c3608853602f608953600b6000608a6000600060056102bcf25a01601555600051601655609560005261046560205260956040527f51e308cca5d5ac57dbe129b458780de43b42d08aa050668a10113010a49dc6f66060527fd82d6601a2baecac57f0e1c15c28b44dabcd90369f1a2f8cd1b1c791b5e41a776080527f7b30038e72372e57653bbd08827dc52e9d409e9c3f856cf957e3aa07935efd3f60a0527f607b55147384e53c54b16ad07bb4f2a4552a5ef66aac08876aa63adcd96fd73360c0527f98ea449950d7e2b1211249ba3a5497695f288c7cfd000000000000000000000060e05260006101005260006101205260006101405260006101605260006101805260006101a05260006101c05260006101e05260006102005260006102205260006102405260006102605260006102805260006102a05260006102c05260006102e05260006103005260006103205260006103405260006103605260006103805260006103a05260006103c05260006103e05260006104005260006104205260006104405260006104605260006104805260006104a05260006104c05260006104e0526000610500526000610520526601864f62290a6d610540527f6e280af90f6c1ab0488405bda8fc417b0f391199fd48342e4336d01c8de18952610560527f5b8ad7f1b5b421f9e73ee1e6fbd2dcac4422fe7a7912ab495c50857aa41d927a610580527fd21c9732633fdfc61ce2b92bb93b1a8138c99bf822c316fdf2a767ec2f111cdd6105a0527f6841a331d9ba76ecdac0bc037be9690a436647ea5f0a066ec929d3f0d103d1596105c05260696105e053604a6105e153607d6105e25360106105e35360596105e45360886105e553605e6105e65360986105e753606b6105e85360716105e953603f6105ea5360fa6105eb5360056105ec53609e6105ed53602f6105ee53609560006105ef600060056301060193f45a01601755600051601855602051601955604051601a55606051601b55608051601c55", + "nonce": "0x0", + "storage": {} + } + }, + "chainId": 1, + "env": { + "currentBaseFee": "0xa", + "currentBlobGasUsed": "0x40000", + "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000", + "currentDifficulty": "0x20000", + "currentExcessBlobGas": "0x20000", + "currentGasLimit": "0x11e1a300", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8" + }, + "fork": "Osaka", + "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f", + "transactions": [ + { + "data": "0x2d", + "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6", + "value": "0x0" + }, + { + "data": "0x", + "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46", + "gas": "0xf42400", + "gasPrice": "0x20", + "nonce": 0, + "to": "0x538A8474EeaB43d5a960164c554A20400151D479", + "value": "0x0" + }, + { + "data": "0xd62ca02e7d6738996d60a387da91a74c438dff99e2e30450d66a7985d5c657d0e2", + "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f", + "value": "0x62f3" + }, + { + "data": "0xa2c35d7d43a94d59ac5163860c03d7c78e1d76a7ba7c31a46b", + "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d", + "value": "0xfec4" + }, + { + "data": "0xf22e90978887563e1316e37d58f9c440c5ff3dad0958ad7a135ac3e2e9138b5341c1194761f2bd698fdc91b7058e657af5941ff7aa1b8890e51ed18677d541eca021c6efe2762bbf0ee6baf42c741a1134ea12", + "from": "0xC192f888ADA47142Ef2c856FC2C35197eea9E718", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3", + "value": "0x6c64" + }, + { + "data": "0x8ad4c41cac6d56fbbf1d0d0bf5d6", + "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F", + "value": "0xe27363" + }, + { + "data": "0x5214c25b6a7f0ecedc0b5a4aabac02ae1235d3503dfe2b50df5ec8e1dfe00b1785cf0f6c000eb9413b0e2929ee87f64c7044853eeed72caba5df53681e4e7b1344ad1f0d79801b94464afb3b080b99953ee906", + "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c", + "value": "0xcf8207" + }, + { + "blobVersionedHashes": [ + "0x01247b3190ad6b61d69c66ac67a278508b7cc80b63a7d3f183965818f46d71c2", + "0x012cad5172a80ba067a9836349573f8c09a6dc870eb9933ed445787556a4ea59", + "0x01b7b97c0fd264b8559089187f1e9c8b736854d626379b9db34473fd96d3bce3", + "0x011907322c3d5ec3b09fa61dcc48f7a0eb8750e9b3cb911a338f126f1a54d2b6", + "0x0159e0a1867bb093a1ed6beb9a7e1aa843a926a8c77ee604899bbea1222ba448", + "0x011eb4c2246fec736cda7b5e62a4f5eded1e6b4948632ed38b7da929c1ca83e5" + ], + "data": "0x87d848", + "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d", + "gas": "0xf42400", + "maxFeePerBlobGas": "0x100", + "maxFeePerGas": "0x20", + "maxPriorityFeePerGas": "0x1", + "nonce": 1, + "sidecar": { + "blobs": 6, + "commitments": 6, + "proofs": 6 + }, + "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89", + "type": "0x3", + "value": "0x0" + }, + { + "data": "0xd317cdd0be355269b7c5b51cd37d519950d774cb5598ffc8e74bca40d0c243a3b83a00612a30fc5faa80722094f38c6002904e1307cddc4e8f191e47191b9584c28bd7561a80b0f4c91be21f4556640d3dd85033038ec2c7a52d951b93c283e4dec10482186d3a732a269deb66abb6d8f560df063baa4ccf74baf3dd0f579b387985541ee3f0427ee3c3c3c229ccd82da43ca03e3561da96eb66c7e983d6efdfc48583998abe381e796863f666bf1a6f99e019a96ca80b8b12415b811f0201f051e6ba702173beca86251fd19b5f172e27d977a730e6986543989a58e39fae4ed6a75a59b9ae505890b2a195001704fab5a0b4af848c04862be48bdd5c82babf9e56b9adff9fa642c762f64b5536cacb260a2615d7b852dc7fc807b1d67a0e54d82557f5d39dbf3c8ef14deee959d261321fc9c7ca64dd05ef869cdfbedc19ac49fa8a92725b1b180a57d1c777e34f583f14215a57c7d33f4b3fa04c81f7cfea48c64ce135aed55b3c23ec58c8bdac489b8f38c6631cfe594b63", + "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb", + "value": "0xa4" + }, + { + "data": "0x", + "from": "0xC192f888ADA47142Ef2c856FC2C35197eea9E718", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xD74CFe323387aE2fd070CD046173026716D8D649", + "value": "0x0" + }, + { + "data": "0x23c2eec37c11cce00a8f704284073089267e7f0bb5b5258035f584b6cd8e3dc2f8c9196e4c4194faf6d4fd4db3", + "from": "0xd5A8353a487e0749707fee138b741aeb2061C14C", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10", + "value": "0xd0" + }, + { + "data": "0x061997d49b5528665dbc3d800ae7d897ac84137fa32000299fdb0c9777ebc080a9aed590d6", + "from": "0x52439296aa999dbCF01bA02E03F5d59F0AE8Ca46", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876", + "value": "0x85689d" + }, + { + "data": "0xcde33a3fa310af41e8a2fc059de3fc0222e0982551d5d80fb8bc2e5f3e34b4f4fe3a8201a9d47b414357fd2db6817eca4d6b81504f6874f82ecd62e6720a0fc7b39d3a4201b024b7ba304e8e7c765fffed771999cc53fd9c93cad3", + "from": "0x535863dA03bc1834eeA10eeab8FF498565F33f2d", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190", + "value": "0xf45bc" + }, + { + "data": "0x88a6f05cf67bbdcc10c4826a7f3dc1a835777e9b99148f860aaa0f4e3403db9d05c9824e2afad1dfff78ca58c8eb57b3570d472049fecb75495effc83061f8561fcdb6a395e35a467359fecab218", + "from": "0x1DEF26E2A310e3984210Bd9d4D67E19d721043A1", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce", + "value": "0x6b2d3b" + }, + { + "authorizationList": [ + { + "address": "0x88f9b82462f6c4bf4a0fb15e5c3971559a316e7f", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xbcad8bdc514baf5efab74757cec1366ad303cb086e4fc286650a499aa2c51979", + "s": "0x291e47131cefbca9f42434f163e1be4d6fec29160ce5f1ed716b3735e5b01e7f", + "v": "0x0" + }, + { + "address": "0x00000000000000000000000000000000000000f9", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x71a82efb37c3ecda82184a469fe3095e61f879e9cd6cd5cc57c8db85623be99d", + "s": "0x62b8658048dc674f566db07998c96909310096f5e90788af763e6b3034e78387", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000010", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xcabfcca10b4052db14893fc01934f4d9ce6a4a06984a8ade1fa538783c89bd7f", + "s": "0x1768f53ad91b153d1340e0e9b1b2cbac0045f3de0fdfc05a108aad36c033091b", + "v": "0x0" + }, + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x36a9141d12a6a5ac448d602b8aef8cad98744204d15197dc9f78e501e792d07e", + "s": "0x32e21e07bd4dfbe1a4f009a32d9e1e69006f290993324c31787e5f110a42e115", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000002", + "chainId": "0x0", + "nonce": "0x1", + "r": "0xd66534866f9f76bc71377f381e6a57df9e7ced92cb350241c0f48b5c776848a8", + "s": "0x4c40ed83b35061e1a7c94909aff2b00ac4b936150ad4de8a3ae3b3e498be0635", + "v": "0x0" + }, + { + "address": "0x00000000000000000000000000000000000000f1", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x64aa96c5157c207876e42787e9dcdb83fea43c95b3264a41a88f5e1d9d4c99ea", + "s": "0x49d207f4228fd08c0b2be3fe77d341fd466ddb4b2cee0426903f608f0ff881eb", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000003", + "chainId": "0x0", + "nonce": "0x1", + "r": "0x7b740e7556488f71d67851fa3b750ed08dc672413d8bc85a31aa10d8b3d41e14", + "s": "0x508ba9c3d39cd3061ec7db5533f01342abd201dc964487baa4eba8ab4394d02c", + "v": "0x0" + } + ], + "data": "0x68f591a70cb6fefad1b2aa3c181edb3b87c7fecc8376afb6719b5c0801ed65920341fc1cab010d3695f9151974e40051a84371823d7b65f1", + "from": "0x862B38c425EF5544d0127449A12c89C46dd3E050", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x000000000000000000000000000000000000000F", + "type": "0x4", + "value": "0x5192a0" + }, + { + "data": "0x00", + "from": "0x0233362c058b2fCc8093841B1073A90D673E7F12", + "gas": "0x30d40", + "maxFeePerGas": "0x1e", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "to": "0x88f9B82462f6C4bf4a0Fb15e5c3971559a316e7f", + "type": "0x2", + "value": "0x3e8" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x1", + "nonce": "0x2", + "r": "0xdd95902a4746dbf0cb38778983b6a5061c9784572e18492bab91b69a04315a29", + "s": "0x115d234e528f56cac392831ef418acb2db384b9b92749f4174e4e2ca2b2878a3", + "v": "0x0" + } + ], + "data": "0x68f591a70cb6fefad1b2aa3c181edb3b87c7fecc8376afb6719b5c0801ed65920341fc1cab010d3695f9151974e40051a84371823d7b65f1", + "from": "0x79cca006f0792Bf40a6d4E011c2884eD862A52DF", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x000000000000000000000000000000000000000F", + "type": "0x4", + "value": "0x5192a0" + } + ], + "version": "2.0" +} \ No newline at end of file diff --git a/cli/tests/vectors/fuzzer_test_1.json b/cli/tests/vectors/fuzzer_test_1.json new file mode 100644 index 0000000000..fa44c8e294 --- /dev/null +++ b/cli/tests/vectors/fuzzer_test_1.json @@ -0,0 +1,497 @@ +{ + "accounts": { + "0x0000000000000000000000000000000000000010": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x00000000000000000000000000000000000000f7": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x0b530C4203F212318CE214ae2F1089d2478cb56c": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x157cbf9b700eef449fabd47069fdbe505932ef1adad4838332992036780813d3", + "storage": {} + }, + "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": { + "balance": "0x989680", + "code": "0x6f19caff34fc5d41317e29d5e9f4f6d82a6000527fe2e0acd91783ca4e41ad927047dd549ad45b2219aa5422dd2c26b3399e84c82e6020527101000d80549ce27f0e5d07c4d9e259b070936040527f11e50838d9b10616817a4190ff6df2638128184b156a81f8c518e6baf19227a16060527a01000000000000000000001246341896a0554751d9a2bf3af6980a6080527ff0a8a04a2ccbd323e6e2346cc2be29847a6706d90abd298ec45e7744d4ef260860a0526f03ade5bba92764a5b115252fb5cc366c60c0527f880d73ac87aa9125199460ab8cab072f8b31ac20d28109b5e243f61d880fd4f660e05260806000610100600060d9600b7f6696b9800943dc76700342da15183f39d04923e24aa510de8c23d73c99cae7dcf26000556000516001556020516002556040516003556060516004556f167215b1682993653beaeff0004b14ca6000527fb88e8f2ceae397ab24a56be8ca4b3d6e2274886602ccd162cf64e110fa4a52b760205275040000000000063cf200b79ed865de1688cdf2b3b5236040527f55f49c08a47c5915a84548a59fc200e5ba430068bb0d1935341a6e634aeb2ded6060527fa9306a65a0e604373a8cb4339d55eb0b53fdff55b9379d1133f18c62d14c6f2e6080526f07b653e774e775f620ddf0e6b50fc9dd60a0527f53953e3cfd57d6616abde936c03f1c94b8c31dae7796cb3553212f26960c012160c0526f07aeb25d937d3d5eccbba85393bac1ea60e0527f5b70af1ae11a228b368f5c67f3c038f40be90299f4118a3dbd31c82b8d909840610100527fc2b9d98f02a25efa9fa8860fa9f80a43c73460a0d20e2113bec1c1fd7bf1618d610120526f02701b17eac732f65624ea3cd8be10e4610140527f70a5c5c3a3d6c10d8e4b45dc00bdc0a5e47f1aca6dcdbfb0e121775d61aa5226610160526f042e9f71c007d9db64ebb918fab442c7610180527f1dbe92ebca595a268909659e8db809e1617398e16e62c5f27cbf81d1c5d19ce76101a0527fc55655c9c78415954c172a18aa445dec340dc63eb0e866afdb0a25bdf1244c286101c052608060006101e06000600c7fcfdafdcbe09640f2464567b36afea525ec5de9358dd848c0b53b421a24139393f460055560005160065560205160075560405160085560605160095560006000526000602052600060405260006060526000608052600060a052600060c052600060e0526f06dd8919fb14bfdfab0f526a1f5239b6610100527f0b450443de757b82dd27fd61c3cb9a71e0573f50c339192ae937a298d2fda166610120526f04eda0faed5992fbedf736c817215d2a610140527f061ab4611c80704a98232c964308c34a42eadf0376a9a6e7a3d70ed862ac5b58610160526f14abc9f2f81080bd0071687392261e83610180527f604dd562c7c618761e4853b134fab49f395d4cfdc10a7779e1ee640d1f87af366101a0526f0621325b4b3f4d5b280989cba49a40446101c0527f8cbc5e4e87ea344b0a59a59cbd6c3f485ffc4f24fc4c0358a89e08e1cffd70006101e05261010060006102006000600d7f7524c013a9951987355d80fe3ac319676bf5d5135301c343fd3d5b79d46da74df4600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f17921415f9ff8bb3fe699b6495fe9bb16000527f6a142ab1e5e402bf55aefa40069d0c51592ce1586eaac5ffc39c1b63b3d0ba7f6020526f0e0aa5850d480a3d8cd9d5fa6f1d24856040527f3d0e7f46925e64fdaf666a9e5141aafcaed131e79d8261666dc8b142122e38126060526f0da917cc0d444ff2df50086d85e9b9576080527f6535e60c11eeafa970e381f95da3ed077e0cd30753342840d2db4d489d475dbe60a0526f0f2d7f29490255daba12b39022dcb6c360c0527fc4393dcbf2c5473d49f853993a9a833a2749a590356dfa608666ccd55c0cd04160e0527f0f83fc7c6c0587c4b87d800c8ef57ce037f9a317cbc6cddd33f9c725dc0d268361010052610100600061012060006000600e7fc4895dcd70512f399cd4a6ab3b9a94e6bce2e677769bf3fc66c3287bebbd89eff260135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f16e9a53c8298651e6d39e7d5b323284c6000527f10244f68ae94dd48bc745fe049e67d70681df88b199a2a2ba8f4ed3ff9e6e1d56020526f08e10f8f043e399f7f98e3a77cf2ed3d6040527f8f4928ca60da534ea929dd155350b5ea46f3f9e561a2b4d210c71b56e3e3c8f06060526f07d50b4d03ba978330fc267892bb168d6080527f746e3109a61583a4a2af18673590c08d1209336e235c8b113f81645a1d0fb7d960a0526eda68b12ee5ae79581f8c5ecf4eee4560c0527f62e30c2043d9336045d9594171a87f85caf11cdce1d305def393e6913110095660e0526f174988222802e2e5c94a516878b8c6db610100527fa56b52a69d70336ae79118f527eb303d2bf1c73c98a839485f5c493b9e738149610120526f0ceb05b1a555e9fb31fdf86cccad49d6610140527f4ce60cd5739c269a1a32b33d0c2ced561bbd35d9f2249edb3b7eb4b788ac8f83610160526f02ac71c4092cb44485e40bb9aba9c9d3610180527f443a137d91357ac2f396c90f00c7108f07e48bea04abc4ce8d31af0f47a2fde26101a0526f0853b2e555c99f7b42203a596493b5536101c0527fbc638d3a9954816a8d1d3a248d75d45df83cdb4362d93ecc3b0ebad969f3ce076101e0526f0e47ed6095014c6bb26aebf873f578d9610200527fba610c5276428f46a65f1eea6a8e69fd917eccbb7df1a06467cf06d59a6e0024610220526f11844e132dce68e4345276947724a03b610240527fdda05c2c6a9c936a9a8775a4b2075b7a6103ce6c2f11a225d13ce265fe55394d610260526f01964a9416e284e459360fa860c89a01610280527f23d65d9a7679e4c9ce0fd8ad33fa07bd6060b60eec7fde88fd73dfca094f94e36102a0526f085b4a9ac88c960ddb422fa88b3568c46102c0527f48604784513f5221eb963855b06bce22bda53affdd70e4b98a0ff40b98beaf676102e0526f15447a27385181684a148242396311f8610300527fc2c01489c6e714f44f14c6bac555c3f09c21f3e1cb8f5a4c9cc667e76bb375a8610320526f187bdee96685d72b15768e87738ac090610340527fce1046af57eb88b9c87977253bfb3fdf10e1e8e8d5eed280766bf6fc3d7b9cd0610360526f024aa2b2f08f0a91260805272dc51051610380527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb86103a0526f13e02b6052719f607dacd3a088274f656103c0527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e6103e0526f0ce5d527727d6e118cc9cdc6da2e351a610400527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801610420527d40000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99610440527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be61046052602060006104806000600f7f7f80628a357d42b11e6fd04a25350afcb2a4ddc960c762759e0edc19d2f2d4fbf4601c55600051601d556f190b5d5db51c6a5368c6fb2aeeeed8fc6000527f55c128be3a72201564946bef2a9190c8a1956d850bf5e72ee546f4d883b6d219602052608060006040600060107f99646682ed7d62087f392cee9340a90c98295fe4038d6b5f2c3e6e457a3870baf4601e55600051601f556020516020556040516021556060516022557d080000000000000000000000000011c2b0d6fb41c389c5d3b1d07553e1896000527f63b36a67f2a0ea76ddc11609088fe22a47fca4dc88ce65fc0209c6918f8b9fd06020526f034cf4436a26bd7f98373de09ce810a36040527f6309d107ead83d7f3c1007b00d58be95a0462264196e81262fb57f47dd18c72060605261010060006080600060c160117f3516f04fd741b0b10a8c7a84cca64e82bed0c8fc4b1c16c0ba6f2fed80e74aeaf260235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55", + "nonce": "0x0", + "storage": {} + }, + "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": { + "balance": "0x0", + "code": "0x602260b960b760f2609060346021148a990397444a3a18991c5214863c4103788a8c3a3d5ef59a857b357d063e555e5d49771b4a1a476f545c9d6f53156238486c45395c465c7a32a37f72a186041785628280440668f55f7d9a315d166159657a13f35264786b7e427359017c7b5e01086f89547335046e99635b647d5c191b477e7e4830076372f2f1635f5479581a129e66a16a853afa733c58467c335f4777375e630bf0557647776d72480038a0417261f2313772561843a34011795e0588714a823e6da174119b928972a220001c444873033e9b9668a2747506997c435430575b7b889b7f7e49ff67703c8f0774441b0695325e95368971028630335b44fd1450f439808cfd73733b547d1071f51470183d6054180640425e72719177643c7981706f579c7a647a9e4a5d357431046e3d6857069105f35ca0741113415d381d064809010a11a33650644410170846557181107a5b9f815b06a450711c3217118b1268167f56757f1210967f3116f24308523a9c024370465851667f626f50746ffe386c351b3263307d133e7b413f5f1e5489790a6c438343a241017a75a0536780895c469b1379856c6a1793090a3997651e9451f147323b3539a1623d9d967d7f428c345108f157396e708972500339806088556cf33e76a0586836100730067006038354036b398059368d3063168a8c006f3c6a5744331a3539876e520a3801a0a160093d67fd093b82a474023d5a3b567a6c816f30415416475f12308e531449578fa0083b14386c5b4412953155f04a78033f6f1597379d3512607219311c6314804918666c8a138663106dfe5e76126479649c096176698330689a6334469d14611b463f73f17f3ff354f0fd301e58a2868f1c42194386760264446c586e376c6dfd75513003027f6a691a65445c8e5b33a07b93156d02707465956a647a9a61924073050a1d17040437f35b6644587d33036c3511764846a3125114531e564490101c345d4a1c8e48525e0b59756c101993413e35455b6e050b9d986d7618919d905c6f8e605f77553b8204517a3a9b80967c507f126a3e639d587a3f8ff0185b01f36e6a513f195646478d6617a3327d5991471e55983980381119856d3e7848810833348f51696c77851c06343863545c677b006681368f407a571a618d3771116f706f329676195d5940135a907000387a3597756e519109948b96799c7a98677c345e668139171a14579f3f6f43081203553a3901160a0a691643517d0889365ff03542026e795c49549288323119416020553d36805201038675197d0942633684696c7b3c3e634646897f044463093a41546777895c58138f8b427c80639406566f1d84956ff530fd6f60fd399ea23631197f31446c330271973a32a3155c41480351774263325a79178919761744335f143a6a7d50", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000d", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000c" + } + }, + "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": { + "balance": "0x0", + "code": "0x60006000557f60016001556000600255600154506001600355600160045560025450600060056000527f557f604060006000600060047f36b4f1d52647aba45de94939600358e701ebb36020527fabb1600052608a60205360bf60215360d5602253600c602353608d60245360226040527f60255360af60265360d960275360c160285360c260295360c7602a5360f4602b6060527f536060602c536006602d536055602e536060602f5360006030536051603153606080527f606032536007603353605560345360606035536020603653605160375360606060a052603860c053605360c153606060c253600860c353606060c453603960c553605360c653606060c753605560c853606060c953603a60ca53605360cb53606060cc53603b60cd53606060ce53600060cf5360f360d0537f3726516ff6afb368da0d12e86e99748428aed23ee5bf03f75aeaee14cf1bdae460e0527f2b83cb68e5ba2c412b683dd5faa66a07e182f4f59dc70d6b320d6d4181ce0ed7610100527f746be7ca124aa2bca0fe3dc55c6cc8f44a5e1e2930f84f5a822b44303e0f790c610120527f92d2f1690821e731d4cb9203421ee925f00617320c317a8671939e61666fd133610140527fc08586e712d5efc118cba245e33dc78269240ffb3b2250da12cd5a9bd4dfcac3610160527fddae063a1cd1400af8af40c2b53904fb939a812c511af8821453f2e611b782c2610180527f0eb6da4b4c07e1e290339bbe5c64f16c5e2666bc7c96910d55531ba23ac61f256101a0527ffa397670c3a25dd3500af010e3310f878ab850ab7d66ec1ce0ba296ca5f10fac6101c0527f29c5aff225053603b31d5c5418eda6d9b8b8f02daac699980d5aa18a904f62d96101e0527fb18cb29151d86fce51629e9de4ec92ddf705dfdd9e8d1208052e43b32d83bed5610200527fbdc9469bf7f3a5f394770b6c66aed956de7be64f028b96da7538d61f8c502f5e610220527ffeddd512f914664dedf2381aed820bb578fd2d56b27d78a603db69035f6ada3d610240527f305910ad13ce1288194c6761cbfaf9ecc04bbd56752ee34bd47752e247b266e1610260527fdd79a40b36434911a9631444daaec918c08d2bc9d045f336796e760045622282610280527fb7ca6111bc82161339ab1a2959e78f60bdedbe67c284558c7ebe989d80a8d8e96102a0527f0b3c1a4cbebf19e61db29be4bbdb79f49c2b3ebf94d3ac00375a12c51a495a886102c0527fff11f7e91dd2f5a922e585bf4a3ccf4caf00088d8497fdd4d0eeb03e24a07dfb6102e0527fcccb5a1b972bb15393867efc308981ef6a625bc031d835cc0120177360590534610300527f13b8f82231514ae3ea8a19a6dd7537c0808bde918b15ff1fa1b2dda28f9d1792610320527fc1e328a14eb9a03ff7eb9d65af91d83301b67a3914960b7e7963bc10a010c767610340527fbc4d45ba427d312da4c934a47dc632e6dc7c14119e16b4cd1a81dab6a5e1fc4d610360527fbcaba568741eccb9f3310a67e3b0974970dc10a337f3be9a65642293c265367f6103805260d160006000f0604060006102c060e0845af4600955600051600a55602051600b55600c55", + "nonce": "0x0", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000010": "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x0000000000000000000000000000000000000000000000000000000000000012": "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000000014": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000015": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000016": "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x0000000000000000000000000000000000000000000000000000000000000017": "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000018": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x0000000000000000000000000000000000000000000000000000000000000019": "0x000000000000000000000000000000000000000000000000000000000000000e" + } + }, + "0x538A8474EeaB43d5a960164c554A20400151D479": { + "balance": "0x989680", + "code": "0x7fe1a31e9d6b65985c0db9b672bb6d55b454de1ca89f693b6305eab9d051e63dac6000527f9ceb3fd5b29ea165b971ea736fc32fbad18ff4464bed46f638085a1005fbf5df6020527f1ec47106d4e3c0c6bc569e045db7b6e890d1687ead46da9e515c6e3b9eef31356040527f8fd11b1d99f82e0f419eb7a9ed13736d83391798a157196fb445495b89a675926060527fc531ca15c827b1b596bd1107f362ad6afc0d426a2c951502734e346f2de8dde56080527f79ff9827b2c0534e01787a1b8dd7fe855adc62a47e55a138dab9c9e368a1ece660a0527f4b2bb32f436806c15bbdd5aa1685271167f90090b0867ed9b9f65467dd01278460c0527ffafa4918f584bd1e5540ffef9ae8737a1f99e0246b8275d48a30893cf987b0f960e0527fa4bbdc014d8d97cb917aaa73d6f9ee28abb331248b7ad35afbc2deda96f49d75610100527fd4994add7a509bf6a3ebc9653b49ef6e7f95399349aabe9d7bdb3b61bdf858d0610120527fa3da114679ef650c371fbf94125a8adce0b2826c9015a258304e0bda3c51118e610140527f27463379eeea92d94e8eba640c22d0de41bff611b1754695905841267161f30e610160527fbf90547c700258cb2d8dd93c097de8359a6599ed8d0780cb59539cc1c2638b44610180527fc3096ad3f1873283d828b50c41efc4ac41aee51cd7f2bd7d3d4f33afbcbe032e6101a0527f5aff79e915ce4ab6f25d50594f799404aceb01050e881e3db774e4d55d5978c26101c0527fba56951b64e7152bcb9194971dda9b0df5f930200b8273734682715c4e6056396101e05260406000610200600060107f2f97ddd75c0c05125fae073ccba46c5e539d71bed8ff23853bf1764460229fdaf4600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x641602bAD4A323C49629d45338d79A2bb984A3fb": { + "balance": "0x989680", + "code": "0x600051600d5560ca610160818120600e55f3", + "nonce": "0x0", + "storage": {} + }, + "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": { + "balance": "0x0", + "code": "0x401d746660008b994772f255600860005560005c5060076001557fbc8df58e6eed20da90e13f5ad2c08765cb6e81439a6da04b12de0540574684ad6000527f7159dcb73f8965ac626a129d4079b06b37f92f0421e62bba810cc8110558453f6020527f1df0080d280babd78d73e16c819f791cde947558cb175008b6491426ef95094e6040527f5c4784a311acf42f8cd893a5c489ea07c3d637d7b64e8ada04ec7c12b46fabf86060527f1d5cb4b437399e6bde518642eae21cc163175f8434d59979098c4d0dbeb50f736080527f852be8ca72f3700871dbbfa86f890081180b5551a802f20a1f5f12de55f3e2f960a0527f318dba96318f6da5462adf7e9589495080040023ef8d45f1a34672ecf71338e760c0527f23936a7f7fbec00a3880ea52fe3e86568ce44061752d5d0bc62d4c83883a57ed60e0527fc467bdb7b28d098a1f1451d9d5c4e8ea8b81e03db78fc63cabb1ca744f75e81a61010052604060006101206000603f60087fa266b49f47d3fe71da4e7a84d4e319f7affb522119f7de9f9a600a5627456b1df1600255600051600355602051600455", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000007" + } + }, + "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": { + "balance": "0x989680", + "code": "0x7c204ca729dad386476072a674923939c221cb19c4b7b4abd0cc43fa5f776000527fd4abaed1ff03eb0617079641124fc2da5e11e3b4eed3f35a8e5a04ba046b72486020527fb2bafb6e4fcecd331fb65ddac17759c71080b15831692735583c69c439e5c7656040527f7443edd4af446493c3011fde316b91daca78c8f767dced885b3166d83feb88046060527f4f016aa7ded3858aff740a0df5c2472456f4278461ba7e89007aa3f1ef7e45236080527f81c3dd9d889bba4caad01c180160b3d402aefc9a33ef0a422dbfce85e5146bbc60a05260ab60c053607260c15360cb60c25360ce60c35360f760c453607860c553601760c653606a60c753603660c85360ef60c953605560ca5360be60cb5360b860cc53604660cd53600a60ce53602b60cf53606560d053607660d153603760d25360ce60d353600060d4536040600060d5600060f060097fe6b64d3649bed6e6bc3a97338bb4211990955bff747c3a0cb26696f5c97e8212f2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x7982c0B61a97cBCf7fF7b3736023b23D159873f4": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x4d9d461b0689c4bd2e0a75f78f8fc9dde4920c554402cac511acdd600e023977", + "storage": {} + }, + "0x79caC06f747229e9F79FA47049fb37884ec384b1": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2d7dce3ec394fd470eca53cc6fae4c8d8b38f19433d56ba6e549a98ab2bec9e9", + "storage": {} + }, + "0x7c2C923D79B9903f29A71bFAB11B24c30C9FF962": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xb1330d826f506a345059475813d946401278a870614ea1128f04ed451d5c9aac", + "storage": {} + }, + "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": { + "balance": "0x989680", + "code": "0x63800000017d7676767676760000000000760000000000000056000000000000000000009018156000557702ffffffffffffffffffffffffffffffffff2000000000007f800000000000000000000000000000000000000000000000000000000000000190117f7effffff800000000000000000000000000200004400000000000000000000017e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00069012760100000000ffffffffffffffff0000000000002e00000068010000000000000000901d684783921454358970527e40000000fd000000db0000000000000000000040000000fd000000db0000016801fffffffffffffffe0990161c600155760100000000ffffffffffffffff0000000000002e00000060057bc9700000000000000000023f00c00014ff002c0000000000002231089008778200000000000000fe000004000000ffff000000fffff7007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a1b901b7d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97702ffffffffffffffffffffffffffffffffff00000003000013600255682100000000000000227ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb1a6003557f80000000000000000000000000000000000000000000000000000000000000016b100000000000000000000000901d901860045571767676767676767676000000767676767676651ce97e1ab91a901676013590cab83b779e708b533b0eef3561483ddeefc841f5778200000000000000fe000004000000ffff000000fffff70090036005557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff1a6006556d01000000000000000000000000006005900790116007556f121212121212121212121212121212126f1212121212121212121212121212121290056fdac7fff9ffd9e13226262626262626007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90181b15762900760076761e000200767600000000767676760000006801fffffffffffffffe1002677fffffffffffffff7f7effffff8000000000000000000000000002000044000000000000000000000190069019901160017e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00901a6008557e1f0000000000000000000000000000002000000001000000000000000000007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10009017901c7f77676767676760000000000000001002e000000000000040000000e0000000007fffffffffffffffff7effffff800000007effffff800000008000ff0000010000901c901c6009557e1f0000000000000000000000000000002000000001000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17600a557f82000000000000000000000000000000000000000000000000000000000000006823232323232323232316600b557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007f7effffff8000000000000000000000000000000000000000d90000000000000190017702ffffffffffffffffffffffffffffffffff2000000000007cc9700000000000000000023f00c00014ff0000000000000000223008059012600c557f7effffff800000000000000000000000000200004400000000000000000000016c100000000000000000000000001790146d0100000000000000000000000000677fffffffffffffff1603684783921454358970526b0100000000000000000000009012126380000001686d5adef08547abf7eb13600d557a0109000000000000000000000000000000000000000000000000006f8000000000000000000000000000000003600e55682100000000000000226770000000000000009006901560006000f3", + "nonce": "0x0", + "storage": {} + }, + "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": { + "balance": "0x989680", + "code": "0x7fb511be36d35b74739a85351c052fa4de58db198a76d03d145a2d33203c2c32b66000527f26ee5abbb7ea9e33fbcc013139bb00934e98d3f25e6da159a52d2e0152bfc4f56020527f6d0dff51561b32482bf7e6dd4c7c2b630ec00581ae93c8e88b02ea3ba6e3f7586040527fe6e1d60bd9c1f8c2f5ac77b0a75b1ac10d5d436517f67132ee04da57ad66c61a6060527f4089ebd6d189c7085362bb204ede3e28c7de082ea6906a192d6fe1e86cfaf16f6080526020600060a060006001610100611b1ef1600055600051600155600060005260006020526000604052600060605260006080526020600060a060006000610100611ac6f16002556000516003557f9a92cfae6639594ef5a936af7206a825039830b70121bd288099792299610c776000527f357d5942107baca8191dc32f847229ea93a7ecd634f96cf82b77603fe057a6676020527f84b09f3632409869d2fa6f36de4eee7cd0071520e71905199c75e18bcfeeef3b6040527f941d0fd4fc5d0a735c27ae11507ab5ea2a786cf14a9254c9afc3df2bd2c08be36060527f3d4798b3215eb8fe2dd88edf7b0b569bf34b9026925eea60bc315c65931ac1cc6080526020600060a06000610100611b2df46004556000516005557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f2caca4cd87938c0530ef51cd1db94e01e69b7e4b7e03df64fcc0805927fabca06060527f7887b1df3e1b05a0ee2e48b7c1165c05befb4beea8606070e12e62c12c127a1e6080526020600060a06000610100611ac8f46006556000516007557f0bbb06c7aeef3093a1a0eff5c46deb9d7d7cc7cf8d821ed636871c880b1a6a556000527f3e28ff5c73e7130c61c678d789af2a87ae9f7c290d7deb610d6ad79f113d94186020527fe671e799198805f8189928646d971703d44cdf97409ddcaf27223f93f54fea606040527fb8122e7f2fea191d2802cb055c051aa598069afddec63d69cc994c7e900172d16060527f60c335144e54220c97209ea95244251059d0f3d442e5bb6dc51af9ae73a457e56080526020600060a06000610100611c1bf46008556000516009557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611be7fa600a55600051600b557f592c81d1677b5196e4d245929e6496a2899555bd2a946d57c23ab32ade99ca986000527f46b70fe7265f36468e64a4361f32e849dd282a0320c260735f21ac79dd1bf26a6020527f042e0e533318524d279d357a0d8e74efc9ba6d3accdf2371a11ceb55c76e59026040527f4b4525528aa2a41f53151a6f41f345989e19dc826bfb59fae30dd3b99411fc816060527f288e3f6c0d35bf78e6cfcfa5f9da83ef49e11dca41b560ce612fb573a94794546080526020600060a06000610100611947f4600c55600051600d557ffa70288e2ea04596712d5db7d2648d0fe15a93ef1361cb32193ea71208b4e1d16000527f01cc6513c119ca09301a270e2b688b54eb9cdfa4f82910ab5e9575c876fd28106020527fadfea09485c17d44738a41923ea61cccf37a76b86392f7df3e5bdeabdf91a3636040527f54bf277179e68b0be4828fb6f0abbc32c5dd04b6f94041dbbc318ca2b73c87e66060527fcce03cbdf75a6153c5f68b229d5eec99c9cd3a3b909759e052555fd3461c18f66080526020600060a06000610100611b48fa600e55600051600f55600060005260006020526000604052600060605260006080526020600060a06000610100611a18f4601055600051601155600060005260006020526000604052600060605260006080526020600060a0600060006101006119c5f16012556000516013557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611bb4f16014556000516015557fd900eed45d1776f9c7fb5481006bb7c814974494d8d64cb48ea64fc45fbb0ba46000527f69c2d7f49d906367e5162dab8ee5a7bd7823c111f921dc9f8f0067da568c7c6f6020527ffdae48e7c41220e433a48c84156e2d83ede6dd68a80e3f272632b2743eb4c7e66040527f0992f0090cad0a5a66b1abbffd6f3edf2cb6479b56e43b587d580a13ef05fbcc6060527f5c80af8232db2e0eaacdd05ff44633998ea9718b003da0288868905ee1f551c96080526020600060a06000610100611a07fa6016556000516017557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f75415288bb9affb8bce0c2c7e9e621d6a039a9eab09a1a9a3a5d948db555530a6060527f1e425924b0e734bf3e320737c8c4d93466125ec8ab3f1c6e27d874d61d8459696080526020600060a0600060016101006119e0f16018556000516019557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f24af7a688a7415dee8c9f61925d9ce1b49c6c52fbd58ca95ed6c966a68abdb626060527f7850ec2e896e2e95eeb06daf3f97f70c7c749ee9dd193cb34e92a5606c0f56ed6080526020600060a060006001610100611bb2f1601a55600051601b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffbffff7ffffffffffffffffffffffffff7ffffffffffffffdffffffffdfffff6020527fffbffff7ffffffffffffffffffffffffff7ffffffffffffffdffffffffdfffff6040527fea73e64300f1f62cc62a21316d8c321f0d94bd46ddd81a3ccc28637e9fcc059c6060527feb47b65c82e04c8d9e2b76e469127a34cc255d65fa7e972c4a2e59b43f362c456080526020600060a06000610100611b99fa601c55600051601d557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c7760005260016020526001604052600160605260016080526020600060a060006000610100611b35f1601e55600051601f557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527f01fffffffe00000002000000000000000000000001ffffffffffffffffffffff6020527f01fffffffe00000002000000000000000000000001ffffffffffffffffffffff6040527f9f9f373679c7afa4dcabfd13c9ad7caadb7a21a1cb644f3cab82894c2fc3945d6060527f1a38fb7e2ae12442797eaf42952fe8c6e1c1905413d679d3b214a795573c66896080526020600060a06000610100611be7fa6020556000516021557ff081432cc644bc72156bf6142c4c64d2e4fc97a00b031e7cbb351d295757248b6000527f3889aeeccb261d4f724fa0f8e59e98808c196af04c6254e04ab6eb4d092450a46020527f142719b3436d45c38cb709a57c9ed6fd29275349ec7cbd8c9bd41de0889642186040527f88f4a68540ab8a1b50cabd1cf090cceeb373d82664498c439a4a32779c0d22c96060527f3e6f058623651dce23bb510f143af1a5ac880c2d37fb418c5842372d1f8c34066080526020600060a060006000610100611a70f16022556000516023557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611a65f16024556000516025557f07dde465c9a3eafef9f67182ac66f082bd13b079e6e1987a230a289731751aca6000527f818ae986aaf82a2557850c44fa8c66c08cbf773a40926c4207f4dedef7f268ff6020527f5d0f62fe7ecedb18fc0a6816290c84e1babcfc3ce7c45eaebd2b3e240590e0d66040527f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2966060527f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f56080526020600060a06000610100611c7af46026556000516027557fc80aeda6f4081e9c31cbb36b0197cc22a8efd63adcb4485f61236cfd06a71ca16000527f1ed7abd2c30eefb6d147a7d0d2f3a8131ec404d52ff52646139398d66a01f3f26020527f79c92381a2a06bfb3b1031bb1b4cdc77d639373002ab0ac314b1523a7de7f68f6040527fafbb22c18f1d6d660576338408c29a612c553e312ba6f8b29b93506aac7adce96060527f0f515ec269b4211979d43151e407cc25f6696ede802c24b68ea55f1342b96fda6080526020600060a060006001610100611b9df16028556000516029557f7c12b2191d8ef871047530a206958736d82d157a10f5f9988f3f751f7c7692426000527f2f5258e2c042a1da26a26c70833f7995b6b861a45ab2fb138f436b5b085b8fcc6020527f5737f2db6ec576ea11b9441ed36d37cfe21d49f779edd05b50fb7e9eb68a4e626040527f7d11792e312872bbb04b7aaefde5e2550098c3f3ccd932512ac1aea601fc47b16060527eba8209eac9863d2b1f4a437705c9ccf468310512b30b8bd9fe41cdfdf2ef9a6080526020600060a06000610100611c33f4602a55600051602b557fcd43b17ee6fcb602f1e29abfa2a9d5b48cdd5c092d98c32e26b1302d4960a5a86000527ff64f37e50c8f8a6ad3aa7ea6b3ccc0bfbd5c2f023a1dba33e7c26f90b72ee02b6020527f66a4bec343d4643c8dbf09232a8b5b00449cf8a99ab6f4038334dd54d6cd7f8f6040527f7db82f7ec4beba67b179c1c2a8983df79a36413992aa5a39503f1428cc4e25016060527fae00f9aece5008162b6f21c518e3ee6434941526acfe840344e9be157bd169636080526020600060a060006001610100611bf4f1602c55600051602d557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a060006000610100611aa3f1602e55600051602f557f7373927df8ebb8a5ac091c307565643314c299619e3aa81e01a2ec6e115f916a6000527f1f248c01540fa05841fcccbb52901e202faec36341b941b94f7adf285b0123446020527ff49056605d85bf9bdf7895b87aeb87d34b5aa57b60d87e53e206c9b2f6074e336040527fec54228434f47ad27d147bc0b47ea82f5c31e0f2eeb2d7aeed573a4c36fcd1d16060527f6d1cec152f3e3e8c6e0d7a4fc389ca47b94c8e34478fb0f61567663746bda2b06080526020600060a060006001610100611ba2f16030556000516031557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000526fffffffff80000000600000002fffffff6020526fffffffff80000000600000002fffffff6040526fffffffff8000000060000000300000006060526fffffffff8000000060000000300000006080526020600060a060006001610100611964f2603255600051603355600060005260006020526000604052600060605260006080526020600060a0600060006101006119aff16034556000516035557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611b07f26036556000516037557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6020527faaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa6040527f19fca7d59f879cc12ec4bf084df587cd4d3ccbc733ec54a0147cc582b4adc0036060527f9e03dddb7ee6f0c81ba11c47ba04d3c039c85cf63f37150313a47cd4c7fd4fc76080526020600060a06000610100611c0dfa6038556000516039557fdfd58aca08532a61992566dc9b53fdb5dd609a84267fc29f28ef77fc4e3c36546000527f11576b29c809bcce8678b900952429f5d435c71987b644e1a07cb6be2fc5e87c6020527f5baf683fefa7a13120e806df4a57cfee97e9d69605b839ac94182a1cf6301e146040527fcdb9ea9af1bf1cde5b8bd83ef72b4fb5b65427b883ccf4e0ada5eec1f167b4176060527f9da601bccdebd3c0a6ad3a73dda7875df3bdba8df4367998adba9839c3aaf8486080526020600060a06000610100611ab8f4603a55600051603b557f8d91d8ef900d4b1496bd67fda046a82037bc18eec3722e72de615262aacfe02f6000527f988aea2d9c20396d364c85b705076a5505a697dc7d60c8ea91d380576745f4e06020527f3e83d58208c5353e179a2f374c2aa5a4f3101dfccd9ca8dd229fa6e801b045e76040527f32f9ae03f79f5f7dbbc96223efb8f7def32a2f7047d7de0d3980706eb8c1fec16060527f96b6a590c004c3a276de89397bdb137f5bb1724daf08e3211477535cb8ca969f6080526020600060a060006000610100611973f1603c55600051603d557f55f877a03e3e31007d8ccb0037592750fe627036579cd37987d3ef76a651dd1a6000527f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f6020527f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f6040527f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f6060527f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f6080526020600060a06000600161010061190af1603e55600051603f55600060005260006020526000604052600060605260006080526020600060a06000610100611c18f46040556000516041557f6cab6c2b703f7d67afcc860f56d8437f3b9ee4c209a5acd9986d3b05ab60d9bc6000527fe7f933b46936a5004907e55c4dc53092c174ba06943bbfbf90e0802164689e816020527fc488f7fb05d3a80397b19b03318deb37babc32c05504c26a6f7d837938506f186040527fdecb3acc028e66754176866c6109a03ac60eff659b87f633ff18ce41a4f9ea616060527f9d95f2926562086975131b2402043777005a5bfb393da343f66f829b77c1969b6080526020600060a060006001610100611b18f16042556000516043557f90d223bd3b8895ad2d6820592d063af8ea6170dd2a6c6800187c545eb592a8116000527f727b03b61f5dde152e04c2ab579d839782cbb29909e54b219e895551cee9798c6020527f71e1a22cae857823d054a504ebe486c1f5edf176ebc327289a90ff07800c453d6040527f37ee2531e5c4063994edecf64d483d05316a25907afa516d9055ac86155b44f96060527f7b7108261418d866350dc293f13dab89cc9782cf00b0936264fccd768e1ba0306080526020600060a06000610100611b11fa6044556000516045557f89a43b8ca5df83cf7b97fde1b28f74c693d1afbd6fd0cb1ae1642625c718b0156000527f0bf972cce64c6fbcb27b07fd0803ff3c4fbfe3f306cd3b1375da67ed0cb725f56020527f71dff7030f06d40941d92a188072478f7387cfb411df41abe6a75efd6d9441176040527f47de18a2173098799b70d71e171fb432f7cff8592d735dab7063c246c37838c56060527f7e3fb2e586aa10db8130958294c8ca92f86746dd39313f9f044ed92ab51ebec66080526020600060a06000610100611902fa604655600051604755600060005260006020526000604052600060605260006080526020600060a06000610100611cb0fa6048556000516049557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6020527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6040527f95f802a4de6bd804746155b418f062143764ef2a147233201bf8495b228647466060527f9d0ef95979bbd0ab36881723e5201d79464fd2b1d4f2f4132c5bc720b4d444206080526020600060a060006001610100611bc8f2604a55600051604b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffffffffffffffff7fffffffffffffffffdfffffffffffffffffffffffeffffff6020527ffffffffffffffff7fffffffffffffffffdfffffffffffffffffffffffeffffff6040527fe353b148a8865c34312ec4be2fd75654fd51c2a6ad9fe7c2415b99e1e88b8d626060527f6ecc2a0c493d21397f0afed91183fe3eafc4608aafbe16752fe678d72a9e2c326080526020600060a06000610100611b4afa604c55600051604d557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffefffffffffffffffefffffffffffffffefffffffffffffffeffffffffffffff6020527ffefffffffffffffffefffffffffffffffefffffffffffffffeffffffffffffff6040527f890be92aa6553fafc61f2d7bc894e0364cc05674cde976108be782fe256658346060527fd327c7ccdc52c8148e193aaa15b9198ce0ac3dfb38edb0fc3f97562ee0cff9c06080526020600060a060006001610100611c4ef2604e55600051604f557f70d493d413d0f97b38ecf03f9936de5569134743f8ebba326bcab2fce1b308bc6000527fad6b307f682762fe700f50be21df0eae15576e3310374b5286fa01f4f580dcb36020527f410597b9fa20da8d725be815a38adf9641d936b67d4e253de45aa0cd0e7531fc6040527f0c75e73b83f06dde3f187454439cec155a7f4085ddb5b0d7c0dc603521ec6a076060527fbcbe14af3e150e96451f8ac7fd46dd5e25e2d6e8877e557d47fd886d930eef996080526020600060a06000610100611900fa605055600051605155600060005260006020526000604052600060605260006080526020600060a06000610100611c38f46052556000516053557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f50adc68d1ed4bc57595c7d24187a1ce9cb7af2a28fcaa41abcc98a4de3884ebc6060527fb88ec0b67329d7fd2dd4689999ff22382c9acf7c067992ba3760f30aeacc60af6080526020600060a06000610100611b3cfa6054556000516055557feff60afe0f78740345253b3cbb65e6dbe63a68fed452790bcbc9c55bc18a70566000527fb9818c88fa8b83ed5a07f59a313424cefca5fdc64dfb8ae2ea83f7d297033c586020527fb5497fdaee7d666f38c78cdefc0050ea7cbe3b27d366332216fc2194c3e6deb36040527f6f9356e40c32cf53e6fe489c0732ab8a6efd0a5ee50c801851cdc2b292f82c006060527fd981ea59cded394ac871b2d0932db19b36121cfaa9827ab6044622b62d5ad6dd6080526020600060a060006000610100611c6ff26056556000516057557fe8a6997bc3ef18a0bfd1f976c6b3a8bbacc623adec46faa8d943dca231d7574a6000527f80795269cfdd07798be6857e606cc0accaeeffe856e6b15f9071cff36579364f6020527f9111e1ee6e26e672d97219d759b5f01d8a511065921ffd3ddadbb52b79552ead6040527f8a4ecb4101550650bfcd765d7131923ae8e507f9bf6aa4fc066f5f793ed9c4b86060527f0e0d94805b96e84096463dc843cdd27b35a31f921115128fbfb97bef4fad13836080526020600060a06000610100611c90f4605855600051605955", + "nonce": "0x0", + "storage": {} + }, + "0xAff0d1Fad46ff203C5b9FF00F10FE1134862571D": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xb20e2e99f2b7b64c0028bfaff9bdbc56f583bc930a85b190582c9f0d4033ede4", + "storage": {} + }, + "0xB6754926EBc05d33a936ffdE524617F45429CCFC": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x9effa2a88d9a8cccb99a856d5e63c52601b8b08c69d7acd0ee942483a4b89370", + "storage": {} + }, + "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": { + "balance": "0x989680", + "code": "0x7f02c2c265e04023dcffe20e4ccec637696d77c6e6fc4e369317999de4e2f22f056000527f23ce7327362b8cb7aa786d6b1df1634b880c790b63e59815801d6b8e2740ff8d6020527f0fc77f348be20708ea60d3b94d9817a096cdc59fb0cc5af2e58566764b522dd26040527f085883a36120154e32ad2690541ef9e1efb62f786b14483153b4972e5974ca216060526040600060806000606960067ffdb4e6ce5813b605ee9a363e27821972b4f64a511b4f4a1c6180eaa3f349e122f2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xBbD9aa098bAF9E636FfDb6f530804Fdf44b55e47": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x80ee8021793940859903f6f4b4b5f8e54cd8d71e8343a4ff0be43248585a7ff7", + "storage": {} + }, + "0xD74CFe323387aE2fd070CD046173026716D8D649": { + "balance": "0x989680", + "code": "0x7f0169f1039479a1cb9e010b1fb7af9e0040fc25c7c635eb7e0c226cbb0ce6bfbd6000527f21ccad796c904514ddd7eed89662d0c10d19c93f8f3bfd9c6654a21e6ff957806020527f5bc83896961a345b57d239af35bc308ac25f6da92e25e50b1463bc186b2346556040527fad5f2939a5f241fa3075babc85771cf9ac6e3106badf3c4531a4ed255601e8e06060527f6d2e313e0bcde117a25041cf347fd8eea303142178574eb114d747bb6e878fe26080527f9db97a5ba9d948ff02d8eabb1cea46d2c924386521f3a546124bdab654f2e36260a0526040600060c06000600a7f85e2bed24cca9c9205c7e917491240569e0469906022d7487d17577195938020fa600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": { + "balance": "0x989680", + "code": "0x6000600052600060205260006040526000606052602060006080600060016117d0f46000556000516001557f296f78b9a90bdd931ccfbe330ac522c4bc3674011373a5c6e2a07dced217e9786000527fc9ad117b3f4d2d304b12779a3c5c7378fee4cbb1ecc43547ea778aa62c67b21d6020527ffff0880374cd8b7b114142bcd47efcfceb46ea1c8b93de691208f6310ef4ab936040527f69d62d9240644396f4d1b2714cda0f47f619aa2c009ff577308390dbe7eef4926060526020600060806000600060016201846bf16002556000516003557f9495b0aedddd62eee6febe6e895d905ef8362d3664e5be36d7a12382a42865216000527f462a3f411ac3c1e25b397435a686a08c5a8c9b4c12daf4c076ec745105b35b1b60205260006040527fbbe793cd818974373af7368a4216889be43f792fee2525b13d65bcc11fb266eb60605260206000608060006001617c77fa6004556000516005557fcd46aad27501fd036bd5103506652b0b8971130ef7fb3ad11c627ff7c48e24ee6000527f34107e6abd2d2894bd30f1dcb5261dbba40132e4ac5adadf633a11970a79131c6020527f317ef659ee0a8e855ba05d47b4ec0dbcc59d155e6763c7f8dc77735787c608a16040527fffffeb1e76363ef29bac4bc4c703ca193c1df892e5322cbbe3e9206f286c8b7b606052602060006080600060006001620146e1f26006556000516007557f7a140174c51cf25c703fee4273fcafa7ac7a2fc87b78e7eb531cedace92187f56000527f60e22f951c13b1025f4eeeac8ec7abf355c91b116b34003e0f1a7de1908cfecb6020527f377bcdf2776552334cf3407b7e20ff850eb2b5e41c6c29a8b0ec7501af4021136040527f7c1301d938bd805aa46a5d4f618e8e6d4748c20f45eb2eb9b9bbfd86b04b0879606052602060006080600060016001611471f16008556000516009557fbdb142cb033f938315b0997d0fedba0f94678ad5ba6157b65d3fbe10fc2a6dbc6000527f66e2364050b7bb9ed95fb653732ce385d4ba8c46432378b1e177a25e5e31b21b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fd1d3f61e7328a38915ae5d4fe64d90cae583c13e412367e083eeefb6241d3d8a6060526020600060806000600162013de4fa600a55600051600b556000600052601b602052600160405260016060526020600060806000600161c914f4600c55600051600d5560006000526000602052600060405260006060526020600060806000600162016e1bfa600e55600051600f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fe90dc134b5745cdf092acec96cea2bf73c870375726f8366c1fa92c9bb9ced266040527f370c68cbf48ab4a9cf9c40b8b97805bc574ef0e0dbac5171e326f8566d290d4e60605260206000608060006000600161d2d8f26010556000516011557ff264b4e7da06c72fb575c7f0a3b9c31986ba5545fa6c68eda775a4d040e264cf6000527f7fd8d2ced0fccd11e450792c18aa5502ec6e59926df193163641376539f4301b60205260006040527f6eea0915c614760dffb89669fd77b21a3c54fbec96445e381999801282c7fe6660605260206000608060006000600161980ff26012556000516013557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f1d889ad783fb93cd8b1a00fafed86ceffb9372869b387e65d0cf149c98f983a06040527f2dee9d460d8207475a3461371307d5a1c982e9e9848afb97b518a4ed17c9fcf4606052602060006080600060006001620178c4f16014556000516015557fb9fd2a1e809c3b7e7d8dfe206432a81de90fa922f4bb7f3adc6a3716abffd3806000527fc6e489e4f2d91554e568b4f959d1f390465e5b1bd23c423774d2dc84c1a9dfb76020527fc8937b5ad7058e304a4e44bbe31cc4efce5ca2dc4500f7b9c697033031f61e6f6040527fc598b13938344c0d6d244599075bd4a602ff4057b041ac5a6b56193d7973861b606052602060006080600060006001612deaf26016556000516017557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f90c2b4aafe3f6f4d25e37e5ebead359fa69060901a6938be171df655cbfe64af6040527f71f2654408880b6690fe5087cd3c7ca3c5d10131c79b7a5b1e652225060f8a806060526020600060806000600162010ac5fa6018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f40bbb8d71baab2003b987bc5f7ccb66df8b04a5201bc89e2f23bcdb144b810506040527f4f11207e7d336d7075a95f57b4a1b5caa5cb4accc50f9de98df1c555ae05934a6060526020600060806000600161ebebfa601a55600051601b556000600052600060205260006040526000606052602060006080600060006001620170aef1601c55600051601d557f70eb8cc6aa62dee5a1e13e0267b43694aed5d5b09835791a1523c9c11634e33a6000527f52b8ce8f1dbd041192fe3c06f7d0904bd1bbe1f15f2e0d78edd625ca9dd9291d6020527f3a4060d4b707437df0d0f1dca6b6290c0fdb1c79b0846e6b8d595be2ae27d9116040527fb919a3300bcd1dcfbbf72efa726ad1313219f0883bd443411a7ccaa10447eb1c60605260206000608060006000600162017822f1601e55600051601f557f5ced1050fb51c2a94cf987d493b396d4fa3a53e46beea80831a5d7e3d6bb86106000527ffa87751775d77462b6b34be506beb70ab28352c7f8e5e39175f728181074361b60205260006040527fe1d256c5100bcad5d9bbcae86dc22ea1b3e19647919f3effbfbce66d37418ed0606052602060006080600060016001618ccaf16020556000516021557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f170d4909ec18966d3e28b7ea77e7823b32c23375110257748b80bc9e7a36dc466040527f40c2a1c302838d759b9a86ecdec3807c17f848e30adc4ad730cbf681cb2cde1860605260206000608060006001611e31fa6022556000516023557f2ba1713bcf21b729b7b5bd648fb582a944fa5c55dfeb08b91e8862e360f312ce6000527fc7a148d54f25335eb6da75e95d1604ca4dffcba41fcaeb4e8eb24681443049b36020527f02a55f450ee865c0caf6ddab1690853be92d0316977bc02de3f5dd17b18c2d136040527f25c2390881011d3dfa6c2dc5adf1e375862220f32e3b35766024ff4090122a146060526020600060806000600161904af46024556000516025557f0fb8ca4f71925cd08c671793082e4accd3050f3128ad1e9b4ab1c6d20fc4f0a76000527f1163c9bb92b221466021d2776b0b7613d47a77d9312db4e5e942930ec1ded31b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fa61767fb6b9f736b4962affdfc29347b0730878f841a7c7f78a9b70245bbc7216060526020600060806000600161f490fa6026556000516027556000600052601b602052600160405260016060526020600060806000600161ef81f46028556000516029557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fc8e6348e2c71786d2ccd1c7c967f420855cc839dc19c80f1b578b6d1c322f9096040527f3f5a8673444c55112df70fdfc64dbb5d07da30535a32c60a4d20055155cd1da76060526020600060806000600162018339f4602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f8abe932511c6b22f6b28bab5650dc28d63f1981103d26534e1956c84c332fc636040527f133e7abea04d45a26b9300224c462c7705feb578e48cea8b5b40c13006be7460606052602060006080600060006001620163bef2602c55600051602d557f16e1c685844a7fa1b621ef440822eb44512fc2b8bee61e62a5874f912e307e5b6000527f9e4d6d753bcb998f92c39ea58808b75ea82bb0e9089f4cfd95afb7e26087431b60205260006040527fb1ec0f8d39f445a49efab6cf246abc10d7d5477361727498d30f555c2ccc94ad60605260206000608060006001620131d5f4602e55600051602f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f7f8c30c8d71ec097a66757459c78919acca9839d99b4cdc3bb9168f5930ec3f66040527f1d33b7ca4b1d6d2f44c2b98eff781b1f0bee479bada720563ec351345feb046c6060526020600060806000600162013984f4603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": { + "balance": "0x0", + "code": "0x7f40000000fd000000db0000000000000000000000000000000000000000000001671fffffffffffffff901c7d7676767676760000000000760000000000000056000000000000000000007f82000000000000000000000000000000000000000000000000000000000000007cc9700000000000000000023f00c00014ff00000000000000002230080509604f557e40000000fd000000db0000000000000000000040000000fd000000db0000017d76767676767600000000007600000000000000560000000000000000000090116050556005712000110000000d0a300e750a000000090a0a901a126fdac7fff9ffd9e13226262626262626006d0100000000000000000000000000900360515569100000000000000000006f121212121212121212121212121212121d90047ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000600590057e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a006101117f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0960525515901517671fffffffffffffff7a010900000000000000000000000000000000000000000000000000901d1860077fffffffffffffffff7effffff800000007effffff800000008000ff00000100001c1a7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a006f800000000000000100000000000000009016176780000000000000016f80000000000000010000000000000000100b7f82000000000000000000000000000000000000000000000000000000000000006f12121212121212121212121212121212610111900990077f7effffff8000000000000000000000000000000000000000d900000000000001677fffffffffffffff901d901b7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7702ffffffffffffffffffffffffffffffffff2000000000000217760100000000ffffffffffffffff0000000000002e000000600790057f77676767676760000000000000001002e000000000000040000000e0000000007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0680100000000000000009008901490187a0109000000000000000000000000000000000000000000000000007f40000000fd000000db000000000000000000000000000000000000000000000167ffffffffffffffff90089001778200000000000000fe000004000000ffff000000fffff7007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000901d90057ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07f800000000000000000000000000000000000000000000000000000000000000017900b7d767676767676000000000076000000000000005600000000000000000000682323232323232323231c1015197a0109000000000000000000000000000000000000000000000000007702ffffffffffffffffffffffffffffffffff000000030000900b60535569100000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff061c7f7effffff8000000000000000000000000000000000000000d9000000000000017176767676767676767600000076767676767611027f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe778200000000000000fe000004000000ffff000000fffff700777effffff8000000000000000000000000000000000008001099019901b60006000f3", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000054": "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x0000000000000000000000000000000000000000000000000000000000000055": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000056": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000057": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000058": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000059": "0x0000000000000000000000000000000000000000000000000000000000000004" + } + }, + "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": { + "balance": "0xffffffffff", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "storage": {} + }, + "0xae7D4902083D51fB69147F97f93522A6ACde32e3": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x095113ac45e3fc3d29c686504b49b5bfa2bbb26afa0ff1b5a6e78199e3aef49a", + "storage": {} + }, + "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": { + "balance": "0x989680", + "code": "0x6000496000556002496001554a6002556001600355", + "nonce": "0x0", + "storage": {} + }, + "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": { + "balance": "0x989680", + "code": "0x606d6000526078602052606d6040527f06969cd3d17047a3c033d477a356eb6ebd02814ae1f49088a1a242623dbf28e66060527fa676380fb7aafe0fa248866ce2f4791be20e44bc99d3f2b8e7187fd2e7b99b196080527f7151476f0af990c48816173b5d9051376c9a7f1047d8ba71e7e79d4a704cdacc60a0527f68c95ec18334d106b3d49cb6120000000000000000000020000000000000000060c052600060e0526000610100526000610120527abc6d485cd9b7850ba153b2251675cb64a9f6a9d2a16d1749eeec42610140527f69786eef9e41fc0119f402f45634776e67372649b652bb6d55163dd4a3d2d775610160527f2558f4470a237c93666a43a4090aabd3dbcc17a8871358e6b78de5d7557491936101805260ac6101a053600a6101a15360506101a253605f6101a35360576101a453609e6101a55360a06101a65360c16101a75360296101a85360ff6101a95360616101aa53601d6101ab53606c6101ac5360146101ad53605d6101ae5360126101af5360b06101b05360ad6101b153606d60006101b260006005620b40e0f45a01600055600051600155602051600255604051600355606051600455601060005261036960205260106040527f3bff515c72d1e83825f674d33c3be5a0c3c1b25b39f7fb3760251512fcac16866060527f892e53cad071d7af40e641c2fe62a738cbc10f710f8618b294ddbc910ec2d3ad6080527faef07d5365cf2749714704088599058eaa79452af493312077db847b9dcfdce160a0527fd1d20d50f580d96730f7ed7c22946530e4ce6ca8915d8186fb9dfa5642c916c160c0527f2a95a3141956373fb3ac67da6b0db573908e66113d2ebaebf5ec12f671b7991460e0527f120b1aa07aa1b8f7b8b3c4f486e9af80aadc99d6ae43e9838f280477db763ea0610100527f70d81ce84a0260bb8ffe0d9a61f086ef701c6a74640ca583270c6592c840983a610120527fc654061c1b0f2db6f1c098f605a7f027036200ad189af26ebd01b953ac70ee76610140527f5469ce22aa99d7595f9b76007d57a086fdb3d605e3c9489d26b3b5ee56133d80610160527f809f2cb0cd4f3a325bae5509fa63f6e6f1f7f95195508f341433016f0adf1471610180527f5a7691337c0f92863f4d8629ac6b072979ad8f94606e6b836360755b98852bf96101a0527f0b3334aed8257dc6287043f97db0786cf3aa5a3ba1790bdd8d7a5c46e2a0641c6101c0527fd06e211746f8d26e83202f1b08c0b47cfc354d30e27d47437f5e5fa33eba160e6101e0527f1b33cd83dc4e3f3d25742bce25c6039dccb1f8fd75c37f12bbec7130f668f36d610200527f7627ebcea7518334fd633674da463f583484712a8b08871ad915b3fc5e844229610220527f25efb7329b1117639f9d71a6b1861b406f4818bb8a60ffa98b68c23815ad9946610240527fc6049241e09a0b4c0fc8f6fd23b145ab1f4b2e865c481d2a29897737552fcc9a610260527f6dacd1f325fd6882cecc9f9eff330bd72b1796bf36be740166dc15c20109d157610280527f3b950f339162d4a9b43f4b152ce6118b5e8d3604655a77df348ed2a59a2ad5bd6102a0527f90029bfc8992471aa9c3210ebfc84122bbea32441303367b82a46d5dc871682a6102c0527f330e3d2feaf6388e1036175258eb6a776a76c02ddffa503058abc7c8cbd93f026102e0527f8917b602885d931ebe52636c9d9372b2a11c1933efa77bb538002d9c6082439e610300527f07d1ffcdf19617d783507043df209734d791fee5715dbcfa84cf9fb516be801f610320527f25edb69cf491500089a08307910e7dffc9fbfd9c4c054220235305b6196d6f73610340527fb8a4296a8f918535cc1266917de9d04e44c874b216f981ddefb18f76ca3557d7610360527f5bf7394e83d4ab174b51e4494779e927bb2cec1158c492cf2703d8d439363081610380527f8bb776cf19fab4db9da420097ae0c01c5877361e90c514ab5ad4ec4269d838b56103a0527fd2718ca190840807337574ca501af530e322da9dbc55f02a0296675d8cadee3a6103c052609d6103e05360836103e153603c6103e25360b56103e35360396103e45360ab6103e553605c6103e65360966103e75360e46103e853601060006103e9600060056204afb6f45a016005556000516006556055600052600260205260686040527fb4033714df43444fae7e7442a9bf1e21b29fe93c31eece3ebc21e3c8096a9efe6060527ff1002242cb3925eac55c4b2206a0fe6f232074d14c559a20515d5d963049936a6080527f4540cb4fbca19aeec551174d86f8ef243035d4c11c1c0ed39c4a14bf7254ece560a0527fe2d28870c3c3c4a0de8479bc9e58460ddeed4f85f6320d356c668d5a4395a64960c0527fbce240b2454432a5860fa357e305c52b6e806d84b43a837142187b38389c21a360e05260ca6101005360e161010153603561010253604061010353604f6101045360a361010553607c61010653600e61010753607061010853601061010953608061010a53601e61010b5360dc61010c5360b461010d53605e61010e53607f61010f53603c61011053609a61011153607161011253601b61011353601c6101145360e561011553609e6101165360d96101175360496101185360a66101195360cc61011a53602361011b53605461011c5360ba61011d5360d461011e536068600061011f60006005611196f45a01600755600051600855602051600955604051600a55606051600b55", + "nonce": "0x0", + "storage": {} + } + }, + "chainId": 1, + "env": { + "currentBaseFee": "0xa", + "currentBlobGasUsed": "0x20000", + "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000", + "currentDifficulty": "0x20000", + "currentExcessBlobGas": "0x60000", + "currentGasLimit": "0x11e1a300", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8" + }, + "fork": "Osaka", + "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f", + "transactions": [ + { + "data": "0x", + "from": "0xae7D4902083D51fB69147F97f93522A6ACde32e3", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6", + "value": "0x0" + }, + { + "data": "0x", + "from": "0x79caC06f747229e9F79FA47049fb37884ec384b1", + "gas": "0xf42400", + "gasPrice": "0x20", + "nonce": 0, + "to": "0x538A8474EeaB43d5a960164c554A20400151D479", + "value": "0x96" + }, + { + "data": "0x8a31d9bb704c555c24f732c6883998e445e86b09be29a2310d87a2a29c1998c1ee667cf95f5686cb613523a0b4fc4025782106b0e8fc299a6054fccb89416257", + "from": "0xBbD9aa098bAF9E636FfDb6f530804Fdf44b55e47", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f", + "value": "0x62" + }, + { + "data": "0x496cc712e00f0f40037adc0b96bea9eadbb3582c856ef10b3211f59e881ef0b332e341b56fac149a8352a5cfd046d4023d4365176ca9d660ae95b5ecefe6e598d4308bc57ee84becc2e6cabf95753a3ce3d7137111f1e265c40a83282f", + "from": "0x7982c0B61a97cBCf7fF7b3736023b23D159873f4", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d", + "value": "0x0" + }, + { + "data": "0x120b3eecdb80166a105dcc8c8ad8afbccf7e6397d125c0e6e9879f2a9edb9f85f646562555777c411d6002282a46f47f3edac617", + "from": "0x0b530C4203F212318CE214ae2F1089d2478cb56c", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3", + "value": "0xcc7947" + }, + { + "data": "0x71268733c98129c80286704a3cae048b4844232d79acac54", + "from": "0xae7D4902083D51fB69147F97f93522A6ACde32e3", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F", + "value": "0xfc1838" + }, + { + "data": "0x2ef88d3dc71b45691876a113f3b1c2faf56158ee3b9d7ea8d047d6a516", + "from": "0x79caC06f747229e9F79FA47049fb37884ec384b1", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c", + "value": "0x8a7e" + }, + { + "blobVersionedHashes": [ + "0x015f55eac6e598ff65cc16149757ffff9074b952549cb8c2dc96901c0f8ff5fe", + "0x01ef0c49e7504ae667b0eea1985b80598d05917f150f1f01389e77ed1465287a", + "0x01fcaae78c0438d7fb1adda2dc67c3dfd5f6432c5815abeb1a44794182b0b5ef", + "0x01670282b0ac787d53c024019bcbefd4765d1477d8136d19f89d3e57ace37d8b", + "0x0168f561e7975219eeaab25239746c7763d4664556e226ec728f71d0ca835e5b", + "0x0112cfe4c7af4e1114aab612902e7618ce92d004012b326e08e71f430eb80e95" + ], + "data": "0xa38f", + "from": "0xBbD9aa098bAF9E636FfDb6f530804Fdf44b55e47", + "gas": "0xf42400", + "maxFeePerBlobGas": "0x100", + "maxFeePerGas": "0x20", + "maxPriorityFeePerGas": "0x1", + "nonce": 1, + "sidecar": { + "blobs": 6, + "commitments": 6, + "proofs": 6 + }, + "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89", + "type": "0x3", + "value": "0x0" + }, + { + "data": "0x82c54de5780525f1a6604ee6fb757ef6985d536827009ade100818174b0214906875c07778068d38f75d1aa9f2c4406228317465137727de5471a1c19cf0d028b76c3b32319f8c80afbce3ffd3", + "from": "0x7982c0B61a97cBCf7fF7b3736023b23D159873f4", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb", + "value": "0xba88" + }, + { + "data": "0x", + "from": "0x0b530C4203F212318CE214ae2F1089d2478cb56c", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xD74CFe323387aE2fd070CD046173026716D8D649", + "value": "0x0" + }, + { + "data": "0x2e228bdfae2d5514c42bb144b04f34377ce64d701d349cafb636c2f73698c171e11d318e37c74c95ed9ba1ec8d327e2ace9b1c4ee285f95edea4cbff6b08ce7d88db009b731577f4da3eb9440315739ab72a77d9", + "from": "0xae7D4902083D51fB69147F97f93522A6ACde32e3", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10", + "value": "0x663" + }, + { + "data": "0xcb2b6ab7acaa2f0a6f60f06d4e445833b05fad7d4510a06afb5cd57d598df72d5107677f0cc8e3dde712123e6b3a558beb515edc22552315d2eaf7e0c6ad524ba23776fb1bc0c29206702b3b389f2c", + "from": "0x79caC06f747229e9F79FA47049fb37884ec384b1", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876", + "value": "0xb712a7" + }, + { + "data": "0x536553f53b491d18ad280730198d44810c496e91e020daf71f0fc49f3d415244000b5af69206dd69db5edfb6602c20f4c75b644f16e50954833808c0f82665ded9a0df95509974b0ea4799cede017b0aca24eec4ac", + "from": "0xBbD9aa098bAF9E636FfDb6f530804Fdf44b55e47", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190", + "value": "0x30" + }, + { + "data": "0xae5c17fd105f53464bfbad2b3c8c44f988bbc93ab17bf1a48a4320f8eb71ac1cf570fb8fb611afbb6481a1399bc8258b7d0215301229a95f2ec440200581491d48e624a2", + "from": "0x7982c0B61a97cBCf7fF7b3736023b23D159873f4", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce", + "value": "0x0" + }, + { + "authorizationList": [ + { + "address": "0x00000000000000000000000000000000000000f7", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x3b9d5e9a36279ed2c81761a8ed35c785cfabca68fe029b9e0462e973c352e857", + "s": "0x60dc03ea63ff6c10dd5cafb63cc2e4e531f4642e7f53a805acc94d8f4e952ca9", + "v": "0x1" + }, + { + "address": "0x00000000000000000000000000000000000000f4", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x87e3b063ecfe90dad2ba6331723b4772dd08a79e918d494633ff5e332ef3e055", + "s": "0x4954a1da6fc047e8ff073b4b1cd5864752a1a00745437319ab7cb91114ab9424", + "v": "0x1" + }, + { + "address": "0x00000000000000000000000000000000000000f2", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xeaaaafc5c341208dc8fa74dd76c680d4e70ff4470b5c7be410a95d4eb9063628", + "s": "0x682254770ea41bc56cff1d5b47f64ceede0da45e5233ebdc9c60d5c10c7a3e15", + "v": "0x0" + }, + { + "address": "0x88f9b82462f6c4bf4a0fb15e5c3971559a316e7f", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xbcad8bdc514baf5efab74757cec1366ad303cb086e4fc286650a499aa2c51979", + "s": "0x291e47131cefbca9f42434f163e1be4d6fec29160ce5f1ed716b3735e5b01e7f", + "v": "0x0" + }, + { + "address": "0x0000000000000000000000000000000000000002", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xf005537a1e36922e7a12f79716b304b6eea3c89fd0ccf0f1cb8584cfa67cfbc0", + "s": "0x2d5fdfe68d1e9c26f36cf82a0b2f24402991987f75946b99ebcfe13194cfb2f9", + "v": "0x1" + }, + { + "address": "0x000000000000000000000000000000000000000a", + "chainId": "0x0", + "nonce": "0x1", + "r": "0xffc1c76933522ee09da5d32efb9514f2fb3fe070c8c9e76ca170222e08b327a", + "s": "0x817fd0bbedb965878d16800f47470195839125925937723193f530fed54f818", + "v": "0x1" + }, + { + "address": "0x00000000000000000000000000000000000000f3", + "chainId": "0x0", + "nonce": "0x1", + "r": "0xf6995406f58d828d4dfc5930773f4ab58af7e00305a0753f61a9635684b16be0", + "s": "0x1a08f1d43abaeb2604e8d21b0509d4549f468ddb60d9dcf4d5020e7b05f1d718", + "v": "0x0" + }, + { + "address": "0x00000000000000000000000000000000000000f2", + "chainId": "0x0", + "nonce": "0x1", + "r": "0xa444813984575f38fe02fb696aacae0fcd71866cb02676318f9ed9f0660d42f5", + "s": "0xe6b7da27d25b3e6e65c663dfbb9eecbef56a8abd03e8b0bdc1d7c691ced3d34", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000010", + "chainId": "0x0", + "nonce": "0x1", + "r": "0x28acb6533b497b0c51e4f38162972c9ad4a60edc90e5ce448cf3f84fa070057f", + "s": "0x6bc95b9f8bfff6d47a61ec78d3cd9e5f60e6d588eb0016198aab9e09a3664f09", + "v": "0x0" + }, + { + "address": "0x00000000000000000000000000000000000000f2", + "chainId": "0x0", + "nonce": "0x2", + "r": "0x75e27043bd9be44d39a3624a9eb427ef06f12fa9748e33cba70d6aeb7707e1d", + "s": "0x5c65fea04d26d8f90a00755fc2375f047922f7b5f2942d9ef13a32b360f7d2dc", + "v": "0x0" + } + ], + "data": "0x4b4ccbd62cf795a7b29973b786c3861c7ce8ea6d66b9c4031283c6c5ba16ef10a7e711aaed4d5ca5a531c786b2da665b687197288570ad7b", + "from": "0x7c2C923D79B9903f29A71bFAB11B24c30C9FF962", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x0000000000000000000000000000000000000010", + "type": "0x4", + "value": "0xee5bdb" + }, + { + "data": "0x00", + "from": "0xAff0d1Fad46ff203C5b9FF00F10FE1134862571D", + "gas": "0x30d40", + "maxFeePerGas": "0x1e", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "to": "0x00000000000000000000000000000000000000f7", + "type": "0x2", + "value": "0x3e8" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x1", + "nonce": "0x2", + "r": "0xf3ff30055a5994e37ff024d18062a0107b978e80c9bebdcb138a0bd916f3396b", + "s": "0x35caf50bdf31d7e5d7f1e1062ca6fe150e7c41dd3fea6bf8f8bc3b3e6b665eff", + "v": "0x1" + } + ], + "data": "0x4b4ccbd62cf795a7b29973b786c3861c7ce8ea6d66b9c4031283c6c5ba16ef10a7e711aaed4d5ca5a531c786b2da665b687197288570ad7b", + "from": "0xB6754926EBc05d33a936ffdE524617F45429CCFC", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x0000000000000000000000000000000000000010", + "type": "0x4", + "value": "0xee5bdb" + } + ], + "version": "2.0" +} \ No newline at end of file diff --git a/cli/tests/vectors/fuzzer_test_2.json b/cli/tests/vectors/fuzzer_test_2.json new file mode 100644 index 0000000000..ee7cf22e11 --- /dev/null +++ b/cli/tests/vectors/fuzzer_test_2.json @@ -0,0 +1,440 @@ +{ + "accounts": { + "0x000000000000000000000000000000000000000A": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x00000000000000000000000000000000000000F5": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x071b56102BcF6C36a20a3a16fE48781448B1C274": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x4957f6f5af2d9acc075b694de14765a3ee3ebadd720ffdb0c471fccdeb1999e0", + "storage": {} + }, + "0x08d033C61e1E55bF868082cf788a3949f4ea949D": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x18c571b8d627c38e4cd2674ff9e1810ac122de605ad7e36051814279ada15f76", + "storage": {} + }, + "0x0b90ABAC5C8F6ce035a107913ea5D7C6eA24f9f2": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xaa7060c894d60af0152633bd7fb04eec13d565d152895681af06b5aa973faebb", + "storage": {} + }, + "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": { + "balance": "0x989680", + "code": "0x6f13354ab4e7cc72ca20ffac17e9c1b49e6000527fa774be197d572deb808140f315c100d2d5b447c60b80a1b74547997ab198d16f6020526f176dfa0b1b23c9b0aa1559abc0e6b3ac6040527fd5fd9911c96b4c2fb77a3083e58ca209789f9dd34748f8cc98b91778eb66d6466060526f04dec2525331e3a900d26f9872d420af6080527ff94c487bc34b1d01d00cbda233627a06fccf69c89b049796cc085f168248341f60a0526f086324d465d550c6ee843b64c6e7759060c0527f8e48c1fa02fda324d5d1cb956e0aab45de89c5276b228c54d1cb2647317614e260e052608060006101006000600b7f4f98dd185cc2f36c1bd041dd1cc98b487ef9602b0578858b7284310edc62d5d6f46000556000516001556020516002556040516003556060516004556f1a702a96876d961f14157b5ef86e16e86000527fc6a1f44881f0ba5f2b765070a0156cf5c485bcb9786e041fbb5c335aeef73b436020526f04b318655f98855db2f8e004a2aa2e276040527fc4f6237e51f0ba883191ac4eee5bdf35d3dcf8bef33156eb619e577bbb38c8416060527fe3e2461badb2e11a04503bdf8c903cfe43cce07d322703d192c3aac1559f76cb6080526f023f3c470ae026e4b8e7d1c7e7c61a0c60a0527f5e1706597302e07b4e610fb7251c52b545642b421fece660fc17206d89144b6f60c0526f1532e6055e532a60024d0fb15ca6e47960e0527f74110b8a237d86f94cd0b459143c3e0c91ef78a41d05bd52c563b7d166cb7e21610100527fc1eec215a08bb347aeb9a1f5c07361975d64957f0673f20844e48a6a14a169c2610120526f1b4b2fd8fc7e8e13a2c559b2309c6dc3610140527f747996328ddd37eb4b6f36f5730b4503d399d4472b6ee2f6a28416f76b5398ad610160526f0859289d4cdb015254ed20cff2f133e8610180527f8e6cc4b53d2df6446c0ccfee4cd91dabc25bb7bbfa44ea0e39d3c592e30d19ce6101a0527f7376a76efdd3625a9f49bede1c096bcc48ea402836db68a38620c647db77c5b36101c052608060006101e060006040600c7f28825afba0dd595ba78aa61e8b06e00e2a57be0f466af3fb2f62468750701d7cf16005556000516006556020516007556040516008556060516009556f1502253d35ec4177f1766f3b652ce1b06000527fedae07c15f0dd155f2a52e7333f76db8295fea99e31c416139a6f42e594847f36020526f0c77dce05d8c9948df79b990832cb5b96040527f6407068a6d15d290574da434bbffdeeea6bf4492942381fb5880f3cb85262be56060526f10353e65e34115652cac77cf24cf6d7e6080527f883e49eed6eae00340d35609bc807b298675006a9b56d5db1bf6fbc0bdd5c38460a0526f07fdb9d1377264bc6977b8fbf21d3c4960c0527fa65fdc065246f3142a9548b8f44b1a8582a893c180aa0e00351c6669cae7d8a160e0526f024aa2b2f08f0a91260805272dc51051610100527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610120526f13e02b6052719f607dacd3a088274f65610140527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610160526f0ce5d527727d6e118cc9cdc6da2e351a610180527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016101a0526f0606c4a02ea734cc32acd2b02bc28b996101c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6101e052610100600061020060006000600d7f41b1dc95a91c0f63475dce8b84d6a2014ca4859b79b38361bc0180aeb9575b32f1600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f09591d15ccd26715c86df27189606a306000527f1074c0108948ec88e06a37ccc58d4a496b614be8a8c061e1889a53602256c3e76020526e729efe8920b0e6554e3fd8ef3ffdc26040527f6a55705d641bee07f894ff253fd3903b18d320640ef92caca5fe8faa5869a2406060526f0d0fa369916ba32740a28c7ffa522e6e6080527f8ba14f4cbcbf26d66863188eecd54b2acda7f1a5f86bf0fe51c6941342e1000f60a0526f054e66d6c3461adcfe918548ee5f024960c0527f0d4f8ca0cebcdc8a6440b8695ca853f216620435cbad0544528c422b517c6ce760e0527fdebe899263c418bd542bc0d0888519f4c8a933074dca8822676913b20becde7a610100526101006000610120600060b0600e7f16d3ec1f09882e6a724e1115fd966740bfc5a1f97b94514b23a68d1168fb25fff160135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b5560006000526000602052600060405260006060526f0eae09f2030077ef6fb53a86b29a6a836080527ff4a91e12d6b9c378fa5d1646b59b49e685ab915672a872f0ad3878a13e90a5e060a0526f0d202a25256ea37788ce16169dc7dcc660c0527fe043c34aa9fdd992b6fd112ad6c882081b547cb181bf21e63b3a2f9a5c1dacc960e0526e7f6de3ad9f0a3810f6c7b9f1f76709610100527f2a1d06f1ff4b8fee5863ff6b0d85866a6aa55c8c5c57d4c9bb6e7ee5f00bfdf1610120526f150e8e3062f97c80ca5c93876db9080e610140527f5e1985a7e619e2b11823018135870f57db88956447a0ef30ae4442abea98d0af6101605260006101805260006101a052688000000000000000006101c05260006101e0526f024aa2b2f08f0a91260805272dc51051610200527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610220526f13e02b6052719f607dacd3a088274f65610240527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610260526f0ce5d527327d6e118cc9cdc6da2e351a610280527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016102a0526f0606c4a02ea734cc32acd2b02bc28b996102c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6102e0526020600061030060006084600f7f4e7f3f831ac0330f4a7145646b2308154f13f0d8b4bd2f4bc1aae77fc58df06ff2601c55600051601d556f164a295a5f96a09041f69ff8b879aaef6000527f1fe370f8797936043fb243918b0bda2342fdc6f8909876cdf648ac35d085a171602052608060006040600060107f543872703925f6e15c6fbf2e92b7b23be4b78a893cb54ce637e9c72526019a8bf4601e55600051601f556020516020556040516021556060516022556f0129250bc1e499805c6dad0c4fb11f786000527f2f344cd82754b3b5a9f23d6d22ae7d8ca47d620ecc6f2cce2e4c5cb4de8441606020526f1385ee97b39f8fa20cfadf1a4ce4a4c86040527f98ef7fe9a5173caa1560c95365d28545e68b8989a184193ea29aaf7855138da460605261010060006080600060117f5c4a5e0205f85cf2e772f816575e415e19d7fc5a03e0772aa7e47f0a54fe8051fa60235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55", + "nonce": "0x0", + "storage": {} + }, + "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": { + "balance": "0x0", + "code": "0x603b6082603c608660b760a260fb1c1b50171b8a7a77a04378111b39537669943377621a046c4702433e163310157615680b7e9256347b650737367662391736f29b3a696f3c779a109910ff7a7a6605355c46599e0a78534a8375767776643e7a6e765c7f1446816797437b7e91541211505a5b96115491741243397a7011196d436e5e7b97166e026a85057445a1f032099f815b936b570359570905136d626f208c9f807477fd7ffe0201523f4a5f611c996e5a683e406978651e54747e571756937f027e3aa4757c705e705c5798534548807d92414953427c195d1477796f5042175d7c678c34a4606868750380440883416e6e596b786e7c016511056104068a3613351539900473f087f45c81463b3581417b3095939852634a3f36358d7a7f657f76024800133479446c6045844403ff60393c1110716604791b086963106ba362fd047286704a63460635648ca159316176040444536a3e0802931d4a306ea2393f50384118313e53407c3d541c67054949045155455c3ff456935f3b323c1733407469f16d7978203d1c707d865753483b056f445662623b801a35fe967c536b695749787e110833709f5719483a8c80013af4a4041c10525b1b6048531d9e66526c00193e4654093b63741d1d5545715d05181e13657a5860443c8b819313124784f4454338556b3b7f407659581d6d4250385c90441290771a58385736664595338175507d72747d505042f57017805630083a7f44455fa208949e5453579c953e4549659a07520a8836206c4a59115f40977c886815a2ff661817fd6695814342918d6c917670569f983e9e150a396b673c7c717a8b5c509c6e3d8b721c3e209f1e497d47739af233175e121a796f3e496f8f3f8f61195af55a803c3219a416a46af33e0b6f1637a234337ff197361d718e7ef1fd606e786982121b886c627a4917003163325d8c5d5e67a33e620a476c7531967f5e8b18ff4719118945577b485d54145e480b636330726b613e89427745811850464966663933fd44655f3798456d1e906079208780676686068d942015663941681087118d413da19e3a5274919e410a69778d5934a018889e058e054814427674f11d84753d9e5b7c30684577701001483c8e705770328247ff6c163556373984005043143f8a766e58313f8802419e4072193e189c727a123c1d6167757e524a3b9007556f5072578111a2006b3997a079738c783605718356363b5734423e737359190047434320990532483f1b31098a476801807b977e0232436f44956a053a5e207d601b08fe79a0665b077b69413e403d9d3a687173616b50995a7a14475a575e3a4976033c757d1b73109083647a7c96175582701b1d3a76381d981d52ff3f393f57004344613b3668a1374214123034715049474291040b8077539d025f064644", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000000000000000000000000000000000000000000f" + } + }, + "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": { + "balance": "0x0", + "code": "0x8d257f6000545060005450600054507f7fead49cfc66cdca062385ae79f051a4390c576000527fd0d9f7f94f1cc8d2fd223482c46000527f7b6000527f5f60d6e582f439f6716f6020527f60774d948fe1acdaceefe862a6e54c11916020527f58621fd1396020527fcca36040527f9191262e95001a15c1ac5065aad0fe33e29b8430636040527f9c0b8a9954d9176060527f3db16040527fdef46cde2c90ad6b23e39f070b2bc52f0998a86060527f833a636080527f75c9f692892ad391dbcf6060527f1d53b2784812f66e0e1531e8e1fc9660805260a0527f7f74c2597d5b8d9ba46d859159d12ad0e6d96080527f337fe7f3d3873486dcf460c0527f1560a0527f911710de8b38999cab6c3cfbd9b05044dc01de196d60a0527f082360e0527fc318899bbf60c0527febd2d6571e07174702ee55c0eebf40af20ce122b5b6a16610100527f1da060c0527fdf45d760e0527fd355a93d2c44e97ddcd60f845e1dcadc66d619610120527f59d8c48fff68ccba6cc660e052610100527f7f79cc531dd20f90521804c1993c610140527f9b331c646cbac8115fa7853cc99df36716c8610120527f656101005260406000610160527f610120600060007fce44c9eaccfe6bf206096f6aa158bb610140527f80e53ca3610180527fac327874562502b099b83df12efa6000556000516001556020516002610160526101a05260606101c05360556101c15360616101c25360016101c35360806101c45360536101c55360616101c65360016101c75360816101c85360606101c95360006101ca5360f36101cb537fc83d61127eefb10b62467c07424b431e4f8ffa2374b5b952590a757fee068d086101e0527f36c5a642e314a4206a0cce31007a78b3461a7631153367453e98bf676c2a3e83610200527f1c7678339b71b6afa89bf3853f130165a3310929c58f73c998cf12d16cf9cb4f610220527f0498e16f982b920f187b7075776fa525caaf69ba2d3b8539975374d24e95864c610240527f1bcd63bc8bc2529377f7892fd3a05a974d09b4763a0db31b795f05e1cd7873e8610260527fe924913b79c49c0f25233620ee249266b4dd373db8c7b3abd7a0af61352325c7610280527fea4f3b8eaaef65564a6f7eed3d44a3b2b8a1e1338a58ca32d0f1c37bafd788e46102a0527f19ad295516b5fda6e2b0525bb1792a8c3854f9ea8b005e02bc1d93c055decad86102c0527feccd32ce7ebb6ed22eb0d8aa38649067c4ba771b38416e9197ca1885a3a6bf906102e0527f1669bb286e4d3fd981a471ef98c077899365e07cb0ae637bf5a983bcbfaaf141610300527fcc64326653b1d5d095a16fea028ee0352ae85d218e177cdf19fbbfe99d12c4dd610320527f87a0bd590fe290637473b63898b5f26aae2d07420714e0eb7b6e0c4c561fe33d6103405260006101cc60006000f5604060006101806101e06000855af2600355600051600455602051600555600655", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000008" + } + }, + "0x538A8474EeaB43d5a960164c554A20400151D479": { + "balance": "0x989680", + "code": "0x7f4b26560b2d940791740f8b3d018c1a3deaabe12c90b03eb180940437763140ed6000527f33b5de51493a0e79ac2eda2a932d7f6bbc34084b6634d25b81144e6980dd08e06020527f80cbaad461f9baa6cc07de7dec06dcbce0affccb02c772280fbab222907284fd6040527fea90ab16040b2db45d81d72fe566035ecdccb3746ba69b0fa0dded372834089f6060527ffbdb9232445406128d083228db41c0a5b67e230e9c014b30781ecb9de3cf5d646080527ff17aa266e879f8b4f50075f700c4b8ff08c0bea32f1c1905cb9a014b410efe4960a0527f8b86bf12b97a6ef8cd94a36eeec0f11605acc64103bc508300b3e50b042d6d1260c0527fa01cd36922eb2caecc22d580c276b849d7f72116e0d157d409d0d08735b60c9660e0527fb3ef17372c4cb5e0e2f4320df85b1423272cd53ddf0a5553cda29dd4e72712a8610100527fc674b6383e153fdb3c0cbc8458196402a7a077f550f21ae53fdbf2c1820a5f7c61012052608060006101406000600c7f48fcd75d2eb0a07a402d6f458c2dc521ec8a9d47ae55aae11ff8a2d5ba81b818fa600055600051600155602051600255604051600355606051600455", + "nonce": "0x0", + "storage": {} + }, + "0x641602bAD4A323C49629d45338d79A2bb984A3fb": { + "balance": "0x989680", + "code": "0x60d2610320fd", + "nonce": "0x0", + "storage": {} + }, + "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": { + "balance": "0x0", + "code": "0x8b7f60ff6000536060600153600060025360546003536050600453606060055360f16000527f60065360ff60075360606008536001600953605c600a536050600b536060600c6020527f536008600d536060600e536000600f536055601053604e60115360606012536060405260206060536060606153601360625360536063536060606453606060655360606066536014606753605360685360606069536000606a536060606b536015606c536053606d536060606e5360fd606f53606060705360166071536053607253606060735360176074536060607553600060765360f36077537faf893e4163047c05289d407b9a702a25aa8e1fdbcbb6e6d94f2f9274e8c305886080527fe0b62d82842386d246eb69a810abdb2809726f7cbe2fa885968c3ce805a1bf0560a0527fc2d94f6ee30e0dfe8fcf22f0144f7bcb976c742351bbbeaf48e4b52bb3ed637f60c0527fd7544f4031d7cd44745ac4b19dd3227e94241ce359463d356f8fd78c9fcf47cf60e0527fbe8dd296d74032dbf63b373f0e10f29ce12bf743a77d052c335f51d21f82349c610100527fba69a74988c5676412c71650f0d069dd1122209f7ba2d0b857b925e14f237b44610120527f8a537da9e5559e3fd686eca7ffa7da09dda8d061e093b8bbd78aaab215a0bd17610140526000607860006000f56040600060e06080845af4600155600051600255602051600355600455", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000e" + } + }, + "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": { + "balance": "0x989680", + "code": "0x7d03c760c325f8cdc4daaae014b8e32d6408fa8ee3ec3f283b6a30d7d42ba56000527f679d181529ad318d93556d9a0101109a11bbbf2d186cec7944fbaf2dbf14d8c96020527ff86ebbcca7ef069f796ba132dd561970ab8492cf0f43f8328d0c0aa98f9655116040527f676b7bb4ea0d4899b02941302abfa653b1f05e9c35e662d65f98c5bebab42c146060527f580da6c9840e9a73a9aba2cfc092f5c4851adb6961d0871abea94ea51c0c938a6080527f908136bad625f9d78e4a032b7f8b99b6a10021a1d0f79e78e176410c918191b960a052605e60c053608060c153605160c253605160c35360a660c453608c60c55360e160c65360d560c753604e60c853606960c953601960ca53601060cb5360cd60cc53607f60cd5360f360ce53604f60cf5360da60d05360f760d153608960d253604160d353600060d4536040600060d5600060f260097fcd3346af51c7b5bac45c869077565dea47dfc7724dcfc2de6f737ef73e779518f2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x89408B1DeE3283a0AE426CeCf5C49cc3073Ed356": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xd13202f0930bfa690a45b6c2831829395d15c95781714271a8054dfb2074dd1b", + "storage": {} + }, + "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": { + "balance": "0x989680", + "code": "0x7ee8e8e8e2000100000009ea02000000000000ff3ffffff8000000100022000067800000000000000190136000556fdac7fff9ffd9e13226262626262626007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff05600155637fffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11677fffffffffffffff7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7f820000000000000000000000000000000000000000000000000000000000000009901590127d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf96f800000000000000100000000000000001d6c100000000000000000000000007f8200000000000000000000000000000000000000000000000000000000000000712000110000000d0a300e750a000000090a0a08901d90046002557ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb019777effffff800000007effffff800000008000ff00000100007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb090071d6003557fffffffffffffffff7effffff800000007effffff800000008000ff00000100007ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a009016778200000000000000fe000004000000ffff000000fffff7007f40000000fd000000db00000000000000000000000000000000000000000000011d901a6005600704600455778200000000000000fe000004000000ffff000000fffff7007feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee10777effffff80000000000000000000000000000000000080016910000000000000000000682100000000000000229009600555901c671fffffffffffffff7f800000000000000180000000000000008000000000000000800000000000000002107f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56b10000000000000000000000090131676013590cab83b779e708b533b0eef3561483ddeefc841f56801fffffffffffffffe9010901660065563800000017cc9700000000000000000023f00c00014ff0000000000000000223008051b6007556b1000000000000000000000007f62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001901a6d01000000000000000000000000007176767676767676767600000076767676767690131990036008557f7effffff8000000000000000000000000002000044000000000000000000000168010000000000000000900b15717676767676767676760000007676767676766f800000000000000000000000000000011b1b19712000110000000d0a300e750a000000090a0a760fffc000000000000767676240000000000002b057604790131a762900760076761e0002007676000000007676767600000060059007901a6009557e40000000fd000000db0000000000000000000040000000fd000000db00000168066aa0a5319bcf5cb4678000000000000001087f8000000000000000000000000000000000000000000000000000000000000000762900760076761e000200767600000000767676760000000a901c63800000007e40000000fd000000db0000000000000000000040000000fd000000db000001901814712000110000000d0a300e750a000000090a0a7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0901a901d600a556f80000000000000000000000000000000196c100000000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff1b651ce97e1ab91a7f7effffff800000000000000000000000000200004400000000000000000000017f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000010860006000f3", + "nonce": "0x0", + "storage": {} + }, + "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": { + "balance": "0x989680", + "code": "0x7fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527ff1f6f7815b1d9ab2d0116ea5cfd5513777f85a9e0ea98319ed1f93327545dd596060527fe993da5edb8e12b4b9ebbbcb94b5a7a01be8606d6e04a2d69fda74e39a6877da6080526020600060a060006001610100611b15f16000556000516001557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611c5af26002556000516003557fe6a85b19d7a91a47c412085e4e7e26e410e36a13b93a9f901a4e60ba32ffbdae6000527fe8c2ec339609ac230d0366063a6ae492ac251168ba0396d62c885d068e80d3986020527f211f80b4b063ea7b9ccc5158fe4bdb99f4b7eeb5c02a953cea6bc82d1f72e4236040527f9ece146764964f6cc5179913a7ea94fc67941932299548b23330f407200a6fc96060527f4874f78b335ce37e6aaf920457ab92bec58d03030fe0dbb8e1c3dbe2fce49c376080526020600060a060006000610100611c7df26004556000516005557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffdfffffffffffffffffffeffffffefefffffffffffffffffffffffd6020527fffffffffffdfffffffffffffffffffeffffffefefffffffffffffffffffffffd6040527f929a627f76294e7041dc0d74d9c3c9ac2cc7ce336a28023405d93aa03834d0bd6060527ff3d7a84534ee20597f4dc1fc9c44744f75a880989f14d24199c6be5490fb24a86080526020600060a06000610100611ca3fa6006556000516007557f0d5d8c3c63c36344c65b288698895195d95bcdc486db6b84bdb44000077b0c776000527f55555555555555555555555555555555555555555555555555555555555555556020527f55555555555555555555555555555555555555555555555555555555555555556040527fc6ff4b3f7a863bead987f1963f6b0aaff9e4951bbc26d6176a825a3d669e30c96060527fa8e431bfa6a9a58e352038b93bd3f670a9f41d16d64391fbfcf0c53e8af119cc6080526020600060a06000600061010061197df26008556000516009557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611b97f2600a55600051600b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb5600052634000000060205263400000006040527f06af349be1401d5693cd9897ff18f24b75c8961730a7fb42f7b8c05adb7ae4aa6060527ffd86c3aefeedf5bd733562eb1c287e20505f7257275d65a3203da7df67d2cfb06080526020600060a060006001610100611b72f1600c55600051600d557f26a77edafe02e595da4fd28a5b12e58f35631825b42942ac45f741a3cc48235d6000527fa813b95c8f745c9e8c74835e6d7294a1f18d8c0223dd9de2195f6fb80e87df1b6020527f729ac1c416279c26f6ef1880807d14fb9e5b59dd04284967b886b763ee3e531f6040527fd55891b3eae94b9d31603841e0a506f4f1ca9707f1e396a1357d03cb7d4874766060527fd5eb98bbd949f52c9202a47ec52b8fd5ffa9e407b3597ee9264794de43fe58726080526020600060a060006000610100611aecf1600e55600051600f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611b52f26010556000516011557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6020527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6040527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6060527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6080526020600060a060006000610100611c9ef2601255600051601355600060005260006020526000604052600060605260006080526020600060a06000610100611abcfa6014556000516015557f91e80dcf2d1c4a9016fb27e21dae230fcf796b906a147329d2299c61e9fd016d6000527f4ab4bf536ecf5c53a5292fdfb6f790ac1ab2fa939c88c011dc458ae9d1c314336020527fccd9f0d9daff86a998d359e6d8590640cda3fd0c02ed358dd62c67ac9a599cb06040527f4b9e55f8048a5156261d796f0735f5322225ad150751c79cd050e054baf0f9716060527fc44c1988e80d316cc9fd2f484030ff014b9009644ead59d37f7d13ac09aef2766080526020600060a060006001610100611a33f16016556000516017557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611c26f46018556000516019557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffffffffffffffffffffffffffffffffffffffffffbfffffbff7fffffffffffff6020527ffffffffffffffffffffffffffffffffffffffffffbfffffbff7fffffffffffff6040527f1ce4cc2c6c9b4ef10f826805726283048e38decfa349b69274668dd196cf20c66060527f280ae8f2a302694e423a2310d8ee05b84f6b34cbd87645bf90e8a7da9bea4f636080526020600060a06000610100611960f4601a55600051601b55600060005260006020526000604052600060605260006080526020600060a060006001610100611910f1601c55600051601d557fda7ec96c9e839e42b8502b8626c53235c48e9901e9914849d7dd107de28f7f806000527f0d654e9e3f27b46f31641cc06966bc91038240c335ee08f569b19900af4ceaf76020527fdfdb06c0fc565ca8fe717ce893796e2262cc4432fffdb3cb183cfd03b3197b696040527f8a38b7e8c499eed9961f8b9275549450ce253c0becb777723bc6cd3f37d2f8c26060527f10650f82e1b46cb015b7f392f549113a19c32649de943a7d5f36f3f71b92962e6080526020600060a06000610100611969f4601e55600051601f557f07e55549b656864ada291099acf04498baecec4ee9e5ffabe3be06ca7f2d70d36000527fc961b86e7fc4b49ed3ab2e9abb290c42b3d4937a8c61ef808daa683ec9ece2496020527f33b1bdb31c143cd58de8752b610d54f1ac4366a83d50554bd881b9fded16c1bb6040527f97a6f2dec960870eb0946d725d0952a0f856a3d049ffae0b49505a16b358f0fe6060527f0b04637614be1f3492cb13ba35138d31672126f91d4fcbc49fa9a7b897d3c9eb6080526020600060a060006001610100611ab4f26020556000516021557fda2564d83aad64c14d0d9ff48b1b1a1a4e6389abfc88b1a84699d5bb46e9a43a6000527f79a5c9ee5f65ad10c9802d3eb05326854a4c7f1daf119125e85193871c192a846020527fc9349f26cb6c3d621a4819dc7abd4552b0d40262ed60c5f4de04966d34d306966040527ff5580e84b736cac1404b9f4653d9d02d99040364e727902bdb7541d9ae3a1ee26060527fbe39d7d06a2a38e968acc2fa53fc55b5816ebed7ca643a55f01e98ac1305c5736080526020600060a060006001610100611b80f26022556000516023557f8fccb068b531ac17d393ea08148715ab1898c1221e597564e77c2c9e78a9cdef6000527f4dc2cfb84a8455b0236d18ce80926abd45467af811f56e6272415193751cdae86020527fc4dcf859a68077f23f823233bf677414fd9590e2a65a24bd19e631b2684c01456040527fa776aedfa3736ca6866a41294f89dc4782ac275121732a97aecb822ff59306586060527fcdc5b3065863cb5d3cf03470e91aafedcb274e4f5d0848f68d2567ee7a9ddfba6080526020600060a06000610100611aedf46024556000516025557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffffffdfffffffffff7fffffffffffffffffffffffffffffffffffffffffdffff6020527ffffffdfffffffffff7fffffffffffffffffffffffffffffffffffffffffdffff6040527fe6fe5af4014fae1b8838a671bfa6509acddb8d61778b223aff75fe49ae234a236060527f7d4bca4cd977976c41986214a10be7463b36bd73e7283a7b62d15d454a9ddc9e6080526020600060a060006001610100611b36f16026556000516027557fc5929fdb9b2ea2f7717901114528523cce282c9958e34dfe1dd97e8b9faefdfd6000527f90785ad69d68434f9be9d6fc656043bf9372b65357822817086c2f06ccdb10666020527fc8e51af9578a30cf291bb0cde19d503d4a75c24ad8becff0d5314c630c30906c6040527f6adac970a61bfac29951187862ce1f66f90ee923742656bd076677d87469b7f16060527f03bec49c0bf8bd2c77dcba46118716009eb49cd098c538b7a4e5db94357441cf6080526020600060a06000610100611a4af4602855600051602955", + "nonce": "0x0", + "storage": {} + }, + "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": { + "balance": "0x989680", + "code": "0x600060005260006020527f0cffdcad2364bf800d4f8ecad5acedf0975a3bd851fd9571673aa9351f5e95306040527f21d1fdc3e210bbb02f211da9de4a47a662b545dce50e4aa7af30a23003201e7d6060526040600060806000604260067fc66e5fe04ae9124419d32a64cd9d5cf2b3f445692192c5fc79b7b49fc73286eaf2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xD74CFe323387aE2fd070CD046173026716D8D649": { + "balance": "0x989680", + "code": "0x7f015822aed75630376d37386f3799b27ec63cb07f30e4659a3b7d9cece811d5a26000527f67c06c3a98df4007b07860fa901efbb50ff143e42809fe2041fa24c02026c1126020527f63ad3f11f2f2eb2478505506675eff6e83f3867ff066fc991f5fe25980c389816040527fb70e5bd3f9e9428c3cbbd6d663f8e3feeb70b54c9197a0de4c49f0b7438466b56060527e14d252daa3180c5e0d1de5f5669551984adcfd0e36d90e1bc29ffdf06696f66080527fe38950d11fd574dad1ad6bd2456121fba6fb6895ac76aebb386b7a98ad76570e60a0526040600060c06000600a7f5c693deea99ec3065d08bb3bbbf8992574d560bcabcbdc8781ecb8dc228efa9bf4600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": { + "balance": "0x989680", + "code": "0x600060005260006020526000604052600060605260206000608060006001617c22f46000556000516001557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f3bee45b3eb35ba25ddf514daba65fef3f327a2ab836025e69585f1a903c7c86f6040527f4499a1a179f672d04a0b2fec1bd260ddda493c524f1b9e513592d2f476b963f560605260206000608060006001620160eef46002556000516003557fd9c84e1cff4c078bf9679ea5bf23592805f37ea1ec5fcd75c1a6e8a3fd66e44c6000527f3d0a9c3803840519f5701b12bc8ba1cf5f5bfd079dcef891120fcfbdc9c2911b60205260006040527fca06c9e53a2cbfab1d6050b4ea989e98b4fa84f2d19c7594b0073962de4e18ae60605260206000608060006001620110befa6004556000516005557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f3154834094fb37ba975716f3970bad6297c47c172e7384670a4ce1f93cd344066040527f1cdaf53e7a35ca88126674601fa2b335be2920986a3cf316840aea84dc1b4a696060526020600060806000600162014802fa6006556000516007557f63efb6cfb44bb2963a13fd5e3fdaffc6fbc619559964acf4e8614e1d15f3ed086000527f024652b7aecaba2bb5d6fd3da04180ba0ae2e2c6ef618fabc25b49581db73b766020527f4421f056c8b311d1c0461d9e241c010377ee025a6aaaa218980a1e8a03b0f4666040527fe19e0855afb14158ae4bafec2480565d839a784cf5fb30ecb1d425b74a8d4503606052602060006080600060016146e9fa6008556000516009557fce846eb15af7598f7fefd78f0efce96830f71a5fa9f360b4c32c546e82fbe9c36000527f0bb1573c8bbd32e2cf127adcbfbc0cfa59330ddd44f22eb7a18aee283001ce1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fef7a75d0b606ceb4a6a8c83052578514aabc80200cf0e965247e40869b01cb7160605260206000608060006001600161fe07f2600a55600051600b556000600052601b602052600160405260016060526020600060806000600161e8e5fa600c55600051600d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f4c23edb3269c38a2b71f2dac376ef96277b30deb4b8b5f4b0a446894fb0434e26040527f4f5320eb658715ac23b12693f7b736660643a49f7bdfc12aa58368387856f7bd606052602060006080600060016201039efa600e55600051600f557f16ec952430685ceab67971d69ba453c0f7c7ace8ced2b2ad05fdbe8855b966856000527f16e01e4b4546a40674fc3e4afa205f32a99e0e0361e1a5bdca14dcba1f4be01d6020527f58e5f30ed3f01bdf0ce96e36e0e18f0ab1f5f4dc441853b7a0a05013eb0588866040527fffda7608c1228a1efb7030695d5d5c52e8b71938f0006be285d3fd45e9548e9660605260206000608060006001600161a448f26010556000516011557f52e92aaab476abc19ccfb6001e47185d032d199e483ade94021701640b96dbd46000527f67fb34f376fa286f69b858fda0aef9dfc878cd3d45a1b4731b602dc8a423181b60205260006040527fd264e88a16f0b0b8fb3baf7a9de435ebe24a3b00d37e02a4502743901910c8ff60605260206000608060006001600161fb2df26012556000516013557f689298d3c55f4a07506ffb08203a915568fb1992f0dbe5265e8311236232b9bc6000527f85d6554f4cca60914a02671b5008cd2328a23b7a20e71f72b30e1ba3bc59071c6020527f6d0ccc79ed8dcd74c3db310a39119e23b2ed6c3352076c9b46a56b00bd9f941b6040527fffffc98dd3b5e04804879b2857f1f05896ea2569f79e81684978dfeea6b19b4060605260206000608060006001600162011fb6f26014556000516015557f1ddd145d47aa6659d09a487fc08ef28ca0370d45a533849285ba2e335ec271ef6000527fab376704c96d23f843cb7095fcb0ef36f74800a5d2f6d015c8a11cb637030d196020527f9f16a0d1950efed2986a574875a2312ee9862b0472eb497682c5f77de39c427b6040527f0de7d8686e5461ec3acb8012d977ed0b685b39152060460c6986d7b60191d5576060526020600060806000600060016201629af26016556000516017557f52c42577ba6da35a6dc6926eea25f40ce638bd287d51880e62587aef56ed476e6000527fdf8f7cac41b8d9d41c8e98eb22e2d3ba333466a3499e6c4f0e3b55c29be7461b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f2e2603f500a5f34360299f4688039a58e69f5ab3f2bf7e7c168b4fd950ab278d606052602060006080600060006001612aa1f26018556000516019556000600052601b60205260016040526001606052602060006080600060016001618b52f1601a55600051601b55600060005260006020526000604052600060605260206000608060006001619b41f4601c55600051601d557fb2b76192badb0847f3b2457590b2d44c9f96bc0abe182d87456e2767ffc40aeb6000527f2c96e9ba9df964f2b4008771c04941993e39156445d70d0f5dbe25cc9d4ffe1d6020527f305608b33c90faa5662c24c23d12e422f3cc849466213be9363d66eeea9991026040527f67c8fa634bf5d705e990f5cb32d9ef356bf4a7145cd2c740b4b1dc56d6cfb9e56060526020600060806000600161eb8efa601e55600051601f557f926d59808b2bc3e14e0fcbcc631dda2f8b3aa372cb37b1423679e598184dc3d06000527fc427b2c4b667b24ee990d36a0ac61c6e6d707f3e3e416d2005a83e3e536f961b60205260006040527f16b4650305fd17eae244c1d693639579d47c538233c2533e3e6f5b86f0089220606052602060006080600060016170f5f46020556000516021557f930e1fd7f9271151fd26823a99c889ecb4ab61546feec146368da7d21f44fb776000527f5fe6d43e7f98243463ac5569776be9e12fcbede7659966ca47a9234bc7bc8f1c6020527f4d27a9cf036879918194afbbb5f7646c0f03e28236cd38973db762b324e04ba86040527fffff287e5f9bd1b2ccf4e8b875aa7c72eb70c51b3b18e3a276736815060f85b360605260206000608060006001600161880af16022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f8bb7ad38f2ccc549cfa98226ed03f00b3542544ff46096e94c69af6ca1ec73be6040527f22ae7721a3f4730a9f09cf0e1f575bccd94ab337cdcef1c3123e4825ba1dd4266060526020600060806000600060016174bef26024556000516025557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f45185c6e5ddd78b586155caf4751ef3969268f7d012d07be817c7cc632a983476040527f20be2543f6125e7806400f8db64d7c1c70894861c08da888f41ddb4b5dbf539f60605260206000608060006001611661fa6026556000516027557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fd8b851bfdafa7d90d5eae79c1db25287222016d88bae4b7856987cd1ab81e81e6040527f6f84238d15c5c049dae779bbef02ba59571258bda10b458cf71b95d1640c26716060526020600060806000600161d66efa60285560005160295560006000526000602052600060405260006060526020600060806000600161aa00f4602a55600051602b557f846458ba17478612f4be17db5ca7c4ee8e2397557a844b612713350a519ec8296000527f21bd55e20abce4ae2cb70e577a3cf541f028abb57b1334e4cd7f7ce8f302941d6020527f044d78e3b2dedc78e77d3faf1685dbc361495122ebcfc719b1cfe48a34c11fcb6040527fbaa38fd4409479113a08882a5d3e16007be8e1d49f5a4697fbffa9ce4b3f599160605260206000608060006000600162014c64f2602c55600051602d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f2bbcad12919eecfc432da299104a72f9ee012e14503b95473f5536f52a89e0f16040527f5b44246c8e7a5314f17fe500b90f6a99c01e8991b0a07d85a1adfd7d10d6e3876060526020600060806000600161ea1efa602e55600051602f557fb3d5b41474c8858089f3b75559e94169729a884e468b01ca05af199455c760446000527fda0114f5d7b57def6f3bfe8a9c943e56cd80622a5b4c9243f448fe62990af71c6020527f6ac9cae3220f21ad35a896c09f219bde9068fd977b67d310fd5ed2521817a6336040527fffff16473d4bb2613dad0ec379c4ad2b99fd5dc294a4978087252621228daa0460605260206000608060006001620170a8fa603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": { + "balance": "0x0", + "code": "0x68066aa0a5319bcf5cb47f7effffff800000000000000000000000000200004400000000000000000000019011610107557fffffffffffffffff7effffff800000007effffff800000008000ff00000100007e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000900b638000000067fffffffffffffffe90019002610108557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7cc9700000000000000000023f00c00014ff000000000000000022300805901b712000110000000d0a300e750a000000090a0a6fdac7fff9ffd9e1322626262626262600901a900a777effffff80000000000000000000000000000000000080017ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb090016101095567ffffffffffffffff67ffffffffffffffff9010901d6101117bc9700000000000000000023f00c00014ff002c0000000000002231081b684783921454358970526a010000000000000000000060000861010a551b677fffffffffffffff7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff096001717676767676760000000000760000007600006c10000000000000000000000000089006901a15686d5adef08547abf7eb7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a001c7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd67d0212626262626267f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe900861010b551b61010c557bc9700000000000000000023f00c00014ff002c000000000000223108762900760076761e000200767600000000767676760000009007777effffff80000000000000000000000000000000000080016c01000000000000000000000000900114157fffffffffffffffff7effffff800000007effffff800000008000ff00000100007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1790187f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd61011190046101116901000000000000000000760fffc000000000000767676240000000000002b0576047900990137e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0712000110000000d0a300e750a000000090a0a089018901561010d557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90050b7f40000000fd000000db00000000000000000000000000000000000000000000017ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a009011901a6f8000000000000000000000000000000167b368d219438b7f3f7f8200000000000000000000000000000000000000000000000000000000000000900861010e557a010900000000000000000000000000000000000000000000000000717676767676767676760000007676767676760b9001777effffff8000000000000000000000000000000000008001682100000000000000229006901276013590cab83b779e708b533b0eef3561483ddeefc841f57f62d8fffffffffffffffffffffffffffffc18000000000000000000ca000000011611778200000000000000fe000004000000ffff000000fffff70067800000000000000102900761010f55760fffc000000000000767676240000000000002b0576047638000000116610110556007600190066c1000000000000000000000000067ffffffffffffffff677fffffffffffffff90081860006000f3", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000011": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000012": "0x000000000000000000000000000000000000000000000000000000000000000f", + "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x0000000000000000000000000000000000000000000000000000000000000014": "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x0000000000000000000000000000000000000000000000000000000000000015": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000016": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000017": "0x0000000000000000000000000000000000000000000000000000000000000004" + } + }, + "0xF0AB5055e5Bdac80D061b1E7f2bA766d0498b697": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2629e617faf4ae81683157df0e0b4f967666ca88b6f2e41be40c619288f76ac4", + "storage": {} + }, + "0xFb4bfba6610Aa9869db78F7c6b8f28b166CC8674": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xce939f993ef29fe9f18cd2fa2ce7ea2d51b23c6b808b850b33226f40d4cf9a86", + "storage": {} + }, + "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": { + "balance": "0xffffffffff", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "storage": {} + }, + "0xabBD7eFF49254583a862901dEd2D2E9DF7542E5E": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xab20700d44a6cb18e72347969198ce9e297e3f58b62c60f9a2450c93eab96240", + "storage": {} + }, + "0xd51fA0De3ccd210D4cCA7f9D739f305CfCAe9117": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x579dd91bd24f9287c7fd47e0eb7b407c83dcbf3217e11f245153ebe0c1136d83", + "storage": {} + }, + "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": { + "balance": "0x989680", + "code": "0x6000496000556001496001556003496002554a6003556002600455", + "nonce": "0x0", + "storage": {} + }, + "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": { + "balance": "0x989680", + "code": "0x60e360005261020060205260e36040527ffaae07a3a2b9fa3a20602d0e9afc484992acae594db6cdb5c5e970b01fe1d2fd6060527ff0b069f3fd126ae60edc9f8fd44e79165d533dd418f68f4df72271a1e4693cd76080527f1bf6cd9b8e4f6ea9eda97e449785f31c52a4b2d56e06a30160ed96a6feb4cd2260a0527fd593551965f337f92ad2ef16ea5fbd47af7fab77720e2b5d1f1431187bd1266960c0527f10f80389536469944c05ecb9e0e5815ecce9aaa8fba0b6df40e4e4ea824c466160e0527f7c62cd4b1aa3e55e1c53163efd4767bf340c7bcfe799823dd813c299eaa43452610100527f8f165b90caebe259b370266184e1f0cafd9d42b37a5d3e888f5ef09dfc54032c610120527f0bd6defa6b5381c9428fafda0fb74a9df34db1d8d695d8810a9622b83b75ec4b610140527fd67130e95cf510a562e00a1b65ef39fa2c8a71008af6243bc382d06bb393a2e2610160527f15184ebac4fa806cd9a59b5a5e7067552acf594b687582fb26d45cef67b04f17610180527f5ceebd64fe9bd9e8440bee276ac5342a3b8a4126fcd137f2b03911c4694e5c436101a0527fe6c897f9f07892811764a8afc441bc4ab2dd353220874dca6ba859a9cbf6bc036101c0527f28e95ae07a5eaedc49a861dd0d89e2d310589d3c1af7c21816c4090909fde9e26101e0527f1d05d29d378a36206ae4f3abae31e26899315180a1c586771cb16fe4ef257361610200527f552b6cd8377b3231d5f955e9ca0933bfe0c900d568852407088d3b3a154aa685610220527fad10605210435009fe1b0bbd13347c8d44107b90c8c8a6e71a9055b33c46e3ac610240527f4a0eb5c400a314152caafd8cb2399e459c06c26804f4a72275d8820f905dd7d5610260527f35257277817de1ec1dc26cd00ebb54e7bdcd2727a93f6ad18c1ff2a3fe058eaf610280527f26014895171a3fbc54327a922b6baa6008f188409b7a057a20f369d1a31082ba6102a0527f8b733a0ea3de93de3edfd4d6cd75704f0705fa00d25ae45d125edd24d74a983d6102c0527f1e8478e4dbc47704425a059f02d999f16d754e5830a451fbef62831e891154816102e0527fdd64f93827ed6c86190fbcdfb861b25832bc7ade533ce7b745e7f09724bc5a66610300527f2e9892e7834d12e6fdddc6f459a787bf624ff3c9491f78b87d15f687a6f1171d610320527f3f730fdc84ebaeddaca539e147900f45f6fe6e685df79cdb6ab2459d03ccbc70610340527fcca041875600703836086de20840d1183317a3fa577890ce6fe82039476a09cd610360527f75c64f3414ce2e4e9db92b2faed2c5e36cb0564e6085f6b418b6d5dabdd3304a610380527fccbd8a35b466aaa12f730b6c5fd79b506ad023e8796db42af39ab5ac6d67697b6103a0527fb01d6cecf3b1e6668744c46db1be303ed3d4efa65f5c8082406f1fda81ece65a6103c0527f978144fee5e0eb04f5a06ec8c5e05581c3d1d41b29036103f04645beec00e0316103e0527f6db832109438b66e4481c69f387825932055264bcac0880659388926223732e161040052607c6104205360846104215360866104225360716104235360236104245360526104255360e360006104266000600562ea33befa5a0160005560005160015560205160025560405160035560605160045560805160055560a05160065560c05160075560e0516008556103e2600052600f6020526103e26040527f248028ef9455230bd7f522958ecaaf82bed59d3e3eb33fa958cf0c9d2f60238b6060527f44943b2e4e40cd93d6d2ec3967500767d5ec8ee835418743f0fd6408287e85d86080527f2f8a7437b7d241a054f1be704da4945e6ee1ca560dc96ce512f583a06bf7530560a0527f36dc00a8c881ce08a5517e4993dc6cf55671ea731e281a652349c8de444a279860c0527f368250dcb2fa909e2f75221837413ff1594aca10c381d3212a0341095705c1c660e0527f45c68c9fdee5d1700940d43b61c26dbb413c7ce32a43135b5e608580f659df19610100527f6ec18e46edb7feaef4f2ef79d14eed52c1a33ce66e7d7100d3e599fa93d5a487610120527f6bf749dfc1147cfc81c360b7d9ddbf818620bc1cb69935fb1aa0968b0341d1e6610140527f7003abd30fd7aab20dc02a2cf219ee4e3370dc944614bf11fc9d7e7b5afe2b64610160527f5230dca1e5154963a38a471021d87e08c4b019a62e4a78077a49d9910aa210b9610180527f74455d43ebb593133cc60bf92750661d4466929d1e33223b808e7830144c0a8d6101a0527f4adeaf27275c0641d2bd7cd987d333c2babd0a1d6dadd4bde27bf7b9f5c756066101c0527f15f2e9a6302c609edaeb3c327366fc0ee173ac89d092cdce9938a64137b1a9096101e0527fb0c77bb621770478ba149ef8bdb5cac919eaac04ebb1b93988ea1fe2d08db09c610200527fd962c98a7b2b0fbf426a137b0c1da1ae9e26b04d9a1120cbdd75aae7d1e347b9610220527f98cc876b2e0c67b1cfc529ec6b905d8fb2c92cb667150f6cf55ad01be28e9db6610240527f0fe3ff0b7067a1584d2c13d2e0d88eaf0d92cf20ccf2069c9adeae3c1935c343610260527f0813c163bf3165486c863aba88cdda635910d0a67a6257fc797900c9d823fede610280527f996247e75b775207a98afd38a3922af9f856572d8611e3bb02881db07ec2b0386102a0527fc1c01ace26be91fb5f4f5a1f40d9d4e08e8467f04cfe3ebb27f896d5aaa295876102c0527f46f445787484e54524c9dee743ed2c7421ff13520859c9845bd48bcfeb277ef16102e0527f08e8f600d4a48ee8c71deea2f511053da84489af32e4b8909fc90f79052cc605610300527f7cd12f8c3ba6650410f01559b8bc869f70ff721ce334d8ee19e1e7bbd52258b2610320527f1a38ddc7183eac35aa6f1d444063379ec52a85c60bef447d6df20b22a35ec846610340527ffc2819284a26887c7dc9eead9ad44d4a685cb048c42bfa434286a776c898ea67610360527f01bafafac3bb3f73f6b2ec355422a65e8f453701d18e6602febc266c88a7c792610380527fa2dd5015e81fda79bb08c408f2ab994a7d30ac41eb14e2a264d9252f473c60776103a0527f31df7fa21fe0a305e3e308ed5dd4ab3707cf2c36f550eb36d06127a44e8079ab6103c0527fff9acf8767e66237a69bea82986cf67e395fedb7cc0f9b313c71e43f15b0cb996103e0527f71ee952eb352d50ca60c38c05359196881e5c92b9b255d3db87f5d049b8dd2dd610400527f9124e3c8a00153bc22ceff34179e0701f387f47ceea3bc39f395ef7bed9882c3610420527f6bd8000000000000000000000000000001f1fc721aaa4119207ef47ad8eb122f610440527ff9d42abb6e626b18641b3106800eb0533016cf48e6c16156c8709b9a715db426610460527f8acde410f5e3406e1903da96d312a40b664c7739273db7c6ed6648239e040a20610480527f2cabadd704d468f241dd904a6632fec62f396418f691553246991f86235783a36104a0527fafa27b738831fe4b18682241410d87fbe96a0e5fb9956bde3405e8f06a6ee1be6104c0527f9b811b69d55cd62936c12b36a8905681f95baa73e38c804f0dd9ce859418aec96104e0527fe6cd0e199631c5561acfdb0f4775dd26f5730c5625fe2799f96cb1d030284499610500527fa9afc4207868c6d5b86a8dcc23c4acd8ad6ab431f4780031f72f810cd7fa74d9610520527f34625a5e5161695cc029dce6569f4d787bc0fc318a8099d6dec7411e96d2ed59610540527f52174be74808d4f3bde58dc2b44ef99a1bba5b5ad5cdf5549f049fe0b184d7d8610560527fc8f06e1de0809d1ac202556892c6596f6da699d61bf9218cede09d49f402de94610580527f6ba89081a0a1e0c3b5e1d2510c1bef2c773952f1628539dc9cf83dc1b70bccbc6105a0527fe4dfa2deb3d771e6f98a8ae4138a8283092ed48bbdd7e25ae6deffe7be3bdecc6105c0527f7a7741900ef61b99f257f3f78b3c4bf782d1d386b38cb7ef1e39f0b5b094e0206105e0527fe7364d03a262655301265f05019b07c401c6a1216daa542f8b9af7063aee8012610600527f7caace2fae0bc642701a9e68679af1edaa352de7b266807cf9ed1f4183c7109f610620527f55d3fd38ba1e4615050ad6b85977898606251555166540ddebb6a2edbec026b5610640527fac02c66f1ab04dbcbfdecbe4b45b23e88b47cea22aa6f9fe54cf5566ee5c8233610660527f076dbad8993743658ec20a6b08011b7e963e84267da8c37973bd60e9575959bc610680527f425c6ab015129cc0ea6630fc7044e458aabd48b9c72f9ab49cd4bc431704395f6106a0527f9a7a1ef1ca5040473b5cbb69b5a5b1b335d56098cc4e21a66b28359a7d7a3d836106c0527f08bda3f52af64cfb832c3d5c1b6c8e6c1c30efde970c00767b0613df6bd551e46106e0527f335ab482163dbaf64f21514e2261607cf8faf45345760c9eb208c07d00605a5d610700527f20c1360ef4857065a011a48e0edf602a97ee036d03c04778c2294588259a62b8610720527f583bd4fe66b6af52f1d2ab8c694e7af74fd1756a98ef0388aa3e04004c3b888e610740527f38a6b73740b97b303554dd7ac963234b5d13c612920018e0f43540afcb50f748610760527f99b3a4b63e7c9548c08bf23821ef55a5a5a1f7a5d8b54294fba52551166c320b610780527f3476912286595061f76abfde7b82d6b37bdc511082ff700c7c0374946e87303a6107a0527fe367d1c0f8d4728b996355f936b87588f9b3119896e75dfed07fec08c7a883066107c0527fd3b5804babc1a6f9dc98f1994d8e3d0ea45c10e164df92a05dca65c1508680856107e0527fe1eecc21fd182df2d3dbf79a9e66a5f9a2117fb9b6455cca7ee8ff3dd35f958a6108005260e161082053606461082153600c6108225360af61082353600461082453600e6108255360c46108265360f361082753601e61082853605f6108295360b761082a5360b761082b53609b61082c53606161082d53604461082e5360cc61082f53603661083053608f6108315360b7610832536103e260006108336000600561927cf45a01600955600051600a55602051600b55604051600c55606051600d55608051600e5560a051600f5560c05160105560e05160115561010051601255610120516013556101405160145561016051601555610180516016556101a0516017556101c0516018556101e05160195561020051601a5561022051601b5561024051601c5561026051601d5561028051601e556102a051601f556102c0516020556102e05160215561030051602255610320516023556103405160245561036051602555610380516026556103a0516027556103c0516028556103e051602955", + "nonce": "0x0", + "storage": {} + } + }, + "chainId": 1, + "env": { + "currentBaseFee": "0xa", + "currentBlobGasUsed": "0x20000", + "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000", + "currentDifficulty": "0x20000", + "currentExcessBlobGas": "0xe0000", + "currentGasLimit": "0x11e1a300", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8" + }, + "fork": "Osaka", + "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f", + "transactions": [ + { + "data": "0x35", + "from": "0x0b90ABAC5C8F6ce035a107913ea5D7C6eA24f9f2", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6", + "value": "0xfe" + }, + { + "data": "0x", + "from": "0xabBD7eFF49254583a862901dEd2D2E9DF7542E5E", + "gas": "0xf42400", + "gasPrice": "0x20", + "nonce": 0, + "to": "0x538A8474EeaB43d5a960164c554A20400151D479", + "value": "0xc4" + }, + { + "data": "0xdf92ac04706765a4e274839cf32f84312e756a6a88f9571ad2cc4b6bde369fb6e1eec69f223fb3a373b720e2c04b3cf6975cac6b07a5db676b54bef65a0542e123d14e1b2a6609d159c733c586", + "from": "0x08d033C61e1E55bF868082cf788a3949f4ea949D", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f", + "value": "0x598d" + }, + { + "data": "0x0fbede1cda5ea094f3d336e7086c33f03a60", + "from": "0x89408B1DeE3283a0AE426CeCf5C49cc3073Ed356", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d", + "value": "0x0" + }, + { + "data": "0x185adb1cbf8c55587a099e646bd7b247a0567c03924be159636e", + "from": "0xd51fA0De3ccd210D4cCA7f9D739f305CfCAe9117", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3", + "value": "0xdd" + }, + { + "data": "0x74186378b78937c2e7cf7cd7d6404c8a4dcfc5e5d727", + "from": "0x0b90ABAC5C8F6ce035a107913ea5D7C6eA24f9f2", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F", + "value": "0x33a7" + }, + { + "data": "0xe02e8207ba2827e4a98f8a5fca6a6a2485896b4f1e120e0990f8f1abde4f14c7d175fec00dbe69d167e0ca48333b99214cd6fd665cebaa7f1e9e6e1f16abd9", + "from": "0xabBD7eFF49254583a862901dEd2D2E9DF7542E5E", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c", + "value": "0x7ffb" + }, + { + "blobVersionedHashes": [ + "0x012c1fb205d2aba4cdc7b1da451737a4496f61db6a9404f086443a9ad6adc41d", + "0x019f3411a7a4978373a8718d07d80152b457d6167e6b2e00eaabb75d23005fb8", + "0x014d775ca00a525bdfd432f7bdcde8821b7434e7d6d041181b009c9ad14767fc", + "0x012063c494734e4905ac1a882e1da4b41dac3c6f4d88165279a5ea3a4e1e65b4", + "0x01d404619f4f9383cbf624a616734f4f13bd4c2e778c5c32f8b9d3205963629f", + "0x01fe71124eeaa9afbcd2c70a0092c0bc8c71738e958c75d896e546304f5f665d" + ], + "data": "0xcae6", + "from": "0x08d033C61e1E55bF868082cf788a3949f4ea949D", + "gas": "0xf42400", + "maxFeePerBlobGas": "0x100", + "maxFeePerGas": "0x20", + "maxPriorityFeePerGas": "0x1", + "nonce": 1, + "sidecar": { + "blobs": 6, + "commitments": 6, + "proofs": 6 + }, + "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89", + "type": "0x3", + "value": "0x0" + }, + { + "data": "0x7fabc0867b153544d0a7a6917649213ea389d9fbb8d2cf1d31a4921c2d19383080dc1752efb642d761d03a87ab3e5fba43e6b5bb9d55e6c3454977c539d55e32c00c02207b00c2ba56c3d800c2716df020f56948eed77d629bb629f6812e9908d3e1e5846faa3ddb00a4eec063222bcddecb516dfd85543169209e07727b860ef2d540c3a60529b836baa37caa3253bf76cee4b2da73884961397d8208303f7aca875b83ab8f0458ad54306d435dabe741380930e4f72130433408dc99c1fdb46503e08b2afaa43fdcaf9d69cc64d45a4763464acb0cd4a8ebdc421c7c4eb55b6870b824732294d4da57b9fd93d9af41676c9ea38eb4d94305582f2ded7fa8ef6de9770a7cdc5e36c879074bed19d32057ac3afb62b016bc42ab1a8631ae96f991cec8d9b55a4078ba3e115e7f1bbe3a1a59b1d25dbca7f12d4aa49f89ba7acf15e72a210fdb6bcc820e0e51ad73169c35c91c5ec53a9d80206d2c911cf72909c56ffdd464e9cad124ddcd09624a27e49454e4240996cf05795d9c80c6de9f5057f0e693b1790e7c1241dd43c4b2171b753eb0e1ce4d03dee9533e0138b6a7ccb3bd963918fae9b528ec34f4bcd0a24766da", + "from": "0x89408B1DeE3283a0AE426CeCf5C49cc3073Ed356", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb", + "value": "0x432c" + }, + { + "data": "0x73", + "from": "0xd51fA0De3ccd210D4cCA7f9D739f305CfCAe9117", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xD74CFe323387aE2fd070CD046173026716D8D649", + "value": "0xbf" + }, + { + "data": "0x8cf9e1e7ecaf9c7fdba7e4e5ce437b3475a6722752a6eda1a5f6f3f8d073f7d854b4b8043d502b0f3d560708cb912bd4d954727b06c1998c31476653936c81544b5398a43189252c1cc1d14280684fab74271fbf4e43b4cf0199d1c322", + "from": "0x0b90ABAC5C8F6ce035a107913ea5D7C6eA24f9f2", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10", + "value": "0xbc" + }, + { + "data": "0xaed6c0af2a3b780d8f64283222061e3546f17c8f89432dd88300ad877a6f3cded23eeff09e65eda5e1d3dc07612d5a4d104957d44ddf8875f1c21cbde16f05683e0889ea62cc5614981f91006165b8298ddc6c16572aa9c4eab011880f81", + "from": "0xabBD7eFF49254583a862901dEd2D2E9DF7542E5E", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876", + "value": "0x81ce" + }, + { + "data": "0x131f100b936e782a5a", + "from": "0x08d033C61e1E55bF868082cf788a3949f4ea949D", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190", + "value": "0x7ee2" + }, + { + "data": "0x77fd456d2b161715b9d91df9a7b38ba3a2697ec0db03ca7bbd44d4768850060e6b0f14724a7240c8f89ad2645f00eaae2846a4815c675c5af4feb83052eb5c05d0856eb1fe0631c3ca5d7295d26fa4e4ca5378c417", + "from": "0x89408B1DeE3283a0AE426CeCf5C49cc3073Ed356", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce", + "value": "0x0" + }, + { + "authorizationList": [ + { + "address": "0x000000000000000000000000000000000000000a", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xfcc66a95eb000258ec04458ea3e7c3fbda47d4e513fb50bd91302c17eb758f9c", + "s": "0x16061ffffa1c3a815c757cb500b5989dddace00fdb3d6d90b93ae38f3b2591c7", + "v": "0x0" + }, + { + "address": "0x8fd379246834eac74b8419ffda202cf8051f7a03", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x62957cb32907e1636ea9fe81e4b5c4b343cb341b9031e0b1cfb757e581726714", + "s": "0x7631afc54a3a4824e975d7817b97a58c48c4b4ee6115c092dc1b8e3902d39baa", + "v": "0x0" + }, + { + "address": "0x00000000000000000000000000000000000000f9", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xbce2fa378f0a346de227333da920658ec00165a3d868a08e24820aa5d661c66f", + "s": "0x79434caa34fd81d2fd6a72e4c37328423b859ba9699db8070eb8cf6cb62ecb5f", + "v": "0x1" + }, + { + "address": "0x88f9b82462f6c4bf4a0fb15e5c3971559a316e7f", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x135760c8d007349409e2e9e91d1920717096e5c322a09fd57aec337e9d45a0f9", + "s": "0x51b01163736696657476c58c28dd1c64611ba807f95d9bf08e498f0a3ff136f0", + "v": "0x1" + }, + { + "address": "0x8fd379246834eac74b8419ffda202cf8051f7a03", + "chainId": "0x0", + "nonce": "0x1", + "r": "0x9a99690542fb5529e0939ad8f6249b224f006b5abe02d6b1266092586d9473da", + "s": "0xeab54e0e8d555a5052579dc28758792ec2ab9811ad89bd74f8ead90f1d0f20a", + "v": "0x0" + } + ], + "data": "0x275bd835384724a426a222f96df619961766984861b90e", + "from": "0x071b56102BcF6C36a20a3a16fE48781448B1C274", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x00000000000000000000000000000000000000F5", + "type": "0x4", + "value": "0x1e" + }, + { + "data": "0x00", + "from": "0xF0AB5055e5Bdac80D061b1E7f2bA766d0498b697", + "gas": "0x30d40", + "maxFeePerGas": "0x1e", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "to": "0x000000000000000000000000000000000000000A", + "type": "0x2", + "value": "0x3e8" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x1", + "nonce": "0x2", + "r": "0xa57450a9f1a11d34fcd9161c926b59b6a49fa5c410ba426f4653d8d5b1efc7d9", + "s": "0x7f32774d49271f17179ff7fca61536e2bdba3e13c5f4935e4249b5d51a6908a3", + "v": "0x1" + } + ], + "data": "0x275bd835384724a426a222f96df619961766984861b90e", + "from": "0xFb4bfba6610Aa9869db78F7c6b8f28b166CC8674", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x00000000000000000000000000000000000000F5", + "type": "0x4", + "value": "0x1e" + } + ], + "version": "2.0" +} \ No newline at end of file diff --git a/cli/tests/vectors/fuzzer_test_3.json b/cli/tests/vectors/fuzzer_test_3.json new file mode 100644 index 0000000000..a099937177 --- /dev/null +++ b/cli/tests/vectors/fuzzer_test_3.json @@ -0,0 +1,451 @@ +{ + "accounts": { + "0x0000000000000000000000000000000000000003": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x00000000000000000000000000000000000000F5": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x6517fa85aafd83a02f88fe864d93249c357cce975bd1f35d0b0430a901613f76", + "storage": {} + }, + "0x18665208d71eAF07c959cB6d2b263aCE3eF24042": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xaf09231cd0ab58828b41ee0ba14866d944b955fbc80243a5bf0bc8c86c664552", + "storage": {} + }, + "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": { + "balance": "0x989680", + "code": "0x6f16e24b8def199c4faf4b0de6ce2c63e66000527fe7791b7fabc464b9917b8670c24bd789323ae58b0f592f02ed3d06e79ecbcffa6020526f1206832c56ded76311a0db4a5bc0b47a6040527f377a7b0ecaf5f702f0a97545192bdf9048a284141d8ec65c40d673bb507d61e26060526f164f4218ce14fdcca1a3917b8352c0836080527ffd2305f25eb90f9195ac522e4f6cd88e81545fb7f10562a26e1aa6d1466bbdc760a0526f144a6f62df019666d40f23c29262f4ec60c0527ffb087c5672a2296e370e37d9978dd2fbe48b2a672b2c4cdca1044065048f4cac60e0526080600061010060006030600b7f21a070d9db735f0bf7584a27bb2989cf7e5394856980d1ba9e331f287f809f76f26000556000516001556020516002556040516003556060516004557bc700000000000000000000000186661c6cb8c557683f3956179418be6000527ffee89013185ca411ac3c1d013761ece59171c177ba2b3ea4a5ba57fd23132bb56020526f1972ee1d32f075d8afbb8bcfe83ae8886040527ff1af141241fe7a10d277654ccee3d1ae5a920045671bc866bbc2fde1d7fd5bda6060527ff6806c397759dafe04362b30bb4cecee2f2c7ad27c5ca85c9a9ee5c0631b82fe6080526e6359ecffaf804508e2133f4cec6fb460a0527fc0af6115166ef142b6955aa1210eeb62ad00eb163ec6f4a136a0433055fe382b60c0526f06218d0729b50ed2c4bb39e9bdd0ef6460e0527fe76fa18f7bd8bcae67625fccaf814b691414b9ae8faab635f5f26a69a5bc39c1610100527f54aefece91198aef0f6aeff12c5bbeee9ac4b7f53e5b0b3df5d18a0b4d883b27610120526f0ea17c12bbe9b722a199f015cd765e30610140527f839f0cc89472d1544db8f1e5a7cdc6cb55a244294ce0927a8cba0bab057482b5610160526f0783e9c6f15f9a5545069dc92d2804e5610180527f49a0323eef45d535d31de25f11bfae9a2232c8ea963eed91a947ac24057774816101a0527fd6487c7c52f985b8fee0c9fe74e2d52126f0cc94bcf6d03a821ca3081e1694e56101c052608060006101e060006099600c7f4322102205f887a7635767bbf3bb40eff62346a24993b2dbd48340d613bd7c1af16005556000516006556020516007556040516008556060516009556e375c316e62646db2c8786a8b0c99f96000527f73c5d11ce498ea04903d444de4db21f1859032a2222b3a1398e989ff66038e1d6020526f02bb1e1e9aa44652a3d2f90cbadff6e26040527fdc4c58d923744044fe05eb40315de822e830e55f24b67b74c7e3fcbe85bc13846060526f169e9504cbdd505e5e011a09319dd5976080527f4c5efd999ccb14045319553f51ac1be0b40789940f1f7b060288d5ddc22f7b3f60a0526f11917a01e6cb9dfb309d424e92ad637260c0527fd7386bca15ce9cc8365ffd362adbc5126f52d6c3d3802bd05684ce68d5e344af60e0526f13cc36e82da85504b9394234ba7bc0ae610100527fd19a92d065480cc7d89463d00a86f3207b514b7e0c10b2ffd4ef7011e2752666610120526f0355c0f12e9ce247869f07f4b25e8ce5610140527fa16eb6a8fb9d1fd3bf2fd16518d276396888965053f66bf8557ca90f269cca90610160526f08ec0da76cc6750ccc460296d791ea40610180527f2284637750bea945d7ec2425afb94b3efbe4813a31be1ae9ca7ae586cdd744d26101a0526f098827f98c92126deea2d037fa4c14bf6101c0527fd26774d199c337ea4c1d1f975598147fd0f7adb7fb3e7c7769c84c44c02d1a4a6101e05261010060006102006000602c600d7fb04339addce3f2e532cf21af244ab062b26ecd058004437c40a04087afb86cb6f1600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f175f42faa24a4f636d8a463f7941f13c6000527f38b53dbe8af42d72270c1b541da8c8dac472f7ec9e9028bb34ffb68635c3567a6020526f0b60ea582837a3b6397096913eaedf266040527f85d30f905969403d9c6012f333d90bf3e8eba0a38a2e20d4775f27f6d5a7aee56060526f0e0730b9d76b6ff1207a7168f9609dcd6080527f5ce106c8a7242d425fe3b4a07db65789e0dbadcc841d04711be513d73fdbeae760a0526f133c63b3f316edf9dd452d522258b39260c0527f280dcfba6160d56f8b6d0a9bf26e733efa882535efac1f7c2c9c7d1806a33b1560e0527fa7e33087160b56e50927d53a940543fcca6ff669cb04d671cad0ee2988ab0bc8610100526e1ff24610aeaef59ecf547fe2708be7610120527f4537ce6a7678ba6967a76907697eb0c0b768f91beac5c6221e030226138b32b9610140526f0e3eba81018c856b86d941a40f26b0e1610160527f561a85f883f1dfa49f1ac2aab5925080417f16b289cccd87aa640a57c207ce61610180526f0874daaffb648d8ef8d8b1d65424d4376101a0527f802f3f60cc6b221a8454783135350b75ccce251abf1ab4e228c0958077318da16101c0526f052493beffc1839977c746f2286a8ae96101e0527f67ea09233649b696976e68f8e89c7faf312eca402b85ab9bb3a8875651457a87610200527f86e1c5c45c73587ab24a91612d97087d0cb17ca75aba181bb3933849dea20d6a6102205261010060006102406000600e7f5966d656a872091de7969b3c78cdc26b8fa86c98472016fee4b05524d116ace2fa60135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556f10c60cab79bbd0a1ca7fee24970273266000527fc50134494b67160faa9d01d31c35f964f553dfc570139af84ce9f94aada1a56c6020526f0e7c6cb18834163ab4ec76c3fac369606040527f4f07721b1bdb858d2eaeb30eba516910f4ff3f809a9d602cb037623bed28d4be6060526f070e5834f155e738b226330f1e1f234d6080527fd2606e390b318f44d0ad923604b18ccd4cebe13edc7516af7be5f4fba545aa3560a0526f1394b964d3fe51eb280a1187c1a03f7960c0527f303da872bdbb83bbf0f52691d6632d205894bd069779fb6096cfc341c208233e60e0526f0b8d5e4b35400bf719728979a7a2e7d4610100527f5c6df065931a258ebbce660eaeb09db3501f7b18756d2dda21351deeede9a097610120526f0947daa09c50d095cc7adc0ed7b362c3610140527fdada2c430295e6c4e859180f93d88a833fe623ae81da2229ea24ff2c18396b056101605270011166b9f441df607c05545f4969139c6b610180527f29a50b35c35ef7369642e91ad7fbbb322fefe41aaff8903e7b3a68a86a3c527b6101a0526f107152bc657840de46821e92d790caa06101c0527fb268c147a995053433215c2d41d31440cdce54c6ce630113d1c8fe0e4aa1a1c16101e0526f024aa2b2f08f0a91260805272dc51051610200527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610220526f13e02b6052719f607dacd3a088274f65610240527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610260526f0ce5d527727d6e118cc9cdc6da2e351a610280527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016102a0526f0606c4a02ea734cc32acd2b02bc28b996102c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6102e052602060006103006000600f7f9535deee52630252dd81819eebd7046936470694754f1b4d92dab7b1e1b1bb11f4601c55600051601d556f175bca4cccc7ffe99528de9434a6ebc36000527ffcfb65055ce6f814efdc8dd4e229be05322f80d17f96ce7d8bd95a093f4d8f3c602052608060006040600060107ff92f99086b528dbda48f43e7514a2ad225b845afd0fd0ccb91c137a3c89b847ff4601e55600051601f556020516020556040516021556060516022556f08237a9d0ac1a6af0eb791d36cb179d96000527f2cbf3a95e85134eac54bf8e4b91f809740e3880368c63d0a85bbd86007f246d06020526f16ca20640460923b84fd15033ddd83ce6040527fbb8d51f9079bad29ee8b31b1f8a8f9cce34475bb87a852916f1d9000b1122167606052610100600060806000600060117f9daaee1428029ce3842e234b0a1727116151bb0f9a60c83187ad9e3413b92621f160235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55", + "nonce": "0x0", + "storage": {} + }, + "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": { + "balance": "0x0", + "code": "0x606160d1606b6053609a609a60e44534857912774a1016438a38fd47785815431c5f10056985333736916b885974f56c7cfe063c369c5b5c363e120b826d1b83a349787b193f1a8d717075746a577d005264f06a461a3ca242087c6bf412183f5014013ca2021a0a1b5b647f449f7b10a1577a6367fe5d135140143e9e529c9686387e57766f7d533c05355a1155125a8d66068170a300704807f140687c3e793e308b0a767b0714776a16791477423159053b31433e850a5c487f1766175b1d40183a81676800981d33427f366d3d5334163a39546f550699200973367d42677e31a11d33686738020233f58805530804a415324977333e077a364217f29c321e6e6119336c90317f081e460a8058183c9404742068346315638c3291fe8d443b56310b7cf0746c3e4a6fa17f77ffff3968377345f25762755f9f6a8e8ffa57367b747264156168609c5a1d307d7b736c475b887a7f1a6143116a83407a765216093ef402450100438b385c485c3e3b7683117139a13b545b806819168a3c1b5f0184031774a20065093ef1430170123b1d4416815646413872033302783306561c5e43534016531488937e533b54495331f31d1a11378e1b86630270166e680b13030b097d7a42128657306af54219009d5e11516ea2a13967550936866a9401160a3e1432427e48994a756a1a05f21a3a511b341e3354207a04a243788b8d3ff26609904a905737854442386d8c92f456468a567304076273663e986d020a6902193b4587650615a4123e367a7915156f3438429b6d133593597c597d0b33779d5150163449206e7602555c9c6341117580f1399d3973010148958117331373151493988ca3536f663b31151714600b8344459b5d085d3e5b02470553916a496e7b7815a1755c1211621414127b08975e463d47603a38927e8f63908c47705e12193e14a3626d34376b7df2743a695f83a0541b663b345682ff343e176b6c63485d653178330a67618870161966353d8314119878418e791781015e0070635a6f424191301145547c884543964434fa6c1c357b7f57713f8017a31c001e6d4935073238546a5e9c6939a35a6b9df4083c5e7a17113e30034605330b9d89790012406175709ef062758f7c3a3a4a4200647508328042687f865f883f4543421956083f9a39841b5ea3995b0662427a15571c0367847b813115fd147b0603876a0b743c4468a120459f3f546595304a815e527a5a5a1995fe1cf105350b659e01015b4806085e0b443a40f47e377b5b5508a36d6880fd7379a48d4539108c333f3b17a05cf25b34920186a38804f1196b3b1282708a58034746771130076c496c605654319c0a3259a03206807613759d3a524634716ea170627e6d8d93fa7635183337395f1960173932545e3187301a7654a4494993949c7665563573f07b", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000002" + } + }, + "0x2837fE6BCdADEa40e14E73df3101847267659772": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2bc9eb16f330b5d3764d1e508af3bcbb84786071e249bad6f91ac38553464bf4", + "storage": {} + }, + "0x35F694E45962Ab9eD665971FdF51A45A3b109c62": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x2ac7d0629b3a39ccca4afd80b787edeccd0f9ceb5a83595c0f6a0e1cff0ebc7e", + "storage": {} + }, + "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xd5b187a1488a0211288f3d420de324151455a6fa819850303f62bd25582b7cf6", + "storage": {} + }, + "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": { + "balance": "0x0", + "code": "0x3d20e47e079e7b696d7f7f600054506001600055600060015560015450319675d11a4a3d869a257f60016000527f606000527f0255600260035560026004556000600555600154506004545060016020527f60066000526020527f7f55600354507f60026007557f977910ced1e5f2611cf16040527f0fd10cca0c0c2201606040527ff26020527f5cf3c0a7bfa76000527fa09027936060527f1fe16000527ffc2e808841d1cb6060527f1011f4fc5c6040527f991d19f4c0a46080527f0aa9d8cc6020527fc56caf7348595e1e256080527f3b6020527fec9e2b08606060a0527f527f121d91ed66a56b3990e7f55479fd6040527fed60a0527f2693f7eeb9302260c0527f1a445683aff26080527f6040527f37f16d2e0764318bda8a2060c0527f172f8a60e0527f6060527f26b7d98bb236ce7cd1f260a0527f90920f631a99cc0f60605260e052610100527f7f6040600060806000600360608052609b60a05360f460c0527f60a153606060610120527fa2610100527f53600860a353605560a453606060a553600060a653605160a760610140527fe0527f536060610120527f60a853600960a953605560aa53606060ab53602060610160527fac53605160ad5360610100610140527f5260606101205360606101215360ae61610180527f01225360536101235360606101245360610160527f0a610125536060610126536101a0527f60af61012753605361012853606061012953605561610180527f012a536060616101c0527f012b5360b061012c53605361012d53606061012e5360b161012f6101a0527f536101e0527f60606101305360006101315360f3610132537f295db4d10d457703fac4a58461610200527f01c0527f5763d8ad4f7fe25d383340a63bd007f1d0fac745610140527f18503e610220527fd067c38b6101e0527f3f15a2db16b993db65b52be1c3751292ab7f726556cc6f610240527f3db861016052610133610200527f60006000f0604060006040610140845afa60610260527f0b55600051600c55602051600d5561022052606061024053600e6102415360556102805260616102a05360026102a15360426102a25360536102a35360616102a45360026102a55360436102a65360606102a75360006102a85360f36102a9537fe3ee942ad25b25369be2c1688b613d779c81839be45594d5fdf66ebe02c5884d6102c0527fc1b8cb2dec124ef66d8514616b19425f8306a7c25ec7319547379c3e2f2a3e716102e0527f676bf6ab4f90e5802f11842312f6c3105ceadcd6e9ec7ff7104e40318837c13b610300527fdd597bf102dd9bacfcb320224a9cf7d69219ebf4ca46e02ffa66876002035be1610320527f101d91264e2f2011201db863853ce65852eded02898b6c2ac970dd990634d17b610340527fe466b225771c74493685be8ca2589a6fc0874cf8930b5ff07c738b703aae0a37610360527fcb08dfbd742c633520a90d3202b758a4cb65f2980cba0d6c0cb75b9723a2cfea610380527fa490bff0e3a32a3bdb0e0858f6d25d043b8d79a6b329c8fd02df2804e4b692e06103a0527f968ce172991a8531da24600abb8747b66d8af0db1cdd002c528eb0354ffdfc166103c0527f37e4358b26718085b990b595281654dfc84ff24aaa257a641bc8be1422fe301c6103e0526102aa60006000f0604060006101406102c0845af4600f55600051601055602051601155601255", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000014": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000015": "0x0000000000000000000000000000000000000000000000000000000000000007" + } + }, + "0x538A8474EeaB43d5a960164c554A20400151D479": { + "balance": "0x989680", + "code": "0x7fb8bc210a6b2898ba233c41ca9920618eea79fc8a5ace79aadeab519a3eb9189d6000527f7bd79287ffc0ffeacb8b778efd44ad58fc6a6488b608dba69d1eee3d4a9799226020527fd4d0115c7dd08822f919c6315ae2984950ef08a85b6a35418de93190b37753b26040527f656124ca0102959f7bd6da4d2d951456a260354d75b4e5c40557336af6dedd656060527f5e7c42f565141777662f033b988197a41247e27f98a46e5f89718064f2c028d76080527f2200c204b98c10e05e544c20f2ac26512806695a083f9c5363e9aaf60521fe5f60a0527fa59326cbfc0ef56563909e19e3ff88d59af8aa304da4daa68122ddfb4356549960c0527f838059777f4f4b14043f7d2938256813a4f66317e40697d62c1060f5476e513260e0527f4c4f97ec8ecbfa1c0c8d31fc2f3ece52614034e18c9c914872f0cc37c6b865fd6101005260406000610120600060fe60077f8828d27885159dda6056c70a602676114dc2ebbaa89240614ab73a567597ccd8f2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x641602bAD4A323C49629d45338d79A2bb984A3fb": { + "balance": "0x989680", + "code": "0x6102a051606060e0fd", + "nonce": "0x0", + "storage": {} + }, + "0x66bBEf07B980c8b5de6F3DB0d5CA7A0389C7f386": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x6888bf43c6b0a7bd72d3d4f360efc2fcf781b746e6de54a559882e71c4ac43a2", + "storage": {} + }, + "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": { + "balance": "0x0", + "code": "0x600560005536841b5f80ee6fee60206000fd", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000005" + } + }, + "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": { + "balance": "0x989680", + "code": "0x7d0819c8cc03a05cd0bb060c4679208c3a385feac991407fe30f137f7abedc6000527ffa5f14bbc34be0fb36e1b8577b662d2b5528b6152cfff1e62805a23d072b964c6020527f4f4b6af3709c8fa80e946e07e0e869608fb689b23498972d172a770d2afa11b96040527ff723c9c9e48eddc4e1fcee8bb6b5df3e184634701681fe9a1fd71f1fbf15bdb26060527f2920d94fa1b64095d1ea56ef0447587309ca666fffb9cdb23ebe6f71235965046080527fa3a2f686f7eaa89c2611a8c33be8bbe053a8db8ffc762b7f3df68dd98a84d5c960a052609c60c053602260c15360ab60c25360e260c353601560c453605960c553608260c653602e60c753607260c853605560c953607460ca5360c560cb53603960cc5360dd60cd53603f60ce53607360cf53600260d05360bc60d15360c260d253600660d353600160d4536040600060d560007ff34c1f709738770ff7d63376077de9f459c1ac7cb882e82c5b41a39530ddb14960097f7742ed7e48cde6954062a5df6b187eb254afb4f65652c8529d1cbc9318db63b7f1600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x87f2957b7228EC6a0dd4F2fCc669BD2ED2B14E11": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xbc501cdb0096cc68817e5b2aa2eb7e97fcf45a56dbd22b6e2de2b234b51f12d5", + "storage": {} + }, + "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": { + "balance": "0x989680", + "code": "0x7f80000000000000000000000000000000000000000000000000000000000000006380000000077d7676767676760000000000760000000000000056000000000000000000006801000000000000000090051c686d5adef08547abf7eb7f800000000000000000000000000000000000000000000000000000000000000218026d01000000000000000000000000006fdac7fff9ffd9e132262626262626260018901d6000557d7676767676760000000000760000000000000056000000000000000000007176767676767600000000007600000076000090171960076f8000000000000000000000000000000007046001557cc9700000000000000000023f00c00014ff000000000000000022300805712000110000000d0a300e750a000000090a0a901d762900760076761e000200767600000000767676760000007f7effffff80000000000000000000000000020000440000000000000000000001638000000190096f800000000000000100000000000000006b010000000000000000000000778200000000000000fe000004000000ffff000000fffff70009901590156002550267ffffffffffffffff7702ffffffffffffffffffffffffffffffffff20000000000090146003557bc9700000000000000000023f00c00014ff002c0000000000002231087f8200000000000000000000000000000000000000000000000000000000000000901d600455671fffffffffffffff7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee901390027cc9700000000000000000023f00c00014ff00000000000000002230080567b368d219438b7f3f901890167cc9700000000000000000023f00c00014ff0000000000000000223008056b010000000000000000000000901c177f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9651ce97e1ab91a0960055576fffff716b61616160b0b0b2b0b230b000008010d0a2b007f7effffff8000000000000000000000000000000000000000d9000000000000011290187a01090000000000000000000000000000000000000000000000000076013590cab83b779e708b533b0eef3561483ddeefc841f5079015901b6006557f40000000fd000000db0000000000000000000000000000000000000000000001600790037feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c901c6007557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd677fffffffffffffff1315717676767676760000000000760000007600007bc9700000000000000000023f00c00014ff002c0000000000002231081d9004196b0100000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200009007046c100000000000000000000000006c1000000000000000000000000090141a6008556b1000000000000000000000007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a017f62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001712000110000000d0a300e750a000000090a0a0390067f7effffff8000000000000000000000000000000000000000d9000000000000017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff900b1460095577800000000000000080000000000000008000000000000000610111900260006000f3", + "nonce": "0x0", + "storage": {} + }, + "0x97511db90b0e141ea4cb42e3b73fe3C24c3D5676": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xe0f8e02e171a2ef7eae37783ecfa6acb82cbacaaff229a4a403134ff420cb4c4", + "storage": {} + }, + "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": { + "balance": "0x989680", + "code": "0x7f24f22a99128cbb4069321393f9093db47175e6518c6edab11963f47871842cfa6000527fa61ad2bf4623a058055dace5152373ce44495781636acbe3ade530c5bfa9e5af6020527f7702525974eabd05751ab013a42162794531ce19b964f523964b3817d73176ff6040527f5e6fe05bbf97827bb85dcad5765d014fc49a1048dd49a38c5c129d14cceb5e5e6060527fbb34b9ba02153c30be036a074e2ee9de7c4095e3467085526207f898f43c1a3e6080526020600060a060006000610100611c35f26000556000516001557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff000000010000000000000000000000010000000000000000000000006020527fffffffff000000010000000000000000000000010000000000000000000000006040527f895720069413cf1ab863112e6e45727bb5f1c2c16cf0cba09c5d3ab527bc9f5a6060527f8aaa289b7cf77196387ce801aea3bd400dbd39fe82bbcf55a0b1539de66c51336080526020600060a060006001610100611a42f26002556000516003557f73d209ac0034eeb9d245ee28c3be7b453ba868e124cf417fa4c2a5edbc1bad0c6000527f7d615e95d2679a60eb6a42bb6936ed3e4b9c3af745c179c9cdcb397a9e0eddcb6020527f79a0d10de0e554431ff1b7a031488a932a16e97adb6dff5b846029ff4bdaf9c86040527fcf3b86e95a2b957d5fafe6d42538c850e5b289c4c840927b96bbaaa7832574a46060527f9799e25d757bf3b4b91a2031d6eaf3071f5b6740c4b286e66d35284f2bcf25a36080526020600060a0600061010061192efa6004556000516005557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611bd4f46006556000516007557fe80484665b6066eb796e789f98f98024c94a8e878a5620a2a923de0de7dd8f8d6000527fc33f0ec09eead991e48c2643432e991bf54fc9d6afb1df86b056a50d440d99576020527f7bc425d87efee0e6a7c0c00568b9422672819241248357dcaa9f50b6905282976040527f98dffe076ad2841ba6059c56b4298f096d2b86fe82e14db2537577accc27e6146060527f5617e88f40eb2d34db4f13618b14b70caf308e786bb8366754c6faa2dabd52406080526020600060a060006001610100611c6af16008556000516009557fba785b717818648aee59b3103ec60111f90bac454a0ddb0fc5aaa0f707b28da26000527fd5fbf36a78b82aa814da906c18a3e1d53105b6c1ad663321f3f37076c67d0a366020527f4773528ced0406f3fe44dc0143bd6b8d6e5064d0883a90abe3d72910c69ec1d06040527f042543aa4843fce3150c493370a49b2d0da36d8f7cc87adf82a646dc04b6133c6060527f698f88f6a07cfcae3dca22cae162e62c3207bc1c03864eeaf0c90247292c24506080526020600060a060006001610100611bd1f2600a55600051600b55600060005260006020526000604052600060605260006080526020600060a06000610100611a31fa600c55600051600d557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527e020000000000000001002000000000000000000000000000000002000000006020527e020000000000000001002000000000000000000000000000000002000000006040526d80400000004000000002000000006060526d80400000004000000002000000006080526020600060a0600061010061190ef4600e55600051600f557fb3190ee410789186a46f6acca8928b7987838124aab0cf04395162654b379ed56000527f4a848ae1352d38ce207566762aefe8bbea9bf9667ade78e72f01eca11387fba06020527fb16d9714b0ddd01921237b52ad1e735062dce5fe414f89be9098276b147320696040527f3860ec3d8c9efd14d66eb591d97c61531183a3be527c7c606ff73bf0b19faaa76060527f4984d660600f9a521431e3a2ff3009dfabaa2358e5bee9d3fc55133b0eaf58ab6080526020600060a060006001610100611bb6f16010556000516011557ffea57daec4e67954a917ca0ca921a7d64b7a7580804f8eabdfbbbc9e5db1eaea6000527f6c10fba5e186af4aea14587dc5041422cbc7c9f58cfb2468e8af8814efd6a65c6020527ff819e8802e912c907cf2812dd18523a351685e22ea1b25dbb7156d673ecc5dba6040527f3e29a7314665829e5e743c8d6823e1d1311a03704729f2082b5f16d38a19f5916060527ff1996c6f05e983b4441ecb4e3c6615c0fd538e03b4911e9169bd3ee3ba1805356080526020600060a060006101006119a4fa6012556000516013557ffa0417bc6bb9511e1eaede67a3f0cd0c23526c4fa155ae1f161365cbe7a7c5546000527f5082ad3a8e669637f9c253d0fc6154de372e5724288c6c6ba0db8b1a6ae06a8a6020527f3d7d7e02a4883006d8fde8284540b369de3dc7a908360c9ac5379430f68d3d1e6040527fb30536063c756ed27e2a7fbabc35a07eb30a617e50d1d6e92242ecaafe5de8146060527f7df7b8c33652dc5761a6faa091b947de9c364989a3388badc71b647fcb68da306080526020600060a060006000610100611929f26014556000516015557fc8fbd3a0d4db90baf77610bc0a31e949fe9356e526a918b2f82bb1f6ce61089f6000527fe902d0b4dd1630eb6e7f693e2f562bb3838e042ca9a40a825d0fc7eb5d095c6c6020527fc40851aa6c579e19e95fc3701838e91160c980e1e2bf27c4e54da3459d99dc9b6040527f5f39da4826bdfee74335689bd009e01c2605433ed6d960a1e019ad1048a85cfa6060527f1520e3d42f5e6d3922fec41e56dc4bafd302ac4c21b4c81e8afaa5de4514ed5d6080526020600060a060006001610100611b67f16016556000516017557f57e1ed957a14c920e7fb86e3355392c5b1e7abb074f8794028b65667f3776bcc6000527f72484872ce77a8fc6e2f3b7ac4ffee8ae7445ef5ed95a78f9215843048b0e8516020527f14f85bb2ce9c577d1ec44cc1fbc698b509f8cb88cf21507be3b317ba7291e44f6040527f50d89afab90ece340df275c0ddbf7f44551c0e872e962fa67727c07b904da71d6060527f5df66416387efc11bbb44a582e139ebbb7a845355ebcca8a51ffdc7c09f1d5386080526020600060a060006101006119cffa6018556000516019557f1589a7c2fb3c896ceded91944be7fddd82c9d2ea37a4caca5661d7c2cbef7f876000527f033f2a9f387a627e26801569d57fc81547cc9434efe65707ae704ac40dacdb9c6020527fe1acaa5075ab21193805eb461a0d3aa9ecf269b5575562178705dd9dffe5d9366040527fdbfc6b49c65ed133eabc6deac7c816dd9d8700d2b013e63c3c61d0b2bfbde4c66060527f1ce4cd3a3b18f7c5dc690b84a9d838cbcd78392bfc23a61e360bb09435591bb26080526020600060a06000610100611b5bfa601a55600051601b557f476936d377e6238e1e6695e302f97be55b9d7a2a3f5795413e6b0cfe7e4b9b0d6000527f3490fd4cb7e398858c30422ec621f0f5f9b4a0a1e0f59cef74e89dacd93bc67a6020527fc7cd4f1f41ebb14d6a5edd9c48d1a4ac8e9faf07e0959bb668374656a8df03626040527f6a1b0f2a71e0c54661665393aee5413d3711df2ed7c11063a47e10750b0843106060527fe389a29310062d1b2a1cee6aaa3d52c534103f82c91996a3e5302dedc5dcbfb26080526020600060a060006101006119d9fa601c55600051601d557f81909aa98db980581d2313e9537b40d40fd5bc2283327173c50d9f585890cdb76000527f41df2169692501f171a7025053b6b3394e3b7750ef97776d085642ef689bf2fb6020527f7049ab6516a6c677ab10becb220399208c891f42f4c12637fe12c5f8448b77be6040527f68147c0912a54642d919f3c546463633d4683b604d2511ec9d142721555965176060527fae65a35ea73220c5e6642676c8491dcdd2d7306e1018c3a139d9efa9eedc55736080526020600060a060006001610100611c89f1601e55600051601f557f38a54a3b9d8f4b3778c2786c9d5b46881ef409236eac1eae02d0a7af3fb5f67c6000527fddf6765e882ab5bc19cba477f16eb56cf1c6f07bf716e3fa80ee4d7cbc3124ec6020527f2b43c572d2373b0f41fbd54d4257495b9a4c6ea0868757558224fd0119f7e1fd6040527f99f5e2f02cfe6af231a6b8174da83b100f76d3b806418fbcc1bc0c773dda61846060527f02ad258ba26f93ba475b3703faa3519fa8c925d25aecba4dcf98e775ff2042446080526020600060a06000610100611c03f46020556000516021557f1d9b9559392a4601e49eaf3d2c6f2708d59befbcd026250f87f62dcd0d99c97c6000527f7772672be8d32fdaf0489d79b2f14ca620605f1861f5ab05efaf9db867cc6ccc6020527fdc414270ffb5cf3cd7d0bf86558a2276f9144dd39178538d87f98c46fca8d67c6040527f2c1da6ca558e5e84fe8a5a6ab830b35d99697af70da38e1f71cadab5d8b82be56060527fc9a8ed8582c16b0ea8762a83768f0bb9c25967717f277505025abd6d719200b26080526020600060a06000600161010061193af16022556000516023557fa266ef6b4f35ffff1ef9dadfa0c17bf9f62fe328ab99aaf9205f58883ac6ad046000527f63bb80afe81c5bde0d2bc0311fb485ad8287c0a32376d71382537518ff801aad6020527f662dd6de566229f71084d4c22ef95abec502f28e55697b08cccccf61f67d25466040527fa70c99d9c9e70aa825b4b3a1856bcb069a84df0abd2aca3d3652e5583e9a29026060527ff5e7061cd7157b7cf70218942f152a98995bb89ae95948ad7fd26472badba80b6080526020600060a06000610100611bc3f46024556000516025557f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f08cfb1ec9f681f021a9a321e1041afa50858597c6e86340ecd0fb90f27f61a4e6060527ffebba51fc691c0be204421998b1c53bf8d3165645147e40c5620574faeec2f8a6080526020600060a06000610100611cb8f4602655600051602755600060005260006020526000604052600060605260006080526020600060a060006000610100611a4bf26028556000516029557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611c3cf2602a55600051602b557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611a57f2602c55600051602d557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6020527bffffffff00000000000000004319055258e8617b0c46353d039cdaaf6040527f705161ba0fb15c41c92b6c48b38f1fd5e12b90733dd1c11ec0a208ff086c7b506060527f1020c461213478ad81d5eecfa1094cabc38bdf59de6af3bef80fab3ac4b08db56080526020600060a060006000610100611ac3f1602e55600051602f557f371ce4e482f494f3938fd93de481a0d4820065968e4826d6404d74e3566cf1996000527f5ce4d043ee558c86a1de059c01cd16158fc549744b61e4182f6a36beece695506020527f52d031db960e606eae783e2b27ad53cb7b5d873074740c0842394604c8abdffd6040527f0dc01fd75abb6644da18665c8c698aac22b63f217dc5491fc3cb2f627b6012706060527fdbc4fa2816249ec4667cbaba1264fde39a1107ad4afe4591a9ebdd0db08257496080526020600060a06000610100611940fa6030556000516031557faabb230926d8306560b7c62f8832294e1c0c5d209a4659fd5e5ca6333f08f3446000527f7d0690e61f42b511937ecb62af7a531b52fcc1e07615ce2a46f4469fbd68cdeb6020527f2e790ce409877cbe56126873b63dd08122b74d2a650a0d5d8bb8788eb4c409596040527fd165b6bca6885a2cbcc2ee024f79f009353b6e194e5fb7e507ea0995ac2b6f316060527fc2c0f5098f1d1250c4faafd7634d99f84032fc1ca82cadc510e33bebe31e03b86080526020600060a060006000610100611a44f26032556000516033557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6060527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6080526020600060a060006000610100611a6bf26034556000516035557f809256c854c346a04981f0a94fcaa3ae1b8b71512532ea1cc13b0d21d51dad5c6000527f65667e28754d2e803604c0d975bfd9a6d472f87e70c9c0be5128a2c4da97b32e6020527f89c17692aa4e75158d30ad930bcfbac8cc9ec0a049b937370153dc532cc54e646040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611a63f2603655600051603755600060005260006020526000604052600060605260006080526020600060a0600060006101006119d6f26038556000516039557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527ffbffffffffffffffffffffffffffbffffffffffffffff7ffffffffffffffffff6020527ffbffffffffffffffffffffffffffbffffffffffffffff7ffffffffffffffffff6040527fad576651d42159e575055dbf913fd5300fe5fe05ab7479d2c303c3941b8bb8e66060527f6c4ea7e65e464d36dce6615b4ea9ed764115aaf547ebd9a74f1b95b298de24e56080526020600060a06000610100611c7bf4603a55600051603b557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006000610100611cc0f2603c55600051603d557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f918074fe4165eb12758053d8eba7ac089d81b90c36299d6ab39b3b707a5e0fcf6060527f6d540c78a7d397143840c1f9c22dfd833eb6f7770adbff9950c607f2d0f312746080526020600060a06000610100611ad4fa603e55600051603f557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a060006001610100611afcf16040556000516041557f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2605d6000526003602052600660405260036060527f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2605e6080526020600060a06000610100611a57f46042556000516043557fc9bbf15b2b036c73bfc676544843010312bdb57034b38abc9867e5505717005e6000527f7e3ec609f4d61528ca15971fee344ba38c878bec7d8a75d820e65a931bde81676020527f47af354cd5d49248c895a78e1cef37058971d0b2793a0940054f2630347799c96040527f15bef465d01428155949805c60b1bf0d1e09f2fdfda7bc0d288f29d89bb179c86060527f5da47bf878cffb792df65ae4a2f58f165296f4ea9b955a795d951493db6c85906080526020600060a060006001610100611beaf16044556000516045557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b00fa6046556000516047557f38bf718bdef500d5c9ae22839f7c55c17c14a0849333ac36f652c15136d91db16000527f74db2fe4a60c76266c1cfd63b78e408d94162304ca9cf24eb33d436d69e58ca26020527f844aa5b7c8ca635b15fc539d99a61639d2f75e1b100d0e0d45515b71dba25a9f6040527f7ee37e25805f4df98db6a971f1c4de08fc34a8352adefdab0a6424fa84aa60e86060527fb048966cdd28e69e7b2adb1ec3503b307ae6e69efcb14ae0d6ff186f1caf0aa16080526020600060a06000610100611c78f46048556000516049557f4f164b8627de3ff73865693b11f9d0fd85ea984f8edea3630faf222b31351c226000527f80d9020d250b0fbdf449a90bbfe680601d3a0cf7ba1e0817db7a5613813895886020527fba4c2114e9e626617daced22efa372833c2621fe45cb90829145083e6238e8686040527f9e09b68f458677a0b740474cd2f51f978f48aa23ecbd434325a0049fa48b267a6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611ad5fa604a55600051604b557fe28e01f7ab4d68377a0c8dd04a71e554936cebfa0b1a221c7f65dda575a430f06000527f18598e385d456428d422835ad545c5639c3c26bda4eefcdcca37aed404c3a4d86020527fcae8afc37833bddbd450cba85f70457da0041ff1414a2452244eea56e6c423f06040527f3758338a77ce7169edeacc42f470480579d9ce05cfeaa2a589b40d8595bfa6dc6060527f9c4763bc6f8166ee9161c90e1ca11dcdbe9d9c3f5e7cdc67ffcb671e1464348c6080526020600060a060006000610100611a7bf1604c55600051604d557f5c5752487c7f609e4c694a8255725847fb6320c4886f2bd0986648b2594b8ad46000527f5e7a594934a521e064fe3695ece89bd6dacc48781b32137710802aa2047de5d96020527f94cf7f556a6634100e5d8871937fb9ce3a44975bd68a3ad9e04b4aa862fb07196040527ffb69bab7c49313344e670f4a2dd309cbdba320299e12ab41dfa359bcf1cdbb4f6060527f03fe4c023ad93ba440a72195a294a6fb506997e23e40c3caedcdff14ba0860386080526020600060a060006001610100611ac6f2604e55600051604f55", + "nonce": "0x0", + "storage": {} + }, + "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": { + "balance": "0x989680", + "code": "0x7f296d88c89256e71631f0d1524276ff9d231ab3be039daf0ea05a4356743dd4ce6000527f0b1e8bb4741355b5b69ef8b1da4df3a3c725a14e058d99ea50bcf0e10ebda84f6020527f039bbbba49263eb8698845477f0ccb82d126e1ae3f62d12ea6facbb93b91c5726040527ee36156f58424254b022769a1970fd4e554fc49545fa15b7470f6b45e70db1d6060526040600060806000605c60067fe9659779482f376fc6349ac9b9caf0bd66415accf29f680c0441b10e2180b935f2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xD74CFe323387aE2fd070CD046173026716D8D649": { + "balance": "0x989680", + "code": "0x7f0131c9766fb600722dc74563bd8ba29a43be4c5a49060e5daaebf7699b4aac476000527f3dcee1a37ddc037617ff8ea6061586a9d600e3ae87fe6b6d42298e3edda1c74d6020527f67e97fc31e12647905e772d643a356899814c796bc17dbbbaff2346b0b9b334c6040527f885d73b14042129e020ba96e83afea37742e1189efa8222db0271a16b639b5996060527f80d83e6166169d6575d6887b1a9d8578930aa2e4b5198bf1aa7a2d8981e075a36080527fff922a7c650f764f9114f76aa4879bb40c846a782e3511b782942c6a13170efe60a0526040600060c06000604a600a7f39f3690c995440fa1457ede1998ed7b63fd2bc2ab9fcd69aeb9b82d940143d45f2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": { + "balance": "0x989680", + "code": "0x7fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f05481a72441b413311d9e023471501901968ff54670bac9177e34b92768d60236040527f506d26538692fcacdf676c86516565c93c421f674012822428e7b92e1d7608d56060526020600060806000600160016164b5f16000556000516001557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f1948af26618c1372d65b161c9ce762997b9ebf6739db422b974f29d299b9a3c86040527f5247bfcc87a7ebeb877fc32269be5d0c049d7b91dcc7f89f8ef30bc8010c366260605260206000608060006000600161e8b3f16002556000516003557f79cdac2dc9e317f476c790aebb192b2958148dc5f37d7bc9f96e69a58378243e6000527fd16ad000a3ba445815dd1bb1cefbf56c0ccb0eb66645faddff179670549b621b60205260006040527f745814686ba9a68fe557eb7604922746db8d8ec7577b71208c5470e7146ef3396060526020600060806000600161f980fa6004556000516005557f47fc344cfa7c6a8aac5db665145c55f2a0d14b2fb0e4aa79b6f5557781f504116000527fb0524ed83e0c191094263d88dbb6179a006fa408eead78668a895f953e424d1c6020527fb24e73007edb60ee591c13a4287edc95ae58ad0d0f1622cea7e99e2771ccc4986040527fffff06bf638525444daf275c7c1681da80cae3176d6a9576752929f49a4b26ea606052602060006080600060006001620130d4f26006556000516007557fec5df8eb6e576fcbc7d4d8247f95f349431beb2fab76e18e79c23d6e267c8fe36000527f43ce1e70b5fb2b68d12e2619861f204fe4c6c294e64fe0a01823e6b8eafc06316020527feb97b042568e35acb0174dc8b90faf9e286ebd5d3a6ac97113dad1d21bc254a16040527f500b416077bc121d7373eabf41ed2d1dfec2dfebfa3cb6543b52765cf164994b606052602060006080600060006001616ea6f26008556000516009557fd2af5d12a95280894d384ec024ff17dced446e7a51d9b64ad34ac76f811e17086000527f53d14f9e1df39e0bcab0dc8485ea2fc899205859e9298af772f8a6667ce0a51b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fb21c9e4123e6bfd748b695714b221218a961617cf03f2095e6b2f1a36c47a7b960605260206000608060006001600161cf23f2600a55600051600b556000600052601b602052600160405260016060526020600060806000600161ccf0fa600c55600051600d5560006000526000602052600060405260006060526020600060806000600161a413fa600e55600051600f557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f4e6da5d59214b04b4a4fb5069920a5ddbb2635283449a2bc8f9eb069cb02df706040527f2500a4266329b135c80f8510e259e9ff3c1fd0404b97a0323ab1ed89b5b6ff846060526020600060806000600060016178a2f26010556000516011557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f8340a4510c346990bc1f00b0200459dbd2f314235adfba65a5a464737edfc7296040527f328cb0a5547ad2273b55921846b72ca8b2523a34cce1cc0c9086db5fc4ee6b2b60605260206000608060006000600161f086f16012556000516013557fbf1cab3d0133c7ff1421bfae14ff400136b060a437544994e461436ce817b9ce6000527fc5c8b84ef06d2d65f6b076b7ad3f13e69a571b276542f6dd377d8713cdb5b81c6020527f70f8a8bafe48a680de156ac5df8241caaea7a27fb453ae041ec593922b84191b6040527fffff0340eb7e0dfee5b1eb7ff3b2aadd6ff3e76e0ba5fe94301736ad0dd5e2cf6060526020600060806000600161162af46014556000516015557eb4d602e526f3e38e75e652f4794a75ca60a643972d06a7d3ea46f8930edfc06000527f3250cbefada8ffebf4875231d6b24a45233e7b258ea836346578bb30aaf153366020527fcde890d5c10086ef523115dd117fdd54bdff7d83842fa8cc5abe5d1aea3f71786040527f77cce59f97949c3337b8d05ce5e994eac3bf9bb0d7d608a1f6567b83f9693a5960605260206000608060006001600162018676f16016556000516017557f1abfd23db143fbf30c2a330c89c999d3ac92ed3b0f951f2d1fedf136039f4f156000527f7fe1c1baced0905ef34741728c5b5df9193fc357db7b7bb9c13d27b5e4435d1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fc02d8d05f4336334605ea09251078997838f9e8004d71041a2e8dcf2d10e402060605260206000608060006000600161364df16018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f0893e72dba7736bd67ab257bbe123fc06c51beb7d5aecb3631350329826596796040527f39392105de20bb1b0cb2ae0782ec9d6c780f699b978d4a91da2b4f93fe8c75f160605260206000608060006000600161e389f1601a55600051601b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fb833dddbccefb4daff2ca2a4fcaf03352bca480798cb44e76725905d4cbf631a6040527f25b3809abaf1bb899b5acb5dbc84bdda737616ea1a923f487597f717bf370a6d6060526020600060806000600060016110fdf2601c55600051601d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f2efc8a47cd06df64fae4cb6b1d379210fc5a355e5f1eb1ba3d8797d44634995e6040527f20f1f25732c41f47db7af98fa4791d3fff9e49fb3da22f5c3c8f53601852db3960605260206000608060006000600161cf50f2601e55600051601f557fad8ad8904b42bee56ed2262bbe546f80c26c1c6c74b58637561934703107ba586000527f51ae5344d1b8b53533cb4cc722b20607ae0606e0cbcdba8146cc4bfe5800c91b60205260006040527ffc6356cb022ccb259b5a91c78478968c553a2d86e90867ef5cbaa6d57beb13f86060526020600060806000600161d7d1fa6020556000516021557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fbb4a74ef35898ff872ed1bd09c5d2a25414f2678b0c841f923f012f07e6f56936040527f60c14815f38abdff046136207b551435e62faf2066ac61a7074c11669b2991dc6060526020600060806000600161dd9dfa6022556000516023557fb651d6d571f7000ec99082187b9206672cbbeeab1b7587d77c1a53be74b603de6000527f38dec10dce0dc826e580b03a7c53b12ae62131ad4ffb44d6375f4c5a6327dee16020527f97dc665ed5a9725aa3e90ca16b7979b1751ca070534574ed035713d6e1da48406040527fdf5ef8d5bff2b3738b1e617d8e9862ff6c57cb95379243f58c079db83557d648606052602060006080600060006001619a09f26024556000516025557ff15606ec5436a07d10e7992d466e0c33dab03fe98276dcf3c57489c227e184396000527fd100c67b168a79443d9777124f556c8664bb0e525c64a2cb8a01f958295f871b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fa36dbfffbf8eb96234bc9a22c8ae309618f769f422769267f086cd7dbb5779cb6060526020600060806000600161895bf46026556000516027556000600052601b602052600160405260016060526020600060806000600161e276fa60285560005160295560006000526000602052600060405260006060526020600060806000600161268df4602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f5fd135840c6524ee72ed6252a676bb5e0a0f7b8ba4819a449f2763cf257c7fb96040527f2c0c965e6c195010dd71ea433ee350d39257b120b9e6753be7bf6acb8a95a32160605260206000608060006001600161da5df2602c55600051602d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527f808254cd9c8636fa7c6ebb01e4c53dac6216238b5e6adfc44a764930acfc3c036040527f1c7c06b1317ca8ea1aab730112c0caa17eed03ddb3154044924b2af728696b416060526020600060806000600161c598f4602e55600051602f557efebc31529d174d3f62ddd8f7d3f28b512398b67e78161c745910eedc58fd136000527f9d8ccdfadce68c55781a69a6de9b9c7365b7af5bd23e9d7bf4221b3a95b6391c6020527fbba630c1b560bc6696a101e85f80c2dc00748170fefd572e4e5eb719b186eb5b6040527fffffbb1be56746c953840183bbb009d6a2dd218758eedb043b7e06922d10e9b660605260206000608060006001600162018420f1603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": { + "balance": "0x0", + "code": "0x7f80000000000000000000000000000000000000000000000000000000000000017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb6b01000000000000000000000009760100000000ffffffffffffffff0000000000002e0000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff070763800000016fdac7fff9ffd9e13226262626262626001d760fffc000000000000767676240000000000002b05760477ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a9008900a90046051557f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5677fffffffffffffff90026c01000000000000000000000000774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a1a1b1968066aa0a5319bcf5cb46f8000000000000000000000000000000118017f7effffff8000000000000000000000000000000000000000d90000000000000177800000000000000080000000000000008000000000000000901c6052557e40000000fd000000db0000000000000000000040000000fd000000db000001760100000000ffffffffffffffff0000000000002e0000000b6c100000000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0915171a76fffff716b61616160b0b0b2b0b230b000008010d0a2b0068478392145435897052901b6053557f77676767676760000000000000001002e000000000000040000000e000000000681000000000000000006780000000000000009008605455157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb01611684783921454358970527ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a90086055556f800000000000000100000000000000006f121212121212121212121212121212121b774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a6f80000000000000010000000000000000691000000000000000000090086056557ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f7effffff800000000000000000000000000200004400000000000000000000017f40000000fd000000db00000000000000000000000000000000000000000000019009190b6057556f80000000000000010000000000000000682323232323232323230190126b0100000000000000000000007e40000000fd000000db0000000000000000000040000000fd000000db0000017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff900803762900760076761e000200767600000000767676760000006f800000000000000100000000000000001a60585568010000000000000000681000000000000000001c056059557e1f0000000000000000000000000000002000000001000000000000000000007a010900000000000000000000000000000000000000000000000000900b680100000000000000007cc9700000000000000000023f00c00014ff00000000000000002230080590021468100000000000000000777effffff800000007effffff800000008000ff0000010000901d027f8000000000000000000000000000000000000000000000000000000000000002778200000000000000fe000004000000ffff000000fffff7001a605a55197f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a56005121a7f80000000000000000000000000000000000000000000000000000000000000027ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe900103605b556101116f8000000000000000000000000000000117605c5560006000f3", + "nonce": "0x0", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000005d": "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x000000000000000000000000000000000000000000000000000000000000005e": "0x0000000000000000000000000000000000000000000000000000000000000004", + "0x000000000000000000000000000000000000000000000000000000000000005f": "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x0000000000000000000000000000000000000000000000000000000000000060": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": { + "balance": "0xffffffffff", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "storage": {} + }, + "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": { + "balance": "0x989680", + "code": "0x6000496000556002496001554a6002556001600355", + "nonce": "0x0", + "storage": {} + }, + "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": { + "balance": "0x989680", + "code": "0x60a860005261037a60205260a86040527ff0b88e202b842bc58b3e815c216d48d84ffe677a97b4b392d471b92b504d42626060527f2e3e9fc17fbb4395780ccb489363f6a76b01c5626f1a0ff7dae0bea0c88160716080527f472bbafef0b8b8a2654644dd363c21b889170b91d27182d2960184d1407317f560a0527f3f66bfa4fa0df97f228c32bc0a7d4ccd9e24dc3e58bb9500450c1d253df7dfe260c0527f5d85b4513acf5957ccaec4fa3b1ca5c79c56233d41178661f2565bb4f3dfecdb60e0527f628017dd1a398d5e6081d6509bc1535415988569f6b54701c5c2e52eded4dddc610100527fca083ca4ecc78090c36a5b030c061d6fd0720c1fe5aaf9e4f7203a09abfba64f610120527fc85664ff0e0ba2b7c7203012ca0b87d26162f8d12a068d16e6de9e7472c8e0c8610140527f818be57ac614b53ac018f3b1abec6beb23aaa243703b29945db6700960d3a57d610160527f6b97cc84054092f03e46b9ce8d59529fbc61433da0c57f02a9015dd145c11239610180527f7cd50d6659f3066fe9ce05dca12dec6f44c6268c0287ef999d2f64203a7e58e76101a0527fefbb4dc4e91263c47883ce938701d055d5142f5a374d7e5abbc4f89f802c36076101c0527f0ade979482d5dd71e56717c4bb687a4bbb441903958aa9497272683c45410cd16101e0527fb8e23e6eca344102dddb6feaecdf8fb7cc61e61a98752af02b7c780cbb126cde610200527f3cf9e0f86b3126b8bf99585ca41c87a6ceb413430620b1dd907eacf1e3c81625610220527f547b197bf80a32546989e6d27686ba6c0db3333878ba2536dd2e39e15491c928610240527fb199565628b92a4296d600c8f7cede07a185f0834751d314ee0fd99285c49532610260527f20e48ccaa106397744ffc78009aceec6b8afd8e580c85b63d349e9d50398fdf9610280527f1a4c8a878e928742b5f12e185a32b9ac3ce6206ab006c6d51357643efc94b7ec6102a0527fcd3d5c364345276b855df411904b5aee514da2d7dc46550d56c42513dc6e08d36102c0527f796f00b0f45871e0c998ac55fd6d3dd3b6ff7591ffe3fecc2b72e119295dfd046102e0527fbb5f3e820145401cc6430008a54825714a6adcbd0e6d46cb5c5de250948f20b5610300527ff6f72b52677448c5f4997844b7826a265165d210bfa1da95598dd6b91c568036610320527ffa84b89fdcc08cb305c15491a494202df904bfc37b6f446b922df1c34f7d1062610340527f7a5be6a14a294e2229a304140fd9529db21972857cf9622787992e187a802ae7610360527fc8e8fe14c21926fcb10c0c839a8f4fb0293df25e8426b822587d139529692706610380527ff53f9f99ed50a968c9a3ac636d913c4c93d581a4ef3ec06fe4e30cb67d5a8fdb6103a0527f082185cdd7a608dd7f877f858586dc9e9427a5cbd1b46f38a0be135473fc8af96103c0527f545b0921bddd426e0dd05d73f14cd230fc805b0d8e1e13ac941749ca5bb6287a6103e0527f953a898d2cc35277bf0dd2baa7c5a43be4b86cce8e0d54fb1637d549c96b4eff610400527f5a17bf9dc9e9b62866dcc92aa7b74be64048d40fc82757e8bd7229a4c2a8026f610420527fee16eef5c6844ea4345fcbd8cb0fb8330e53e9e9e568b04253a0578b70cbb22b610440527f9378fb903c6f3b0de425669e7b20275b73241c415f3607018efdb79db118c75a610460527f3057e1a48556655448f0080f9394012dfedf80ea22f5c20600a9b088abb957b2610480527f952e5c01afc58257bfd0fd991075edc9a78ebc574d362372714543506ccaced76104a0527f21efc898ca581be8cf766c8cc047a3a4f1d3066a3d351fec5d0506beee85ab1f6104c0527f56f0ee109cc0a31cf55c52037d4764010284a22440a75752b22ddaecf9d7443e6104e0527fe0eed74f524258c6853312232de13c93a80fd6f5296dd4392f3e8b11579389466105005260b76105205360ab6105215360fd61052253602c61052353606a6105245360e36105255360e461052653605b6105275360b861052853601a6105295360a8600061052a6000600562fe08aff45a0160005560005160015560205160025560405160035560605160045560805160055560a051600655606160005261046560205260616040527f6d0d399beee8791c6a12d890598a300f54ffb91c84b86ac27e21c4ffb10d23436060527f61a0479c2a20f3aa130387323166dec8acfcc5be6cbd59a01690dc61a79ca5fc6080527f129b38d0b055ac4d468496a6400b7e78df076275ca6a0f9f5215b40d1994090760a0527fa0b42c23f247024472be573d76fbbd3b40a7291aaf2cf6236a94e137c263204360c0527fe5f21f3a6e26ed1ecffc39e3b4e250e001694de663a52bfd06b687e38ec3211c60e0527fc8e4569a7baada911cd0ebfb9e34982ddf119bba8b6e53b0f17172f03ac9f686610100527f3a0750db630493cb3c82cf86db5f5321072a2e60868c7bc4df77e990aacd864f610120527fe0541732d6c098cdfca0976eed34dedacc8768b4043de91670b46c2998c9ea1a610140527fab0908635f7a0a521b03f9bdd8e439c26493e073284f31a8c94931596d289495610160527f0d9d4f8228b6fb8786fd0ddc8fb9779754f0afbac231d34e0418c1ff15abda2c610180527f6aeb3c4deff9c782536072981a5f5a5f903f0e8d0919bb88988dfd8297548e316101a0527f471af342e540a99e087b966a29f07248bf746b5257a16c3ea3a6ae729199e03f6101c0527fb1ad70289609ee0de9757af4b42816ff1bb84cbfda4ec6812f14fda504936d906101e0527f0579d01de02618a658f31969293c363c88ea85d1eaa8f0173937c9ef74065ffa610200527f0b6db5e353bf88c1868df5518eb79ecb617638968c4bc7dc7aebeadfaba1af98610220527f5a1e2dc0080f4c72c3dfa0980914c7f166bbccd9611bacebc509945373d9eeeb610240527f3508e014ded76cf0547184270633449ff62c26448b77d06f76d293bcbcf0c5a2610260527fc33faa90573d5dd05b297c0e7a361d233f1787c0fc4a7efa54a8c2e21a7dbf9c610280527fee8b7c788b2c846438503d8e84336c0f61afad8843fbc52677753b5f9ccfcd1b6102a0527f566ff8c1a89def377278f892bb270509902298f7ff66090013f6aa0862666a3e6102c0527fd503bd8cda6a85fcd498e2a1f16c25b858d0ef09fe3f2e2701ee197ecca5388a6102e0527ff0c272de44e15d8be23e624e18776bf2d69a2fafd5451ae5195dccba6816ffa6610300527fb6548978b6aaf7bf9ae5f550acccfef9fd56060d29f571b16eff18633929c31f610320527f7ac51a0456b86ad28e2dc1754b3026c299b7483e0363c366409d0692b63ad89c610340527faf22c08ac2a3a0b837ad7d46b7a8410dbe0be22b87a50048ae477e2e5cd6da96610360527fde1096331201adc7cae8259ab737babfa2678f30d9c8a8ebb36a5bae9d0ae362610380527f96c2db37b400fc68d4bf4824ad0976b2ce6054a4f9cd54b0003988f4c0e5a7346103a0527fd0d1c7c23cc73ca0855106aee34299f8005bd20686eea573f58085f8881b5bd36103c0527f9e973851996421f3ab73032a59a965d2815ed45cdd437e2b2e6a109661b9c4ca6103e0527f1b90e608fb4e09ccb7a4cfa1bc2233aa5474dc16f1237ded95afb56713277dd4610400527f61029aa3589b65c7c6625b3e6cc158e9bc68367ed43ea5ea9c1a1c1cd5ad25c5610420527fb207f5644f04965dbf58c2f9da104dcb0fe657cbac9d3675cdde01c628e131c3610440527f47f1b5e3d4aaf4e45cabfa8e7426e73f49ffbc783702d717ab128812f85b0e0f610460527f2e9e786806d106d7b3548fa3880074c55f6f7b12dd5901f62487882b93ab9c70610480527f493c591847872925f5f6f1467567b46ae1b20fcc504e819aa9892824a061226c6104a0527f7ad3ba3a65506f470f57477e9da43014a6d8154367618e1c55ea7887b087c2f66104c0527f3287255cfbc00bc6da86e07aabd37fe1d03ed9b54eb3ff2d8dd73048a913b0a36104e0527fd7c9ac374404002a4d5d41fba312a8ff0d8fb258b819b9ff9e4bfefce482e068610500527fd33944395dc8cb85e9fa82211d0087cf9996de1669f3121c2342c7058e554261610520527f9529bcd34e669b11a75a78fb3d5a1451ff26542208e72d7828ca7e21ad3637be610540527f2b9cef530ca7dcaa5a469eb3c7d6ede8e79588a03d498c11ae37b71d164ef3e56105605260b76105805360916105815360436105825360f761058353609a61058453603761058553603b61058653606160006105876000600060056278cab8f25a01600755600051600855602051600955604051600a55606051600b5560626000526020602052606c6040527f6ea6afa40b5f1b4cb48214b6e6e56a074998a201aa82cdc81c35ad2910e854bb6060527f86fa21730be4ecf2263dbadc0d79eb07e2f4e198ae4aa6201b0a09b17926cabe6080527fbce1ed98b86b6bc3e0a97b3b1fcb42588f27206ca558b452731218d72a0c86a760a0527f740100000000000000000000000000000000000000000000000000000000000060c0527fe3dc8cc642df7e9cf4934a539c46233788e41b60e1f2973cce7e9bde05035cb160e0527ffe1e90f891a5cf105592e9a10b833dc27f5919384201ec73b7ce2302e421d15e610100527f3b5d135d2bce73f8c15ba3166326ab20c33f2dbd2e473aa649e6c3ee9e62d22761012052603361014053606c6101415360556101425360346101435360366101445360726101455360d16101465360706101475360b76101485360d461014953608461014a5360a761014b53606e61014c53606a61014d53606c600061014e60006005611ec7fa5a01600c55600051600d55602051600e55604051600f55606051601055", + "nonce": "0x0", + "storage": {} + } + }, + "chainId": 1, + "env": { + "currentBaseFee": "0xa", + "currentBlobGasUsed": "0x20000", + "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000", + "currentDifficulty": "0x20000", + "currentExcessBlobGas": "0x0", + "currentGasLimit": "0x11e1a300", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8" + }, + "fork": "Osaka", + "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f", + "transactions": [ + { + "data": "0x", + "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6", + "value": "0x0" + }, + { + "data": "0x", + "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62", + "gas": "0xf42400", + "gasPrice": "0x20", + "nonce": 0, + "to": "0x538A8474EeaB43d5a960164c554A20400151D479", + "value": "0xcc12" + }, + { + "data": "0xe4004233f44dbea05485b3167d58bbc59a9a573470d1a4c7450ce35894a0eb4ba4a064b4c6cb7d6146a1bc57c774763287c2237c897a1f0ceab9e2fab9", + "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f", + "value": "0x0" + }, + { + "data": "0xccd57cc53461a4b792f7818d9c44db35ca7fd3edb10166e251d4b47bec0dde2c", + "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d", + "value": "0x2966eb" + }, + { + "data": "0xc299908efb3fdb12835d4bff2d03ca4bcbac3e714a83", + "from": "0x2837fE6BCdADEa40e14E73df3101847267659772", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3", + "value": "0x90" + }, + { + "data": "0xbefba71d7b677d6ba980c878f996e35911521fa11e5f0d025547ba7ef825d03dff687fd67e8fe13d4f8b1d115679b79b7bbaab18c4868ddec15c5b7c73578ca4d29b", + "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F", + "value": "0xdafb" + }, + { + "data": "0x9b547c7fc5eb3aa918193db18544aa183ec027ec89abc23a36dcbc401c10882abb1a226c81be965e293e938c4239998475", + "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c", + "value": "0x1519" + }, + { + "blobVersionedHashes": [ + "0x01abafda8405600f28850c93d20702b19b16786a43e7df7be3ca5769524f5d6c", + "0x010d7a9df5c5c8a68be7cc36e1628e87af4bdb9e79bc12efe485461bc7b9baf0", + "0x0134705ed50ee98f42b7c4be013bd5c99a190d95f488f6c71e4056f1db2dc9ad", + "0x014f220702bf4565e1674e56b6176d45a43f946512c80c0f8a5674be0a884047", + "0x012c8fc983035a94a2908a0a67e0cfe1d9ad034da6393984ea89f73c85bb3a04", + "0x01be52509c6f3022057f374ceb77216c6484bad1aa601a35f3f31948cbcc1fbd" + ], + "data": "0x6f", + "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9", + "gas": "0xf42400", + "maxFeePerBlobGas": "0x100", + "maxFeePerGas": "0x20", + "maxPriorityFeePerGas": "0x1", + "nonce": 1, + "sidecar": { + "blobs": 6, + "commitments": 6, + "proofs": 6 + }, + "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89", + "type": "0x3", + "value": "0x0" + }, + { + "data": "0xbdf020dc94ecf8f9a12512749beacb34358916f7bafd7d82ff8e836bd3ae5c17fadcf0992e", + "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb", + "value": "0x28" + }, + { + "data": "0x", + "from": "0x2837fE6BCdADEa40e14E73df3101847267659772", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xD74CFe323387aE2fd070CD046173026716D8D649", + "value": "0xcf" + }, + { + "data": "0x73c35e6653df1732e0ecd546054542f4299cdae4527f4f0c5399288d0e18644143fc6b378981c0ae2e62a9d9a57a8ca0fad3feb8e1cef68b0ffeb86504376cd0656c481753042411dfd2c4e5f2cd8526724ba4", + "from": "0x18665208d71eAF07c959cB6d2b263aCE3eF24042", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10", + "value": "0x3a" + }, + { + "data": "0xa86e7b43393bb964f0fca6abebff173b079ac1db5f651547b7a31e09267f0e5ea231dd424360a641d7315d1e31665e14895b475f5d43e10baa63e63a1dd67d66853f8777e7f41eccb134162096495d652eff05cbaab7ad7bb0", + "from": "0x35F694E45962Ab9eD665971FdF51A45A3b109c62", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876", + "value": "0xae53b5" + }, + { + "data": "0xc102d4b975649d4af883da0f6dc25ffea3bb27906faef989181963d5a9aac717dfddfd84320087cc8b22c8f63d04e7034c856251101093eab6677a15b5b11abb439b", + "from": "0x03D28A8a81F218F63CCCc11AD16b94f7f787b6d9", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190", + "value": "0xe3ac41" + }, + { + "data": "0x3a70fdbd", + "from": "0x3AcB272cf9665ba7113b07E79F0DB094DF7E3009", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce", + "value": "0x2e" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000003", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xb5619cbffc861bbfdaa3e64f9b355f8fdabb9d799849d2dabb2f25876c145292", + "s": "0x66361779b642b5632ef692bc04337f9bca791762c47ae2baeef6773fb592c46", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000005", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x138340166a399b49c1f7edde6c633a453e0ba59e46c413194fb91008e79799bd", + "s": "0x39ce8b301d482b43275473f83a2fcbcbfc4c99cfdd53e96cd5b3323cfa0f6ce9", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000005", + "chainId": "0xdee1f5da8e288cc6d27740ced28df1110000000000000000e2d5020464d553c5", + "nonce": "0x0", + "r": "0xcf969060aaa8dd8e52c23a2226e67dc4f5f97d38798bbbc038f173dea5a9c7f8", + "s": "0x6ee5755aa86f2f8117d761d592bd100610f120ca66c0bacae2bc973ec88adf0a", + "v": "0x0" + }, + { + "address": "0x0000000000000000000000000000000000000010", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x9a71a0c0c44a05d8a2471cb0262241ee69c28d156d6f34ba485db33f00a42f8c", + "s": "0x4945d99f7b2bc60ffd4e45936413244b2107ba059d6bb8ec9ce9f0962f8924a6", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000004", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x431784db736d7a7b32afa2a06f9b2dd9b7947510fcfe270ea15c2ae08af9c7fc", + "s": "0x780ae64313ba535e023075c4b6ba0b292377005a380b83e0483cb71d70cdf9d1", + "v": "0x1" + }, + { + "address": "0x19e7e376e7c213b7e7e7e46cc70a5dd086daff2a", + "chainId": "0x0", + "nonce": "0x1", + "r": "0x58ad4fc6a48d58600a99e258dadf774ccf993a35dca2c92822d103e988d77aae", + "s": "0x69054ccea2f3364fe4ded44910d741d4ed75cde286fd5c7fab299322fc9869f0", + "v": "0x1" + }, + { + "address": "0x00000000000000000000000000000000000000f7", + "chainId": "0x0", + "nonce": "0x1", + "r": "0xea81c59ad4c4ab86d403d72e88317f89cc3f886d5b730baec3ad01ae5f29b54f", + "s": "0x4bae176e31ff39b38a35bd67cab30312129402ce912094b173cb131933f6849e", + "v": "0x0" + } + ], + "data": "0xe964b68a16dfccb7300e2a3cfe8b30", + "from": "0x87f2957b7228EC6a0dd4F2fCc669BD2ED2B14E11", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x00000000000000000000000000000000000000F5", + "type": "0x4", + "value": "0x76" + }, + { + "data": "0x00", + "from": "0x66bBEf07B980c8b5de6F3DB0d5CA7A0389C7f386", + "gas": "0x30d40", + "maxFeePerGas": "0x1e", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "to": "0x0000000000000000000000000000000000000003", + "type": "0x2", + "value": "0x3e8" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x1", + "nonce": "0x2", + "r": "0xb69e5f919d0b7c265606ddcc668583ef819323ff6b65b9f0485cbadb495e5bae", + "s": "0x7296df3d02e403899fbe72a1676027a5216c5bf1f0891d945a992eaaf8b9b614", + "v": "0x0" + } + ], + "data": "0xe964b68a16dfccb7300e2a3cfe8b30", + "from": "0x97511db90b0e141ea4cb42e3b73fe3C24c3D5676", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0x00000000000000000000000000000000000000F5", + "type": "0x4", + "value": "0x76" + } + ], + "version": "2.0" +} \ No newline at end of file diff --git a/cli/tests/vectors/fuzzer_test_4.json b/cli/tests/vectors/fuzzer_test_4.json new file mode 100644 index 0000000000..420a52ebe3 --- /dev/null +++ b/cli/tests/vectors/fuzzer_test_4.json @@ -0,0 +1,427 @@ +{ + "accounts": { + "0x0000000000000000000000000000000000000011": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876": { + "balance": "0x989680", + "code": "0x6f02ff392a51880045bd81679eaa49a4616000527f56254cd73afb65c9cabbf00635edb003b0949a8d90b534a408dd40a52b34b53a6020526f154e9920deee06460b9f0155c2178bd96040527eaf16581576839c74614c7c797feb90a61c78e9ac32794649c5ddb41e71b0376060526f165ce2d026e3030555255bc02de9e0456080527f5cbba50b5838eef82ad2c62559770709e2eec3e33fc262b93031d1e1310571e460a0526f0f1b05c33731af7afba9d1ecc2633dca60c0527fa4bd69106c11f78a81e0ed331499740a2c373f32c0d4a4267294c6eef012768560e0526080600061010060006012600b7fca8a3de5474d7684781187c350d780ba82382a44e9fb4fbf62ff85135be18d01f16000556000516001556020516002556040516003556060516004556f15b4a62d16dc800c53d56be3fe06e5316000527ffc90983d1670ea4e0a1c6734c84842961f48ba265b9d1f297db1f6e8f02dbaf06020526f08b2357993c3e46c6df5b4b2a46ac5a86040527f70ed033e5811dbc949080863278cd9ad5a82cd548c03631e9ec7399a196eb72f6060527f6770676283a7b8efb208baaa6360e7408e14ea5b7bc2f32cb27e1a7c6778b5a46080526f064e8898ba5c5a5bab9094b07da7f20960a0527f1d1afd7e9359a3f426001184ed645999406a94095f4393e1133e4ec2f6b5679660c0526f0bc360809709f9fd2972058c40fab13c60e0527f9bd8951b6b7471dccbe0badc90f293e13a0f86fa61eeb656aa287156aed92b14610100527fa7861e47dc4e8f93552ff56950ea7503df311f304aeb00d1a11ce0d96349cb32610120526f100d8556b514febe4262aae2072804ff610140527f1f56cfa643f61c69f8c51986e8526dbf4193b0ba16ebea15e9778c5f1b4bec67610160526f1091ec443cba26cff31f1414be3fc9e4610180527f974fe0473b7aa7f82dcd9c2b16fc28604ba37c5df7834fb62b89dd833fc8a16f6101a0527fe7b8359329021c4595683ceab94e844edc3620b0a5ad0d2e1910ecb9ad4131346101c052608060006101e06000600c7fd2b9d1379879bffa5e6922a3da5bab4c1a1db97b7871f9954a7c0bd550e0964cfa6005556000516006556020516007556040516008556060516009556f11b16d7904cc71ed898cc1c837e83b676000527f7df1a142b4deaa7b27e13ca689d3aa5629ef7aa71f8a535b5f05f61382fff4166020526f0d1425bf71bcdd58e3b2f9914d8203246040527fe26477573206e5cd968229b997c0eb7af9c71cf2a99ea24e76cf6c19b78f9c376060526f032e55ce5592c38376c764bc8f50fab96080527f61b56efce5109366bd037ddcc414886fae97bbf829386ff2b354139814411e0060a0526f06beaaa166ca6f8314d26c9e5220b1ff60c0527f8c0c6d18cb69ab15622a53440dc2548cdcb7161010462636ecaf0a5b7b25fc3560e0526f0c39133f125c1317b348aaa704bfddd0610100527fc158523af83cc3a8c71ce7a6477b60e1218e739286dee601ba70ae924e4bebbb610120526f172f256ab753ee1a075825541bf23515610140527fccf3abc52005fbf9f40147337ed5fd1e8183fad8fae8de4e326b8a3d34479685610160526f1342b383357d50e943731ac03588e0c7610180527f941b16c9474f96dc1f3c4aa50a19bf5aa9e537ad16feec31fddd7595bb0cc88c6101a0526f0f62618f6bccb765aac5e98264e350426101c0527f8c697823eb1f8a342b70e07ed1261be43bdb9a0954ea3195d04885ebd8205d686101e05261010060006102006000600d7f13b55944bab9533cf4f2f8d302aa5ec0ee3e3be0eca70f1520ef656175d872fef4600a55600051600b55602051600c55604051600d55606051600e55608051600f5560a05160105560c05160115560e0516012556f150f4d385f70db4c9e1b2977950b224f6000527f104d3d0064de56ce97739c57d661fe0663c04d4c8f8816a6016770b4c93b81816020526f015253a3b2d98f552647a63c85ded9686040527fc5144b738ad3405c03569364a92f376af88484d19f9fdf9ae6aaccf9180f126460605277080000000000000002bf1a30168165233e0e3bc3f108cdd36080527fe367f4d86aa54962114ebc46bc2eb9697cba0fc2a1aa62765904fea31e6ef4c660a0526f12eb730a67099dc608a80aa528055ab660c0527f7613de79580ff064e76deaa2db26900b01162044f9f17fd27916efbf36e5456c60e0527f7157e40f7328332c6e934963ef8716bb4bfb82203d7909c4d848619d33dc87d96101005261010060006101206000600e7f78dbccfa9a44f1f9e4d26170fbb1d4707811b1586c31bf00a64736db763bd820f460135560005160145560205160155560405160165560605160175560805160185560a05160195560c051601a5560e051601b556e25e6908c41d058bae0017a22c624e56000527fca389a0bd0d682c2d9523b96e2265831a615b249655b882f7327d32d6fdcb4676020526f0749a3da8fa5121b3bade706cd9e74986040527f518e511fa24c4de40f7fa3a8f369b509709d827a2b08bbfe1bdbd78d7ada85126060526f05e128d52c8948aa1e315fa887ea40126080527f89fc5c7803f60a919634a0666f433b6763c075e2a084e43ffcf9602f0c2d622160a0526f0156a0880d3a086e087f0f33c704ef5e60c0527f6154dbc43cb1b72c1d0cf6e695a89e7ef190110fb2b3d72ab3d081a70a9a9c7160e0526f19c0137ba6b2d34a3a4ddd3cfb730005610100527f893413c417397764cb18e8f851ac7e9efe0f32fc5e008af9358a1de973ae70ca610120526f0bf891fd97111ff31ec86b7ebdf60e3c610140527feec4c2cef82e2d5a06fb56d48ae79d725ce304bfe329062db6ff2822b6345c75610160526f02d7185ac827392f6f5127315c7b9b60610180527f4d5d8710dac6bf4d8654423061f924c13d4689da8a8cb6bef7aa5f8f45094ad76101a0526f0db900a3ffe0a9be8ad5edc61ceebfac6101c0527faa7a11a5a505cefe702ab37b37c43d6b1fe5ca8b9ca2012fab0a152a1160de506101e0526f0c0997f6859be162aca94558bb3ce1d4610200527fc58e587162b3f3629996decc96cc0d918a0e395f20be8e2bb1a16597fafe3fa8610220526f04dee2da3a3c4a817130ac1f22b5a05e610240527f7106c5dd497df5d7db92507eb51753e09ff6b50bc798f6a8033ac094b6fd3b57610260526f19a6e21f439afad2d66027984e4644b1610280527fb6532e8789ad68199ea946b511bd18d07a8ad353d87eb3c9f66a6864f33d2e5e6102a0526f18224c9c69a95343548571e650ca96876102c0527f0d274959a9a9b4e4f1c0720df7c3d81d5e51e9b5aa67e73acbb15d4f226aa8726102e0526f09e4e495fe4d9ccf8dbf0c1395c7c0a1610300527f6cc855f92121ea0e801b429f738bc248f336b85d2f59c1effaa5921c60adb623610320526f0f702fb07c66ec3b44e3dd9cbcb1df9d610340527fbaf5e0cf6c415ee9a88ab176719b7e4084e0959372263c7db8c6628a9f3eb81d610360526f10dbea22d2d12eb07ab7af782790af68610380527f94f388250be3c9f7de80db50891202df1daffdfdea2903b846de9d1d169e2d4d6103a0526f04f13c07b6e8530d51bf79111f7e2dcc6103c0527f85bbaf3bb101d1e24e01d687a0967188def03b25e5a01c2e14b7d0191df125456103e0526f195ff16e04a35c0e19cd8621a7d7714f610400527f2eeb11becd22c4397d009144245d468f1c68c8ea68c6570ca3b9ad65f8c7e616610420526f18601dd1f89f6e8ffaa613d4ce374221610440527fb2fc0db4e405c63a3db6f9a63b3ac72306f3231603455fe0cc93f92121439df8610460526f19e867999b3fc03c51d71fe28c5bdd00610480527f185c4e8caf0665f2cb756351e4ce123168280765cd122e935466919ae78e7c946104a0526f0b4b6e440e9a6fe52f0f6f44c72641126104c0527f5e2d9ee84a1f4fcde2a8a1fbb5e131774369605abf5aee5a8d1700297727d73c6104e0526f024aa2b2f08f0a91260805272dc51051610500527fc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8610520526f13e02b6052719f607dacd3a088274f65610540527f596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e610560526f0ce5d527727d6e118cc9cdc6da2e351a610580527fadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b828016105a0526f0606c4a02ea734cc32acd2b02bc28b996105c0527fcb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be6105e052602060006106006000600f7f247aa40947a72170799d532697899c366999c2aa400acb85f59c4d0f57266768f4601c55600051601d556f13570d9fd2db4959dfec409d4638602b6000527fa3f04941f45ec554899c4d0f7f53d70e03f9693ce01d037edf011b17ca8493f16020526080600060406000600060107faa336809d445eb5793ca323cca0116b6f90884cd2de24e968c4f3030b348a955f1601e55600051601f556020516020556040516021556060516022556f0e27e5e11d58e678c11a040fd27bf27f6000527f06effaa3b77f09e1fa12a5d8d26b8638a0f01afed29e75150e2b492eae4db9be6020526f0439d0327c8d1b43a20fd7bd2404a90b6040527f47a0cbda67c8dafb13c10143dd6c9c0e4dd5a91f91d57a4947d5b6076927f74f606052610100600060806000604d60117f9ebcee41df8ac99bc589009f8a7e47e4299477856793e1dc9392bcc167dacf74f260235560005160245560205160255560405160265560605160275560805160285560a05160295560c051602a5560e051602b55", + "nonce": "0x0", + "storage": {} + }, + "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3": { + "balance": "0x0", + "code": "0x60ef6049609660136040602a60d38a0a3e1a640b08a05400315960423c0b435609f4f0107e701d17667e534a9f037c6757f3123d399535661dfd6c159149611532178e727e57fd72491260941a1347056c885d1c5d006a1145307e82739310116e3e018b769515f373137b37461d0b193e397b7343063416301a34116657f598755a9e6413025a7356181a81623b683a55357f1967458d140a7831445c5f5f7f0a409b3e76071702fe3d55408879751c55ff6ef01e3d54193c6b75485c3a1d678e4005175d047a5d54007a8bf13e549751590b7d672091323e7d303299697a4464f03b9a89377c9d0b716e0467143720101179516509537c0a510a59f44962586873067960036a5d3f85f29c721039556c7206137b7108955a5d94fd0702867b6d65fa79456219863611705a404533430a40597b3055ff0596835d5337619a007e7a513d7866f1653115447341f44a1c6a3bf2676272333a666c7f666f445303738d3c3a8960925474586b5b5607025772568c6b1d095d368737066264663e334a7495068d097974879c6f30101699744217925d53924147625574a04049411804806e7c5c7d40505e3d7659141094736c523f7d3d02fd466134626830004a791e643b163e807a75798e817366945c5360663e5c01727b881d8e191cfd047f043e81936e5ff54a8e3f97657cfe3c49038c171e6f8b55094104202000699d497a527d1c127b7311587014f24687717d0966503f5d016f371d4000083900a36b50601c941e521a6c5fa37c54a23450063b42961e73844407327a6a06341c1d671b62111c061b694540643340a23b798961f10b627135653e123e373d3f576251675717186b71009d148e56581e1d0943097d005c408c0430951365011b8600649e7a7c673f8b718c49194047073530315a115019fa329bf0a16834fd62908536f535193579047b3a9f32184174a3ff9e03850670680810158e10470a333298674a716a769d204919065367207b53fa6843555906677f159e81797a9a9f1e417b721931a0629d1c7b3e50101690715e007f8a187716107a803d864983585b6931080246547b585b8efe599246610811573e487833507a57a28c5b676b6a353b619c7e65523514744095774060f01d06f258481eff6e940516550811633936144a377d6b11786f94817a360b093310856b98f29f18666c9e901d08a08aa07c5c5b1757425e9a12433e6548495c785d661a90710b3f619f7839047c6c1b3317806a94610862688d1007865648123241919f206e7a060773735234a4755a11149a03199d570a65a2883d6c71f27b1998957d5e75425b8f457906460b66395f395e7e0942ff436a180a20857f491537866e5b80395a6b4689803507590661651c50331a8a7e0550905d8161890637848f9c96726d061c7544ff8c593d486431980b5d19", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000005" + } + }, + "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f": { + "balance": "0x0", + "code": "0x60f9ff08e55301a405600aff7f838f432b398d67edd79d315dc36a90f8b6cec82cc931e9902c1977c41d815a1f6000527f13fe905749a9fa23e5e6d19d6bc2b116647971e33108b06569f3c5102c60c73f6020527ffbebb93b018b3214b7fb132b27e4a482ef0bc3108d1e7476fa9ae8145a0d52a36040527fff9e5a128ba578caf9dfbb892ca6ff783f8dd7c48389a16d315843dd7dfc0aec6060527f615846a2a8d4ff72d120c18d25778080fafb47fd942cb8db3deb30f9225c81f06080527f16b22134b6bbea2a3fd6fc5ea7ca4ee2626ce45e18265fa072a6b0afd3209a1f60a0527fe83451f442f5180389a5f9dfc9aa2255be1c74faf6f88d95c533cf1457d2362a60c0527f53337028167932cf8acca7e83f755d4d30e80aa033d0bb8511efe8b19cf49fba60e0527fe1535d12c7bb0a7718f875d946d90792b1aa54e135e91d644933763ca1148aec610100527ff79ad2a22352e9ca9a0c445ab02dd151fb08b251275b4171b0fe073dfdce154f610120527fecfd9d2f7e17b9b598ea4fdc1a1a136bc133371fceca1c2375b10c728b75b1a4610140527ff2c027a65ba4bce87721c1e22be423e68594d156ac2ed671ee49a1a6d1810d22610160527ffdf921a8aeba249b30de81ff9b7044ae3be7067e9c15100c3825745121a0373961018052604060006101a0600060037f39a0f0e5a3034ddab629963f71f3a2c805d5de5e485f50470c4788b609891297fa600055600051600155602051600255", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000000000000000000000000000000000003", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000007" + } + }, + "0x4133B3E532cC750d0a4691c8Bb0B03fba51707FC": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xdcaa7645870b9ff21dc74c437d77781b7366c4f352caa0c0f1e7acec0c780181", + "storage": {} + }, + "0x538A8474EeaB43d5a960164c554A20400151D479": { + "balance": "0x989680", + "code": "0x7f5cff5e24ab538a91033a6503871ae05abcafe0d859c02f011b73a34fc3c9268d6000527f05c734d437bfc67f9c0201fc5ad0440d2160361d66a5b9e740fac13f2e8053966020527fe5261c43f657361f90396c96da8dfddf51d4e1006fcf030c38272acd6e9cd5226040527f9f354515f0fe58d09aad2b4e7533ed7ba3fedc12996bf860f5f4ba6bb743c2a96060527fd042e4df018e59bc0f575f146560fc50879d525e5bc1b7816fa66a650a6be0fe6080526020600060a0600060566101007f70ded0da3434e4d08343f854a5d5ff9af5b6f2a0a45d505487bd115d5a95dfd2f2600055600051600155", + "nonce": "0x0", + "storage": {} + }, + "0x641602bAD4A323C49629d45338d79A2bb984A3fb": { + "balance": "0x989680", + "code": "0x602060006103803e60056003607439602a60246103a0376080600661028039602760276103a03760006102802060c760006103203e6001610380fd", + "nonce": "0x0", + "storage": {} + }, + "0x6EB54E66856fD47bd539A986B19F0Bc9B7B4dA9F": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x38b446fe4e737b60383040233f4e9d2a40598cc6da8bcd879c52501b7bd413c9", + "storage": {} + }, + "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190": { + "balance": "0x0", + "code": "0x7f60065c507f60045c507f3f4a6783e043cade83e3efd7c036b5517630586e70666000527ff745609afc6000527f26ac0c300b6000527f1ae979211aef9d5b178c50b254496020527fc94746f9c9f4bc902c6020527f748b1677bd0ef214ce6020527f0547200a26736040527f78956e009667fa7cdcbafee1fe6040527fff58301e64554c7d0f22aff66460406060527f527fc0e58badd643e78e6951c18212baac6060527f8b47d9ec7813b1b2c134086080527f698364dbe21e6060527fabd6c4319461b934544dc06080527fbe25ee574dee9260a0527f8da0cb487ef89497954aa30e26a86080526040600060a0600060a0527f60446060c0527ff67f02548193b632f42d7037186903e461b65d592b996f244819ec079f60c05260e0527f606560e053605160e153606260e25360fb60e353606760e45360f160e5536060610100527f60e653600060e753605560e853606060e953600060ea53605160eb53606060ec610120527f53600160ed53605560ee53606060ef53602060f053605160f153606060f253606101405260026101605360606101615360f36101625360536101635360606101645360556101655360606101665360f46101675360536101685360606101695360f561016a53606061016b53600061016c5360f361016d537f4176702b63bcdc4cb9c73abfc785e626a5d48ed79834c65870dc6b076df773ae610180527fe514ce5369e1515e7c76205f39dc50325f5524af55385127fb99708a160791a06101a0527f540f9745ee262948be29f7c4ff39b29f069012ca8d661cfe500180d47866523d6101c0527f3d871f52edc9e5ee936538aba6b1a574f8c6df1bfe2a4bcf7793bc0bb008b1336101e0527f848fb85541568fc4035f73bf00ab79eb687773ea0878b4b25e4f443b23673b22610200527ffb6a3205053e9cfe09d60513da475141b7102e6c775fc1afd88244e30f98216f610220527fa3a57f172d51608c8a4082a4eb4089f513d89a7916a000af45ecebd20b6b4590610240527f261600b57bee20a830b2b5dff7a02f640cb410fefe2aee2cdfd7cff007f6da3b610260527fe537919b87b961f6f0e06e0b95989a4c4c7976613994af296b67c727e9417099610280527f5cdc062258c2642c1153b1f4ec9d3ec1cf7966d3fb1874d8274863c4c0c4320a6102a0527fa1fc3931caa764bebd3c7d05743c9887f9a7371bb9ad17d5a3c117cf769b54806102c0527f282edeb064f32937da73d7ce692146aed14888fa10e4ff12a005651a41c4b07b6102e0527f91e02452a5a0f1672757344255aec5842f69a3635046e560bc1b54d606c42af8610300527f6bab911858f883ce4f4d0838210ebfd5ae7ffd75d46a9637908e78e4d1943ff4610320527f5a0ef79ffff9ff5f8bef33a8b8eda6a9189ac5eab77d636deeb93c8474a458e0610340527f5fc5680e125bfee5991675741d0e5604667a26970dd8f0ce4753a7209a0b67996103605261016e60006000f060406000610200610180845af4600355600051600455602051600555600655", + "nonce": "0x0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x000000000000000000000000000000000000000000000000000000000000000e", + "0x0000000000000000000000000000000000000000000000000000000000000008": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + }, + "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10": { + "balance": "0x989680", + "code": "0x7c30094d9e93c6538447c7f71879ebc33171319acae4d27701c7b3fed94c6000527f28c7989c23b52e07b22635abfda126cf1a14981ede6fef9a9ef409d36ad639bf6020527f1f4dab7bac2a1d1205e2d552299144f2724e1e071a3c937dd0651aee95d859d36040527ff57bf8b81daa6cbae4959a13988b1e8fcc9bdb8be682a8a6f7fe0707d1ddeda46060527f0fc1f5ad1138e3d799bbae17dd28fcca35a3ec19c8bcd49b4b3338610d9429656080527f693bb5ee5c4320832b5134056658e570f5341a8cf1b5d6051c15367ff473fdc360a052604360c053606060c153604f60c25360d260c35360f760c45360ba60c553606f60c65360ca60c753606460c853608060c95360c160ca5360df60cb5360d260cc53608160cd53603a60ce5360cd60cf53602860d05360a360d153604260d25360bd60d353600160d4536040600060d5600060d560097f63823a27ea3a21fe353b0124ab9c852fd4ba8cb0c2dff0e45e1a17c15378f7bcf1600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0x78011f4E10a54C02296EfeB11034d561320e8949": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x8260476d5e5d66360702af75fbb09e6db415c6663c7ca092e358bfea4448f770", + "storage": {} + }, + "0x82361b537D93C7A0079Dba1E4f367EaE7b5D5f2E": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xd8681c573cfe16cd18cac8fb006983725de8f2b9bf2044cf8d122b7c6aa02822", + "storage": {} + }, + "0x94b690A97d429F297d32b8fED10213e759861599": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xad696fc9e254151c47bf314c3d113e3d6f61dbae1a524f30bc67772429681ff1", + "storage": {} + }, + "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F": { + "balance": "0x989680", + "code": "0x760100000000ffffffffffffffff0000000000002e0000007e40000000fd000000db0000000000000000000040000000fd000000db0000d3901a7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002200006fdac7fff9ffd9e13226262626262626009005900b6c10000000000000000000000000762900760076761e00020076760000000076767676000000901a13778200000000000000fe000004000000ffff000000fffff70060071a05671fffffffffffffff7806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a117ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7e40000000fd000000db0000000000000000000040000000fd000000db0000d368066aa0a5319bcf5cb40906901d6a01000000000000000000007f8000000000000000000000000000000000000000000000000000000000000001056000557f80000000000000000000000000000000000000000000000000000000000000017f7effffff80000000000000000000000000020000440000000000000000000001901c900b7f80000000000000000000000000000000000000000000000000000000000000026c01000000000000000000000000900290037d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9682323232323232323230305197780000000000000008000000000000000800000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b0017901a6001557f40000000fd000000db00000000000000000000000000000000000000000000017806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a9012777effffff8000000000000000000000000000000000008001717676767676760000000000760000007600007806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a0990066002557806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1a678000000000000000762900760076761e00020076760000000076767676000000011b6a1000000000000000000000637fffffff1d90176003557cc9700000000000000000023f00c00014ff00000000000000002230080567ffffffffffffffff90147f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6801000000000000000010126fdac7fff9ffd9e1322626262626262600778200000000000000fe000004000000ffff000000fffff7009018166004557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd900b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe101a7ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb07ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff901b037f80000000000000018000000000000000800000000000000080000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff90116005557feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6f80000000000000000000000000000000901290177f7effffff8000000000000000000000000000000000000000d90000000000000168210000000000000022774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a08196006557f80000000000000000000000000000000000000000000000000000000000000006f800000000000000100000000000000009007900760075568066aa0a5319bcf5cb467800000000000000190177f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7f800000000000000000000000000000000000000000000000000000000000000190050b7fffffffffffffffff7effffff800000007effffff800000008000ff000001000067700000000000000017901c7702ffffffffffffffffffffffffffffffffff0000000300007f82000000000000000000000000000000000000000000000000000000000000000b600855686d5adef08547abf7eb6c100000000000000000000000007f7effffff8000000000000000000000000000000000000000d90000000000000190091d7702ffffffffffffffffffffffffffffffffff200000000000677fffffffffffffff070b686d5adef08547abf7eb7f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd900b600955762900760076761e00020076760000000076767676000000777effffff800000000000000000000000000000000000800190139006777effffff8000000000000000000000000000000000008001760fffc000000000000767676240000000000002b0576047181b7cc9700000000000000000023f00c00014ff0000000000000000223008057bc9700000000000000000023f00c00014ff002c0000000000002231089013057f77676767676760000000000000001002e000000000000040000000e0000000007702ffffffffffffffffffffffffffffffffff200000000000901090016a01000000000000000000006a01000000000000000000009005900a67d02126262626262661011103137ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f82000000000000000000000000000000000000000000000000000000000000000b600a556780000000000000016780000000000000016801000000000000000008901d197e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007e1f0000000000000000000000000000002000000001000000000000000000000204600b557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006fdac7fff9ffd9e132262626262626260090137ee8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000760100000000ffffffffffffffff0000000000002e0000009004176101117f80000000000000000000000000000000000000000000000000000000000000000a06677fffffffffffffff7f77676767676760000000000000001002e000000000000040000000e000000000900390137f80000000000000000000000000000000000000000000000000000000000000016b1000000000000000000000001c151c712000110000000d0a300e750a000000090a0a774b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a9004027ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff00000190101b7806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a6000900b0468478392145435897052637fffffff109016760fffc000000000000767676240000000000002b05760477feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1890027ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff637fffffff9010900b682323232323232323237f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd68478392145435897052900904600c557f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd197d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf97f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd1d107f77676767676760000000000000001002e000000000000040000000e00000000063800000019016076823232323232323232376013590cab83b779e708b533b0eef3561483ddeefc841f5181b778000000000000000800000000000000080000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9018027f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe67ffffffffffffffff7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee900890166fdac7fff9ffd9e13226262626262626007f7effffff8000000000000000000000000000000000000000d90000000000000104901c600d557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10006b10000000000000000000000090107e40000000fd000000db0000000000000000000040000000fd000000db0000d361011190071a6b01000000000000000000000063800000011b600e556b0100000000000000000000007f7effffff800000000000000000000000000200004400000000000000000000010b1d7e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb901b901c7806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a7a0109000000000000000000000000000000000000000000000000007702ffffffffffffffffffffffffffffffffff200000000000081a7f7effffff8000000000000000000000000000000000000000d90000000000000160071b9012600f556101117f5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001900b6010557806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a677fffffffffffffff1d601155778200000000000000fe000004000000ffff000000fffff7007d0c76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf90560125569100000000000000000007f7effffff8000000000000000000000000000000000000000d9000000000000019006600067700000000000000016900315601355678000000000000000677000000000000000187f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a567fffffffffffffffe90139005778000000000000000800000000000000080000000000000007176767676767676767600000076767676767690181d760100000000ffffffffffffffff0000000000002e0000007f12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a57e050beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a0009901819760100000000ffffffffffffffff0000000000002e000000638000000003057f80000000000000000000000000000000000000000000000000000000000000017f40000000fd000000db00000000000000000000000000000000000000000000011c1c76013590cab83b779e708b533b0eef3561483ddeefc841f5610111901113671fffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff137e1f000000000000000000000000000000200000000100000000000000000000777effffff80000000000000000000000000000000000080017e1f00000000000000000000000000000020000000010000000000000000000008050360016780000000000000007cc9700000000000000000023f00c00014ff00000000000000002230080509900563800000007702ffffffffffffffffffffffffffffffffff000000030000111c7e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a10007d76767676767600000000007600000000000000560000000000000000000090176014556c100000000000000000000000006847839214543589705207900b67fffffffffffffffe77800000000000000080000000000000008000000000000000901c901a19712000110000000d0a300e750a000000090a0a7fffffffffffffffff7effffff800000007effffff800000008000ff0000010000171a778200000000000000fe000004000000ffff000000fffff7006a10000000000000000000009016901a7f40000000fd000000db00000000000000000000000000000000000000000000016a010000000000000000000090121a6770000000000000006910000000000000000000131469010000000000000000006380000001777effffff800000007effffff800000008000ff00000100009008900a67fffffffffffffffe760fffc000000000000767676240000000000002b0576047901890101960056f80000000000000010000000000000000901c90190667b368d219438b7f3f7a0109000000000000000000000000000000000000000000000000009010900a7d7676767676760000000000760000000000000056000000000000000000007ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff90179007196015556a10000000000000000000006a010000000000000000000090067702ffffffffffffffffffffffffffffffffff20000000000068232323232323232323119016638000000067b368d219438b7f3f180268232323232323232323600790061c6801000000000000000067800000000000000090177f8000000000000001800000000000000080000000000000008000000000000000778000000000000000800000000000000080000000000000007a010900000000000000000000000000000000000000000000000000900990016016557f7effffff800000000000000000000000000200004400000000000000000000017a01090000000000000000000000000000000000000000000000000007116c1000000000000000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b000a900160006000f3", + "nonce": "0x0", + "storage": {} + }, + "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d": { + "balance": "0x989680", + "code": "0x7f0f0ea7c172f5a60807b88890ceef3613666c7bc8b46ab8c6ba7f9d44c7c8d9c56000527fffffffff000000010000000000000000000000010000000000000000000000006020527fffffffff000000010000000000000000000000010000000000000000000000006040527fe9d59270783f28e43ddf8f1b6a232fe86e59f3d054ae7056d7dc642d51f14a406060527f9d34ef22e83586115f72b401b9910edf0a3d4eb5ab5842d6526bab09d77e14c06080526020600060a06000610100611c68fa6000556000516001557f7b94c577a72510ad55418281ad7a8629f5b63bf1147d5268283b11beafd9ebe26000527f7810b9459c76111c880ea84e8499a26242792c36ba27d395c41b9c95359bfdea6020527f59b4f9fa4df5b677ff6e52720980987d5fba33171483e8c5cf862cabc2c24d646040527fc47f208c959f2304a9fa862623380053810c0d0ff750736436ac6d0b3fee66996060527f7905e517823b66df754c53a4f041cc1779a861eca59dad07955b10b697346eab6080526020600060a06000610100611a68fa6002556000516003557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f19f6370259c54b5fe9d70769e1d13b5cd7de9174704c0b751ae8c05c2a24ab2b6060527f4ccf54ccc3a23c5051da573be9703d9a2aa6a80862da9de38493d2ef63d024a46080526020600060a060006000610100611b8ef16004556000516005557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6080526020600060a06000610100611aeef46006556000516007557f27a75fd0382a000f4435415fb07c1ebc1443135f515ea0f1fa570cff63ebbd136000527fcb22c16ad640faaf88f97a84294e8e0bcdb706d94619e821ab82353b7c42fdca6020527f1f5d30fd6961f15a5a77fe525068e0fa278a2787045863e42a69dd24ac1550e46040527f0f306538f795f5bdad7d2beee3c7e75663965997393b690b437411d0d58ce9f26060527f065cbb1784b9a5c653bcc54a914fa50fe730b23528518fc9bd2aec4b27fa2f436080526020600060a060006000610100611cd3f16008556000516009557f36c057851467b4e8f1d9f625862e82538302e0fd975d1cb4e0d516b96ca8b6626000527f4889a3454be76415ccdcce4678704e94af7a3b11985f7a5ae34bd43fb8a4e12c6020527f657224d9b3bb1f69b7c751ec64b612f9f6d5e41737b172cb0e28557eda13a0996040527f3b1e2febeff11f1197266d1574cb00e7924937cddfe0e81a9a6ab5c06abb13536060527fd6e7449ca1278aabfb488a187b82f0a2cc8696575c88932f02ac052d7891a82a6080526020600060a060006001610100611badf1600a55600051600b557f61952ed2690b680aa593a089363d056da851c37e412c53b8d4a5c900876eae886000527f5364c572df38b3eb57d39a9adedddb179a6af9903ab70e6024a8413b13aeb2746020527fc1bc39d8e0c8c05f94a2bb6e9452586003a72b77e2958d07e005d29cb50cdbf96040527f7118c768a2994569c1f71c8e428ee1ed44f13fe0941b16b118765b562713c0196060527f2585a6698c187ea3ed93f12ee13ebd03987d8cba11438973a54406babe0d49326080526020600060a060006001610100611aa3f2600c55600051600d557f9a894ef20b37c1057182fbe7e5f59a3c42f177d9d152ed9dd344d15dec691d956000527f17b51769636e3661b9b0aed1d13c16a50a9f2dfbd79812686b89c6cbd4c8d0e36020527fe66b4011bdad92cf17219c9b80d87e927c7fcc9401922e85ad16260161ed20356040527ff29286409619dc0318eed274c26b87091ec9ccfb3fcbece8a9b326d534030e716060527f31b58bc996aa65a72a9deda0cb19b05a763c26bacd130fdb58c01574d2d6445d6080526020600060a060006001610100611babf1600e55600051600f557fa2f800b0138f1ceb4099b6db46869088b058b877995906229851f3a1ed4a6c566000527fb92bf3b0ddfe9442002c2906fcda67052525a68d54dfdcd18c5697079c4b621f6020527f7d8194ac1768fa99ce3ec308ee5b6b738fde4d07efc44f391e20b8e31233d43b6040527fa35bbb2e53209d4b742d108ce5c643e2520939e5c40f41eb4b5ca6987d1efd9f6060527f0aa9f8e9bbbeacd8362f094f3c4eac043400c457e9d342d8096098542f2c1dc26080526020600060a060006001610100611c89f16010556000516011557ffd5c529bd322eebcca73bba55ad93fcf1663423e06074af41f0ca99575cb32b16000527f458837808d6a6e287bd424bff26bb52a73246b8fb8a142ef523e607e3e84d9f56020527f362b527afb3224b47e0754b3b56dcc24c34874f1936a3db1852ce6c2a717e0786040527f75a34b8ae705ac9a5d79ebd92742c1b18c71e84e3541ba8dd078faff04ba50546060527fc1bdb57d01a87b6ddcdcadd5e40b36ed2d4bafb5a59867821ff95f42b3d7069f6080526020600060a06000610100611c91fa6012556000516013557f9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a086000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527f68019add2e307b5807330d28d8577e078bcb965e9a852103a79d25185ee01a0a6060527fd9d79438bcd4e05d060c8b02c7ceba7abebe01846516257cb85e50c2c41d37746080526020600060a060006001610100611bcaf16014556000516015557f3e866a7b7a4024f8e07421be8291c5cc80bed4659564367fd2aa1e2d17a757156000527f5c1803812b8dceaf1d1aeb67107579a1586b07d8033d0772a644c89c9eecfc8960205260436040527f931c499350eb57b965618a1770ad601ee72b1d2f7534572e57bdc2a16e08d1266060527f22d032db5ab09081ca16ebddf3475c04c59a08252e57f318e87c122e64f439d36080526020600060a060006101006119bafa6016556000516017557fef02d493f62b3af6a7bfacaf888c58ae1b41d3e62bd483459f1682842ade1c726000527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f1a52172d34aa8c12e27afd17916b4a3dd4e4767bae7d5f499df89c7d0b6bd0936060527f8da714fb1068cd61fda3cf511ecde05e8345471ac198dd02cef0dbe4526c132d6080526020600060a06000610100611b06fa6018556000516019557fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6000527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6020527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6080526020600060a06000610100611b67fa601a55600051601b557f309481fc9139adcdc6f07820b3cf6426f6dcec887e1769ee0b31007ea4a28e616000527f82da988b9dae706975a53b1b941c835a17cbb087efcd65fef9888ef4002a6c3e6020527fbb0672091ddf44a9a90202fb492ecd36f7d2b00be1096d6b372de353f60825296040527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff6060527f1d4df86c05e1b0aa40f4b2bb71876cb83d620ed52c608a990bcea20ccb20a61f6080526020600060a06000610100611b47f4601c55600051601d557f60fe3ec609d65041e5ac55b70de7281992889ad1786a60708710789a275d184c6000527f6789ee5622bbe61476741d925215c89c6ec90fb1c030fe2b7fc9115c5de4c1676020527f81ed559065083889f9b510aca63d4cc839c788991a3285d66434a2a930253cb96040527f6d6625dab4ff1516dc694b2a75ca0ae67105db20b29ffb26be51727f188e0ecb6060527f831fbde00ea788aa911818c1ffe8770c231214487e24ee209f533fccbc5f8f0a6080526020600060a060006000610100611c63f2601e55600051601f557f2b4d344ca37e370e6bce4d4d1b1f362d461709d8d7c676af6e6baaedb7947f136000527f2a9fcf851669dfb57aa0da70d5ad9e172dfdf89100ce9c6a034600b81211f8e56020527f6f0c3598071c216d471205667642f6b6d92a6c67b3deed518623c24e14f29ea76040527f5492389cd1891859b4afda3b89f99f8728c4491e2c7d05ab64317008276d843e6060527f31311a9f1858beecc762365d6b5980f9aaa889f9b34759fad1e0ab0a38f4597b6080526020600060a060006001610100611a13f16020556000516021557f86f5d8b49ceba7aeaf63e9c713c820dd8ed3f6852dc6bda135eb1849be189b4e6000527f3681867bcb7d33e72ffcb95310886698ef860db22b38607ed8adf05b13b828416020527f360a8074d67de629bfa3f8b3446f858878e201c1dfa90903a4aea5eca61146c06040527f392f90a658a4cdf01da2dd1ed687654b201f922d0d02e50618376cab335427db6060527f94c0e5df352182e7a2644cb07c5e8fbfd4f3873470f134a0bb0ba8ad48a32a596080526020600060a06000610100611960f46022556000516023557f2187e0b39b0602365f1a0d76868183a38cb1fd0f2a4d730ce4f6045c2d4926756000527f16fcabc35bf48a06b56b00493dffd9509f6c383a908754774922e9bcc4a8f7a46020527fd9420df2f0b941a7d9c8fe403ff0260b7c0af26ea3eda679cdbb4349eabf8b6f6040527fe10adfc7e992b0511b40fcc442e48e8898ec157cf51935d8dce8a05bf352c63f6060527fd22d191a8791b292932694ddf0a872e5ade42ed3419e15c2019a3684d222d9dc6080526020600060a060006001610100611bbaf26024556000516025557f5b0f9dbb43cdd626807517c7312f503bbdac76dfa29cc22cdd222b22a11adaad6000527fa119ba6510ea446dd9eaaa0bfc98392e23c4ec578498f33681ab6165e634aade6020527f26c16c5fd456933738accd67d30266854cabc2c87913f739b00596f6df3b47326040527f9203ea28df657ce09a406539e155680e09ced0b0bc312920ac2cb4d9820338036060527f27476b844dd0dcd6257f8e279f5f4bd9f79af95ec1054e9e38be7e4fe95f580b6080526020600060a060006000610100611be3f26026556000516027557fd833cd561af31de9949b67669b99be4e9d1c65b71a0dc822bac620e8627909c46000527ff273e568887d5c7c232c3b5b80cbb4304e12edec490de12f8ad1be8aa058ba7c6020527f845589edc62021e0437125910ed1cea3800c60f231c82dd049e462b0e58c3f52604052600060605260006080526020600060a06000610100611ba2f4602855600051602955600060005260006020526000604052600060605260006080526020600060a06000610100611c4cf4602a55600051602b557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb56000527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506020527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325506040527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6060527fffffffff00000001000000000000000000000000fffffffffffffffffffffffe6080526020600060a06000610100611a4bfa602c55600051602d557f18edc615251fb19db1799d1e0d9cc499707553d6f7e75fdef32e177a9c198ce76000527fc23b9c3d62f717841e0b1a251b772c1f286991f41bf6c2b6744c4d5db0c6c44f6020527f1642cc67c1202959cd38dca27c57aba75579fb113eb38759c4a5fcc46fb435ca6040527f445a1575344053415bed4619d4be1c958b6e61971073fc08d3830216443b02196060527ff5b127e67009d3373f5b7c9b4fcaf785eccb823da9d09f984b2d16a2fa3e05836080526020600060a06000610100611bd3f4602e55600051602f557fdc7a6a7dbd8a42cf97100cbfb5343286879ea772d7f0e486bff85bac63a41cb560005274800000000000000000000000000000000000000000602052748000000000000000000000000000000000000000006040527f9dcd2d2e205014181bcce7fa788a0ef7fa1dd6dcf1ae31bd0e6d4bee41a918cb6060527f126e9db6839b8c9f27aec5a6ac351952146ac9dc3f4b2b09f7849eb92bfe363c6080526020600060a06000600061010061199af1603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xB9A8D444BbCDFb9a6b19f59e0024184fbe10761c": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x8ffb0595345154a7a19e50c98c725ce7ae2231b522d58776a3f4472f3d622ca0", + "storage": {} + }, + "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6": { + "balance": "0x989680", + "code": "0x7f26cc064393e356f34a892dd1815dc54437b2b669f31eb4c62b4903c08aabedc86000527f25ea1cdb71917d07e3f0d2620379e0a5ba2c4061bd663b291e619e795631b07a6020527f1ba0e01f911e12cbdd641b6b387876d2c45db434f342280af8cb43c45b5afd8d6040526040600060606000608860077fc71d868d71d0d82d13bf3293e7fc8a8e17e400ed0bf8ff4ab65cebe1ad753cfbf2600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xD74CFe323387aE2fd070CD046173026716D8D649": { + "balance": "0x989680", + "code": "0x7f0120d0aeeaa75bcae6522020acde356d3b204cfda02419322a0b875bbe21490a6000527f1a200d4e4f07055a7de7507ea7be401aea666dae89de07142f8023e2b9ec5d966020527edc46c0113055cb6d18d48c6e1b46c188afb53373ed78cbd52ce8fa11f4e4a76040527fae9fb4d83a16077a020981dad4912dad522e8014117fa49408095016742564fd6060527ffd3879f9d9e46f2314c33e39b5cf41608395bc00161da71e3a3cbcf1c173165c6080527f437d18c6fbb60f851752e0bd2c44c8f59618faadcf06117915fbc0f0f620d60860a0526040600060c06000600a7f2c6d339c3f6418873266d0bdde127282b35741c9b47c522d30ce2ddb992b8dd6fa600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + }, + "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce": { + "balance": "0x989680", + "code": "0x600060005260006020526000604052600060605260206000608060006000600161265ef16000556000516001557f8ffba10a0017ca5f8219909e128d511f31ba382b0d16f2df9c188d675ec691606000527f1d1f6dc7fd280f0613985080dd8712abfb86f6ab501331c2f76b1b75b41fd81d6020527f6ebbe1a2bf52d21e98477f1c849c68c5bc869cea5747e2b63272a8acdb0567866040527fd187e3992461b86080fe2d5de2844e395df602593ebb1821b20e0172daca8b7760605260206000608060006000600161d949f26002556000516003557f66b4f6e8a92f3f16280310feed70a2566d9af4d89434c564a3b6c581cfc62c7c6000527fafc59625004fd16e389059faef7927f7d6d1da75b445daa3d07c4baba821051b60205260006040527fbf941c82a54c09c167606a6efae9306aafbbe0ab3da162f92e97f389f62abc5060605260206000608060006001616c4cfa6004556000516005557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f9d2ea85682769dce1d8d837360f17bed8c18f08157e7e3c75cd02d43e22d18156040527f641af4a62533813dc42df075c1d56e12c49a0b15e76d6673984a966904c8718160605260206000608060006001600161a349f26006556000516007557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527f2281e311cea2cfa2d47a95ecc920d2fd303025a731594cb63b341fab784f7f976040527f551dca8bd75d4b9a7a70c580fe2bd64c1645051a27764a1a0be26835a0a6c35760605260206000608060006000600162016959f26008556000516009557fd11c4a1918b16339575c493b5e703a275f0c72dfa9c48ecb2a5634f8c37929a16000527fe44db503c9eb138b141d8aa54cd48df9539d966001850963446a57b1f51bdb1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f13e1f66edabdc35841c531fb7387f640116df72c4e24f7d40050819e5ed7bedc60605260206000608060006000600162011544f1600a55600051600b556000600052601b60205260016040526001606052602060006080600060016001614b65f1600c55600051600d556000600052600060205260006040526000606052602060006080600060016201687ef4600e55600051600f557f9cae8ac6460c880a4245cc665db1bec3a711ede7de8cff6b374e70395b86dd256000527f27181ce37efb15fa507728635acef6bc88447cae85aade5709d5b66ed6705a1d6020527f8e2b295c578c6c3efa1980162d62733e54afd977da407669c1599acd1fe7d25a6040527f3a4e3ec1e15a60d4031f9067a24376f9e28c6857c9718c62a89886bde764466360605260206000608060006000600162010f56f16010556000516011557fefe4130c9e6b6fe6e37733bb46c25753aac68618489ce41ae0624e14d40363976000527ff874b185f1f225860aab85b3d4963966b9171cfaa46622db6e0782b59e8d1e1b60205260006040527fc9a2d0e35763f3dbd99acb56fb534c350ee000a65f9fdca5474f1aa0f1b31ec060605260206000608060006001620160f3f46012556000516013557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fe436034a72ef7c34b9b1f2c3eac91192cb84b22d087e5884dacdd8696ff34b726040527f48803a6ed19bfc202f898a085136dd3ee4a918fdb3835663bdd96a50975e1745606052602060006080600060006001620142c7f26014556000516015557fd5042e3ec2ca8fde8b18909f94d7348e8b438a7263d2feeb2c422cb60f83bad86000527f55584a92ed548e75f6dcd3b25f48c5703fb8f0a85d772d8f587599b93f87fad46020527ffb1ced138fd8af5f88a6dcb089edafd1d2908513ef25ee480fdeadb2e83695146040527fa453d375eba08e416c4b97217f65e0b9307d4f5d3eaa7da79fdabe8e0f49bda6606052602060006080600060016001611401f26016556000516017557f82f33cf000118e725f5eed0187c8b6095a051ddbac8ded15de0d3c8928a808636000527fb8bc86053e103bb2549c3ff06a84d902e514c7e1ba1393502217d68a4aadb31b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f08011bce289447868d688b9973ae2bbe9d8ad6c143ecfdc6b9b70fe282a496b860605260206000608060006001600161e1eff16018556000516019557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fbe6d8c84796ce695fa00e4d0b0ac7132b50632ad157af5b1adc7c6702e9599d06040527f35381b299c20c4ba894596a0db9caddf538a0074684b690560e95be04a190d5e606052602060006080600060016001614ffdf1601a55600051601b556000600052600060205260006040526000606052602060006080600060016155c8f4601c55600051601d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fb0b5271225f035633edd33399f0913cbbef801313afb172c5fcd0590a94cf7b16040527f7e21e99a654ff21645693c71c11b776d4a9b61b7d9f15e5d97566f3eee5e60d3606052602060006080600060016001616deff2601e55600051601f557fb0e50afc95032ef3f21c5a95297c0d938886cb86da733009ef3d5e07193b7e1b6000527f4b48a05eb03d69aceb85b68608beebbd4bc578adf27f3b74091f5fc5df9df01b60205260006040527f2f9b55f0a732315697939e9d44523bf9b0c939ebc9a0e21edd2739a5923d0bcd60605260206000608060006001620182effa6020556000516021557fc39046a1193d18e62e84969d1a188a1c607d8ebfcef95072b96c7949676dd76f6000527f81726196fb4b59c1ba65eaefd21a431f9a3558de6d72087a82ed3563f0fc411c6020527f8f2ba33d42cb6bce63318886374c1fa956f1057cd6d529e2265874d75c5f35356040527fffffa2299df57260c1cbf85ea7379f90a3d546b6a4ad568d4935acd69a34db3c60605260206000608060006001600161af20f16022556000516023557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527ffe374920b47cf11a7b5da58393d25c34e5fe6e82b0d51d4a6e5c21b034e56ca86040527f17095694c8d8c9c8d28ac82b2f9df8f6618bacfc76c11d46b4d0c9e430f331ae606052602060006080600060006001620162acf26024556000516025557f15f24e505d16ac34cff2135dff87c71c10e11b65a33116164024b27cf27d1d006000527f536998cc03c326a9be90624f39787d5a14f9d5ebb2fd3b64823dd60f217fab1b6020527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040527f28dd42754fe747224d3095cd4d4a4107df952a05789098d2eca919073b149b9d60605260206000608060006001616d36fa6026556000516027557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fd293fff8f5adb1cde1fc86abd0c24f5649eca393b7808fa635e4c0732457dd346040527f2fcb00f81dad8b140cc9cd948c7d3065911f8b07b23fdcfd558a7bfcb435cde860605260206000608060006001619593fa6028556000516029556000600052600060205260006040526000606052602060006080600060016123d8fa602a55600051602b557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601b6020527fbe7c2cdd179b62736e7d27dc41b00d66b0676aaf1416229f58f93c229be4d6d96040527f45419dc3d82bf0241483c47de0c38aea663dfb4e2fd3dd5db35155e4c582fd5f60605260206000608060006001600161897bf1602c55600051602d557fea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935600052601c6020527fbd5cd8a674673281e0ba3b891773dd48b80608999a9e6d2957f489e195854d4e6040527f1d3cb422a300a1292e963d0c85300794e42c3f57378ec436be9c331c88d600016060526020600060806000600161a560f4602e55600051602f557fdecd52e420acf17cc0d451565b7c67671329e510c8c62ad03a95cc7351c043cb6000527f8f9991901996d733ef224cedc1826d06918df3f6ed4588cb2736e2e0f50d891c6020527f3e03b0ff538af2ccc877e59141b53a07bf3942b8078713a07900276f3cd33f9f6040527fffff38e35ae5b3c57a64627f66b4e44d6f0e38a593eee27710ae85a61ab95310606052602060006080600060016192a2f4603055600051603155", + "nonce": "0x0", + "storage": {} + }, + "0xE2f4CF89C9B94178B5725B8b1fd9a7F40c4a674C": { + "balance": "0x0", + "code": "0x671fffffffffffffff6b10000000000000000000000090187ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe7f7effffff800000000000000000000000000200004400000000000000000000019014901c6000557d76767676767600000000007600000000000000560000000000000000000060006380000001097ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0681000000000000000009006901767d02126262626262667b368d219438b7f3f187702ffffffffffffffffffffffffffffffffff000000030000638000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b009008600155901c7702ffffffffffffffffffffffffffffffffff2000000000007f77676767676760000000000000001002e000000000000040000000e000000000900a901590191871767676767676767676000000767676767676690100000000000000000060070890187ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007ff6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb09011196002557e4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a100067ffffffffffffffff020b6780000000000000006fdac7fff9ffd9e1322626262626262600901a712000110000000d0a300e750a000000090a0a7f8000000000000000000000000000000000000000000000000000000000000002691000000000000000000009076003556b1000000000000000000000007bc9700000000000000000023f00c00014ff002c000000000000223108901190047cc9700000000000000000023f00c00014ff0000000000000000223008057feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee9012901590046d01000000000000000000000000007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90179004681000000000000000006f80000000000000010000000000000000177d767676767676000000000076000000000000005600000000000000000000760fffc000000000000767676240000000000002b05760477ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9009901960045504762900760076761e000200767600000000767676760000007702ffffffffffffffffffffffffffffffffff2000000000009010901c156005556c1000000000000000000000000076fffff716b61616160b0b0b2b0b230b000008010d0a2b0003778200000000000000fe000004000000ffff000000fffff7006fdac7fff9ffd9e132262626262626260013027f40000000fd000000db0000000000000000000000000000000000000000000001637fffffff90106006556fdac7fff9ffd9e13226262626262626006847839214543589705216900260075577800000000000000080000000000000008000000000000000681000000000000000000a7ee8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee016008557806400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a677fffffffffffffff1390106f800000000000000100000000000000006001121c7ffffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a007bc9700000000000000000023f00c00014ff002c000000000000223108901860095560006000f3", + "nonce": "0x0", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000b": "0x000000000000000000000000000000000000000000000000000000000000000a", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x000000000000000000000000000000000000000000000000000000000000000e": "0x0000000000000000000000000000000000000000000000000000000000000011", + "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000000000000000000000000000000000008" + } + }, + "0xa94f5374Fce5edBC8E2a8697C15331677e6EbF0B": { + "balance": "0xffffffffff", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "storage": {} + }, + "0xe1fAE9b4fAB2F5726677ECfA912d96b0B683e6a9": { + "balance": "0x0", + "code": "0x", + "nonce": "0x0", + "storage": {} + }, + "0xe583e10A46B183759EBdA6b6C9F4c5c8Bac3f93B": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0xd04de6bff05c8224a456b8903e1eccc90b0536886d56e39545afdebcfd03bed3", + "storage": {} + }, + "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89": { + "balance": "0x989680", + "code": "0x6000496000556001496001556003496002554a6003556002600455", + "nonce": "0x0", + "storage": {} + }, + "0xf7c6909762e861F8c904c21cf3Da0D2f4307978D": { + "balance": "0x8ac7230489e80000", + "code": "0x", + "nonce": "0x0", + "privateKey": "0x7b323b16770a849a484590f9b4bba2c1f64d350b326633d6d120bfca55a11efd", + "storage": {} + }, + "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c": { + "balance": "0x989680", + "code": "0x60216000526103f260205260216040527f3623fd54cd06b75de7239ccf1b2449a0c9fd70c16f144a6bd2c9b0ac1fbfa8426060527f5d682940046b0afaf1eb7c6108fc0c970b258534d91d98209d333897b4b59b846080527f4c11a995c208cf5b0d4a29d98e5febda07077f48c48e29111a22442dee68cb9460a0527f950bef146802e0392142abe6ee810af996bea2fb476355f7593642d094ac676260c0527fd0b37c652e6f974b1a3c20664bb531a1e90a07d2d2c72b6115b9688f2002657660e0527ff631350425b8e604137eab399d6197e946a94e944bd07cb999e55efb5e744c94610100527f316b2d67bc1e378311ca594b35b3db4bf9b62cc5c83067a5147007124415f517610120527f1653e592c605857d24772e234ab2688aae83ac8deacdcaa5106fb4af091c8f81610140527f21ea6e72b65e0a16201deb8766050c2bc0612d7777f7b38b865ca773fb5b564c610160527fb69766036db609f36cf7a7c24a8b29254a6f2087ee0d7cccae89c0a3960f3294610180527f3d6a4d27eb848d841c593cac2bfd6f193e1aa156f89786510162d5f9662d49856101a0527f40c0d5118ea194423736359189066377b8195b4659fc3beada17066ba04132a76101c0527f8fc99a206ed6cdac47c088c9b71f4c8ffedb694103f96dddccc1457b7a71318e6101e0527f5649a7fa1ddb7d657a9102f7f5a1a0bd31d21a9388ab01bcf3ff7a0dafc7caeb610200527ffe8d1945e75ffc64e7e1a0e28e6ddab729070484ab13e7b4588eee69fd20980d610220527f06b489907a05480d4bd15c2e811243b0e69483a1759b21dfd02119359c61be16610240527f2476c6aa2b8e075e8c5e60c22223ab7610f7961b88f6f94a35f48ac59c0ccab6610260527fdba179d99abb3d9cb827d031e122f1b6ae6ff0761ce5e62ff2f6b439d7d5c721610280527f3f1ea572872467aac1cea6022193187d39de665fa8eba806cc43f0ab92e5b0816102a0527fb40663f10434fc54da8900ecc24c1ce52254d229603ff06a0a91a393f58c04416102c0527f38cbdf77b1cb1fff9022d5f3ffd04f1ce41442ec8c0086b94aaf2700525f60816102e0527f6beb95bbee2d635427cb55c90edf55323fda330b1709eaf414b391187e096830610300527fe07054ce1cc262cf540e7672266cc70e616c9fcb2b770daa52ee17329a1b3f19610320527fe6c7acff91edb2d66c98f2290c641b4c230f59db3f978964af0549ae58d3a1f4610340527f8537d71840b84339ef799929127470bbe566945ba3600b765fdcc2dd1c1f470e610360527f4dfa8d7e7650e02b28eb62be4eb0c79a718b70e84bf63a10bcb050a0b0db2469610380527f7858ec131355134d102649bfe55ca13bf7812924d28d5851f5c4b1d4ed3c28066103a0527f4668d069b63983dc376dd9940250c84fe5fad561f60c3cccac2ac3d5e79df7666103c0527f4d8520a4c52e2fa81849f4eba861282e70f6fc67ef38d5727bead9bb96432bb26103e0527fa4e584909b998e4926f86f26c61e7dbb2ff97e0ff20fb9cc15afeab67b8ce5ca610400527f616b8111dcb7a9e369eb0fc06366dac06ddc34eb75efe6e8a758d2a46d1deaa1610420527f0dc20600f514db6ef4b5da00e489e2bf64386e4d91b5cdcd3151f98b83ee6ced610440527f2ab02ae3d7f233d2a21d6188b372fad4957220a3c1357422d3902689fb536eef6104605260446104805360c86104815360c96104825360966104835360f36104845360c061048553605661048653604b6104875360836104885360256104895360c861048a5360bf61048b53602561048c53609461048d53602961048e53608d61048f536083610490536078610491536049610492536096610493536021600061049460006005620fe4adf45a01600055600051600155602051600255", + "nonce": "0x0", + "storage": {} + } + }, + "chainId": 1, + "env": { + "currentBaseFee": "0xa", + "currentBlobGasUsed": "0x40000", + "currentCoinbase": "0xc014Ba5e00000000000000000000000000000000", + "currentDifficulty": "0x20000", + "currentExcessBlobGas": "0x40000", + "currentGasLimit": "0x11e1a300", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8" + }, + "fork": "Osaka", + "parentBeaconBlockRoot": "0x6c31fc15422ebad28aaf9089c306702f67540b53c7eea8b7d2941044b027100f", + "transactions": [ + { + "data": "0x8e", + "from": "0x78011f4E10a54C02296EfeB11034d561320e8949", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0xBa0E31A0E75AC9a4cac4c57d6c7EF2a10e87D4e6", + "value": "0x4a" + }, + { + "data": "0x", + "from": "0x94b690A97d429F297d32b8fED10213e759861599", + "gas": "0xf42400", + "gasPrice": "0x20", + "nonce": 0, + "to": "0x538A8474EeaB43d5a960164c554A20400151D479", + "value": "0x74402e" + }, + { + "data": "0x5fba026aad22ba6d36391ae06cc12b8887c2f8b66741f5c57853e6480826ad6b4fe3bb038561", + "from": "0xf7c6909762e861F8c904c21cf3Da0D2f4307978D", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x3Bd84e661C47a73eEe4137D185E4c31c194C343f", + "value": "0xa6" + }, + { + "data": "0xb9e0c6c06b57302452e876c996345d34e9ad5434bbeacf59e90fff975f1fe072e7f6f3f33266af1aa0ea535d2741ceafaafa745d5d9653008598379dcd69594e00544ffe6c1509c8ff28dd459e1410e61827cd01dc05bef761bdda", + "from": "0x82361b537D93C7A0079Dba1E4f367EaE7b5D5f2E", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x9E607bB0Bae19b8bC75638fd1aB98594b36ba46d", + "value": "0x1fe4" + }, + { + "data": "0xb88caa18d4de9c90178eecb316248c992f6fc85c57a7970cb37bb1dc781aa8848e011b5a741a61f67e505ee5532d849365395fb740ed631138e9edae986483563d29", + "from": "0xB9A8D444BbCDFb9a6b19f59e0024184fbe10761c", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 0, + "to": "0x22986B2F9A2f5E7119F940898c35e7128A4Ce7E3", + "value": "0xa8ac92" + }, + { + "data": "0x3ef31a11b704ef279b601279a6296bf1039df853abdfc74f36a10522a7af9040a0e907e9fd14cd2e81a5d079e8a723e8aa39956f73387afaa9c1d2eee1ff14", + "from": "0x78011f4E10a54C02296EfeB11034d561320e8949", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x9529cc6891Fbd5aBFABE0AE6c79D30F0CCAe848F", + "value": "0x750d9e" + }, + { + "data": "0xd4559e7fd8a8496695ae9233914fa1fba8ddb2e4eab01d79d9426299a5", + "from": "0x94b690A97d429F297d32b8fED10213e759861599", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xfD6241df8Ce82b2Fb4126dD0e9FA931806Fa573c", + "value": "0x0" + }, + { + "blobVersionedHashes": [ + "0x01b9a0a66963a7a2735327cbb69cec9c07c2644c444a4a75bb58ae87fe70ec6e", + "0x01c0937d94e0a52b9af97df93c6f0d33392f2b3ccdb55c84808a9a29988197d6", + "0x01b736808fd4fc140fa4af910c0265186faad28a8a087730a3e71e5bdacad36d", + "0x013a1bef93a852ea266538894c417e60875c907875d58766051d3677585a651a", + "0x01ea6e6b1e708d9dccabdfa016f94d7f5b18a2bc565b438724634bcc72643927", + "0x0145f4cc59d6d83e1a5ff9d4c4171ef8854be73adbca43f41f1dfe53a1f8afb8" + ], + "data": "0x8c54f5", + "from": "0xf7c6909762e861F8c904c21cf3Da0D2f4307978D", + "gas": "0xf42400", + "maxFeePerBlobGas": "0x100", + "maxFeePerGas": "0x20", + "maxPriorityFeePerGas": "0x1", + "nonce": 1, + "sidecar": { + "blobs": 6, + "commitments": 6, + "proofs": 6 + }, + "to": "0xf3eAc1d1B1EC8cA737bD148b1E96168024fB3F89", + "type": "0x3", + "value": "0x0" + }, + { + "data": "0x3139811779e97d51edcca9f0f79b1b2fcd5bc74a1da9a7c90ac6fc1366ade717b52e58e1b0", + "from": "0x82361b537D93C7A0079Dba1E4f367EaE7b5D5f2E", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0x641602bAD4A323C49629d45338d79A2bb984A3fb", + "value": "0x0" + }, + { + "data": "0x", + "from": "0xB9A8D444BbCDFb9a6b19f59e0024184fbe10761c", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 1, + "to": "0xD74CFe323387aE2fd070CD046173026716D8D649", + "value": "0x92" + }, + { + "data": "0x25257c9ea9a05c62de65f6f1613928d3dd9f1694b0ce543c5cf7a4cdd41a21b33053082b2312eb71122e3c5901c4ad7797bc6a98b067e7268da2de8d02d544", + "from": "0x78011f4E10a54C02296EfeB11034d561320e8949", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x766C0844EBC3c4ef4ddb86260a4D3516cCa03A10", + "value": "0x47" + }, + { + "data": "0x48a095c06665b1190c6653014033badc12021c60193e8eb6e8c8822ec3a5605086f4cee4b39c17abb9b02d1046e5c9e59915bf3968b9529020a499", + "from": "0x94b690A97d429F297d32b8fED10213e759861599", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x1d891f21BB2a55cD9EC7a32478f7c74d757c4876", + "value": "0xf69e" + }, + { + "data": "0xfba48342d570d662f5cc18448171f710e934b7", + "from": "0xf7c6909762e861F8c904c21cf3Da0D2f4307978D", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0x7458F9b8B5ee360A32b0b0Fe648C996C68AE8190", + "value": "0xc920" + }, + { + "data": "0xec004e5112fb80f934d824af5b6ae62f5397ca8c95ab9efb09baa7a67524ba3d4c51f4d774715bd442806ef5dc3ec256c3d61f97ded829c8", + "from": "0x82361b537D93C7A0079Dba1E4f367EaE7b5D5f2E", + "gas": "0xf42400", + "gasPrice": "0x10", + "nonce": 2, + "to": "0xDa78807c1C4567c23EB713E9fbB3b1508C1284ce", + "value": "0x4cc67" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000011", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xc85231701b4522e30f0612a30f5232b35d33a866a963ade8ff2c5e8852871b63", + "s": "0x67cc51220312f0e513ca06ee1923c144e1717f4485ba44ecfd3f5b802cfbbc34", + "v": "0x1" + }, + { + "address": "0x0000000000000000000000000000000000000011", + "chainId": "0x0", + "nonce": "0x0", + "r": "0xd7fd315f0a21617cbad586fe26272506edb4a08088290683c37dd206e53aaa0e", + "s": "0x240d9bc9570a3d1d6a5018dcec493b70620f59f01ec75873f6ecfdd31ae488", + "v": "0x1" + }, + { + "address": "0x000000000000000000000000000000000000000a", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x9f38d3bef386cc1c61793f5a3eb8642a0df6ec0c0099f6fd390b99a35ad63e5b", + "s": "0x7d728242231f8632e0e89861c8053024e3bed6de2e29f47b4e034712b45f3c3d", + "v": "0x0" + }, + { + "address": "0x0000000000000000000000000000000000000005", + "chainId": "0x0", + "nonce": "0x0", + "r": "0x2b6bbd42a3b7c53e20e688b857c21ae5ea552e203fb85d173c15bccbb5c1a0b6", + "s": "0x11fbe9f4188ebc5c59c80cc65f0d555d41ec0148434d1b37fc348f41b87625bc", + "v": "0x0" + } + ], + "data": "0x190b8a4289", + "from": "0x6EB54E66856fD47bd539A986B19F0Bc9B7B4dA9F", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0xe1fAE9b4fAB2F5726677ECfA912d96b0B683e6a9", + "type": "0x4", + "value": "0x0" + }, + { + "data": "0x00", + "from": "0x4133B3E532cC750d0a4691c8Bb0B03fba51707FC", + "gas": "0x30d40", + "maxFeePerGas": "0x1e", + "maxPriorityFeePerGas": "0x1", + "nonce": 0, + "to": "0x0000000000000000000000000000000000000011", + "type": "0x2", + "value": "0x3e8" + }, + { + "authorizationList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "chainId": "0x1", + "nonce": "0x2", + "r": "0x5dacfa13af5badbc0d7892ab80bdfb50697fdcf55eda65d933585fff39a52def", + "s": "0x1dbc77f20853c92d53095f9e2e5280b3e2565a14ea4a24fb2e9706892d04f236", + "v": "0x1" + } + ], + "data": "0x190b8a4289", + "from": "0xe583e10A46B183759EBdA6b6C9F4c5c8Bac3f93B", + "gas": "0xf42400", + "maxFeePerGas": "0x10", + "maxPriorityFeePerGas": "0x10", + "nonce": 0, + "to": "0xe1fAE9b4fAB2F5726677ECfA912d96b0B683e6a9", + "type": "0x4", + "value": "0x0" + } + ], + "version": "2.0" +} \ No newline at end of file From 89d58075abb1e9afcf37a0a57f5d70fd406bfa70 Mon Sep 17 00:00:00 2001 From: Mario Vega Date: Wed, 8 Oct 2025 06:28:44 +0200 Subject: [PATCH 096/102] new(tests): EIP-7610: init-collision tests (#636) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * new(tests): EIP-7610: init-collision tests * fixup * fix(tests): Remove static variants * Review suggestions Co-authored-by: 蔡佳誠 Louis Tsai <72684086+LouisTsai-Csie@users.noreply.github.com> --------- Co-authored-by: 蔡佳誠 Louis Tsai <72684086+LouisTsai-Csie@users.noreply.github.com> --- paris/eip7610_create_collision/__init__.py | 1 + .../test_initcollision.py | 156 ++++++++++++++++ .../InitCollisionNonZeroNonceFiller.json | 161 ----------------- .../InitCollisionParisFiller.json | 169 ------------------ 4 files changed, 157 insertions(+), 330 deletions(-) create mode 100644 paris/eip7610_create_collision/__init__.py create mode 100644 paris/eip7610_create_collision/test_initcollision.py delete mode 100644 static/state_tests/stSStoreTest/InitCollisionNonZeroNonceFiller.json delete mode 100644 static/state_tests/stSStoreTest/InitCollisionParisFiller.json diff --git a/paris/eip7610_create_collision/__init__.py b/paris/eip7610_create_collision/__init__.py new file mode 100644 index 0000000000..6a0e54c5fd --- /dev/null +++ b/paris/eip7610_create_collision/__init__.py @@ -0,0 +1 @@ +"""Cross-client Create Collision Tests.""" diff --git a/paris/eip7610_create_collision/test_initcollision.py b/paris/eip7610_create_collision/test_initcollision.py new file mode 100644 index 0000000000..683bf816b9 --- /dev/null +++ b/paris/eip7610_create_collision/test_initcollision.py @@ -0,0 +1,156 @@ +""" +Test collision in CREATE/CREATE2 account creation, where the existing account +only has a non-zero storage slot set. +""" + +import pytest + +from ethereum_test_tools import ( + Account, + Alloc, + Bytecode, + Initcode, + StateTestFiller, + Transaction, + compute_create_address, +) +from ethereum_test_tools import Opcodes as Op + +REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7610.md" +REFERENCE_SPEC_VERSION = "80ef48d0bbb5a4939ade51caaaac57b5df6acd4e" + +pytestmark = [ + pytest.mark.valid_from("Paris"), + pytest.mark.ported_from( + [ + "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stSStoreTest/InitCollisionFiller.json", + "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stSStoreTest/InitCollisionNonZeroNonceFiller.json", + "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stSStoreTest/InitCollisionParisFiller.json", + ], + pr=["https://github.com/ethereum/execution-spec-tests/pull/636"], + ), + pytest.mark.parametrize( + "collision_nonce,collision_balance,collision_code", + [ + pytest.param(0, 0, b"\0", id="non-empty-code"), + pytest.param(0, 1, b"", id="non-empty-balance"), + pytest.param(1, 0, b"", id="non-empty-nonce"), + ], + ), + pytest.mark.parametrize( + "initcode", + [ + pytest.param( + Initcode( + deploy_code=Op.STOP, + initcode_prefix=Op.SSTORE(0, 1) + Op.SSTORE(1, 0), + ), + id="correct-initcode", + ), + pytest.param(Op.REVERT(0, 0), id="revert-initcode"), + pytest.param(Op.MSTORE(0xFFFFFFFFFFFFFFFFFFFFFFFFFFF, 1), id="oog-initcode"), + ], + ), + pytest.mark.pre_alloc_modify, # We need to modify the pre-alloc to include the collision +] + + +@pytest.mark.with_all_contract_creating_tx_types +def test_init_collision_create_tx( + state_test: StateTestFiller, + pre: Alloc, + tx_type: int, + collision_nonce: int, + collision_balance: int, + collision_code: bytes, + initcode: Bytecode, +): + """ + Test that a contract creation transaction exceptionally aborts when + the target address has a non-empty storage, balance, nonce, or code. + """ + tx = Transaction( + sender=pre.fund_eoa(), + type=tx_type, + to=None, + data=initcode, + gas_limit=200_000, + ) + + created_contract_address = tx.created_contract + + # This is the collision + pre[created_contract_address] = Account( + storage={0x01: 0x01}, + nonce=collision_nonce, + balance=collision_balance, + code=collision_code, + ) + + state_test( + pre=pre, + post={ + created_contract_address: Account( + storage={0x01: 0x01}, + ), + }, + tx=tx, + ) + + +@pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2]) +def test_init_collision_create_opcode( + state_test: StateTestFiller, + pre: Alloc, + opcode: Op, + collision_nonce: int, + collision_balance: int, + collision_code: bytes, + initcode: Bytecode, +): + """ + Test that a contract creation opcode exceptionally aborts when the target + address has a non-empty storage, balance, nonce, or code. + """ + assert len(initcode) <= 32 + contract_creator_code = ( + Op.MSTORE(0, Op.PUSH32(bytes(initcode).ljust(32, b"\0"))) + + Op.SSTORE(0x01, opcode(value=0, offset=0, size=len(initcode))) + + Op.STOP + ) + contract_creator_address = pre.deploy_contract( + contract_creator_code, + storage={0x01: 0x01}, + ) + created_contract_address = compute_create_address( + address=contract_creator_address, + nonce=1, + salt=0, + initcode=initcode, + opcode=opcode, + ) + + tx = Transaction( + sender=pre.fund_eoa(), + to=contract_creator_address, + data=initcode, + gas_limit=2_000_000, + ) + + pre[created_contract_address] = Account( + storage={0x01: 0x01}, + nonce=collision_nonce, + balance=collision_balance, + code=collision_code, + ) + + state_test( + pre=pre, + post={ + created_contract_address: Account( + storage={0x01: 0x01}, + ), + contract_creator_address: Account(storage={0x01: 0x00}), + }, + tx=tx, + ) diff --git a/static/state_tests/stSStoreTest/InitCollisionNonZeroNonceFiller.json b/static/state_tests/stSStoreTest/InitCollisionNonZeroNonceFiller.json deleted file mode 100644 index ea62807efd..0000000000 --- a/static/state_tests/stSStoreTest/InitCollisionNonZeroNonceFiller.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "InitCollisionNonZeroNonce" : { - "_info" : { - "comment" : "account already has storage X. create -> in init code change that account's storage -> 0 -> change it to X again " - }, - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentGasLimit" : "10000000", - "currentNumber" : "1", - "currentTimestamp" : "1000" - }, - "expect" : [ - { - "//comment" : "Collision on transaction create", - "indexes" : { - "data" : [0], - "gas" : 0, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "" : { - "nonce" : "1", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "nonce" : "1", - "storage" : { - "0x01" : "0x01" - } - } - } - }, - { - "//comment" : "Collision on create2", - "indexes" : { - "data" : [1], - "gas" : 0, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "" : { - "nonce" : "1", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "nonce" : "1", - "storage" : { - "0x01" : "0x01" - } - } - } - }, - { - "//comment" : "Collision on create2 and REVERT", - "indexes" : { - "data" : [2], - "gas" : 0, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "" : { - "nonce" : "1", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "nonce" : "1", - "storage" : { - "0x01" : "0x01" - } - } - } - }, - { - "//comment" : "Collision on create2 and OOG", - "indexes" : { - "data" : [3], - "gas" : 0, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "" : { - "nonce" : "1", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "nonce" : "1", - "storage" : { - "0x01" : "0x01" - } - } - } - } - ], - "pre" : - { - "" : { - "balance" : "1000000000000", - "code" : "", - "nonce" : "1", - "storage" : { - } - }, - "" : { - "//comment" : "transaction create account", - "balance" : "", - "code" : "", - "nonce" : "1", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "//comment" : "Create2 account", - "balance" : "", - "code" : "", - "nonce" : "1", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "balance" : "", - "code" : "{ [[1]] 1 [[1]] 0 [[2]] 1 [[2]] 0 [[3]] 1 [[3]] 0 [[4]] 1 [[4]] 0 [[5]] 1 [[5]] 0 [[6]] 1 [[6]] 0 [[7]] 1 [[7]] 0 [[8]] 1 [[8]] 0 [[9]] 1 [[9]] 0 [[10]] 1 [[10]] 0 [[11]] 1 [[11]] 0 [[12]] 1 [[12]] 0 [[13]] 1 [[13]] 0 [[14]] 1 [[14]] 0 [[15]] 1 [[15]] 0 [[16]] 1 [[16]] 0 [[1]] 1 }", - "nonce" : "1", - "storage" : { - } - } - }, - "transaction" : { - "data" : [ - "{ (SSTORE 1 0) (SSTORE 1 1) }", - "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (STOP) ) }", - "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (REVERT 0 0) (STOP) ) }", - "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (CALL 200000 0 0 0 0 0) (STOP) ) }" - ], - "gasLimit" : [ - "200000" - ], - "gasPrice" : "10", - "nonce" : "1", - "secretKey" : "", - "to" : "", - "value" : [ - "0" - ] - } - } -} diff --git a/static/state_tests/stSStoreTest/InitCollisionParisFiller.json b/static/state_tests/stSStoreTest/InitCollisionParisFiller.json deleted file mode 100644 index 77efbc57e0..0000000000 --- a/static/state_tests/stSStoreTest/InitCollisionParisFiller.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "InitCollisionParis" : { - "_info" : { - "comment" : "account already has storage X. create -> in init code change that account's storage -> 0 -> change it to X again " - }, - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x020000", - "currentGasLimit" : "10000000", - "currentNumber" : "1", - "currentTimestamp" : "1000" - }, - "expect" : [ - { - "//comment" : "Collision on transaction create", - "indexes" : { - "data" : [0], - "gas" : 0, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "" : { - "balance" : "10", - "nonce" : "0", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "balance" : "10", - "nonce" : "0", - "storage" : { - "0x01" : "0x01" - } - } - } - }, - { - "//comment" : "Collision on create2", - "indexes" : { - "data" : [1], - "gas" : 0, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "" : { - "balance" : "10", - "nonce" : "0", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "balance" : "10", - "nonce" : "0", - "storage" : { - "0x01" : "0x01" - } - } - } - }, - { - "//comment" : "Collision on create2 and REVERT", - "indexes" : { - "data" : [2], - "gas" : 0, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "" : { - "balance" : "10", - "nonce" : "0", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "balance" : "10", - "nonce" : "0", - "storage" : { - "0x01" : "0x01" - } - } - } - }, - { - "//comment" : "Collision on create2 and OOG", - "indexes" : { - "data" : [3], - "gas" : 0, - "value" : -1 - }, - "network" : [">=Cancun"], - "result" : { - "" : { - "balance" : "10", - "nonce" : "0", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "balance" : "10", - "nonce" : "0", - "storage" : { - "0x01" : "0x01" - } - } - } - } - ], - "pre" : - { - "" : { - "balance" : "1000000000000", - "code" : "", - "nonce" : "0", - "storage" : { - } - }, - "" : { - "//comment" : "transaction create account", - "balance" : "10", - "code" : "", - "nonce" : "", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "//comment" : "Create2 account", - "balance" : "10", - "code" : "", - "nonce" : "", - "storage" : { - "0x01" : "0x01" - } - }, - "" : { - "balance" : "", - "code" : "{ [[1]] 1 [[1]] 0 [[2]] 1 [[2]] 0 [[3]] 1 [[3]] 0 [[4]] 1 [[4]] 0 [[5]] 1 [[5]] 0 [[6]] 1 [[6]] 0 [[7]] 1 [[7]] 0 [[8]] 1 [[8]] 0 [[9]] 1 [[9]] 0 [[10]] 1 [[10]] 0 [[11]] 1 [[11]] 0 [[12]] 1 [[12]] 0 [[13]] 1 [[13]] 0 [[14]] 1 [[14]] 0 [[15]] 1 [[15]] 0 [[16]] 1 [[16]] 0 [[1]] 1 }", - "nonce" : "", - "storage" : { - } - } - }, - "transaction" : { - "data" : [ - "{ (SSTORE 1 0) (SSTORE 1 1) }", - "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (STOP) ) }", - "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (REVERT 0 0) (STOP) ) }", - "{ (seq (CREATE2 0 0 (lll (seq (SSTORE 1 0) (SSTORE 1 1) ) 0) 0) (CALL 200000 0 0 0 0 0) (STOP) ) }" - ], - "gasLimit" : [ - "200000" - ], - "gasPrice" : "10", - "nonce" : "0", - "secretKey" : "", - "to" : "", - "value" : [ - "0" - ] - } - } -} From 5bf06c237f3291d5ed0a016e833963b452a96859 Mon Sep 17 00:00:00 2001 From: spencer Date: Wed, 8 Oct 2025 11:53:29 +0100 Subject: [PATCH 097/102] chore(ci|tests|fill): fixes for release ci when filling with `--generate-all-formats` (#2275) * chore(ci|tests|fill): fixes for releases. * chore: lint 79 line lenght. * chore(execute): when fork is none check. --- prague/eip6110_deposits/test_deposits.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prague/eip6110_deposits/test_deposits.py b/prague/eip6110_deposits/test_deposits.py index edf36f7510..9574ce4157 100644 --- a/prague/eip6110_deposits/test_deposits.py +++ b/prague/eip6110_deposits/test_deposits.py @@ -318,7 +318,7 @@ signature=0x03, index=i, ) - for i in range(500) + for i in range(450) ], tx_gas_limit=16_777_216, ), @@ -490,7 +490,7 @@ index=i, valid=False, ) - for i in range(500) + for i in range(450) ], tx_gas_limit=10_000_000, ), From 3b1a276a6e92cd6441a9ed831cc06f4440f69ccc Mon Sep 17 00:00:00 2001 From: spencer Date: Wed, 8 Oct 2025 11:53:29 +0100 Subject: [PATCH 098/102] chore(ci|tests|fill): fixes for release ci when filling with `--generate-all-formats` (#2275) * chore(ci|tests|fill): fixes for releases. * chore: lint 79 line lenght. * chore(execute): when fork is none check. --- pytest_plugins/execute/pre_alloc.py | 6 ++++++ pytest_plugins/filler/pre_alloc.py | 11 +++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pytest_plugins/execute/pre_alloc.py b/pytest_plugins/execute/pre_alloc.py index 58131e5cbb..e7af7ddc80 100644 --- a/pytest_plugins/execute/pre_alloc.py +++ b/pytest_plugins/execute/pre_alloc.py @@ -548,6 +548,12 @@ def pre( request: pytest.FixtureRequest, ) -> Generator[Alloc, None, None]: """Return default pre allocation for all tests (Empty alloc).""" + # FIXME: Static tests dont have a fork so we need to get it from the node. + actual_fork = fork + if actual_fork is None: + assert hasattr(request.node, "fork") + actual_fork = request.node.fork + # Record the starting balance of the sender sender_test_starting_balance = eth_rpc.get_balance(sender_key) diff --git a/pytest_plugins/filler/pre_alloc.py b/pytest_plugins/filler/pre_alloc.py index 50f9fe40f7..244f28a4b2 100644 --- a/pytest_plugins/filler/pre_alloc.py +++ b/pytest_plugins/filler/pre_alloc.py @@ -434,13 +434,20 @@ def pre( contract_address_iterator: Iterator[Address], eoa_iterator: Iterator[EOA], evm_code_type: EVMCodeType, - fork: Fork, + fork: Fork | None, + request: pytest.FixtureRequest, ) -> Alloc: """Return default pre allocation for all tests (Empty alloc).""" + # FIXME: Static tests dont have a fork so we need to get it from the node. + actual_fork = fork + if actual_fork is None: + assert hasattr(request.node, "fork") + actual_fork = request.node.fork + return Alloc( alloc_mode=alloc_mode, contract_address_iterator=contract_address_iterator, eoa_iterator=eoa_iterator, - fork=fork, + fork=actual_fork, evm_code_type=evm_code_type, ) From ddbed877ce5696de5b95120597fd2d0f29b4ec6a Mon Sep 17 00:00:00 2001 From: Sam Wilson <57262657+SamWilsn@users.noreply.github.com> Date: Wed, 8 Oct 2025 07:16:42 -0400 Subject: [PATCH 099/102] feat(tests): test call for eip2929 (#689) * Test EIP-2929 * feat(eip2929): add aborted call scenario * Update tests/berlin/eip2929_gas_cost_increases/test_call.py --------- Co-authored-by: LouisTsai Co-authored-by: spencer --- .../eip2929_gas_cost_increases/test_call.py | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 berlin/eip2929_gas_cost_increases/test_call.py diff --git a/berlin/eip2929_gas_cost_increases/test_call.py b/berlin/eip2929_gas_cost_increases/test_call.py new file mode 100644 index 0000000000..a285a562a5 --- /dev/null +++ b/berlin/eip2929_gas_cost_increases/test_call.py @@ -0,0 +1,71 @@ +"""Test the CALL opcode after EIP-2929.""" + +import pytest + +from ethereum_test_forks import Fork +from ethereum_test_tools import ( + Account, + Alloc, + CodeGasMeasure, + Environment, + StateTestFiller, + Transaction, +) +from ethereum_test_vm import Opcodes as Op + +REFERENCE_SPEC_GIT_PATH = "EIPS/eip-2929.md" +REFERENCE_SPEC_VERSION = "0e11417265a623adb680c527b15d0cb6701b870b" + + +@pytest.mark.valid_from("Berlin") +def test_call_insufficient_balance( + state_test: StateTestFiller, pre: Alloc, env: Environment, fork: Fork +): + """ + Test a regular CALL to see if it warms the destination with insufficient + balance. + """ + gas_costs = fork.gas_costs() + destination = pre.fund_eoa(1) + contract_address = pre.deploy_contract( + # Perform the aborted external calls + Op.SSTORE( + 0, + Op.CALL( + gas=Op.GAS, + address=destination, + value=1, + args_offset=0, + args_size=0, + ret_offset=0, + ret_size=0, + ), + ) + # Measure the gas cost for BALANCE operation + + CodeGasMeasure( + code=Op.BALANCE(destination), + overhead_cost=gas_costs.G_VERY_LOW, # PUSH20 costs 3 gas + extra_stack_items=1, # BALANCE puts balance on stack + sstore_key=1, + ), + balance=0, + ) + + tx = Transaction( + to=contract_address, + gas_limit=100_000, + sender=pre.fund_eoa(), + ) + + post = { + destination: Account( + balance=1, + ), + contract_address: Account( + storage={ + 0: 0, # The CALL is aborted + 1: gas_costs.G_WARM_ACCOUNT_ACCESS, # Warm access cost + }, + ), + } + state_test(env=env, pre=pre, post=post, tx=tx) From b272eb28511f071abed44936c19db610fe451cef Mon Sep 17 00:00:00 2001 From: spencer Date: Wed, 8 Oct 2025 15:05:16 +0100 Subject: [PATCH 100/102] chore(ci|fill): bump eels for bpo1/2 param changes (#2270) * chore(ci): bump eels for bpo1/2 param changes. * chore: use eels upstream. --- pytest_plugins/eels_resolutions.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytest_plugins/eels_resolutions.json b/pytest_plugins/eels_resolutions.json index f7b1dd9908..13d19d35cb 100644 --- a/pytest_plugins/eels_resolutions.json +++ b/pytest_plugins/eels_resolutions.json @@ -1,8 +1,8 @@ { "EELSMaster": { - "git_url": "https://github.com/marioevz/execution-specs.git", - "branch": "forks/bpo1", - "commit": "3387e5f4aedfe99becfdc39b444d6371e25e0924" + "git_url": "https://github.com/ethereum/execution-specs.git", + "branch": "forks/bpos", + "commit": "7aacb2c54111391af5e98c505d5010b5698a770f" }, "Frontier": { "same_as": "EELSMaster" From 395c88e31448c97c8f406f8708e746a7b6c89c95 Mon Sep 17 00:00:00 2001 From: Sam Wilson Date: Mon, 29 Sep 2025 12:09:04 -0400 Subject: [PATCH 101/102] Move eest to its own package --- .gitignore | 1 + packages/tests/pyproject.toml | 216 ++++ .../tests/src}/cli/__init__.py | 0 .../tests/src}/cli/check_fixtures.py | 0 .../tests/src}/cli/compare_fixtures.py | 0 .../tests/src}/cli/eest/__init__.py | 0 .../tests/src}/cli/eest/cli.py | 0 .../tests/src}/cli/eest/commands/__init__.py | 0 .../tests/src}/cli/eest/commands/clean.py | 0 .../tests/src}/cli/eest/commands/info.py | 0 .../tests/src}/cli/eest/make/__init__.py | 0 .../tests/src}/cli/eest/make/cli.py | 0 .../src}/cli/eest/make/commands/__init__.py | 0 .../tests/src}/cli/eest/make/commands/env.py | 0 .../tests/src}/cli/eest/make/commands/test.py | 0 .../eest/make/templates/blockchain_test.py.j2 | 0 .../cli/eest/make/templates/state_test.py.j2 | 0 .../tests/src}/cli/eest/quotes.py | 0 .../tests/src}/cli/eofwrap.py | 0 .../tests/src}/cli/evm_bytes.py | 0 .../tests/src}/cli/extract_config.py | 0 .../src}/cli/fillerconvert/fillerconvert.py | 0 .../src}/cli/fillerconvert/verify_filled.py | 0 .../tests/src}/cli/gen_index.py | 0 .../src}/cli/generate_checklist_stubs.py | 0 .../tests/src}/cli/gentest/__init__.py | 0 .../tests/src}/cli/gentest/cli.py | 0 .../tests/src}/cli/gentest/request_manager.py | 0 .../src}/cli/gentest/source_code_generator.py | 0 .../blockchain_test/transaction.py.j2 | 0 .../cli/gentest/test_context_providers.py | 0 .../tests/src}/cli/gentest/test_providers.py | 0 .../tests/src}/cli/gentest/tests/__init__.py | 0 .../tests/src}/cli/gentest/tests/test_cli.py | 0 .../tests/src}/cli/hasher.py | 0 .../tests/src}/cli/input/__init__.py | 0 .../tests/src}/cli/input/input_repository.py | 0 .../cli/input/questionary_input_repository.py | 0 .../src}/cli/modify_static_test_gas_limits.py | 0 .../tests/src}/cli/order_fixtures.py | 0 .../src}/cli/pytest_commands/__init__.py | 0 .../tests/src}/cli/pytest_commands/base.py | 0 .../cli/pytest_commands/check_eip_versions.py | 0 .../src}/cli/pytest_commands/checklist.py | 0 .../tests/src}/cli/pytest_commands/consume.py | 0 .../tests/src}/cli/pytest_commands/execute.py | 0 .../tests/src}/cli/pytest_commands/fill.py | 0 .../src}/cli/pytest_commands/processors.py | 0 .../pytest-check-eip-versions.ini | 0 .../pytest_ini_files/pytest-consume.ini | 0 .../pytest-execute-eth-config.ini | 0 .../pytest_ini_files/pytest-execute-hive.ini | 0 .../pytest-execute-recover.ini | 0 .../pytest_ini_files/pytest-execute.ini | 0 .../pytest_ini_files/pytest-fill.ini | 0 .../src}/cli/show_pre_alloc_group_stats.py | 0 .../tests/src}/cli/tests/__init__.py | 0 .../tests/src}/cli/tests/test_eofwrap.py | 0 .../tests/src}/cli/tests/test_evm_bytes.py | 0 .../cli/tests/test_generate_all_formats.py | 0 .../src}/cli/tests/test_order_fixtures.py | 0 .../cli/tests/test_pytest_execute_command.py | 0 .../cli/tests/test_pytest_fill_command.py | 0 .../tests/src}/cli/tox_helpers.py | 0 .../tests/src}/config/__init__.py | 0 .../tests/src}/config/app.py | 0 .../tests/src}/config/check_eip_versions.py | 0 .../tests/src}/config/docs.py | 0 .../tests/src}/config/env.py | 0 .../tests/src}/config/templates/env.yaml.j2 | 0 .../tests/src}/conftest.py | 0 .../tests/src}/ethereum_clis/__init__.py | 0 .../tests/src}/ethereum_clis/clis/__init__.py | 0 .../tests/src}/ethereum_clis/clis/besu.py | 0 .../tests/src}/ethereum_clis/clis/erigon.py | 0 .../src}/ethereum_clis/clis/ethereumjs.py | 0 .../tests/src}/ethereum_clis/clis/ethrex.py | 0 .../tests/src}/ethereum_clis/clis/evmone.py | 0 .../ethereum_clis/clis/execution_specs.py | 0 .../tests/src}/ethereum_clis/clis/geth.py | 0 .../src}/ethereum_clis/clis/nethermind.py | 0 .../tests/src}/ethereum_clis/clis/nimbus.py | 0 .../tests/src}/ethereum_clis/clis/reth.py | 0 .../tests/src}/ethereum_clis/ethereum_cli.py | 0 .../tests/src}/ethereum_clis/file_utils.py | 0 .../ethereum_clis/fixture_consumer_tool.py | 0 .../tests/src}/ethereum_clis/py.typed | 0 .../ethereum_clis/tests/fixtures/1/alloc.json | 0 .../ethereum_clis/tests/fixtures/1/env.json | 0 .../ethereum_clis/tests/fixtures/1/exp.json | 0 .../ethereum_clis/tests/fixtures/1/txs.json | 0 .../ethereum_clis/tests/fixtures/3/alloc.json | 0 .../ethereum_clis/tests/fixtures/3/env.json | 0 .../ethereum_clis/tests/fixtures/3/exp.json | 0 .../ethereum_clis/tests/fixtures/3/readme.md | 0 .../ethereum_clis/tests/fixtures/3/txs.json | 0 .../tests/test_execution_specs.py | 0 .../tests/test_transition_tool.py | 0 .../tests/test_transition_tools_support.py | 0 .../src}/ethereum_clis/transition_tool.py | 0 .../tests/src}/ethereum_clis/types.py | 0 .../src}/ethereum_test_base_types/__init__.py | 0 .../ethereum_test_base_types/base_types.py | 0 .../composite_types.py | 0 .../ethereum_test_base_types/constants.py | 0 .../ethereum_test_base_types/conversions.py | 0 .../src}/ethereum_test_base_types/json.py | 0 .../src}/ethereum_test_base_types/mixins.py | 0 .../src}/ethereum_test_base_types/py.typed | 0 .../src}/ethereum_test_base_types/pydantic.py | 0 .../reference_spec/__init__.py | 0 .../reference_spec/git_reference_spec.py | 0 .../reference_spec/reference_spec.py | 0 .../ethereum_test_base_types/serialization.py | 0 .../tests/__init__.py | 0 .../tests/test_base_types.py | 0 .../tests/test_reference_spec.py | 0 .../src}/ethereum_test_checklists/__init__.py | 0 .../ethereum_test_checklists/eip_checklist.py | 0 .../eip_checklist.pyi | 0 .../tests/__init__.py | 0 .../test_checklist_template_consistency.py | 0 .../src}/ethereum_test_exceptions/__init__.py | 0 .../ethereum_test_exceptions/engine_api.py | 0 .../exception_mapper.py | 0 .../ethereum_test_exceptions/exceptions.py | 0 .../exceptions/__init__.py | 0 .../exceptions/base.py | 0 .../exceptions/block.py | 0 .../exceptions/eof.py | 0 .../exceptions/transaction.py | 0 .../exceptions/types.py | 0 .../src}/ethereum_test_exceptions/py.typed | 0 .../tests/__init__.py | 0 .../tests/test_exceptions.py | 0 .../src}/ethereum_test_execution/__init__.py | 0 .../src}/ethereum_test_execution/base.py | 0 .../blob_transaction.py | 0 .../transaction_post.py | 0 .../src}/ethereum_test_fixtures/__init__.py | 0 .../tests/src}/ethereum_test_fixtures/base.py | 0 .../src}/ethereum_test_fixtures/blockchain.py | 0 .../src}/ethereum_test_fixtures/collector.py | 0 .../src}/ethereum_test_fixtures/common.py | 0 .../src}/ethereum_test_fixtures/consume.py | 0 .../tests/src}/ethereum_test_fixtures/eof.py | 0 .../tests/src}/ethereum_test_fixtures/file.py | 0 .../pre_alloc_groups.py | 0 .../src}/ethereum_test_fixtures/py.typed | 0 .../src}/ethereum_test_fixtures/state.py | 0 .../ethereum_test_fixtures/tests/__init__.py | 0 .../ethereum_test_fixtures/tests/test_base.py | 0 .../tests/test_blockchain.py | 0 .../ethereum_test_fixtures/tests/test_eof.py | 0 .../tests/test_state.py | 0 .../ethereum_test_fixtures/transaction.py | 0 .../src}/ethereum_test_forks/__init__.py | 0 .../ethereum_test_forks/base_decorators.py | 0 .../src}/ethereum_test_forks/base_fork.py | 0 .../ethereum_test_forks/forks/__init__.py | 0 .../forks/contracts/consolidation_request.bin | Bin .../forks/contracts/deposit_contract.bin | Bin .../forks/contracts/history_contract.bin | Bin .../forks/contracts/withdrawal_request.bin | Bin .../src}/ethereum_test_forks/forks/forks.py | 0 .../src}/ethereum_test_forks/forks/helpers.py | 0 .../ethereum_test_forks/forks/transition.py | 0 .../src}/ethereum_test_forks/gas_costs.py | 0 .../tests/src}/ethereum_test_forks/helpers.py | 0 .../tests/src}/ethereum_test_forks/py.typed | 0 .../ethereum_test_forks/tests/__init__.py | 0 .../tests/test_fork_range_descriptor.py | 0 .../ethereum_test_forks/tests/test_forks.py | 0 .../transition_base_fork.py | 0 .../tests/src}/ethereum_test_rpc/__init__.py | 0 .../tests/src}/ethereum_test_rpc/rpc.py | 0 .../src}/ethereum_test_rpc/tests/__init__.py | 0 .../ethereum_test_rpc/tests/test_types.py | 0 .../tests/src}/ethereum_test_rpc/types.py | 0 .../src}/ethereum_test_specs/__init__.py | 0 .../tests/src}/ethereum_test_specs/base.py | 0 .../src}/ethereum_test_specs/base_static.py | 0 .../tests/src}/ethereum_test_specs/blobs.py | 0 .../src}/ethereum_test_specs/blockchain.py | 0 .../src}/ethereum_test_specs/debugging.py | 0 .../tests/src}/ethereum_test_specs/eof.py | 0 .../tests/src}/ethereum_test_specs/helpers.py | 0 .../tests/src}/ethereum_test_specs/py.typed | 0 .../tests/src}/ethereum_test_specs/state.py | 0 .../static_state/__init__.py | 0 .../static_state/account.py | 0 .../static_state/common/__init__.py | 0 .../static_state/common/common.py | 0 .../static_state/common/compile_yul.py | 0 .../static_state/common/tags.py | 0 .../static_state/environment.py | 0 .../static_state/expect_section.py | 0 .../static_state/general_transaction.py | 0 .../static_state/state_static.py | 0 .../ethereum_test_specs/tests/__init__.py | 0 .../blockchain_london_invalid_filled.json | 0 .../blockchain_london_valid_filled.json | 0 ...kchain_shanghai_invalid_filled_engine.json | 0 ...ockchain_shanghai_valid_filled_engine.json | 0 ...ncun_blockchain_test_engine_tx_type_0.json | 0 ...inid_cancun_blockchain_test_tx_type_0.json | 0 .../chainid_cancun_state_test_tx_type_0.json | 0 .../chainid_cancun_state_test_tx_type_1.json | 0 ...id_istanbul_blockchain_test_tx_type_0.json | 0 ...inid_london_blockchain_test_tx_type_0.json | 0 ...aris_blockchain_test_engine_tx_type_0.json | 0 .../chainid_paris_state_test_tx_type_0.json | 0 ...ghai_blockchain_test_engine_tx_type_0.json | 0 ...chainid_shanghai_state_test_tx_type_0.json | 0 .../fixtures/tx_simple_type_0_shanghai.json | 0 .../src}/ethereum_test_specs/tests/helpers.py | 0 .../ethereum_test_specs/tests/test_expect.py | 0 .../tests/test_fixtures.py | 0 .../tests/test_transaction.py | 0 .../ethereum_test_specs/tests/test_types.py | 0 .../src}/ethereum_test_specs/transaction.py | 0 .../src}/ethereum_test_tools/__init__.py | 0 .../src}/ethereum_test_tools/code/__init__.py | 0 .../ethereum_test_tools/code/generators.py | 0 .../src}/ethereum_test_tools/code/yul.py | 0 .../tests/src}/ethereum_test_tools/py.typed | 0 .../ethereum_test_tools/tests/__init__.py | 0 .../ethereum_test_tools/tests/test_code.py | 0 ...kchain_shanghai_invalid_filled_engine.json | 0 .../ethereum_test_tools/utility/__init__.py | 0 .../ethereum_test_tools/utility/generators.py | 0 .../ethereum_test_tools/utility/pytest.py | 0 .../utility/tests/test_pytest.py | 0 .../ethereum_test_tools/utility/versioning.py | 0 .../src}/ethereum_test_tools/vm/__init__.py | 0 .../src}/ethereum_test_tools/vm/opcode.py | 0 .../src}/ethereum_test_types/__init__.py | 0 .../src}/ethereum_test_types/account_types.py | 0 .../src}/ethereum_test_types/blob_types.py | 0 .../block_access_list/__init__.py | 0 .../block_access_list/modifiers.py | 0 .../src}/ethereum_test_types/block_types.py | 0 .../ethereum_test_types/chain_config_types.py | 0 .../src}/ethereum_test_types/eof/__init__.py | 0 .../src}/ethereum_test_types/eof/constants.py | 0 .../ethereum_test_types/eof/v1/__init__.py | 0 .../ethereum_test_types/eof/v1/constants.py | 0 .../tests/src}/ethereum_test_types/helpers.py | 0 .../ethereum_test_types/kzg_trusted_setup.txt | 0 .../tests/src}/ethereum_test_types/py.typed | 0 .../src}/ethereum_test_types/receipt_types.py | 0 .../src}/ethereum_test_types/request_types.py | 0 .../ethereum_test_types/tests/__init__.py | 0 .../tests/test_blob_types.py | 0 .../tests/test_block_access_lists.py | 0 .../ethereum_test_types/tests/test_eof_v1.py | 0 .../ethereum_test_types/tests/test_helpers.py | 0 .../tests/test_post_alloc.py | 0 .../tests/test_transactions.py | 0 .../ethereum_test_types/tests/test_types.py | 0 .../ethereum_test_types/transaction_types.py | 0 .../tests/src}/ethereum_test_types/trie.py | 0 .../tests/src}/ethereum_test_types/utils.py | 0 .../tests/src}/ethereum_test_vm/__init__.py | 0 .../tests/src}/ethereum_test_vm/bytecode.py | 0 .../tests/src}/ethereum_test_vm/evm_types.py | 0 .../tests/src}/ethereum_test_vm/helpers.py | 0 .../tests/src}/ethereum_test_vm/opcode.py | 0 .../tests/src}/ethereum_test_vm/py.typed | 0 .../src}/ethereum_test_vm/tests/__init__.py | 0 .../src}/ethereum_test_vm/tests/test_vm.py | 0 .../tests/src}/pytest_plugins/__init__.py | 0 .../tests/src}/pytest_plugins/concurrency.py | 0 .../src}/pytest_plugins/consume/__init__.py | 0 .../src}/pytest_plugins/consume/consume.py | 0 .../pytest_plugins/consume/direct/__init__.py | 0 .../pytest_plugins/consume/direct/conftest.py | 0 .../consume/direct/test_via_direct.py | 0 .../consume/hive_engine_test/__init__.py | 0 .../consume/hive_simulators_reorg/__init__.py | 0 .../src}/pytest_plugins/consume/releases.py | 0 .../consume/simulators/__init__.py | 0 .../pytest_plugins/consume/simulators/base.py | 0 .../consume/simulators/engine/__init__.py | 0 .../consume/simulators/engine/conftest.py | 0 .../consume/simulators/exceptions.py | 0 .../consume/simulators/helpers/__init__.py | 0 .../consume/simulators/helpers/exceptions.py | 0 .../consume/simulators/helpers/ruleset.py | 0 .../consume/simulators/helpers/timing.py | 0 .../consume/simulators/rlp/__init__.py | 0 .../consume/simulators/rlp/conftest.py | 0 .../simulators/simulator_logic/__init__.py | 0 .../simulator_logic/test_via_engine.py | 0 .../simulator_logic/test_via_rlp.py | 0 .../simulator_logic/test_via_sync.py | 0 .../consume/simulators/single_test_client.py | 0 .../consume/simulators/sync/__init__.py | 0 .../consume/simulators/sync/conftest.py | 0 .../simulators/test_case_description.py | 0 .../consume/simulators/timing_data.py | 0 .../pytest_plugins/consume/tests/__init__.py | 0 .../consume/tests/release_information.json | 0 .../consume/tests/test_consume_args.py | 0 .../tests/test_fixtures_source_input_types.py | 0 .../consume/tests/test_releases.py | 0 .../src}/pytest_plugins/execute/__init__.py | 0 .../execute/eth_config/__init__.py | 0 .../execute/eth_config/eth_config.py | 0 .../execute/eth_config/execute_eth_config.py | 0 .../execute/eth_config/networks.yml | 0 .../execute/eth_config/tests/__init__.py | 0 .../eth_config/tests/genesis_example.json | 0 .../tests/test_execute_eth_config.py | 0 .../execute/eth_config/tests/test_genesis.py | 0 .../execute/eth_config/types.py | 0 .../src}/pytest_plugins/execute/execute.py | 0 .../pytest_plugins/execute/execute_recover.py | 0 .../src}/pytest_plugins/execute/pre_alloc.py | 0 .../src}/pytest_plugins/execute/recover.py | 0 .../pytest_plugins/execute/rpc/__init__.py | 0 .../execute/rpc/chain_builder_eth_rpc.py | 0 .../src}/pytest_plugins/execute/rpc/hive.py | 0 .../src}/pytest_plugins/execute/rpc/remote.py | 0 .../execute/rpc/remote_seed_sender.py | 0 .../src}/pytest_plugins/execute/sender.py | 0 .../pytest_plugins/execute/tests/__init__.py | 0 .../execute/tests/test_pre_alloc.py | 0 .../src}/pytest_plugins/filler/__init__.py | 0 .../pytest_plugins/filler/eip_checklist.py | 0 .../src}/pytest_plugins/filler/filler.py | 0 .../pytest_plugins/filler/fixture_output.py | 0 .../filler/gen_test_doc/__init__.py | 0 .../filler/gen_test_doc/gen_test_doc.py | 0 .../filler/gen_test_doc/page_props.py | 0 .../pytest_plugins/filler/ported_tests.py | 0 .../src}/pytest_plugins/filler/pre_alloc.py | 0 .../pytest_plugins/filler/static_filler.py | 0 .../pytest_plugins/filler/tests/__init__.py | 0 .../filler/tests/test_benchmarking.py | 0 .../filler/tests/test_collect_only.py | 0 .../filler/tests/test_eip_checklist.py | 0 .../filler/tests/test_filler.py | 0 .../filler/tests/test_filling_session.py | 0 .../filler/tests/test_format_selector.py | 0 .../filler/tests/test_generate_all_formats.py | 0 .../filler/tests/test_output_directory.py | 0 .../filler/tests/test_phase_manager.py | 0 .../filler/tests/test_pre_alloc.py | 0 .../filler/tests/test_prealloc_group.py | 0 .../test_prealloc_group_usage_example.py | 0 .../tests/test_slow_marker_pre_alloc.py | 0 .../filler/tests/test_verify_sync_marker.py | 0 .../src}/pytest_plugins/filler/witness.py | 0 .../pytest_plugins/fix_package_test_path.py | 0 .../src}/pytest_plugins/forks/__init__.py | 0 .../tests/src}/pytest_plugins/forks/forks.py | 0 .../pytest_plugins/forks/tests/__init__.py | 0 .../tests/test_bad_command_line_options.py | 0 .../forks/tests/test_bad_validity_markers.py | 0 .../forks/tests/test_covariant_markers.py | 0 .../tests/test_fork_parametrizer_types.py | 0 .../pytest_plugins/forks/tests/test_forks.py | 0 .../forks/tests/test_markers.py | 0 .../src}/pytest_plugins/help/__init__.py | 0 .../tests/src}/pytest_plugins/help/help.py | 0 .../pytest_plugins/help/tests/test_help.py | 0 .../src}/pytest_plugins/logging/__init__.py | 0 .../src}/pytest_plugins/logging/logging.py | 0 .../pytest_plugins/logging/tests/__init__.py | 0 .../logging/tests/test_logging.py | 0 .../tests/src}/pytest_plugins/py.typed | 0 .../pytest_plugins/pytest_hive/hive_info.py | 0 .../pytest_plugins/pytest_hive/pytest_hive.py | 0 .../pytest_plugins/shared/benchmarking.py | 0 .../pytest_plugins/shared/execute_fill.py | 0 .../src}/pytest_plugins/shared/helpers.py | 0 .../shared/transaction_fixtures.py | 0 .../src}/pytest_plugins/solc/__init__.py | 0 .../tests/src}/pytest_plugins/solc/solc.py | 0 .../spec_version_checker/__init__.py | 0 .../spec_version_checker.py | 0 pyproject.toml | 150 +-- src/ethereum/__init__.py | 2 +- tox.ini | 8 +- uv.lock | 969 ++++++++++++++++-- 386 files changed, 1100 insertions(+), 246 deletions(-) create mode 100644 packages/tests/pyproject.toml rename {src/ethereum_spec_tests => packages/tests/src}/cli/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/check_fixtures.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/compare_fixtures.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/cli.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/commands/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/commands/clean.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/commands/info.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/make/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/make/cli.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/make/commands/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/make/commands/env.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/make/commands/test.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/make/templates/blockchain_test.py.j2 (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/make/templates/state_test.py.j2 (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eest/quotes.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/eofwrap.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/evm_bytes.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/extract_config.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/fillerconvert/fillerconvert.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/fillerconvert/verify_filled.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/gen_index.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/generate_checklist_stubs.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/gentest/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/gentest/cli.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/gentest/request_manager.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/gentest/source_code_generator.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/gentest/templates/blockchain_test/transaction.py.j2 (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/gentest/test_context_providers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/gentest/test_providers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/gentest/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/gentest/tests/test_cli.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/hasher.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/input/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/input/input_repository.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/input/questionary_input_repository.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/modify_static_test_gas_limits.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/order_fixtures.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/base.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/check_eip_versions.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/checklist.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/consume.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/execute.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/fill.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/processors.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/pytest_ini_files/pytest-check-eip-versions.ini (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/pytest_ini_files/pytest-consume.ini (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/pytest_ini_files/pytest-execute-hive.ini (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/pytest_ini_files/pytest-execute-recover.ini (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/pytest_ini_files/pytest-execute.ini (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/pytest_commands/pytest_ini_files/pytest-fill.ini (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/show_pre_alloc_group_stats.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/tests/test_eofwrap.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/tests/test_evm_bytes.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/tests/test_generate_all_formats.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/tests/test_order_fixtures.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/tests/test_pytest_execute_command.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/tests/test_pytest_fill_command.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/cli/tox_helpers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/config/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/config/app.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/config/check_eip_versions.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/config/docs.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/config/env.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/config/templates/env.yaml.j2 (100%) rename {src/ethereum_spec_tests => packages/tests/src}/conftest.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/besu.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/erigon.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/ethereumjs.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/ethrex.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/evmone.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/execution_specs.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/geth.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/nethermind.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/nimbus.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/clis/reth.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/ethereum_cli.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/file_utils.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/fixture_consumer_tool.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/py.typed (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/fixtures/1/alloc.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/fixtures/1/env.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/fixtures/1/exp.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/fixtures/1/txs.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/fixtures/3/alloc.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/fixtures/3/env.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/fixtures/3/exp.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/fixtures/3/readme.md (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/fixtures/3/txs.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/test_execution_specs.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/test_transition_tool.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/tests/test_transition_tools_support.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/transition_tool.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_clis/types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/base_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/composite_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/constants.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/conversions.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/json.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/mixins.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/py.typed (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/pydantic.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/reference_spec/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/reference_spec/git_reference_spec.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/reference_spec/reference_spec.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/serialization.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/tests/test_base_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_base_types/tests/test_reference_spec.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_checklists/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_checklists/eip_checklist.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_checklists/eip_checklist.pyi (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_checklists/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_checklists/tests/test_checklist_template_consistency.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/engine_api.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/exception_mapper.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/exceptions.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/exceptions/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/exceptions/base.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/exceptions/block.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/exceptions/eof.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/exceptions/transaction.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/exceptions/types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/py.typed (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_exceptions/tests/test_exceptions.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_execution/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_execution/base.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_execution/blob_transaction.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_execution/transaction_post.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/base.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/blockchain.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/collector.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/common.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/consume.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/eof.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/file.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/pre_alloc_groups.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/py.typed (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/state.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/tests/test_base.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/tests/test_blockchain.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/tests/test_eof.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/tests/test_state.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_fixtures/transaction.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/base_decorators.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/base_fork.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/forks/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/forks/contracts/consolidation_request.bin (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/forks/contracts/deposit_contract.bin (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/forks/contracts/history_contract.bin (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/forks/contracts/withdrawal_request.bin (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/forks/forks.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/forks/helpers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/forks/transition.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/gas_costs.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/helpers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/py.typed (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/tests/test_fork_range_descriptor.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/tests/test_forks.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_forks/transition_base_fork.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_rpc/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_rpc/rpc.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_rpc/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_rpc/tests/test_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_rpc/types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/base.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/base_static.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/blobs.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/blockchain.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/debugging.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/eof.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/helpers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/py.typed (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/state.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/static_state/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/static_state/account.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/static_state/common/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/static_state/common/common.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/static_state/common/compile_yul.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/static_state/common/tags.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/static_state/environment.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/static_state/expect_section.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/static_state/general_transaction.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/static_state/state_static.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine_tx_type_0.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_tx_type_0.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_0.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_1.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test_tx_type_0.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test_tx_type_0.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine_tx_type_0.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/chainid_paris_state_test_tx_type_0.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine_tx_type_0.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test_tx_type_0.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/fixtures/tx_simple_type_0_shanghai.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/helpers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/test_expect.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/test_fixtures.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/test_transaction.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/tests/test_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_specs/transaction.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/code/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/code/generators.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/code/yul.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/py.typed (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/tests/test_code.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_engine.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/utility/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/utility/generators.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/utility/pytest.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/utility/tests/test_pytest.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/utility/versioning.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/vm/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_tools/vm/opcode.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/account_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/blob_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/block_access_list/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/block_access_list/modifiers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/block_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/chain_config_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/eof/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/eof/constants.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/eof/v1/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/eof/v1/constants.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/helpers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/kzg_trusted_setup.txt (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/py.typed (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/receipt_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/request_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/tests/test_blob_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/tests/test_block_access_lists.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/tests/test_eof_v1.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/tests/test_helpers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/tests/test_post_alloc.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/tests/test_transactions.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/tests/test_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/transaction_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/trie.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_types/utils.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_vm/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_vm/bytecode.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_vm/evm_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_vm/helpers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_vm/opcode.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_vm/py.typed (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_vm/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/ethereum_test_vm/tests/test_vm.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/concurrency.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/consume.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/direct/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/direct/conftest.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/direct/test_via_direct.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/hive_engine_test/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/hive_simulators_reorg/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/releases.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/base.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/engine/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/engine/conftest.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/exceptions.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/helpers/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/helpers/exceptions.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/helpers/ruleset.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/helpers/timing.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/rlp/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/rlp/conftest.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/simulator_logic/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/single_test_client.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/sync/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/sync/conftest.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/test_case_description.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/simulators/timing_data.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/tests/release_information.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/tests/test_consume_args.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/tests/test_fixtures_source_input_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/consume/tests/test_releases.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/eth_config/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/eth_config/eth_config.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/eth_config/execute_eth_config.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/eth_config/networks.yml (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/eth_config/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/eth_config/tests/genesis_example.json (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/eth_config/tests/test_genesis.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/eth_config/types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/execute.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/execute_recover.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/pre_alloc.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/recover.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/rpc/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/rpc/hive.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/rpc/remote.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/rpc/remote_seed_sender.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/sender.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/execute/tests/test_pre_alloc.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/eip_checklist.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/filler.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/fixture_output.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/gen_test_doc/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/gen_test_doc/gen_test_doc.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/gen_test_doc/page_props.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/ported_tests.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/pre_alloc.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/static_filler.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_benchmarking.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_collect_only.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_eip_checklist.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_filler.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_filling_session.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_format_selector.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_generate_all_formats.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_output_directory.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_phase_manager.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_pre_alloc.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_prealloc_group.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/tests/test_verify_sync_marker.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/filler/witness.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/fix_package_test_path.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/forks/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/forks/forks.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/forks/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/forks/tests/test_bad_command_line_options.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/forks/tests/test_bad_validity_markers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/forks/tests/test_covariant_markers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/forks/tests/test_fork_parametrizer_types.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/forks/tests/test_forks.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/forks/tests/test_markers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/help/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/help/help.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/help/tests/test_help.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/logging/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/logging/logging.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/logging/tests/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/logging/tests/test_logging.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/py.typed (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/pytest_hive/hive_info.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/pytest_hive/pytest_hive.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/shared/benchmarking.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/shared/execute_fill.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/shared/helpers.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/shared/transaction_fixtures.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/solc/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/solc/solc.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/spec_version_checker/__init__.py (100%) rename {src/ethereum_spec_tests => packages/tests/src}/pytest_plugins/spec_version_checker/spec_version_checker.py (100%) diff --git a/.gitignore b/.gitignore index fd08eaf32b..68ffdb4860 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ __pycache__ __pycache__/ *.py[cod] *$py.class +.mypy_cache/ # C extensions *.so diff --git a/packages/tests/pyproject.toml b/packages/tests/pyproject.toml new file mode 100644 index 0000000000..2779e50270 --- /dev/null +++ b/packages/tests/pyproject.toml @@ -0,0 +1,216 @@ +[build-system] +requires = [ + "setuptools==78.0.2", + "wheel==0.45.1", +] # the setuptools version here should match that of setuptools below in docs in optional-dependencies +build-backend = "setuptools.build_meta" + +[project] +name = "ethereum-execution-tests" +version = "1.0.0" +description = "Ethereum execution client test authoring framework" +readme = "README.md" +requires-python = ">=3.11" +license = "MIT" +license-files = [ "LICENSE" ] +keywords = ["ethereum", "testing", "blockchain"] +classifiers = [ + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] +dependencies = [ + "click>=8.1.0,<9", + "ethereum-hive>=0.1.0a1,<1.0.0", + "ethereum-execution", + "gitpython>=3.1.31,<4", + "PyJWT>=2.3.0,<3", + "requests>=2.31.0,<3", + "requests_unixsocket2>=0.4.0", + "colorlog>=6.7.0,<7", + "pytest>=8,<9", + "pytest-custom-report>=1.0.1,<2", + "pytest-html>=4.1.0,<5", + "pytest-metadata>=3,<4", + "pytest-xdist>=3.3.1,<4", + "coincurve>=20.0.0,<21", + "trie>=3.1.0,<4", + "semver>=3.0.1,<4", + "pydantic>=2.11.0,<3", + "rich>=13.7.0,<14", + "filelock>=3.15.1,<4", + "ethereum-types>=0.2.1,<0.3", + "pyyaml>=6.0.2,<7", + "types-pyyaml>=6.0.12.20240917,<7", + "pytest-json-report>=1.5.0,<2", + "typing-extensions>=4.12.2,<5", + "questionary>=2.1.0,<3", + "ethereum-rlp>=0.1.3,<0.2", + "pytest-regex>=0.2.0,<0.3", + "eth-abi>=5.2.0", + "joblib>=1.4.2", + "ckzg>=2.1.3,<3", + "tenacity>=9.0.0,<10", +] + +[project.urls] +Homepage = "https://github.com/ethereum/execution-specs" +Documentation = "https://eest.ethereum.org" +Repository = "https://github.com/ethereum/execution-specs" +Issues = "https://github.com/ethereum/execution-specs/issues" +Changelog = "https://eest.ethereum.org/main/CHANGELOG/" + +[project.optional-dependencies] +test = ["pytest-cov>=4.1.0,<5"] +lint = [ + "ruff==0.13.2", + "mypy==1.17.0", + "types-requests>=2.31,<2.33", +] +docs = [ + "cairosvg>=2.7.0,<3", + "codespell>=2.4.1,<3", + "markdown==3.8", + "mike>=1.1.2,<2", + "mkdocs>=1.4.3,<2", + "mkdocs-click>=0.8,<1", + "mkdocs-gen-files>=0.5.0,<1", + "mkdocs-git-authors-plugin>=0.7.1,<1", + "mkdocs-glightbox>=0.3.4,<1", + "mkdocs-literate-nav>=0.6.0,<1", + "mkdocs-material>=9.1.14,<10", + "mkdocs-material-extensions>=1.1.1,<2", + "mkdocstrings>=0.21.2,<1", + "mkdocstrings-python>=1.0.0,<2", + "pillow>=10.0.1,<11", + "pyspelling>=2.8.2,<3", + "lxml>=6.0.0,<7", # needs to be >= 6.0 for pypy + "setuptools==78.0.2", +] + +[project.scripts] +fill = "cli.pytest_commands.fill:fill" +phil = "cli.pytest_commands.fill:phil" +execute = "cli.pytest_commands.execute:execute" +attac = "cli.pytest_commands.execute:execute" +checkfixtures = "cli.check_fixtures:check_fixtures" +check_eip_versions = "cli.pytest_commands.check_eip_versions:check_eip_versions" +consume = "cli.pytest_commands.consume:consume" +protec = "cli.pytest_commands.consume:consume" +checklist = "cli.pytest_commands.checklist:checklist" +generate_checklist_stubs = "cli.generate_checklist_stubs:generate_checklist_stubs" +genindex = "cli.gen_index:generate_fixtures_index_cli" +gentest = "cli.gentest:generate" +eofwrap = "cli.eofwrap:eof_wrap" +pyspelling_soft_fail = "cli.tox_helpers:pyspelling" +markdownlintcli2_soft_fail = "cli.tox_helpers:markdownlint" +order_fixtures = "cli.order_fixtures:order_fixtures" +evm_bytes = "cli.evm_bytes:evm_bytes" +hasher = "cli.hasher:main" +eest = "cli.eest.cli:eest" +fillerconvert = "cli.fillerconvert.fillerconvert:main" +groupstats = "cli.show_pre_alloc_group_stats:main" +extract_config = "cli.extract_config:extract_config" +compare_fixtures = "cli.compare_fixtures:main" +modify_static_test_gas_limits = "cli.modify_static_test_gas_limits:main" + +[tool.setuptools.packages.find] +where = ["src"] +exclude = ["*tests*"] + +[tool.pyright] +exclude = ["tests/static/**"] + +[tool.setuptools.package-data] +ethereum_test_forks = ["forks/contracts/*.bin"] +"pytest_plugins.execute" = ["eth_config/networks.yml"] +"pytest_plugins" = ["eels_resolutions.json"] +"cli.eest.make" = ["templates/*.j2"] +"cli.pytest_commands" = ["pytest_ini_files/*.ini"] +"ethereum_test_types" = ["kzg_trusted_setup.txt"] + +[tool.ruff] +line-length = 99 + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "F", # Pyflakes + "B", # flake8-bugbear + "W", # pycodestyle warnings + "I", # isort + "A", # flake8-builtins + "N", # pep8-naming + "D", # pydocstyle + "C4", # flake8-comprehensions + "ARG", # flake8-unused-arguments +] +fixable = [ + "E", # pycodestyle errors + "F", # Pyflakes + "B", # flake8-bugbear + "W", # pycodestyle warnings + "I", # isort + "D", # pydocstyle +] +ignore = [ + "C401", # Unnecessary generator set + "C408", # Unnecessary collection call + "D107", # Missing docstring in __init__ + "D200", # One-line docstring should fit on one line with quotes + "D203", # 1 blank line required before class docstring + "D205", # Missing blank line after summary + "D212", # Multi-line docstring summary should start at the first line + "D401", # First line should be in imperative mood ("Do", not "Does") + # TODO: ethereum/execution-spec-tests#2176 + "ARG002", # unused-method-argument + "ARG003", # unused-class-method-argument + "ARG005", # unused-lambda-argument +] + +[tool.ruff.lint.per-file-ignores] +"tests/*" = ["ARG001"] # TODO: ethereum/execution-spec-tests#2188 + +[tool.mypy] +disable_error_code = ["import-untyped"] +mypy_path = ["src", "$MYPY_CONFIG_FILE_DIR/stubs"] +files = ["src", "tests"] +exclude = [ + '^\.cache/', + '^\.git/', + '^\.pytest_cache/', + '^\.ruff_cache/', + '^\.tox/', + '^\.venv/', + '^\.vscode/', + '^fixtures/', + '^logs/', + '^site/', +] +plugins = ["pydantic.mypy"] + +[tool.codespell] +skip = ".venv,__pycache__,.git,build,dist,*.pyc,*.lock" +check-filenames = true +ignore-words-list = "ingenuous" + +[tool.pytest.ini_options] +console_output_style = "count" +minversion = "7.0" +python_files = [ + "test_*.py" +] +testpaths = [ + "src" +] +addopts = [ + "-p", "pytester", + "--ignore=src/pytest_plugins/consume/test_cache.py", + "--ignore=src/pytest_plugins/consume/direct/", + "--ignore=src/pytest_plugins/consume/simulators/", +] + +[tool.uv] +required-version = ">=0.7.0" + +[tool.uv.sources] +ethereum-execution = { workspace = true } diff --git a/src/ethereum_spec_tests/cli/__init__.py b/packages/tests/src/cli/__init__.py similarity index 100% rename from src/ethereum_spec_tests/cli/__init__.py rename to packages/tests/src/cli/__init__.py diff --git a/src/ethereum_spec_tests/cli/check_fixtures.py b/packages/tests/src/cli/check_fixtures.py similarity index 100% rename from src/ethereum_spec_tests/cli/check_fixtures.py rename to packages/tests/src/cli/check_fixtures.py diff --git a/src/ethereum_spec_tests/cli/compare_fixtures.py b/packages/tests/src/cli/compare_fixtures.py similarity index 100% rename from src/ethereum_spec_tests/cli/compare_fixtures.py rename to packages/tests/src/cli/compare_fixtures.py diff --git a/src/ethereum_spec_tests/cli/eest/__init__.py b/packages/tests/src/cli/eest/__init__.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/__init__.py rename to packages/tests/src/cli/eest/__init__.py diff --git a/src/ethereum_spec_tests/cli/eest/cli.py b/packages/tests/src/cli/eest/cli.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/cli.py rename to packages/tests/src/cli/eest/cli.py diff --git a/src/ethereum_spec_tests/cli/eest/commands/__init__.py b/packages/tests/src/cli/eest/commands/__init__.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/commands/__init__.py rename to packages/tests/src/cli/eest/commands/__init__.py diff --git a/src/ethereum_spec_tests/cli/eest/commands/clean.py b/packages/tests/src/cli/eest/commands/clean.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/commands/clean.py rename to packages/tests/src/cli/eest/commands/clean.py diff --git a/src/ethereum_spec_tests/cli/eest/commands/info.py b/packages/tests/src/cli/eest/commands/info.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/commands/info.py rename to packages/tests/src/cli/eest/commands/info.py diff --git a/src/ethereum_spec_tests/cli/eest/make/__init__.py b/packages/tests/src/cli/eest/make/__init__.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/make/__init__.py rename to packages/tests/src/cli/eest/make/__init__.py diff --git a/src/ethereum_spec_tests/cli/eest/make/cli.py b/packages/tests/src/cli/eest/make/cli.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/make/cli.py rename to packages/tests/src/cli/eest/make/cli.py diff --git a/src/ethereum_spec_tests/cli/eest/make/commands/__init__.py b/packages/tests/src/cli/eest/make/commands/__init__.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/make/commands/__init__.py rename to packages/tests/src/cli/eest/make/commands/__init__.py diff --git a/src/ethereum_spec_tests/cli/eest/make/commands/env.py b/packages/tests/src/cli/eest/make/commands/env.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/make/commands/env.py rename to packages/tests/src/cli/eest/make/commands/env.py diff --git a/src/ethereum_spec_tests/cli/eest/make/commands/test.py b/packages/tests/src/cli/eest/make/commands/test.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/make/commands/test.py rename to packages/tests/src/cli/eest/make/commands/test.py diff --git a/src/ethereum_spec_tests/cli/eest/make/templates/blockchain_test.py.j2 b/packages/tests/src/cli/eest/make/templates/blockchain_test.py.j2 similarity index 100% rename from src/ethereum_spec_tests/cli/eest/make/templates/blockchain_test.py.j2 rename to packages/tests/src/cli/eest/make/templates/blockchain_test.py.j2 diff --git a/src/ethereum_spec_tests/cli/eest/make/templates/state_test.py.j2 b/packages/tests/src/cli/eest/make/templates/state_test.py.j2 similarity index 100% rename from src/ethereum_spec_tests/cli/eest/make/templates/state_test.py.j2 rename to packages/tests/src/cli/eest/make/templates/state_test.py.j2 diff --git a/src/ethereum_spec_tests/cli/eest/quotes.py b/packages/tests/src/cli/eest/quotes.py similarity index 100% rename from src/ethereum_spec_tests/cli/eest/quotes.py rename to packages/tests/src/cli/eest/quotes.py diff --git a/src/ethereum_spec_tests/cli/eofwrap.py b/packages/tests/src/cli/eofwrap.py similarity index 100% rename from src/ethereum_spec_tests/cli/eofwrap.py rename to packages/tests/src/cli/eofwrap.py diff --git a/src/ethereum_spec_tests/cli/evm_bytes.py b/packages/tests/src/cli/evm_bytes.py similarity index 100% rename from src/ethereum_spec_tests/cli/evm_bytes.py rename to packages/tests/src/cli/evm_bytes.py diff --git a/src/ethereum_spec_tests/cli/extract_config.py b/packages/tests/src/cli/extract_config.py similarity index 100% rename from src/ethereum_spec_tests/cli/extract_config.py rename to packages/tests/src/cli/extract_config.py diff --git a/src/ethereum_spec_tests/cli/fillerconvert/fillerconvert.py b/packages/tests/src/cli/fillerconvert/fillerconvert.py similarity index 100% rename from src/ethereum_spec_tests/cli/fillerconvert/fillerconvert.py rename to packages/tests/src/cli/fillerconvert/fillerconvert.py diff --git a/src/ethereum_spec_tests/cli/fillerconvert/verify_filled.py b/packages/tests/src/cli/fillerconvert/verify_filled.py similarity index 100% rename from src/ethereum_spec_tests/cli/fillerconvert/verify_filled.py rename to packages/tests/src/cli/fillerconvert/verify_filled.py diff --git a/src/ethereum_spec_tests/cli/gen_index.py b/packages/tests/src/cli/gen_index.py similarity index 100% rename from src/ethereum_spec_tests/cli/gen_index.py rename to packages/tests/src/cli/gen_index.py diff --git a/src/ethereum_spec_tests/cli/generate_checklist_stubs.py b/packages/tests/src/cli/generate_checklist_stubs.py similarity index 100% rename from src/ethereum_spec_tests/cli/generate_checklist_stubs.py rename to packages/tests/src/cli/generate_checklist_stubs.py diff --git a/src/ethereum_spec_tests/cli/gentest/__init__.py b/packages/tests/src/cli/gentest/__init__.py similarity index 100% rename from src/ethereum_spec_tests/cli/gentest/__init__.py rename to packages/tests/src/cli/gentest/__init__.py diff --git a/src/ethereum_spec_tests/cli/gentest/cli.py b/packages/tests/src/cli/gentest/cli.py similarity index 100% rename from src/ethereum_spec_tests/cli/gentest/cli.py rename to packages/tests/src/cli/gentest/cli.py diff --git a/src/ethereum_spec_tests/cli/gentest/request_manager.py b/packages/tests/src/cli/gentest/request_manager.py similarity index 100% rename from src/ethereum_spec_tests/cli/gentest/request_manager.py rename to packages/tests/src/cli/gentest/request_manager.py diff --git a/src/ethereum_spec_tests/cli/gentest/source_code_generator.py b/packages/tests/src/cli/gentest/source_code_generator.py similarity index 100% rename from src/ethereum_spec_tests/cli/gentest/source_code_generator.py rename to packages/tests/src/cli/gentest/source_code_generator.py diff --git a/src/ethereum_spec_tests/cli/gentest/templates/blockchain_test/transaction.py.j2 b/packages/tests/src/cli/gentest/templates/blockchain_test/transaction.py.j2 similarity index 100% rename from src/ethereum_spec_tests/cli/gentest/templates/blockchain_test/transaction.py.j2 rename to packages/tests/src/cli/gentest/templates/blockchain_test/transaction.py.j2 diff --git a/src/ethereum_spec_tests/cli/gentest/test_context_providers.py b/packages/tests/src/cli/gentest/test_context_providers.py similarity index 100% rename from src/ethereum_spec_tests/cli/gentest/test_context_providers.py rename to packages/tests/src/cli/gentest/test_context_providers.py diff --git a/src/ethereum_spec_tests/cli/gentest/test_providers.py b/packages/tests/src/cli/gentest/test_providers.py similarity index 100% rename from src/ethereum_spec_tests/cli/gentest/test_providers.py rename to packages/tests/src/cli/gentest/test_providers.py diff --git a/src/ethereum_spec_tests/cli/gentest/tests/__init__.py b/packages/tests/src/cli/gentest/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/cli/gentest/tests/__init__.py rename to packages/tests/src/cli/gentest/tests/__init__.py diff --git a/src/ethereum_spec_tests/cli/gentest/tests/test_cli.py b/packages/tests/src/cli/gentest/tests/test_cli.py similarity index 100% rename from src/ethereum_spec_tests/cli/gentest/tests/test_cli.py rename to packages/tests/src/cli/gentest/tests/test_cli.py diff --git a/src/ethereum_spec_tests/cli/hasher.py b/packages/tests/src/cli/hasher.py similarity index 100% rename from src/ethereum_spec_tests/cli/hasher.py rename to packages/tests/src/cli/hasher.py diff --git a/src/ethereum_spec_tests/cli/input/__init__.py b/packages/tests/src/cli/input/__init__.py similarity index 100% rename from src/ethereum_spec_tests/cli/input/__init__.py rename to packages/tests/src/cli/input/__init__.py diff --git a/src/ethereum_spec_tests/cli/input/input_repository.py b/packages/tests/src/cli/input/input_repository.py similarity index 100% rename from src/ethereum_spec_tests/cli/input/input_repository.py rename to packages/tests/src/cli/input/input_repository.py diff --git a/src/ethereum_spec_tests/cli/input/questionary_input_repository.py b/packages/tests/src/cli/input/questionary_input_repository.py similarity index 100% rename from src/ethereum_spec_tests/cli/input/questionary_input_repository.py rename to packages/tests/src/cli/input/questionary_input_repository.py diff --git a/src/ethereum_spec_tests/cli/modify_static_test_gas_limits.py b/packages/tests/src/cli/modify_static_test_gas_limits.py similarity index 100% rename from src/ethereum_spec_tests/cli/modify_static_test_gas_limits.py rename to packages/tests/src/cli/modify_static_test_gas_limits.py diff --git a/src/ethereum_spec_tests/cli/order_fixtures.py b/packages/tests/src/cli/order_fixtures.py similarity index 100% rename from src/ethereum_spec_tests/cli/order_fixtures.py rename to packages/tests/src/cli/order_fixtures.py diff --git a/src/ethereum_spec_tests/cli/pytest_commands/__init__.py b/packages/tests/src/cli/pytest_commands/__init__.py similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/__init__.py rename to packages/tests/src/cli/pytest_commands/__init__.py diff --git a/src/ethereum_spec_tests/cli/pytest_commands/base.py b/packages/tests/src/cli/pytest_commands/base.py similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/base.py rename to packages/tests/src/cli/pytest_commands/base.py diff --git a/src/ethereum_spec_tests/cli/pytest_commands/check_eip_versions.py b/packages/tests/src/cli/pytest_commands/check_eip_versions.py similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/check_eip_versions.py rename to packages/tests/src/cli/pytest_commands/check_eip_versions.py diff --git a/src/ethereum_spec_tests/cli/pytest_commands/checklist.py b/packages/tests/src/cli/pytest_commands/checklist.py similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/checklist.py rename to packages/tests/src/cli/pytest_commands/checklist.py diff --git a/src/ethereum_spec_tests/cli/pytest_commands/consume.py b/packages/tests/src/cli/pytest_commands/consume.py similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/consume.py rename to packages/tests/src/cli/pytest_commands/consume.py diff --git a/src/ethereum_spec_tests/cli/pytest_commands/execute.py b/packages/tests/src/cli/pytest_commands/execute.py similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/execute.py rename to packages/tests/src/cli/pytest_commands/execute.py diff --git a/src/ethereum_spec_tests/cli/pytest_commands/fill.py b/packages/tests/src/cli/pytest_commands/fill.py similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/fill.py rename to packages/tests/src/cli/pytest_commands/fill.py diff --git a/src/ethereum_spec_tests/cli/pytest_commands/processors.py b/packages/tests/src/cli/pytest_commands/processors.py similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/processors.py rename to packages/tests/src/cli/pytest_commands/processors.py diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-check-eip-versions.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-check-eip-versions.ini similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-check-eip-versions.ini rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-check-eip-versions.ini diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-consume.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-consume.ini similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-consume.ini rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-consume.ini diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-eth-config.ini diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-hive.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-hive.ini similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-hive.ini rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-hive.ini diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-recover.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-recover.ini similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute-recover.ini rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute-recover.ini diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute.ini similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-execute.ini rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-execute.ini diff --git a/src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-fill.ini b/packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini similarity index 100% rename from src/ethereum_spec_tests/cli/pytest_commands/pytest_ini_files/pytest-fill.ini rename to packages/tests/src/cli/pytest_commands/pytest_ini_files/pytest-fill.ini diff --git a/src/ethereum_spec_tests/cli/show_pre_alloc_group_stats.py b/packages/tests/src/cli/show_pre_alloc_group_stats.py similarity index 100% rename from src/ethereum_spec_tests/cli/show_pre_alloc_group_stats.py rename to packages/tests/src/cli/show_pre_alloc_group_stats.py diff --git a/src/ethereum_spec_tests/cli/tests/__init__.py b/packages/tests/src/cli/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/cli/tests/__init__.py rename to packages/tests/src/cli/tests/__init__.py diff --git a/src/ethereum_spec_tests/cli/tests/test_eofwrap.py b/packages/tests/src/cli/tests/test_eofwrap.py similarity index 100% rename from src/ethereum_spec_tests/cli/tests/test_eofwrap.py rename to packages/tests/src/cli/tests/test_eofwrap.py diff --git a/src/ethereum_spec_tests/cli/tests/test_evm_bytes.py b/packages/tests/src/cli/tests/test_evm_bytes.py similarity index 100% rename from src/ethereum_spec_tests/cli/tests/test_evm_bytes.py rename to packages/tests/src/cli/tests/test_evm_bytes.py diff --git a/src/ethereum_spec_tests/cli/tests/test_generate_all_formats.py b/packages/tests/src/cli/tests/test_generate_all_formats.py similarity index 100% rename from src/ethereum_spec_tests/cli/tests/test_generate_all_formats.py rename to packages/tests/src/cli/tests/test_generate_all_formats.py diff --git a/src/ethereum_spec_tests/cli/tests/test_order_fixtures.py b/packages/tests/src/cli/tests/test_order_fixtures.py similarity index 100% rename from src/ethereum_spec_tests/cli/tests/test_order_fixtures.py rename to packages/tests/src/cli/tests/test_order_fixtures.py diff --git a/src/ethereum_spec_tests/cli/tests/test_pytest_execute_command.py b/packages/tests/src/cli/tests/test_pytest_execute_command.py similarity index 100% rename from src/ethereum_spec_tests/cli/tests/test_pytest_execute_command.py rename to packages/tests/src/cli/tests/test_pytest_execute_command.py diff --git a/src/ethereum_spec_tests/cli/tests/test_pytest_fill_command.py b/packages/tests/src/cli/tests/test_pytest_fill_command.py similarity index 100% rename from src/ethereum_spec_tests/cli/tests/test_pytest_fill_command.py rename to packages/tests/src/cli/tests/test_pytest_fill_command.py diff --git a/src/ethereum_spec_tests/cli/tox_helpers.py b/packages/tests/src/cli/tox_helpers.py similarity index 100% rename from src/ethereum_spec_tests/cli/tox_helpers.py rename to packages/tests/src/cli/tox_helpers.py diff --git a/src/ethereum_spec_tests/config/__init__.py b/packages/tests/src/config/__init__.py similarity index 100% rename from src/ethereum_spec_tests/config/__init__.py rename to packages/tests/src/config/__init__.py diff --git a/src/ethereum_spec_tests/config/app.py b/packages/tests/src/config/app.py similarity index 100% rename from src/ethereum_spec_tests/config/app.py rename to packages/tests/src/config/app.py diff --git a/src/ethereum_spec_tests/config/check_eip_versions.py b/packages/tests/src/config/check_eip_versions.py similarity index 100% rename from src/ethereum_spec_tests/config/check_eip_versions.py rename to packages/tests/src/config/check_eip_versions.py diff --git a/src/ethereum_spec_tests/config/docs.py b/packages/tests/src/config/docs.py similarity index 100% rename from src/ethereum_spec_tests/config/docs.py rename to packages/tests/src/config/docs.py diff --git a/src/ethereum_spec_tests/config/env.py b/packages/tests/src/config/env.py similarity index 100% rename from src/ethereum_spec_tests/config/env.py rename to packages/tests/src/config/env.py diff --git a/src/ethereum_spec_tests/config/templates/env.yaml.j2 b/packages/tests/src/config/templates/env.yaml.j2 similarity index 100% rename from src/ethereum_spec_tests/config/templates/env.yaml.j2 rename to packages/tests/src/config/templates/env.yaml.j2 diff --git a/src/ethereum_spec_tests/conftest.py b/packages/tests/src/conftest.py similarity index 100% rename from src/ethereum_spec_tests/conftest.py rename to packages/tests/src/conftest.py diff --git a/src/ethereum_spec_tests/ethereum_clis/__init__.py b/packages/tests/src/ethereum_clis/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/__init__.py rename to packages/tests/src/ethereum_clis/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/__init__.py b/packages/tests/src/ethereum_clis/clis/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/__init__.py rename to packages/tests/src/ethereum_clis/clis/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/besu.py b/packages/tests/src/ethereum_clis/clis/besu.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/besu.py rename to packages/tests/src/ethereum_clis/clis/besu.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/erigon.py b/packages/tests/src/ethereum_clis/clis/erigon.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/erigon.py rename to packages/tests/src/ethereum_clis/clis/erigon.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/ethereumjs.py b/packages/tests/src/ethereum_clis/clis/ethereumjs.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/ethereumjs.py rename to packages/tests/src/ethereum_clis/clis/ethereumjs.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/ethrex.py b/packages/tests/src/ethereum_clis/clis/ethrex.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/ethrex.py rename to packages/tests/src/ethereum_clis/clis/ethrex.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/evmone.py b/packages/tests/src/ethereum_clis/clis/evmone.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/evmone.py rename to packages/tests/src/ethereum_clis/clis/evmone.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/execution_specs.py b/packages/tests/src/ethereum_clis/clis/execution_specs.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/execution_specs.py rename to packages/tests/src/ethereum_clis/clis/execution_specs.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/geth.py b/packages/tests/src/ethereum_clis/clis/geth.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/geth.py rename to packages/tests/src/ethereum_clis/clis/geth.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/nethermind.py b/packages/tests/src/ethereum_clis/clis/nethermind.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/nethermind.py rename to packages/tests/src/ethereum_clis/clis/nethermind.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/nimbus.py b/packages/tests/src/ethereum_clis/clis/nimbus.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/nimbus.py rename to packages/tests/src/ethereum_clis/clis/nimbus.py diff --git a/src/ethereum_spec_tests/ethereum_clis/clis/reth.py b/packages/tests/src/ethereum_clis/clis/reth.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/clis/reth.py rename to packages/tests/src/ethereum_clis/clis/reth.py diff --git a/src/ethereum_spec_tests/ethereum_clis/ethereum_cli.py b/packages/tests/src/ethereum_clis/ethereum_cli.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/ethereum_cli.py rename to packages/tests/src/ethereum_clis/ethereum_cli.py diff --git a/src/ethereum_spec_tests/ethereum_clis/file_utils.py b/packages/tests/src/ethereum_clis/file_utils.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/file_utils.py rename to packages/tests/src/ethereum_clis/file_utils.py diff --git a/src/ethereum_spec_tests/ethereum_clis/fixture_consumer_tool.py b/packages/tests/src/ethereum_clis/fixture_consumer_tool.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/fixture_consumer_tool.py rename to packages/tests/src/ethereum_clis/fixture_consumer_tool.py diff --git a/src/ethereum_spec_tests/ethereum_clis/py.typed b/packages/tests/src/ethereum_clis/py.typed similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/py.typed rename to packages/tests/src/ethereum_clis/py.typed diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/alloc.json b/packages/tests/src/ethereum_clis/tests/fixtures/1/alloc.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/alloc.json rename to packages/tests/src/ethereum_clis/tests/fixtures/1/alloc.json diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/env.json b/packages/tests/src/ethereum_clis/tests/fixtures/1/env.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/env.json rename to packages/tests/src/ethereum_clis/tests/fixtures/1/env.json diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/exp.json b/packages/tests/src/ethereum_clis/tests/fixtures/1/exp.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/exp.json rename to packages/tests/src/ethereum_clis/tests/fixtures/1/exp.json diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/txs.json b/packages/tests/src/ethereum_clis/tests/fixtures/1/txs.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/1/txs.json rename to packages/tests/src/ethereum_clis/tests/fixtures/1/txs.json diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/alloc.json b/packages/tests/src/ethereum_clis/tests/fixtures/3/alloc.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/alloc.json rename to packages/tests/src/ethereum_clis/tests/fixtures/3/alloc.json diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/env.json b/packages/tests/src/ethereum_clis/tests/fixtures/3/env.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/env.json rename to packages/tests/src/ethereum_clis/tests/fixtures/3/env.json diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/exp.json b/packages/tests/src/ethereum_clis/tests/fixtures/3/exp.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/exp.json rename to packages/tests/src/ethereum_clis/tests/fixtures/3/exp.json diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/readme.md b/packages/tests/src/ethereum_clis/tests/fixtures/3/readme.md similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/readme.md rename to packages/tests/src/ethereum_clis/tests/fixtures/3/readme.md diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/txs.json b/packages/tests/src/ethereum_clis/tests/fixtures/3/txs.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/fixtures/3/txs.json rename to packages/tests/src/ethereum_clis/tests/fixtures/3/txs.json diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/test_execution_specs.py b/packages/tests/src/ethereum_clis/tests/test_execution_specs.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/test_execution_specs.py rename to packages/tests/src/ethereum_clis/tests/test_execution_specs.py diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/test_transition_tool.py b/packages/tests/src/ethereum_clis/tests/test_transition_tool.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/test_transition_tool.py rename to packages/tests/src/ethereum_clis/tests/test_transition_tool.py diff --git a/src/ethereum_spec_tests/ethereum_clis/tests/test_transition_tools_support.py b/packages/tests/src/ethereum_clis/tests/test_transition_tools_support.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/tests/test_transition_tools_support.py rename to packages/tests/src/ethereum_clis/tests/test_transition_tools_support.py diff --git a/src/ethereum_spec_tests/ethereum_clis/transition_tool.py b/packages/tests/src/ethereum_clis/transition_tool.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/transition_tool.py rename to packages/tests/src/ethereum_clis/transition_tool.py diff --git a/src/ethereum_spec_tests/ethereum_clis/types.py b/packages/tests/src/ethereum_clis/types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_clis/types.py rename to packages/tests/src/ethereum_clis/types.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/__init__.py b/packages/tests/src/ethereum_test_base_types/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/__init__.py rename to packages/tests/src/ethereum_test_base_types/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/base_types.py b/packages/tests/src/ethereum_test_base_types/base_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/base_types.py rename to packages/tests/src/ethereum_test_base_types/base_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/composite_types.py b/packages/tests/src/ethereum_test_base_types/composite_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/composite_types.py rename to packages/tests/src/ethereum_test_base_types/composite_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/constants.py b/packages/tests/src/ethereum_test_base_types/constants.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/constants.py rename to packages/tests/src/ethereum_test_base_types/constants.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/conversions.py b/packages/tests/src/ethereum_test_base_types/conversions.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/conversions.py rename to packages/tests/src/ethereum_test_base_types/conversions.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/json.py b/packages/tests/src/ethereum_test_base_types/json.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/json.py rename to packages/tests/src/ethereum_test_base_types/json.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/mixins.py b/packages/tests/src/ethereum_test_base_types/mixins.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/mixins.py rename to packages/tests/src/ethereum_test_base_types/mixins.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/py.typed b/packages/tests/src/ethereum_test_base_types/py.typed similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/py.typed rename to packages/tests/src/ethereum_test_base_types/py.typed diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/pydantic.py b/packages/tests/src/ethereum_test_base_types/pydantic.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/pydantic.py rename to packages/tests/src/ethereum_test_base_types/pydantic.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/__init__.py b/packages/tests/src/ethereum_test_base_types/reference_spec/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/__init__.py rename to packages/tests/src/ethereum_test_base_types/reference_spec/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/git_reference_spec.py b/packages/tests/src/ethereum_test_base_types/reference_spec/git_reference_spec.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/git_reference_spec.py rename to packages/tests/src/ethereum_test_base_types/reference_spec/git_reference_spec.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/reference_spec.py b/packages/tests/src/ethereum_test_base_types/reference_spec/reference_spec.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/reference_spec/reference_spec.py rename to packages/tests/src/ethereum_test_base_types/reference_spec/reference_spec.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/serialization.py b/packages/tests/src/ethereum_test_base_types/serialization.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/serialization.py rename to packages/tests/src/ethereum_test_base_types/serialization.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/tests/__init__.py b/packages/tests/src/ethereum_test_base_types/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/tests/__init__.py rename to packages/tests/src/ethereum_test_base_types/tests/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/tests/test_base_types.py b/packages/tests/src/ethereum_test_base_types/tests/test_base_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/tests/test_base_types.py rename to packages/tests/src/ethereum_test_base_types/tests/test_base_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_base_types/tests/test_reference_spec.py b/packages/tests/src/ethereum_test_base_types/tests/test_reference_spec.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_base_types/tests/test_reference_spec.py rename to packages/tests/src/ethereum_test_base_types/tests/test_reference_spec.py diff --git a/src/ethereum_spec_tests/ethereum_test_checklists/__init__.py b/packages/tests/src/ethereum_test_checklists/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_checklists/__init__.py rename to packages/tests/src/ethereum_test_checklists/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_checklists/eip_checklist.py b/packages/tests/src/ethereum_test_checklists/eip_checklist.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_checklists/eip_checklist.py rename to packages/tests/src/ethereum_test_checklists/eip_checklist.py diff --git a/src/ethereum_spec_tests/ethereum_test_checklists/eip_checklist.pyi b/packages/tests/src/ethereum_test_checklists/eip_checklist.pyi similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_checklists/eip_checklist.pyi rename to packages/tests/src/ethereum_test_checklists/eip_checklist.pyi diff --git a/src/ethereum_spec_tests/ethereum_test_checklists/tests/__init__.py b/packages/tests/src/ethereum_test_checklists/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_checklists/tests/__init__.py rename to packages/tests/src/ethereum_test_checklists/tests/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_checklists/tests/test_checklist_template_consistency.py b/packages/tests/src/ethereum_test_checklists/tests/test_checklist_template_consistency.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_checklists/tests/test_checklist_template_consistency.py rename to packages/tests/src/ethereum_test_checklists/tests/test_checklist_template_consistency.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/__init__.py b/packages/tests/src/ethereum_test_exceptions/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/__init__.py rename to packages/tests/src/ethereum_test_exceptions/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/engine_api.py b/packages/tests/src/ethereum_test_exceptions/engine_api.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/engine_api.py rename to packages/tests/src/ethereum_test_exceptions/engine_api.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exception_mapper.py b/packages/tests/src/ethereum_test_exceptions/exception_mapper.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/exception_mapper.py rename to packages/tests/src/ethereum_test_exceptions/exception_mapper.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions.py b/packages/tests/src/ethereum_test_exceptions/exceptions.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions.py rename to packages/tests/src/ethereum_test_exceptions/exceptions.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/__init__.py b/packages/tests/src/ethereum_test_exceptions/exceptions/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/__init__.py rename to packages/tests/src/ethereum_test_exceptions/exceptions/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/base.py b/packages/tests/src/ethereum_test_exceptions/exceptions/base.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/base.py rename to packages/tests/src/ethereum_test_exceptions/exceptions/base.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/block.py b/packages/tests/src/ethereum_test_exceptions/exceptions/block.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/block.py rename to packages/tests/src/ethereum_test_exceptions/exceptions/block.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/eof.py b/packages/tests/src/ethereum_test_exceptions/exceptions/eof.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/eof.py rename to packages/tests/src/ethereum_test_exceptions/exceptions/eof.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/transaction.py b/packages/tests/src/ethereum_test_exceptions/exceptions/transaction.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/transaction.py rename to packages/tests/src/ethereum_test_exceptions/exceptions/transaction.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/types.py b/packages/tests/src/ethereum_test_exceptions/exceptions/types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/exceptions/types.py rename to packages/tests/src/ethereum_test_exceptions/exceptions/types.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/py.typed b/packages/tests/src/ethereum_test_exceptions/py.typed similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/py.typed rename to packages/tests/src/ethereum_test_exceptions/py.typed diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/tests/__init__.py b/packages/tests/src/ethereum_test_exceptions/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/tests/__init__.py rename to packages/tests/src/ethereum_test_exceptions/tests/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_exceptions/tests/test_exceptions.py b/packages/tests/src/ethereum_test_exceptions/tests/test_exceptions.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_exceptions/tests/test_exceptions.py rename to packages/tests/src/ethereum_test_exceptions/tests/test_exceptions.py diff --git a/src/ethereum_spec_tests/ethereum_test_execution/__init__.py b/packages/tests/src/ethereum_test_execution/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_execution/__init__.py rename to packages/tests/src/ethereum_test_execution/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_execution/base.py b/packages/tests/src/ethereum_test_execution/base.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_execution/base.py rename to packages/tests/src/ethereum_test_execution/base.py diff --git a/src/ethereum_spec_tests/ethereum_test_execution/blob_transaction.py b/packages/tests/src/ethereum_test_execution/blob_transaction.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_execution/blob_transaction.py rename to packages/tests/src/ethereum_test_execution/blob_transaction.py diff --git a/src/ethereum_spec_tests/ethereum_test_execution/transaction_post.py b/packages/tests/src/ethereum_test_execution/transaction_post.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_execution/transaction_post.py rename to packages/tests/src/ethereum_test_execution/transaction_post.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/__init__.py b/packages/tests/src/ethereum_test_fixtures/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/__init__.py rename to packages/tests/src/ethereum_test_fixtures/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/base.py b/packages/tests/src/ethereum_test_fixtures/base.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/base.py rename to packages/tests/src/ethereum_test_fixtures/base.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/blockchain.py b/packages/tests/src/ethereum_test_fixtures/blockchain.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/blockchain.py rename to packages/tests/src/ethereum_test_fixtures/blockchain.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/collector.py b/packages/tests/src/ethereum_test_fixtures/collector.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/collector.py rename to packages/tests/src/ethereum_test_fixtures/collector.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/common.py b/packages/tests/src/ethereum_test_fixtures/common.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/common.py rename to packages/tests/src/ethereum_test_fixtures/common.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/consume.py b/packages/tests/src/ethereum_test_fixtures/consume.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/consume.py rename to packages/tests/src/ethereum_test_fixtures/consume.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/eof.py b/packages/tests/src/ethereum_test_fixtures/eof.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/eof.py rename to packages/tests/src/ethereum_test_fixtures/eof.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/file.py b/packages/tests/src/ethereum_test_fixtures/file.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/file.py rename to packages/tests/src/ethereum_test_fixtures/file.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/pre_alloc_groups.py b/packages/tests/src/ethereum_test_fixtures/pre_alloc_groups.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/pre_alloc_groups.py rename to packages/tests/src/ethereum_test_fixtures/pre_alloc_groups.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/py.typed b/packages/tests/src/ethereum_test_fixtures/py.typed similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/py.typed rename to packages/tests/src/ethereum_test_fixtures/py.typed diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/state.py b/packages/tests/src/ethereum_test_fixtures/state.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/state.py rename to packages/tests/src/ethereum_test_fixtures/state.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/__init__.py b/packages/tests/src/ethereum_test_fixtures/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/tests/__init__.py rename to packages/tests/src/ethereum_test_fixtures/tests/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_base.py b/packages/tests/src/ethereum_test_fixtures/tests/test_base.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_base.py rename to packages/tests/src/ethereum_test_fixtures/tests/test_base.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_blockchain.py b/packages/tests/src/ethereum_test_fixtures/tests/test_blockchain.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_blockchain.py rename to packages/tests/src/ethereum_test_fixtures/tests/test_blockchain.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_eof.py b/packages/tests/src/ethereum_test_fixtures/tests/test_eof.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_eof.py rename to packages/tests/src/ethereum_test_fixtures/tests/test_eof.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_state.py b/packages/tests/src/ethereum_test_fixtures/tests/test_state.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/tests/test_state.py rename to packages/tests/src/ethereum_test_fixtures/tests/test_state.py diff --git a/src/ethereum_spec_tests/ethereum_test_fixtures/transaction.py b/packages/tests/src/ethereum_test_fixtures/transaction.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_fixtures/transaction.py rename to packages/tests/src/ethereum_test_fixtures/transaction.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/__init__.py b/packages/tests/src/ethereum_test_forks/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/__init__.py rename to packages/tests/src/ethereum_test_forks/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/base_decorators.py b/packages/tests/src/ethereum_test_forks/base_decorators.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/base_decorators.py rename to packages/tests/src/ethereum_test_forks/base_decorators.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/base_fork.py b/packages/tests/src/ethereum_test_forks/base_fork.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/base_fork.py rename to packages/tests/src/ethereum_test_forks/base_fork.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/__init__.py b/packages/tests/src/ethereum_test_forks/forks/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/forks/__init__.py rename to packages/tests/src/ethereum_test_forks/forks/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/consolidation_request.bin b/packages/tests/src/ethereum_test_forks/forks/contracts/consolidation_request.bin similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/consolidation_request.bin rename to packages/tests/src/ethereum_test_forks/forks/contracts/consolidation_request.bin diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/deposit_contract.bin b/packages/tests/src/ethereum_test_forks/forks/contracts/deposit_contract.bin similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/deposit_contract.bin rename to packages/tests/src/ethereum_test_forks/forks/contracts/deposit_contract.bin diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/history_contract.bin b/packages/tests/src/ethereum_test_forks/forks/contracts/history_contract.bin similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/history_contract.bin rename to packages/tests/src/ethereum_test_forks/forks/contracts/history_contract.bin diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/withdrawal_request.bin b/packages/tests/src/ethereum_test_forks/forks/contracts/withdrawal_request.bin similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/forks/contracts/withdrawal_request.bin rename to packages/tests/src/ethereum_test_forks/forks/contracts/withdrawal_request.bin diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/forks.py b/packages/tests/src/ethereum_test_forks/forks/forks.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/forks/forks.py rename to packages/tests/src/ethereum_test_forks/forks/forks.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/helpers.py b/packages/tests/src/ethereum_test_forks/forks/helpers.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/forks/helpers.py rename to packages/tests/src/ethereum_test_forks/forks/helpers.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/forks/transition.py b/packages/tests/src/ethereum_test_forks/forks/transition.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/forks/transition.py rename to packages/tests/src/ethereum_test_forks/forks/transition.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/gas_costs.py b/packages/tests/src/ethereum_test_forks/gas_costs.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/gas_costs.py rename to packages/tests/src/ethereum_test_forks/gas_costs.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/helpers.py b/packages/tests/src/ethereum_test_forks/helpers.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/helpers.py rename to packages/tests/src/ethereum_test_forks/helpers.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/py.typed b/packages/tests/src/ethereum_test_forks/py.typed similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/py.typed rename to packages/tests/src/ethereum_test_forks/py.typed diff --git a/src/ethereum_spec_tests/ethereum_test_forks/tests/__init__.py b/packages/tests/src/ethereum_test_forks/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/tests/__init__.py rename to packages/tests/src/ethereum_test_forks/tests/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/tests/test_fork_range_descriptor.py b/packages/tests/src/ethereum_test_forks/tests/test_fork_range_descriptor.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/tests/test_fork_range_descriptor.py rename to packages/tests/src/ethereum_test_forks/tests/test_fork_range_descriptor.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/tests/test_forks.py b/packages/tests/src/ethereum_test_forks/tests/test_forks.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/tests/test_forks.py rename to packages/tests/src/ethereum_test_forks/tests/test_forks.py diff --git a/src/ethereum_spec_tests/ethereum_test_forks/transition_base_fork.py b/packages/tests/src/ethereum_test_forks/transition_base_fork.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_forks/transition_base_fork.py rename to packages/tests/src/ethereum_test_forks/transition_base_fork.py diff --git a/src/ethereum_spec_tests/ethereum_test_rpc/__init__.py b/packages/tests/src/ethereum_test_rpc/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_rpc/__init__.py rename to packages/tests/src/ethereum_test_rpc/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_rpc/rpc.py b/packages/tests/src/ethereum_test_rpc/rpc.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_rpc/rpc.py rename to packages/tests/src/ethereum_test_rpc/rpc.py diff --git a/src/ethereum_spec_tests/ethereum_test_rpc/tests/__init__.py b/packages/tests/src/ethereum_test_rpc/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_rpc/tests/__init__.py rename to packages/tests/src/ethereum_test_rpc/tests/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_rpc/tests/test_types.py b/packages/tests/src/ethereum_test_rpc/tests/test_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_rpc/tests/test_types.py rename to packages/tests/src/ethereum_test_rpc/tests/test_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_rpc/types.py b/packages/tests/src/ethereum_test_rpc/types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_rpc/types.py rename to packages/tests/src/ethereum_test_rpc/types.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/__init__.py b/packages/tests/src/ethereum_test_specs/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/__init__.py rename to packages/tests/src/ethereum_test_specs/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/base.py b/packages/tests/src/ethereum_test_specs/base.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/base.py rename to packages/tests/src/ethereum_test_specs/base.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/base_static.py b/packages/tests/src/ethereum_test_specs/base_static.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/base_static.py rename to packages/tests/src/ethereum_test_specs/base_static.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/blobs.py b/packages/tests/src/ethereum_test_specs/blobs.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/blobs.py rename to packages/tests/src/ethereum_test_specs/blobs.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/blockchain.py b/packages/tests/src/ethereum_test_specs/blockchain.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/blockchain.py rename to packages/tests/src/ethereum_test_specs/blockchain.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/debugging.py b/packages/tests/src/ethereum_test_specs/debugging.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/debugging.py rename to packages/tests/src/ethereum_test_specs/debugging.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/eof.py b/packages/tests/src/ethereum_test_specs/eof.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/eof.py rename to packages/tests/src/ethereum_test_specs/eof.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/helpers.py b/packages/tests/src/ethereum_test_specs/helpers.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/helpers.py rename to packages/tests/src/ethereum_test_specs/helpers.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/py.typed b/packages/tests/src/ethereum_test_specs/py.typed similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/py.typed rename to packages/tests/src/ethereum_test_specs/py.typed diff --git a/src/ethereum_spec_tests/ethereum_test_specs/state.py b/packages/tests/src/ethereum_test_specs/state.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/state.py rename to packages/tests/src/ethereum_test_specs/state.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/__init__.py b/packages/tests/src/ethereum_test_specs/static_state/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/__init__.py rename to packages/tests/src/ethereum_test_specs/static_state/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/account.py b/packages/tests/src/ethereum_test_specs/static_state/account.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/account.py rename to packages/tests/src/ethereum_test_specs/static_state/account.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/__init__.py b/packages/tests/src/ethereum_test_specs/static_state/common/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/common/__init__.py rename to packages/tests/src/ethereum_test_specs/static_state/common/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/common.py b/packages/tests/src/ethereum_test_specs/static_state/common/common.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/common/common.py rename to packages/tests/src/ethereum_test_specs/static_state/common/common.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/compile_yul.py b/packages/tests/src/ethereum_test_specs/static_state/common/compile_yul.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/common/compile_yul.py rename to packages/tests/src/ethereum_test_specs/static_state/common/compile_yul.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/common/tags.py b/packages/tests/src/ethereum_test_specs/static_state/common/tags.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/common/tags.py rename to packages/tests/src/ethereum_test_specs/static_state/common/tags.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/environment.py b/packages/tests/src/ethereum_test_specs/static_state/environment.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/environment.py rename to packages/tests/src/ethereum_test_specs/static_state/environment.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/expect_section.py b/packages/tests/src/ethereum_test_specs/static_state/expect_section.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/expect_section.py rename to packages/tests/src/ethereum_test_specs/static_state/expect_section.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/general_transaction.py b/packages/tests/src/ethereum_test_specs/static_state/general_transaction.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/general_transaction.py rename to packages/tests/src/ethereum_test_specs/static_state/general_transaction.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/static_state/state_static.py b/packages/tests/src/ethereum_test_specs/static_state/state_static.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/static_state/state_static.py rename to packages/tests/src/ethereum_test_specs/static_state/state_static.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/__init__.py b/packages/tests/src/ethereum_test_specs/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/__init__.py rename to packages/tests/src/ethereum_test_specs/tests/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_london_invalid_filled.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_london_valid_filled.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_invalid_filled_engine.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/blockchain_shanghai_valid_filled_engine.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine_tx_type_0.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine_tx_type_0.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_engine_tx_type_0.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_tx_type_0.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_tx_type_0.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_blockchain_test_tx_type_0.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_0.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_0.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_0.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_1.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_1.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_1.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_cancun_state_test_tx_type_1.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test_tx_type_0.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test_tx_type_0.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_istanbul_blockchain_test_tx_type_0.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test_tx_type_0.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test_tx_type_0.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_london_blockchain_test_tx_type_0.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine_tx_type_0.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine_tx_type_0.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_paris_blockchain_test_engine_tx_type_0.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_paris_state_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_paris_state_test_tx_type_0.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_paris_state_test_tx_type_0.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_paris_state_test_tx_type_0.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine_tx_type_0.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine_tx_type_0.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_blockchain_test_engine_tx_type_0.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test_tx_type_0.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test_tx_type_0.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test_tx_type_0.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/chainid_shanghai_state_test_tx_type_0.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/tx_simple_type_0_shanghai.json b/packages/tests/src/ethereum_test_specs/tests/fixtures/tx_simple_type_0_shanghai.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/fixtures/tx_simple_type_0_shanghai.json rename to packages/tests/src/ethereum_test_specs/tests/fixtures/tx_simple_type_0_shanghai.json diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/helpers.py b/packages/tests/src/ethereum_test_specs/tests/helpers.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/helpers.py rename to packages/tests/src/ethereum_test_specs/tests/helpers.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/test_expect.py b/packages/tests/src/ethereum_test_specs/tests/test_expect.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/test_expect.py rename to packages/tests/src/ethereum_test_specs/tests/test_expect.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/test_fixtures.py b/packages/tests/src/ethereum_test_specs/tests/test_fixtures.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/test_fixtures.py rename to packages/tests/src/ethereum_test_specs/tests/test_fixtures.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/test_transaction.py b/packages/tests/src/ethereum_test_specs/tests/test_transaction.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/test_transaction.py rename to packages/tests/src/ethereum_test_specs/tests/test_transaction.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/tests/test_types.py b/packages/tests/src/ethereum_test_specs/tests/test_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/tests/test_types.py rename to packages/tests/src/ethereum_test_specs/tests/test_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_specs/transaction.py b/packages/tests/src/ethereum_test_specs/transaction.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_specs/transaction.py rename to packages/tests/src/ethereum_test_specs/transaction.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/__init__.py b/packages/tests/src/ethereum_test_tools/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/__init__.py rename to packages/tests/src/ethereum_test_tools/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/code/__init__.py b/packages/tests/src/ethereum_test_tools/code/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/code/__init__.py rename to packages/tests/src/ethereum_test_tools/code/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/code/generators.py b/packages/tests/src/ethereum_test_tools/code/generators.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/code/generators.py rename to packages/tests/src/ethereum_test_tools/code/generators.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/code/yul.py b/packages/tests/src/ethereum_test_tools/code/yul.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/code/yul.py rename to packages/tests/src/ethereum_test_tools/code/yul.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/py.typed b/packages/tests/src/ethereum_test_tools/py.typed similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/py.typed rename to packages/tests/src/ethereum_test_tools/py.typed diff --git a/src/ethereum_spec_tests/ethereum_test_tools/tests/__init__.py b/packages/tests/src/ethereum_test_tools/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/tests/__init__.py rename to packages/tests/src/ethereum_test_tools/tests/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/tests/test_code.py b/packages/tests/src/ethereum_test_tools/tests/test_code.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/tests/test_code.py rename to packages/tests/src/ethereum_test_tools/tests/test_code.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_engine.json b/packages/tests/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_engine.json similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_engine.json rename to packages/tests/src/ethereum_test_tools/tests/test_filling/fixtures/blockchain_shanghai_invalid_filled_engine.json diff --git a/src/ethereum_spec_tests/ethereum_test_tools/utility/__init__.py b/packages/tests/src/ethereum_test_tools/utility/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/utility/__init__.py rename to packages/tests/src/ethereum_test_tools/utility/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/utility/generators.py b/packages/tests/src/ethereum_test_tools/utility/generators.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/utility/generators.py rename to packages/tests/src/ethereum_test_tools/utility/generators.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/utility/pytest.py b/packages/tests/src/ethereum_test_tools/utility/pytest.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/utility/pytest.py rename to packages/tests/src/ethereum_test_tools/utility/pytest.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/utility/tests/test_pytest.py b/packages/tests/src/ethereum_test_tools/utility/tests/test_pytest.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/utility/tests/test_pytest.py rename to packages/tests/src/ethereum_test_tools/utility/tests/test_pytest.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/utility/versioning.py b/packages/tests/src/ethereum_test_tools/utility/versioning.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/utility/versioning.py rename to packages/tests/src/ethereum_test_tools/utility/versioning.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/vm/__init__.py b/packages/tests/src/ethereum_test_tools/vm/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/vm/__init__.py rename to packages/tests/src/ethereum_test_tools/vm/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_tools/vm/opcode.py b/packages/tests/src/ethereum_test_tools/vm/opcode.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_tools/vm/opcode.py rename to packages/tests/src/ethereum_test_tools/vm/opcode.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/__init__.py b/packages/tests/src/ethereum_test_types/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/__init__.py rename to packages/tests/src/ethereum_test_types/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/account_types.py b/packages/tests/src/ethereum_test_types/account_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/account_types.py rename to packages/tests/src/ethereum_test_types/account_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/blob_types.py b/packages/tests/src/ethereum_test_types/blob_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/blob_types.py rename to packages/tests/src/ethereum_test_types/blob_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/block_access_list/__init__.py b/packages/tests/src/ethereum_test_types/block_access_list/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/block_access_list/__init__.py rename to packages/tests/src/ethereum_test_types/block_access_list/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/block_access_list/modifiers.py b/packages/tests/src/ethereum_test_types/block_access_list/modifiers.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/block_access_list/modifiers.py rename to packages/tests/src/ethereum_test_types/block_access_list/modifiers.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/block_types.py b/packages/tests/src/ethereum_test_types/block_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/block_types.py rename to packages/tests/src/ethereum_test_types/block_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/chain_config_types.py b/packages/tests/src/ethereum_test_types/chain_config_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/chain_config_types.py rename to packages/tests/src/ethereum_test_types/chain_config_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/eof/__init__.py b/packages/tests/src/ethereum_test_types/eof/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/eof/__init__.py rename to packages/tests/src/ethereum_test_types/eof/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/eof/constants.py b/packages/tests/src/ethereum_test_types/eof/constants.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/eof/constants.py rename to packages/tests/src/ethereum_test_types/eof/constants.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/eof/v1/__init__.py b/packages/tests/src/ethereum_test_types/eof/v1/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/eof/v1/__init__.py rename to packages/tests/src/ethereum_test_types/eof/v1/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/eof/v1/constants.py b/packages/tests/src/ethereum_test_types/eof/v1/constants.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/eof/v1/constants.py rename to packages/tests/src/ethereum_test_types/eof/v1/constants.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/helpers.py b/packages/tests/src/ethereum_test_types/helpers.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/helpers.py rename to packages/tests/src/ethereum_test_types/helpers.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/kzg_trusted_setup.txt b/packages/tests/src/ethereum_test_types/kzg_trusted_setup.txt similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/kzg_trusted_setup.txt rename to packages/tests/src/ethereum_test_types/kzg_trusted_setup.txt diff --git a/src/ethereum_spec_tests/ethereum_test_types/py.typed b/packages/tests/src/ethereum_test_types/py.typed similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/py.typed rename to packages/tests/src/ethereum_test_types/py.typed diff --git a/src/ethereum_spec_tests/ethereum_test_types/receipt_types.py b/packages/tests/src/ethereum_test_types/receipt_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/receipt_types.py rename to packages/tests/src/ethereum_test_types/receipt_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/request_types.py b/packages/tests/src/ethereum_test_types/request_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/request_types.py rename to packages/tests/src/ethereum_test_types/request_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/__init__.py b/packages/tests/src/ethereum_test_types/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/tests/__init__.py rename to packages/tests/src/ethereum_test_types/tests/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_blob_types.py b/packages/tests/src/ethereum_test_types/tests/test_blob_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_blob_types.py rename to packages/tests/src/ethereum_test_types/tests/test_blob_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_block_access_lists.py b/packages/tests/src/ethereum_test_types/tests/test_block_access_lists.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_block_access_lists.py rename to packages/tests/src/ethereum_test_types/tests/test_block_access_lists.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_eof_v1.py b/packages/tests/src/ethereum_test_types/tests/test_eof_v1.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_eof_v1.py rename to packages/tests/src/ethereum_test_types/tests/test_eof_v1.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_helpers.py b/packages/tests/src/ethereum_test_types/tests/test_helpers.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_helpers.py rename to packages/tests/src/ethereum_test_types/tests/test_helpers.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_post_alloc.py b/packages/tests/src/ethereum_test_types/tests/test_post_alloc.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_post_alloc.py rename to packages/tests/src/ethereum_test_types/tests/test_post_alloc.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_transactions.py b/packages/tests/src/ethereum_test_types/tests/test_transactions.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_transactions.py rename to packages/tests/src/ethereum_test_types/tests/test_transactions.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/tests/test_types.py b/packages/tests/src/ethereum_test_types/tests/test_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/tests/test_types.py rename to packages/tests/src/ethereum_test_types/tests/test_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/transaction_types.py b/packages/tests/src/ethereum_test_types/transaction_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/transaction_types.py rename to packages/tests/src/ethereum_test_types/transaction_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/trie.py b/packages/tests/src/ethereum_test_types/trie.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/trie.py rename to packages/tests/src/ethereum_test_types/trie.py diff --git a/src/ethereum_spec_tests/ethereum_test_types/utils.py b/packages/tests/src/ethereum_test_types/utils.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_types/utils.py rename to packages/tests/src/ethereum_test_types/utils.py diff --git a/src/ethereum_spec_tests/ethereum_test_vm/__init__.py b/packages/tests/src/ethereum_test_vm/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_vm/__init__.py rename to packages/tests/src/ethereum_test_vm/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_vm/bytecode.py b/packages/tests/src/ethereum_test_vm/bytecode.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_vm/bytecode.py rename to packages/tests/src/ethereum_test_vm/bytecode.py diff --git a/src/ethereum_spec_tests/ethereum_test_vm/evm_types.py b/packages/tests/src/ethereum_test_vm/evm_types.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_vm/evm_types.py rename to packages/tests/src/ethereum_test_vm/evm_types.py diff --git a/src/ethereum_spec_tests/ethereum_test_vm/helpers.py b/packages/tests/src/ethereum_test_vm/helpers.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_vm/helpers.py rename to packages/tests/src/ethereum_test_vm/helpers.py diff --git a/src/ethereum_spec_tests/ethereum_test_vm/opcode.py b/packages/tests/src/ethereum_test_vm/opcode.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_vm/opcode.py rename to packages/tests/src/ethereum_test_vm/opcode.py diff --git a/src/ethereum_spec_tests/ethereum_test_vm/py.typed b/packages/tests/src/ethereum_test_vm/py.typed similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_vm/py.typed rename to packages/tests/src/ethereum_test_vm/py.typed diff --git a/src/ethereum_spec_tests/ethereum_test_vm/tests/__init__.py b/packages/tests/src/ethereum_test_vm/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_vm/tests/__init__.py rename to packages/tests/src/ethereum_test_vm/tests/__init__.py diff --git a/src/ethereum_spec_tests/ethereum_test_vm/tests/test_vm.py b/packages/tests/src/ethereum_test_vm/tests/test_vm.py similarity index 100% rename from src/ethereum_spec_tests/ethereum_test_vm/tests/test_vm.py rename to packages/tests/src/ethereum_test_vm/tests/test_vm.py diff --git a/src/ethereum_spec_tests/pytest_plugins/__init__.py b/packages/tests/src/pytest_plugins/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/__init__.py rename to packages/tests/src/pytest_plugins/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/concurrency.py b/packages/tests/src/pytest_plugins/concurrency.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/concurrency.py rename to packages/tests/src/pytest_plugins/concurrency.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/__init__.py b/packages/tests/src/pytest_plugins/consume/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/__init__.py rename to packages/tests/src/pytest_plugins/consume/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/consume.py b/packages/tests/src/pytest_plugins/consume/consume.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/consume.py rename to packages/tests/src/pytest_plugins/consume/consume.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/direct/__init__.py b/packages/tests/src/pytest_plugins/consume/direct/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/direct/__init__.py rename to packages/tests/src/pytest_plugins/consume/direct/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/direct/conftest.py b/packages/tests/src/pytest_plugins/consume/direct/conftest.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/direct/conftest.py rename to packages/tests/src/pytest_plugins/consume/direct/conftest.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/direct/test_via_direct.py b/packages/tests/src/pytest_plugins/consume/direct/test_via_direct.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/direct/test_via_direct.py rename to packages/tests/src/pytest_plugins/consume/direct/test_via_direct.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/hive_engine_test/__init__.py b/packages/tests/src/pytest_plugins/consume/hive_engine_test/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/hive_engine_test/__init__.py rename to packages/tests/src/pytest_plugins/consume/hive_engine_test/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/hive_simulators_reorg/__init__.py b/packages/tests/src/pytest_plugins/consume/hive_simulators_reorg/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/hive_simulators_reorg/__init__.py rename to packages/tests/src/pytest_plugins/consume/hive_simulators_reorg/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/releases.py b/packages/tests/src/pytest_plugins/consume/releases.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/releases.py rename to packages/tests/src/pytest_plugins/consume/releases.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/__init__.py rename to packages/tests/src/pytest_plugins/consume/simulators/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/base.py b/packages/tests/src/pytest_plugins/consume/simulators/base.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/base.py rename to packages/tests/src/pytest_plugins/consume/simulators/base.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/engine/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/engine/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/engine/__init__.py rename to packages/tests/src/pytest_plugins/consume/simulators/engine/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/engine/conftest.py b/packages/tests/src/pytest_plugins/consume/simulators/engine/conftest.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/engine/conftest.py rename to packages/tests/src/pytest_plugins/consume/simulators/engine/conftest.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/exceptions.py b/packages/tests/src/pytest_plugins/consume/simulators/exceptions.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/exceptions.py rename to packages/tests/src/pytest_plugins/consume/simulators/exceptions.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/helpers/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/__init__.py rename to packages/tests/src/pytest_plugins/consume/simulators/helpers/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/exceptions.py b/packages/tests/src/pytest_plugins/consume/simulators/helpers/exceptions.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/exceptions.py rename to packages/tests/src/pytest_plugins/consume/simulators/helpers/exceptions.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/ruleset.py b/packages/tests/src/pytest_plugins/consume/simulators/helpers/ruleset.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/ruleset.py rename to packages/tests/src/pytest_plugins/consume/simulators/helpers/ruleset.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/timing.py b/packages/tests/src/pytest_plugins/consume/simulators/helpers/timing.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/helpers/timing.py rename to packages/tests/src/pytest_plugins/consume/simulators/helpers/timing.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/rlp/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/rlp/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/rlp/__init__.py rename to packages/tests/src/pytest_plugins/consume/simulators/rlp/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/rlp/conftest.py b/packages/tests/src/pytest_plugins/consume/simulators/rlp/conftest.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/rlp/conftest.py rename to packages/tests/src/pytest_plugins/consume/simulators/rlp/conftest.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/__init__.py rename to packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py rename to packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_engine.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py rename to packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_rlp.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py b/packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py rename to packages/tests/src/pytest_plugins/consume/simulators/simulator_logic/test_via_sync.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/single_test_client.py b/packages/tests/src/pytest_plugins/consume/simulators/single_test_client.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/single_test_client.py rename to packages/tests/src/pytest_plugins/consume/simulators/single_test_client.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/sync/__init__.py b/packages/tests/src/pytest_plugins/consume/simulators/sync/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/sync/__init__.py rename to packages/tests/src/pytest_plugins/consume/simulators/sync/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/sync/conftest.py b/packages/tests/src/pytest_plugins/consume/simulators/sync/conftest.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/sync/conftest.py rename to packages/tests/src/pytest_plugins/consume/simulators/sync/conftest.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/test_case_description.py b/packages/tests/src/pytest_plugins/consume/simulators/test_case_description.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/test_case_description.py rename to packages/tests/src/pytest_plugins/consume/simulators/test_case_description.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/simulators/timing_data.py b/packages/tests/src/pytest_plugins/consume/simulators/timing_data.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/simulators/timing_data.py rename to packages/tests/src/pytest_plugins/consume/simulators/timing_data.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/tests/__init__.py b/packages/tests/src/pytest_plugins/consume/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/tests/__init__.py rename to packages/tests/src/pytest_plugins/consume/tests/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/tests/release_information.json b/packages/tests/src/pytest_plugins/consume/tests/release_information.json similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/tests/release_information.json rename to packages/tests/src/pytest_plugins/consume/tests/release_information.json diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/tests/test_consume_args.py b/packages/tests/src/pytest_plugins/consume/tests/test_consume_args.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/tests/test_consume_args.py rename to packages/tests/src/pytest_plugins/consume/tests/test_consume_args.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/tests/test_fixtures_source_input_types.py b/packages/tests/src/pytest_plugins/consume/tests/test_fixtures_source_input_types.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/tests/test_fixtures_source_input_types.py rename to packages/tests/src/pytest_plugins/consume/tests/test_fixtures_source_input_types.py diff --git a/src/ethereum_spec_tests/pytest_plugins/consume/tests/test_releases.py b/packages/tests/src/pytest_plugins/consume/tests/test_releases.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/consume/tests/test_releases.py rename to packages/tests/src/pytest_plugins/consume/tests/test_releases.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/__init__.py b/packages/tests/src/pytest_plugins/execute/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/__init__.py rename to packages/tests/src/pytest_plugins/execute/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/__init__.py b/packages/tests/src/pytest_plugins/execute/eth_config/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/__init__.py rename to packages/tests/src/pytest_plugins/execute/eth_config/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/eth_config.py b/packages/tests/src/pytest_plugins/execute/eth_config/eth_config.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/eth_config.py rename to packages/tests/src/pytest_plugins/execute/eth_config/eth_config.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/execute_eth_config.py b/packages/tests/src/pytest_plugins/execute/eth_config/execute_eth_config.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/execute_eth_config.py rename to packages/tests/src/pytest_plugins/execute/eth_config/execute_eth_config.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/networks.yml b/packages/tests/src/pytest_plugins/execute/eth_config/networks.yml similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/networks.yml rename to packages/tests/src/pytest_plugins/execute/eth_config/networks.yml diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/__init__.py b/packages/tests/src/pytest_plugins/execute/eth_config/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/__init__.py rename to packages/tests/src/pytest_plugins/execute/eth_config/tests/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/genesis_example.json b/packages/tests/src/pytest_plugins/execute/eth_config/tests/genesis_example.json similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/genesis_example.json rename to packages/tests/src/pytest_plugins/execute/eth_config/tests/genesis_example.json diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py b/packages/tests/src/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py rename to packages/tests/src/pytest_plugins/execute/eth_config/tests/test_execute_eth_config.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/test_genesis.py b/packages/tests/src/pytest_plugins/execute/eth_config/tests/test_genesis.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/tests/test_genesis.py rename to packages/tests/src/pytest_plugins/execute/eth_config/tests/test_genesis.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/eth_config/types.py b/packages/tests/src/pytest_plugins/execute/eth_config/types.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/eth_config/types.py rename to packages/tests/src/pytest_plugins/execute/eth_config/types.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/execute.py b/packages/tests/src/pytest_plugins/execute/execute.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/execute.py rename to packages/tests/src/pytest_plugins/execute/execute.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/execute_recover.py b/packages/tests/src/pytest_plugins/execute/execute_recover.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/execute_recover.py rename to packages/tests/src/pytest_plugins/execute/execute_recover.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/pre_alloc.py b/packages/tests/src/pytest_plugins/execute/pre_alloc.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/pre_alloc.py rename to packages/tests/src/pytest_plugins/execute/pre_alloc.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/recover.py b/packages/tests/src/pytest_plugins/execute/recover.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/recover.py rename to packages/tests/src/pytest_plugins/execute/recover.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/__init__.py b/packages/tests/src/pytest_plugins/execute/rpc/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/rpc/__init__.py rename to packages/tests/src/pytest_plugins/execute/rpc/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py b/packages/tests/src/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py rename to packages/tests/src/pytest_plugins/execute/rpc/chain_builder_eth_rpc.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/hive.py b/packages/tests/src/pytest_plugins/execute/rpc/hive.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/rpc/hive.py rename to packages/tests/src/pytest_plugins/execute/rpc/hive.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/remote.py b/packages/tests/src/pytest_plugins/execute/rpc/remote.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/rpc/remote.py rename to packages/tests/src/pytest_plugins/execute/rpc/remote.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/rpc/remote_seed_sender.py b/packages/tests/src/pytest_plugins/execute/rpc/remote_seed_sender.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/rpc/remote_seed_sender.py rename to packages/tests/src/pytest_plugins/execute/rpc/remote_seed_sender.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/sender.py b/packages/tests/src/pytest_plugins/execute/sender.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/sender.py rename to packages/tests/src/pytest_plugins/execute/sender.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/tests/__init__.py b/packages/tests/src/pytest_plugins/execute/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/tests/__init__.py rename to packages/tests/src/pytest_plugins/execute/tests/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/execute/tests/test_pre_alloc.py b/packages/tests/src/pytest_plugins/execute/tests/test_pre_alloc.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/execute/tests/test_pre_alloc.py rename to packages/tests/src/pytest_plugins/execute/tests/test_pre_alloc.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/__init__.py b/packages/tests/src/pytest_plugins/filler/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/__init__.py rename to packages/tests/src/pytest_plugins/filler/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/eip_checklist.py b/packages/tests/src/pytest_plugins/filler/eip_checklist.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/eip_checklist.py rename to packages/tests/src/pytest_plugins/filler/eip_checklist.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/filler.py b/packages/tests/src/pytest_plugins/filler/filler.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/filler.py rename to packages/tests/src/pytest_plugins/filler/filler.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/fixture_output.py b/packages/tests/src/pytest_plugins/filler/fixture_output.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/fixture_output.py rename to packages/tests/src/pytest_plugins/filler/fixture_output.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/__init__.py b/packages/tests/src/pytest_plugins/filler/gen_test_doc/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/__init__.py rename to packages/tests/src/pytest_plugins/filler/gen_test_doc/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/gen_test_doc.py b/packages/tests/src/pytest_plugins/filler/gen_test_doc/gen_test_doc.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/gen_test_doc.py rename to packages/tests/src/pytest_plugins/filler/gen_test_doc/gen_test_doc.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/page_props.py b/packages/tests/src/pytest_plugins/filler/gen_test_doc/page_props.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/gen_test_doc/page_props.py rename to packages/tests/src/pytest_plugins/filler/gen_test_doc/page_props.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/ported_tests.py b/packages/tests/src/pytest_plugins/filler/ported_tests.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/ported_tests.py rename to packages/tests/src/pytest_plugins/filler/ported_tests.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/pre_alloc.py b/packages/tests/src/pytest_plugins/filler/pre_alloc.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/pre_alloc.py rename to packages/tests/src/pytest_plugins/filler/pre_alloc.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/static_filler.py b/packages/tests/src/pytest_plugins/filler/static_filler.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/static_filler.py rename to packages/tests/src/pytest_plugins/filler/static_filler.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/__init__.py b/packages/tests/src/pytest_plugins/filler/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/__init__.py rename to packages/tests/src/pytest_plugins/filler/tests/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_benchmarking.py b/packages/tests/src/pytest_plugins/filler/tests/test_benchmarking.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_benchmarking.py rename to packages/tests/src/pytest_plugins/filler/tests/test_benchmarking.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_collect_only.py b/packages/tests/src/pytest_plugins/filler/tests/test_collect_only.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_collect_only.py rename to packages/tests/src/pytest_plugins/filler/tests/test_collect_only.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_eip_checklist.py b/packages/tests/src/pytest_plugins/filler/tests/test_eip_checklist.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_eip_checklist.py rename to packages/tests/src/pytest_plugins/filler/tests/test_eip_checklist.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_filler.py b/packages/tests/src/pytest_plugins/filler/tests/test_filler.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_filler.py rename to packages/tests/src/pytest_plugins/filler/tests/test_filler.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_filling_session.py b/packages/tests/src/pytest_plugins/filler/tests/test_filling_session.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_filling_session.py rename to packages/tests/src/pytest_plugins/filler/tests/test_filling_session.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_format_selector.py b/packages/tests/src/pytest_plugins/filler/tests/test_format_selector.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_format_selector.py rename to packages/tests/src/pytest_plugins/filler/tests/test_format_selector.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_generate_all_formats.py b/packages/tests/src/pytest_plugins/filler/tests/test_generate_all_formats.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_generate_all_formats.py rename to packages/tests/src/pytest_plugins/filler/tests/test_generate_all_formats.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_output_directory.py b/packages/tests/src/pytest_plugins/filler/tests/test_output_directory.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_output_directory.py rename to packages/tests/src/pytest_plugins/filler/tests/test_output_directory.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_phase_manager.py b/packages/tests/src/pytest_plugins/filler/tests/test_phase_manager.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_phase_manager.py rename to packages/tests/src/pytest_plugins/filler/tests/test_phase_manager.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_pre_alloc.py b/packages/tests/src/pytest_plugins/filler/tests/test_pre_alloc.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_pre_alloc.py rename to packages/tests/src/pytest_plugins/filler/tests/test_pre_alloc.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_prealloc_group.py b/packages/tests/src/pytest_plugins/filler/tests/test_prealloc_group.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_prealloc_group.py rename to packages/tests/src/pytest_plugins/filler/tests/test_prealloc_group.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py b/packages/tests/src/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py rename to packages/tests/src/pytest_plugins/filler/tests/test_prealloc_group_usage_example.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py b/packages/tests/src/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py rename to packages/tests/src/pytest_plugins/filler/tests/test_slow_marker_pre_alloc.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/tests/test_verify_sync_marker.py b/packages/tests/src/pytest_plugins/filler/tests/test_verify_sync_marker.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/tests/test_verify_sync_marker.py rename to packages/tests/src/pytest_plugins/filler/tests/test_verify_sync_marker.py diff --git a/src/ethereum_spec_tests/pytest_plugins/filler/witness.py b/packages/tests/src/pytest_plugins/filler/witness.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/filler/witness.py rename to packages/tests/src/pytest_plugins/filler/witness.py diff --git a/src/ethereum_spec_tests/pytest_plugins/fix_package_test_path.py b/packages/tests/src/pytest_plugins/fix_package_test_path.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/fix_package_test_path.py rename to packages/tests/src/pytest_plugins/fix_package_test_path.py diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/__init__.py b/packages/tests/src/pytest_plugins/forks/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/forks/__init__.py rename to packages/tests/src/pytest_plugins/forks/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/forks.py b/packages/tests/src/pytest_plugins/forks/forks.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/forks/forks.py rename to packages/tests/src/pytest_plugins/forks/forks.py diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/__init__.py b/packages/tests/src/pytest_plugins/forks/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/__init__.py rename to packages/tests/src/pytest_plugins/forks/tests/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_bad_command_line_options.py b/packages/tests/src/pytest_plugins/forks/tests/test_bad_command_line_options.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_bad_command_line_options.py rename to packages/tests/src/pytest_plugins/forks/tests/test_bad_command_line_options.py diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_bad_validity_markers.py b/packages/tests/src/pytest_plugins/forks/tests/test_bad_validity_markers.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_bad_validity_markers.py rename to packages/tests/src/pytest_plugins/forks/tests/test_bad_validity_markers.py diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_covariant_markers.py b/packages/tests/src/pytest_plugins/forks/tests/test_covariant_markers.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_covariant_markers.py rename to packages/tests/src/pytest_plugins/forks/tests/test_covariant_markers.py diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_fork_parametrizer_types.py b/packages/tests/src/pytest_plugins/forks/tests/test_fork_parametrizer_types.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_fork_parametrizer_types.py rename to packages/tests/src/pytest_plugins/forks/tests/test_fork_parametrizer_types.py diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_forks.py b/packages/tests/src/pytest_plugins/forks/tests/test_forks.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_forks.py rename to packages/tests/src/pytest_plugins/forks/tests/test_forks.py diff --git a/src/ethereum_spec_tests/pytest_plugins/forks/tests/test_markers.py b/packages/tests/src/pytest_plugins/forks/tests/test_markers.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/forks/tests/test_markers.py rename to packages/tests/src/pytest_plugins/forks/tests/test_markers.py diff --git a/src/ethereum_spec_tests/pytest_plugins/help/__init__.py b/packages/tests/src/pytest_plugins/help/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/help/__init__.py rename to packages/tests/src/pytest_plugins/help/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/help/help.py b/packages/tests/src/pytest_plugins/help/help.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/help/help.py rename to packages/tests/src/pytest_plugins/help/help.py diff --git a/src/ethereum_spec_tests/pytest_plugins/help/tests/test_help.py b/packages/tests/src/pytest_plugins/help/tests/test_help.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/help/tests/test_help.py rename to packages/tests/src/pytest_plugins/help/tests/test_help.py diff --git a/src/ethereum_spec_tests/pytest_plugins/logging/__init__.py b/packages/tests/src/pytest_plugins/logging/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/logging/__init__.py rename to packages/tests/src/pytest_plugins/logging/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/logging/logging.py b/packages/tests/src/pytest_plugins/logging/logging.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/logging/logging.py rename to packages/tests/src/pytest_plugins/logging/logging.py diff --git a/src/ethereum_spec_tests/pytest_plugins/logging/tests/__init__.py b/packages/tests/src/pytest_plugins/logging/tests/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/logging/tests/__init__.py rename to packages/tests/src/pytest_plugins/logging/tests/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/logging/tests/test_logging.py b/packages/tests/src/pytest_plugins/logging/tests/test_logging.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/logging/tests/test_logging.py rename to packages/tests/src/pytest_plugins/logging/tests/test_logging.py diff --git a/src/ethereum_spec_tests/pytest_plugins/py.typed b/packages/tests/src/pytest_plugins/py.typed similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/py.typed rename to packages/tests/src/pytest_plugins/py.typed diff --git a/src/ethereum_spec_tests/pytest_plugins/pytest_hive/hive_info.py b/packages/tests/src/pytest_plugins/pytest_hive/hive_info.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/pytest_hive/hive_info.py rename to packages/tests/src/pytest_plugins/pytest_hive/hive_info.py diff --git a/src/ethereum_spec_tests/pytest_plugins/pytest_hive/pytest_hive.py b/packages/tests/src/pytest_plugins/pytest_hive/pytest_hive.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/pytest_hive/pytest_hive.py rename to packages/tests/src/pytest_plugins/pytest_hive/pytest_hive.py diff --git a/src/ethereum_spec_tests/pytest_plugins/shared/benchmarking.py b/packages/tests/src/pytest_plugins/shared/benchmarking.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/shared/benchmarking.py rename to packages/tests/src/pytest_plugins/shared/benchmarking.py diff --git a/src/ethereum_spec_tests/pytest_plugins/shared/execute_fill.py b/packages/tests/src/pytest_plugins/shared/execute_fill.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/shared/execute_fill.py rename to packages/tests/src/pytest_plugins/shared/execute_fill.py diff --git a/src/ethereum_spec_tests/pytest_plugins/shared/helpers.py b/packages/tests/src/pytest_plugins/shared/helpers.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/shared/helpers.py rename to packages/tests/src/pytest_plugins/shared/helpers.py diff --git a/src/ethereum_spec_tests/pytest_plugins/shared/transaction_fixtures.py b/packages/tests/src/pytest_plugins/shared/transaction_fixtures.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/shared/transaction_fixtures.py rename to packages/tests/src/pytest_plugins/shared/transaction_fixtures.py diff --git a/src/ethereum_spec_tests/pytest_plugins/solc/__init__.py b/packages/tests/src/pytest_plugins/solc/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/solc/__init__.py rename to packages/tests/src/pytest_plugins/solc/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/solc/solc.py b/packages/tests/src/pytest_plugins/solc/solc.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/solc/solc.py rename to packages/tests/src/pytest_plugins/solc/solc.py diff --git a/src/ethereum_spec_tests/pytest_plugins/spec_version_checker/__init__.py b/packages/tests/src/pytest_plugins/spec_version_checker/__init__.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/spec_version_checker/__init__.py rename to packages/tests/src/pytest_plugins/spec_version_checker/__init__.py diff --git a/src/ethereum_spec_tests/pytest_plugins/spec_version_checker/spec_version_checker.py b/packages/tests/src/pytest_plugins/spec_version_checker/spec_version_checker.py similarity index 100% rename from src/ethereum_spec_tests/pytest_plugins/spec_version_checker/spec_version_checker.py rename to packages/tests/src/pytest_plugins/spec_version_checker/spec_version_checker.py diff --git a/pyproject.toml b/pyproject.toml index 5407127960..5c753b938c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,97 +30,9 @@ dependencies = [ [tool.setuptools.package-dir] "" = "src" -cli = "src/ethereum_spec_tests/cli" -config = "src/ethereum_spec_tests/config" -ethereum_clis = "src/ethereum_spec_tests/ethereum_clis" -ethereum_test_base_types = "src/ethereum_spec_tests/ethereum_test_base_types" -ethereum_test_checklists = "src/ethereum_spec_tests/ethereum_test_checklists" -ethereum_test_exceptions = "src/ethereum_spec_tests/ethereum_test_exceptions" -ethereum_test_execution = "src/ethereum_spec_tests/ethereum_test_execution" -ethereum_test_fixtures = "src/ethereum_spec_tests/ethereum_test_fixtures" -ethereum_test_forks = "src/ethereum_spec_tests/ethereum_test_forks" -ethereum_test_rpc = "src/ethereum_spec_tests/ethereum_test_rpc" -ethereum_test_specs = "src/ethereum_spec_tests/ethereum_test_specs" -ethereum_test_tools = "src/ethereum_spec_tests/ethereum_test_tools" -ethereum_test_types = "src/ethereum_spec_tests/ethereum_test_types" -ethereum_test_vm = "src/ethereum_spec_tests/ethereum_test_vm" -pytest_plugins = "src/ethereum_spec_tests/pytest_plugins" [tool.setuptools] packages = [ - "cli", - "cli.eest", - "cli.eest.commands", - "cli.eest.make", - "cli.eest.make.commands", - "cli.gentest", - "cli.gentest.tests", - "cli.input", - "cli.pytest_commands", - "cli.tests", - "config", - "ethereum_clis", - "ethereum_clis.clis", - "ethereum_test_base_types", - "ethereum_test_base_types.reference_spec", - "ethereum_test_base_types.tests", - "ethereum_test_checklists", - "ethereum_test_checklists.tests", - "ethereum_test_exceptions", - "ethereum_test_exceptions.exceptions", - "ethereum_test_exceptions.tests", - "ethereum_test_execution", - "ethereum_test_fixtures", - "ethereum_test_fixtures.tests", - "ethereum_test_forks", - "ethereum_test_forks.forks", - "ethereum_test_forks.tests", - "ethereum_test_rpc", - "ethereum_test_rpc.tests", - "ethereum_test_specs", - "ethereum_test_specs.static_state", - "ethereum_test_specs.static_state.common", - "ethereum_test_specs.tests", - "ethereum_test_tools", - "ethereum_test_tools.code", - "ethereum_test_tools.tests", - "ethereum_test_tools.utility", - "ethereum_test_tools.vm", - "ethereum_test_types", - "ethereum_test_types.block_access_list", - "ethereum_test_types.eof", - "ethereum_test_types.eof.v1", - "ethereum_test_types.tests", - "ethereum_test_vm", - "ethereum_test_vm.tests", - "pytest_plugins", - "pytest_plugins.consume", - "pytest_plugins.consume.direct", - "pytest_plugins.consume.hive_engine_test", - "pytest_plugins.consume.hive_simulators_reorg", - "pytest_plugins.consume.simulators", - "pytest_plugins.consume.simulators.engine", - "pytest_plugins.consume.simulators.helpers", - "pytest_plugins.consume.simulators.rlp", - "pytest_plugins.consume.simulators.simulator_logic", - "pytest_plugins.consume.simulators.sync", - "pytest_plugins.consume.tests", - "pytest_plugins.execute", - "pytest_plugins.execute.eth_config", - "pytest_plugins.execute.eth_config.tests", - "pytest_plugins.execute.rpc", - "pytest_plugins.filler", - "pytest_plugins.filler.gen_test_doc", - "pytest_plugins.filler.tests", - "pytest_plugins.forks", - "pytest_plugins.forks.tests", - "pytest_plugins.help", - "pytest_plugins.logging", - "pytest_plugins.logging.tests", - "pytest_plugins.pytest_hive", - "pytest_plugins.shared", - "pytest_plugins.solc", - "pytest_plugins.spec_version_checker", "ethereum_spec_tools", "ethereum_spec_tools.evm_tools", "ethereum_spec_tools.evm_tools.t8n", @@ -242,11 +154,6 @@ packages = [ "assets/blocks/block_12964999.json", ] "ethereum_spec_tools" = ["py.typed"] -"ethereum_test_forks" = ["forks/contracts/*.bin"] -"pytest_plugins.execute" = ["eth_config/networks.yml"] -"cli.eest.make" = ["templates/*.j2"] -"cli.pytest_commands" = ["pytest_ini_files/*.ini"] -"ethereum_test_types" = ["kzg_trusted_setup.txt"] [project.optional-dependencies] test = [ @@ -258,37 +165,8 @@ test = [ "requests", "requests-cache>=1.2.1,<2", "libcst>=1.8,<2", + "ethereum-execution-tests", ] - -fill = [ - "click>=8.1.0,<9", - "ethereum-hive>=0.1.0a1,<1.0.0", - "gitpython>=3.1.31,<4", - "PyJWT>=2.3.0,<3", - "tenacity>8.2.0,<9", - "requests_unixsocket2>=0.4.0", - "colorlog>=6.7.0,<7", - "pytest-custom-report>=1.0.1,<2", - "pytest-html>=4.1.0,<5", - "pytest-metadata>=3,<4", - "coincurve>=20.0.0,<21", - "trie>=3.1.0,<4", - "semver>=3.0.1,<4", - "pydantic>=2.11.0,<3", - "rich>=13.7.0,<14", - "ethereum-types>=0.2.1,<0.3", - "pyyaml>=6.0.2,<7", - "types-pyyaml>=6.0.12.20240917,<7", - "pytest-json-report>=1.5.0,<2", - "typing-extensions>=4.12.2,<5", - "questionary>=2.1.0,<3", - "ethereum-rlp>=0.1.3,<0.2", - "pytest-regex>=0.2.0,<0.3", - "eth-abi>=5.2.0", - "joblib>=1.4.2", - "ckzg>=2.1.1", -] - lint = [ "codespell==2.4.1", "mypy==1.17.0", @@ -317,25 +195,6 @@ ethereum-spec-sync = "ethereum_spec_tools.sync:main" ethereum-spec-new-fork = "ethereum_spec_tools.new_fork.cli:main" ethereum-spec-patch = "ethereum_spec_tools.patch_tool:main" ethereum-spec-evm = "ethereum_spec_tools.evm_tools:main" -check_eip_versions = "cli.pytest_commands.check_eip_versions:check_eip_versions" -checkfixtures = "cli.check_fixtures:check_fixtures" -checklist = "cli.pytest_commands.checklist:checklist" -compare_fixtures = "cli.compare_fixtures:main" -consume = "cli.pytest_commands.consume:consume" -eest = "cli.eest.cli:eest" -eofwrap = "cli.eofwrap:eof_wrap" -evm_bytes = "cli.evm_bytes:evm_bytes" -execute = "cli.pytest_commands.execute:execute" -extract_config = "cli.extract_config:extract_config" -fill = "cli.pytest_commands.fill:fill" -fillerconvert = "cli.fillerconvert.fillerconvert:main" -generate_checklist_stubs = "cli.generate_checklist_stubs:generate_checklist_stubs" -genindex = "cli.gen_index:generate_fixtures_index_cli" -gentest = "cli.gentest:generate" -groupstats = "cli.show_pre_alloc_group_stats:main" -hasher = "cli.hasher:main" -order_fixtures = "cli.order_fixtures:order_fixtures" -phil = "cli.pytest_commands.fill:phil" [project.entry-points."docc.plugins"] "ethereum_spec_tools.docc.discover" = "ethereum_spec_tools.docc:EthereumDiscover" @@ -409,7 +268,6 @@ paths = [ excluded_paths = [ "src/ethereum_optimized", "src/ethereum_spec_tools", - "src/ethereum_spec_tests", ] [tool.docc.plugins."docc.html.context"] @@ -508,3 +366,9 @@ check-hidden = false # Don't check hidden files (starting with .) [tool.uv] required-version = ">=0.7.0" + +[tool.uv.workspace] +members = ["packages/*"] + +[tool.uv.sources] +ethereum-execution-tests = { workspace = true } diff --git a/src/ethereum/__init__.py b/src/ethereum/__init__.py index e46aa41100..145437d149 100644 --- a/src/ethereum/__init__.py +++ b/src/ethereum/__init__.py @@ -21,7 +21,7 @@ import sys -__version__ = "2.18.0rc5.dev1" +__version__ = "2.18.0rc5.dev2" # # Ensure we can reach 1024 frames of recursion diff --git a/tox.ini b/tox.ini index de618d1c50..b5be296e52 100644 --- a/tox.ini +++ b/tox.ini @@ -15,10 +15,10 @@ extras = test doc commands = - codespell -I whitelist.txt src tests --skip 'src/ethereum_spec_tests,tests/eest' - ruff check src tests --exclude src/ethereum_spec_tests,tests/eest - ruff format src tests --check --exclude src/ethereum_spec_tests,tests/eest - mypy src tests --exclude "src/ethereum_spec_tests/*|tests/json_infra/fixtures/*|tests/eest/*" --namespace-packages + codespell -I whitelist.txt src tests --skip 'tests/eest' + ruff check src tests --exclude tests/eest + ruff format src tests --check --exclude tests/eest + mypy src tests --exclude "tests/json_infra/fixtures/*|tests/eest/*" --namespace-packages ethereum-spec-lint uv lock --check diff --git a/uv.lock b/uv.lock index 6c0aad0575..675a155e20 100644 --- a/uv.lock +++ b/uv.lock @@ -6,6 +6,12 @@ resolution-markers = [ "python_full_version < '3.13'", ] +[manifest] +members = [ + "ethereum-execution", + "ethereum-execution-tests", +] + [[package]] name = "annotated-types" version = "0.7.0" @@ -33,6 +39,79 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, ] +[[package]] +name = "babel" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, +] + +[[package]] +name = "backrefs" +version = "5.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/a7/312f673df6a79003279e1f55619abbe7daebbb87c17c976ddc0345c04c7b/backrefs-5.9.tar.gz", hash = "sha256:808548cb708d66b82ee231f962cb36faaf4f2baab032f2fbb783e9c2fdddaa59", size = 5765857, upload-time = "2025-06-22T19:34:13.97Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/4d/798dc1f30468134906575156c089c492cf79b5a5fd373f07fe26c4d046bf/backrefs-5.9-py310-none-any.whl", hash = "sha256:db8e8ba0e9de81fcd635f440deab5ae5f2591b54ac1ebe0550a2ca063488cd9f", size = 380267, upload-time = "2025-06-22T19:34:05.252Z" }, + { url = "https://files.pythonhosted.org/packages/55/07/f0b3375bf0d06014e9787797e6b7cc02b38ac9ff9726ccfe834d94e9991e/backrefs-5.9-py311-none-any.whl", hash = "sha256:6907635edebbe9b2dc3de3a2befff44d74f30a4562adbb8b36f21252ea19c5cf", size = 392072, upload-time = "2025-06-22T19:34:06.743Z" }, + { url = "https://files.pythonhosted.org/packages/9d/12/4f345407259dd60a0997107758ba3f221cf89a9b5a0f8ed5b961aef97253/backrefs-5.9-py312-none-any.whl", hash = "sha256:7fdf9771f63e6028d7fee7e0c497c81abda597ea45d6b8f89e8ad76994f5befa", size = 397947, upload-time = "2025-06-22T19:34:08.172Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/fa31834dc27a7f05e5290eae47c82690edc3a7b37d58f7fb35a1bdbf355b/backrefs-5.9-py313-none-any.whl", hash = "sha256:cc37b19fa219e93ff825ed1fed8879e47b4d89aa7a1884860e2db64ccd7c676b", size = 399843, upload-time = "2025-06-22T19:34:09.68Z" }, + { url = "https://files.pythonhosted.org/packages/fc/24/b29af34b2c9c41645a9f4ff117bae860291780d73880f449e0b5d948c070/backrefs-5.9-py314-none-any.whl", hash = "sha256:df5e169836cc8acb5e440ebae9aad4bf9d15e226d3bad049cf3f6a5c20cc8dc9", size = 411762, upload-time = "2025-06-22T19:34:11.037Z" }, + { url = "https://files.pythonhosted.org/packages/41/ff/392bff89415399a979be4a65357a41d92729ae8580a66073d8ec8d810f98/backrefs-5.9-py39-none-any.whl", hash = "sha256:f48ee18f6252b8f5777a22a00a09a85de0ca931658f1dd96d4406a34f3748c60", size = 380265, upload-time = "2025-06-22T19:34:12.405Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/e9/df2358efd7659577435e2177bfa69cba6c33216681af51a707193dec162a/beautifulsoup4-4.14.2.tar.gz", hash = "sha256:2a98ab9f944a11acee9cc848508ec28d9228abfd522ef0fad6a02a72e0ded69e", size = 625822, upload-time = "2025-09-29T10:05:42.613Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/fe/3aed5d0be4d404d12d36ab97e2f1791424d9ca39c2f754a6285d59a3b01d/beautifulsoup4-4.14.2-py3-none-any.whl", hash = "sha256:5ef6fa3a8cbece8488d66985560f97ed091e22bbc4e9c2338508a9d5de6d4515", size = 106392, upload-time = "2025-09-29T10:05:43.771Z" }, +] + +[[package]] +name = "bracex" +version = "2.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/63/9a/fec38644694abfaaeca2798b58e276a8e61de49e2e37494ace423395febc/bracex-2.6.tar.gz", hash = "sha256:98f1347cd77e22ee8d967a30ad4e310b233f7754dbf31ff3fceb76145ba47dc7", size = 26642, upload-time = "2025-06-22T19:12:31.254Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/2a/9186535ce58db529927f6cf5990a849aa9e052eea3e2cfefe20b9e1802da/bracex-2.6-py3-none-any.whl", hash = "sha256:0b0049264e7340b3ec782b5cb99beb325f36c3782a32e36e876452fd49a09952", size = 11508, upload-time = "2025-06-22T19:12:29.781Z" }, +] + +[[package]] +name = "cairocffi" +version = "1.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/70/c5/1a4dc131459e68a173cbdab5fad6b524f53f9c1ef7861b7698e998b837cc/cairocffi-1.7.1.tar.gz", hash = "sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b", size = 88096, upload-time = "2024-06-18T10:56:06.741Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/d8/ba13451aa6b745c49536e87b6bf8f629b950e84bd0e8308f7dc6883b67e2/cairocffi-1.7.1-py3-none-any.whl", hash = "sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f", size = 75611, upload-time = "2024-06-18T10:55:59.489Z" }, +] + +[[package]] +name = "cairosvg" +version = "2.8.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cairocffi" }, + { name = "cssselect2" }, + { name = "defusedxml" }, + { name = "pillow" }, + { name = "tinycss2" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ab/b9/5106168bd43d7cd8b7cc2a2ee465b385f14b63f4c092bb89eee2d48c8e67/cairosvg-2.8.2.tar.gz", hash = "sha256:07cbf4e86317b27a92318a4cac2a4bb37a5e9c1b8a27355d06874b22f85bef9f", size = 8398590, upload-time = "2025-05-15T06:56:32.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/48/816bd4aaae93dbf9e408c58598bc32f4a8c65f4b86ab560864cb3ee60adb/cairosvg-2.8.2-py3-none-any.whl", hash = "sha256:eab46dad4674f33267a671dce39b64be245911c901c70d65d2b7b0821e852bf5", size = 45773, upload-time = "2025-05-15T06:56:28.552Z" }, +] + [[package]] name = "cattrs" version = "25.1.1" @@ -150,43 +229,43 @@ wheels = [ [[package]] name = "ckzg" -version = "2.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/55/df/f6db8e83bd4594c1ea685cd37fb81d5399e55765aae16d1a8a9502598f4e/ckzg-2.1.1.tar.gz", hash = "sha256:d6b306b7ec93a24e4346aa53d07f7f75053bc0afc7398e35fa649e5f9d48fcc4", size = 1120500, upload-time = "2025-03-31T21:24:12.324Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/95/2c/44120b2d9dcb0246d67a1f28b9eaa625c499014d4d42561467e28eedd285/ckzg-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:465e2b71cf9dc383f66f1979269420a0da9274a3a9e98b1a4455e84927dfe491", size = 116378, upload-time = "2025-03-31T21:22:36.96Z" }, - { url = "https://files.pythonhosted.org/packages/23/88/c5b89ba9a730fee5e089be9e0c7048fb6707c1a0e4b6c30fcf725c3eef44/ckzg-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ee2f26f17a64ad0aab833d637b276f28486b82a29e34f32cf54b237b8f8ab72d", size = 100202, upload-time = "2025-03-31T21:22:37.799Z" }, - { url = "https://files.pythonhosted.org/packages/ee/11/b0a473e80346db52ad9a629bc9fd8f773c718ed78932ea3a70392306ffc3/ckzg-2.1.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99cc2c4e9fb8c62e3e0862c7f4df9142f07ba640da17fded5f6e0fd09f75909f", size = 175595, upload-time = "2025-03-31T21:22:39.013Z" }, - { url = "https://files.pythonhosted.org/packages/52/fa/17a7e125d07a96dd6dce4db7262231f7583856b2be5d5b7df59e04bfa188/ckzg-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773dd016693d74aca1f5d7982db2bad7dde2e147563aeb16a783f7e5f69c01fe", size = 161681, upload-time = "2025-03-31T21:22:40.257Z" }, - { url = "https://files.pythonhosted.org/packages/57/bd/46d6b90bf53da732f9adab7593d132a0834ed4f2f7659b4c7414d8f78d39/ckzg-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af2b2144f87ba218d8db01382a961b3ecbdde5ede4fa0d9428d35f8c8a595ba", size = 170471, upload-time = "2025-03-31T21:22:41.513Z" }, - { url = "https://files.pythonhosted.org/packages/9d/98/113c7704749d037d75f23240ffc5c46dfe8416de574b946438587835715f/ckzg-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8f55e63d3f7c934a2cb53728ed1d815479e177aca8c84efe991c2920977cff6", size = 173595, upload-time = "2025-03-31T21:22:42.534Z" }, - { url = "https://files.pythonhosted.org/packages/2f/d5/05fca6dcb5a19327be491157794eafc3d7498daf615c2ff5a5b745852945/ckzg-2.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ecb42aaa0ffa427ff14a9dde9356ba69e5ae6014650b397af55b31bdae7a9b6e", size = 188417, upload-time = "2025-03-31T21:22:43.466Z" }, - { url = "https://files.pythonhosted.org/packages/72/36/131ae2dfc82d0fdc98fae8e3bbfe71ff14265bb434b23bd07b585afc6d61/ckzg-2.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5a01514239f12fb1a7ad9009c20062a4496e13b09541c1a65f97e295da648c70", size = 183286, upload-time = "2025-03-31T21:22:44.732Z" }, - { url = "https://files.pythonhosted.org/packages/c5/6a/d371b27024422b25228fc11fa57b1ba7756a94cc9fb0c75da292c235fdaa/ckzg-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:6516b9684aae262c85cf7fddd8b585b8139ad20e08ec03994e219663abbb0916", size = 98819, upload-time = "2025-03-31T21:22:45.57Z" }, - { url = "https://files.pythonhosted.org/packages/93/a1/9c07513dd0ea01e5db727e67bd2660f3b300a4511281cdb8d5e04afa1cfd/ckzg-2.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c60e8903344ce98ce036f0fabacce952abb714cad4607198b2f0961c28b8aa72", size = 116421, upload-time = "2025-03-31T21:22:46.434Z" }, - { url = "https://files.pythonhosted.org/packages/27/04/b69a0dfbb2722a14c98a52973f276679151ec56a14178cb48e6f2e1697bc/ckzg-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4299149dd72448e5a8d2d1cc6cc7472c92fc9d9f00b1377f5b017c089d9cd92", size = 100216, upload-time = "2025-03-31T21:22:47.633Z" }, - { url = "https://files.pythonhosted.org/packages/2e/24/9cc850d0b8ead395ad5064de67c7c91adacaf31b6b35292ab53fbd93270b/ckzg-2.1.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:025dd31ffdcc799f3ff842570a2a6683b6c5b01567da0109c0c05d11768729c4", size = 175764, upload-time = "2025-03-31T21:22:48.768Z" }, - { url = "https://files.pythonhosted.org/packages/c0/c1/eb13ba399082a98b932f10b230ec08e6456051c0ce3886b3f6d8548d11ab/ckzg-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b42ab8385c273f40a693657c09d2bba40cb4f4666141e263906ba2e519e80bd", size = 161885, upload-time = "2025-03-31T21:22:50.05Z" }, - { url = "https://files.pythonhosted.org/packages/57/c7/58baa64199781950c5a8c6139a46e1acff0f057a36e56769817400eb87fb/ckzg-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1be3890fc1543f4fcfc0063e4baf5c036eb14bcf736dabdc6171ab017e0f1671", size = 170757, upload-time = "2025-03-31T21:22:51.282Z" }, - { url = "https://files.pythonhosted.org/packages/65/bd/4b8e1c70972c98829371b7004dc750a45268c5d3442d602e1b62f13ca867/ckzg-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b754210ded172968b201e2d7252573af6bf52d6ad127ddd13d0b9a45a51dae7b", size = 173761, upload-time = "2025-03-31T21:22:52.6Z" }, - { url = "https://files.pythonhosted.org/packages/1f/32/c3fd1002f97ba3e0c5b1d9ab2c8fb7a6f475fa9b80ed9c4fa55975501a54/ckzg-2.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b2f8fda87865897a269c4e951e3826c2e814427a6cdfed6731cccfe548f12b36", size = 188666, upload-time = "2025-03-31T21:22:53.47Z" }, - { url = "https://files.pythonhosted.org/packages/e2/d9/91cf5a8169ee60c9397c975163cbca34432571f94facec5f8c0086bb47d8/ckzg-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:98e70b5923d77c7359432490145e9d1ab0bf873eb5de56ec53f4a551d7eaec79", size = 183652, upload-time = "2025-03-31T21:22:54.351Z" }, - { url = "https://files.pythonhosted.org/packages/25/d4/8c9f6b852f99926862344b29f0c59681916ccfec2ac60a85952a369e0bca/ckzg-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:42af7bde4ca45469cd93a96c3d15d69d51d40e7f0d30e3a20711ebd639465fcb", size = 98816, upload-time = "2025-03-31T21:22:55.23Z" }, - { url = "https://files.pythonhosted.org/packages/b7/9a/fa698b12e97452d11dd314e0335aae759725284ef6e1c1665aed56b1cd3e/ckzg-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7e4edfdaf87825ff43b9885fabfdea408737a714f4ce5467100d9d1d0a03b673", size = 116426, upload-time = "2025-03-31T21:22:56.108Z" }, - { url = "https://files.pythonhosted.org/packages/a1/a6/8cccd308bd11b49b40eecad6900b5769da117951cac33e880dd25e851ef7/ckzg-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:815fd2a87d6d6c57d669fda30c150bc9bf387d47e67d84535aa42b909fdc28ea", size = 100219, upload-time = "2025-03-31T21:22:56.982Z" }, - { url = "https://files.pythonhosted.org/packages/30/0e/63573d816c1292b9a4d70eb6a7366b3593d29a977794039e926805a76ca0/ckzg-2.1.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c32466e809b1ab3ff01d3b0bb0b9912f61dcf72957885615595f75e3f7cc10e5", size = 175725, upload-time = "2025-03-31T21:22:58.213Z" }, - { url = "https://files.pythonhosted.org/packages/86/f6/a279609516695ad3fb8b201098c669ba3b2844cbf4fa0d83a0f02b9bb29b/ckzg-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f11b73ccf37b12993f39a7dbace159c6d580aacacde6ee17282848476550ddbc", size = 161835, upload-time = "2025-03-31T21:22:59.448Z" }, - { url = "https://files.pythonhosted.org/packages/39/e4/8cf7aef7dc05a777cb221e94046f947c6fe5317159a8dae2cd7090d52ef2/ckzg-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de3b9433a1f2604bd9ac1646d3c83ad84a850d454d3ac589fe8e70c94b38a6b0", size = 170759, upload-time = "2025-03-31T21:23:01.022Z" }, - { url = "https://files.pythonhosted.org/packages/0b/17/b34e3c08eb36bc67e338b114f289b2595e581b8bdc09a8f12299a1db5d2f/ckzg-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b7d7e1b5ea06234558cd95c483666fd785a629b720a7f1622b3cbffebdc62033", size = 173787, upload-time = "2025-03-31T21:23:01.974Z" }, - { url = "https://files.pythonhosted.org/packages/2e/f0/aff87c3ed80713453cb6c84fe6fbb7582d86a7a5e4460fda2a497d47f489/ckzg-2.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9f5556e6675866040cc4335907be6c537051e7f668da289fa660fdd8a30c9ddb", size = 188722, upload-time = "2025-03-31T21:23:02.966Z" }, - { url = "https://files.pythonhosted.org/packages/44/d9/1f08bfb8fd1cbb8c7513e7ad3fb76bbb5c3fb446238c1eba582276e4d905/ckzg-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:55b2ba30c5c9daac0c55f1aac851f1b7bf1f7aa0028c2db4440e963dd5b866d6", size = 183686, upload-time = "2025-03-31T21:23:03.905Z" }, - { url = "https://files.pythonhosted.org/packages/a3/ff/434f6d2893cbdfad00c20d17e9a52d426ca042f5e980d5c3db96bc6b6e15/ckzg-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:10d201601fc8f28c0e8cec3406676797024dd374c367bbeec5a7a9eac9147237", size = 98817, upload-time = "2025-03-31T21:23:05.2Z" }, - { url = "https://files.pythonhosted.org/packages/7f/ba/7d9c1f9cec7e0e382653c72165896194a05743e589b1dae2aa80236aa87f/ckzg-2.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4b0c850bd6cad22ac79b2a2ab884e0e7cd2b54a67d643cd616c145ebdb535a11", size = 113188, upload-time = "2025-03-31T21:23:46.337Z" }, - { url = "https://files.pythonhosted.org/packages/2f/92/9728f5ccc1c5e87c6c5ae7941250a447b61fd5a63aadbc15249e29c21bcf/ckzg-2.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:26951f36bb60c9150bbd38110f5e1625596f9779dad54d1d492d8ec38bc84e3a", size = 96208, upload-time = "2025-03-31T21:23:47.255Z" }, - { url = "https://files.pythonhosted.org/packages/39/63/5e27d587bd224fee70cb66b022e7c4ef95d0e091e08ee76c25ec12094b0d/ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe12445e49c4bee67746b7b958e90a973b0de116d0390749b0df351d94e9a8c", size = 126158, upload-time = "2025-03-31T21:23:48.195Z" }, - { url = "https://files.pythonhosted.org/packages/43/98/e0a45946575a7b823d8ee0b47afb104b6017e54e1208f07da2529bc01900/ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71c5d4f66f09de4a99271acac74d2acb3559a77de77a366b34a91e99e8822667", size = 102812, upload-time = "2025-03-31T21:23:49.16Z" }, - { url = "https://files.pythonhosted.org/packages/cb/50/718ca7b03e4b89b18cdf99cc3038050105b0acbf9b612c23cd513093c6de/ckzg-2.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42673c1d007372a4e8b48f6ef8f0ce31a9688a463317a98539757d1e2fb1ecc7", size = 111327, upload-time = "2025-03-31T21:23:50.126Z" }, - { url = "https://files.pythonhosted.org/packages/29/c5/80e5a0c6967d02d801150104320484a258e5a49bd191e198643e74039320/ckzg-2.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:57a7dc41ec6b69c1d9117eb61cf001295e6b4f67a736020442e71fb4367fb1a5", size = 98847, upload-time = "2025-03-31T21:23:51.084Z" }, +version = "2.1.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/e8/b262fff67d6bcaecd19c71d19ebea9184a1204e00368664e1544a2511bd8/ckzg-2.1.5.tar.gz", hash = "sha256:e48e092f9b89ebb6aaa195de2e2bb72ad2d4b35c87d3a15e4545f13c51fbbe30", size = 1123745, upload-time = "2025-09-30T19:09:13.391Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/32/d82185ecd05a91d1a35229c587eac9c518b30693c4c983ffde37e1f5a1a2/ckzg-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cead4ba760a49eaa4d7a50a0483aad9727d6103fc00c408aef15f2cd8f8dec7b", size = 116304, upload-time = "2025-09-30T19:07:44.531Z" }, + { url = "https://files.pythonhosted.org/packages/94/a7/d22f813e032a7380f758d437348d791e8609a5c8ef2bd3654201f85a0047/ckzg-2.1.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3156983ba598fa05f0136325125e75197e4cf24ded255aaa6ace068cede92932", size = 99811, upload-time = "2025-09-30T19:07:45.311Z" }, + { url = "https://files.pythonhosted.org/packages/41/62/82ee6852a629bd9a783fb7787bcc2ee6e8c00c26b4ceb821a17484081760/ckzg-2.1.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d05e2c9466b2a4214dc19da35ea4cae636e033f3434768b982d37317a0f9c520", size = 176458, upload-time = "2025-09-30T19:07:46.433Z" }, + { url = "https://files.pythonhosted.org/packages/6d/00/5c68bb77f12eab6ba464f3955263e515ae988ddfc4bc57023b54b60feda0/ckzg-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c754bbc253cfce8814d633f135be4891e6f83a50125f418fee01323ba306f59a", size = 161841, upload-time = "2025-09-30T19:07:47.261Z" }, + { url = "https://files.pythonhosted.org/packages/42/b3/c75079d270a7895ba6b5a95f86674d5c95f2f7e0db03328f1b21dc9a90eb/ckzg-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2b766d4aed52c8c717322f2af935da0b916bf59fbba771adb822499b45e491", size = 171101, upload-time = "2025-09-30T19:07:48.471Z" }, + { url = "https://files.pythonhosted.org/packages/63/bf/81c533231f3bdc0029a0ec8abef9c24b2eaf929a044a77c15b6da54b91dc/ckzg-2.1.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dd7a296475baa5f20b5e7972448d4cb2f44d00b920d680de756c90c512af1c3b", size = 173403, upload-time = "2025-09-30T19:07:49.288Z" }, + { url = "https://files.pythonhosted.org/packages/58/6e/bbfd04b25185c6371020dd1f1c3eb0557e36878ad6cdd78a1ea2bb47d8df/ckzg-2.1.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:97d3e93b3d94031fbd376005d86bf9b2c230ecfb4a4f4ced3b06b4aeefae6c9f", size = 188738, upload-time = "2025-09-30T19:07:50.64Z" }, + { url = "https://files.pythonhosted.org/packages/3c/83/ab3cd495a2b37b72b4d886276b3669f101c4927b1d54b7e528aa537362ab/ckzg-2.1.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3d2d35ba937f002b72a9a168696d0073a8e5912fa7058e77a06c370b86586401", size = 183202, upload-time = "2025-09-30T19:07:51.544Z" }, + { url = "https://files.pythonhosted.org/packages/19/37/4ad60c2879b5e6988337b776f580b7aacb40ae6c05ef264e9835bed35e80/ckzg-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:ce2047071353ee099d44aa6575974648663204eb9b42354bfa5ac6f9b8fb63e9", size = 100965, upload-time = "2025-09-30T19:07:52.437Z" }, + { url = "https://files.pythonhosted.org/packages/dd/9f/3ef8acd201e4d098af6bc368991ac1469a5390399abd1e78307fffb65218/ckzg-2.1.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:edead535bd9afef27b8650bba09659debd4f52638aee5ec1ab7d2c9d7e86953c", size = 116333, upload-time = "2025-09-30T19:07:53.223Z" }, + { url = "https://files.pythonhosted.org/packages/25/c2/202947c143336185180216a4939296d824cbffca4e1438d0fe696daf1904/ckzg-2.1.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc78622855de3d47767cdeecfdf58fd58911f43a0fa783524e414b7e75149020", size = 99822, upload-time = "2025-09-30T19:07:54.06Z" }, + { url = "https://files.pythonhosted.org/packages/ac/20/ace67811fbabcfece937f8286cdd96f5668757b8944a74630b6454131545/ckzg-2.1.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:094add5f197a3d278924ec1480d258f3b8b0e9f8851ae409eec83a21a738bffe", size = 176595, upload-time = "2025-09-30T19:07:54.792Z" }, + { url = "https://files.pythonhosted.org/packages/f1/65/127fa59aae21688887249ec1caa92dabaced331de5cb4e0224216270c3d0/ckzg-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b4b05f798784400e8c4dedaf1a1d57bbbc54de790855855add876fff3c9f629", size = 162014, upload-time = "2025-09-30T19:07:55.776Z" }, + { url = "https://files.pythonhosted.org/packages/35/de/dcaa260f6f5aca83eb9017ea0c691d3d37458e08e24dcad5efcd348d807e/ckzg-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64aef50a1cf599041b9af018bc885a3fad6a20bbaf443fc45f0457cb47914610", size = 171396, upload-time = "2025-09-30T19:07:56.583Z" }, + { url = "https://files.pythonhosted.org/packages/c4/72/f87db164d687759ae0666a2188c5f5d11a62cac9093464efbedc1f69f4e1/ckzg-2.1.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0171484eedc42b9417a79e33aff3f35d48915b01c54f42c829b891947ac06551", size = 173548, upload-time = "2025-09-30T19:07:58.555Z" }, + { url = "https://files.pythonhosted.org/packages/03/ad/b5a88a445f27dbd39eece56edffbe986bf356003bded75f79ef59e2b37c9/ckzg-2.1.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2342b98acd7b6e6e33fbbc48ccec9093e1652461daf4353115adcd708498efcd", size = 188988, upload-time = "2025-09-30T19:07:59.496Z" }, + { url = "https://files.pythonhosted.org/packages/6e/57/42fbf29d39bd3f11a673a4e61af41b5485aa0ecf99473a0d4afc2528d24b/ckzg-2.1.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cbce75c1e17fa60b5c33bae5069b8533cf5a4d028ef7d1f755b14a16f72307cf", size = 183513, upload-time = "2025-09-30T19:08:00.341Z" }, + { url = "https://files.pythonhosted.org/packages/27/c0/ef4c9e9256088e5a425cedb80f26e2a0c853128571b027d8174caf97b2f6/ckzg-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:827be2aeffc8a10bfb39b8dad45def82164dfcde735818c4053f5064474ae1b4", size = 100992, upload-time = "2025-09-30T19:08:01.633Z" }, + { url = "https://files.pythonhosted.org/packages/ba/4b/089392b6f0015bb368b453f26330c643bf0087f77835df2328a1da2af401/ckzg-2.1.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d955f4e18bb9a9b3a6f55114052edd41650c29edd5f81e417c8f01abace8207", size = 116340, upload-time = "2025-09-30T19:08:02.478Z" }, + { url = "https://files.pythonhosted.org/packages/bb/45/4d8b70f69f0bc67e9262ec68200707d2d92a27e712cda2c163ebd4b4dcfa/ckzg-2.1.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0c0961a685761196264aa49b1cf06e8a2b2add4d57987853d7dd7a7240dc5de7", size = 99822, upload-time = "2025-09-30T19:08:03.65Z" }, + { url = "https://files.pythonhosted.org/packages/c4/95/4193e4af65dc4839fa9fe07efad689fe726303b3ba62ee2f46c403458bec/ckzg-2.1.5-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:badb1c7dc6b932bed2c3f7695e1ce3e4bcc9601706136957408ac2bde5dd0892", size = 176586, upload-time = "2025-09-30T19:08:04.818Z" }, + { url = "https://files.pythonhosted.org/packages/7d/9e/850f48cb41685f5016028dbde8f7846ce9c56bfdc2e9e0f3df1a975263fe/ckzg-2.1.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58d92816b9babaee87bd9f23be10c07d5d07c709be184aa7ea08ddb2bcf2541c", size = 161970, upload-time = "2025-09-30T19:08:05.734Z" }, + { url = "https://files.pythonhosted.org/packages/ca/df/a9993dc124e95eb30059c108efd83a1504709cf069d3bee0745d450262a0/ckzg-2.1.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cf39f9abe8b3f1a71188fb601a8589672ee40eb0671fc36d8cdf4e78f00f43f", size = 171364, upload-time = "2025-09-30T19:08:06.979Z" }, + { url = "https://files.pythonhosted.org/packages/f9/03/78e8a723c1b832766e5698f7b39cc8dc27da95b62bc5c738a59564cb5f2c/ckzg-2.1.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:999df675674d8d31528fd9b9afd548e86decc86447f5555b451237e7953fd63f", size = 173571, upload-time = "2025-09-30T19:08:08.173Z" }, + { url = "https://files.pythonhosted.org/packages/e3/64/27f96201c6d78fbdb9a0812cf45dded974c4d03d876dac11d9c764ef858f/ckzg-2.1.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c39a1c7b32ac345cc44046076fd069ad6b7e6f7bef230ef9be414c712c4453b8", size = 189014, upload-time = "2025-09-30T19:08:09.045Z" }, + { url = "https://files.pythonhosted.org/packages/d2/6e/82177c4530265694f7ec151821c79351a07706dda4d8b23e8b37d0c122f0/ckzg-2.1.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4564765b0cc65929eca057241b9c030afac1dbae015f129cb60ca6abd6ff620", size = 183530, upload-time = "2025-09-30T19:08:09.867Z" }, + { url = "https://files.pythonhosted.org/packages/4d/41/1edfbd007b0398321defeedf6ad2d9f86a73f6a99d5ca4b4944bf6f2d757/ckzg-2.1.5-cp313-cp313-win_amd64.whl", hash = "sha256:55013b36514b8176197655b929bc53f020aa51a144331720dead2efc3793ed85", size = 100992, upload-time = "2025-09-30T19:08:10.719Z" }, + { url = "https://files.pythonhosted.org/packages/03/bd/4cc75266991d2420c3212614dc6e659490bcb8c1a03a638ff688cc775ff8/ckzg-2.1.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0ae260c705a82d9cf4b88eaa2e8f86263c23d99d4ec282f22838f27d24f9306c", size = 113098, upload-time = "2025-09-30T19:08:49.956Z" }, + { url = "https://files.pythonhosted.org/packages/d6/4c/fc5e6a3463b8d8bb36d21230f41fee13d5ba3fe3f594f1c20bb9bab1fab3/ckzg-2.1.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:7c21b0a4ad05a9e32e715118695d7a0912b4ee73198d63cc98de4d585597627e", size = 95811, upload-time = "2025-09-30T19:08:50.883Z" }, + { url = "https://files.pythonhosted.org/packages/6d/2e/3be3977c57a51f516f2897d543ddca7901659ae1705b5dc3dbf54e0b66f2/ckzg-2.1.5-pp311-pypy311_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c0577aee9848d7a9cef750ff6f303f586caf33da986a762ca57ac0c57e59fb6d", size = 126633, upload-time = "2025-09-30T19:08:51.734Z" }, + { url = "https://files.pythonhosted.org/packages/72/3b/8314ca493654bd035cc0a66308cec9a1089cf3bc33c2837e3e265345f3cc/ckzg-2.1.5-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e15faa1145b2408e17e3b2f0b159de325b0198615aa30268bb6cd8f4385ed745", size = 102844, upload-time = "2025-09-30T19:08:52.621Z" }, + { url = "https://files.pythonhosted.org/packages/f4/9b/1729ee420865a71e68f18880341b37ef980c2881674dc0b06460253ef25e/ckzg-2.1.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d009dba9838630183610008a81bd80aafb389d45d8293d7a2fff7a5ea82266", size = 111739, upload-time = "2025-09-30T19:08:53.54Z" }, + { url = "https://files.pythonhosted.org/packages/40/40/f259e2bf986d39717427bc12baa8189cd43f9675e81cd3bcab639e593614/ckzg-2.1.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:df66d2be54d91f74aded4ceb71e7b1f789e2636a3015f438904a22ec9de750f1", size = 101018, upload-time = "2025-09-30T19:08:54.391Z" }, ] [[package]] @@ -363,6 +442,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f6/34/31a1604c9a9ade0fdab61eb48570e09a796f4d9836121266447b0eaf7feb/cryptography-45.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e357286c1b76403dd384d938f93c46b2b058ed4dfcdce64a770f0537ed3feb6f", size = 3331106, upload-time = "2025-07-02T13:06:18.058Z" }, ] +[[package]] +name = "cssselect2" +version = "0.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tinycss2" }, + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/86/fd7f58fc498b3166f3a7e8e0cddb6e620fe1da35b02248b1bd59e95dbaaa/cssselect2-0.8.0.tar.gz", hash = "sha256:7674ffb954a3b46162392aee2a3a0aedb2e14ecf99fcc28644900f4e6e3e9d3a", size = 35716, upload-time = "2025-03-05T14:46:07.988Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/e7/aa315e6a749d9b96c2504a1ba0ba031ba2d0517e972ce22682e3fccecb09/cssselect2-0.8.0-py3-none-any.whl", hash = "sha256:46fc70ebc41ced7a32cd42d58b1884d72ade23d21e5a4eaaf022401c13f0e76e", size = 15454, upload-time = "2025-03-05T14:46:06.463Z" }, +] + [[package]] name = "cytoolz" version = "1.0.1" @@ -416,6 +508,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/40/eb/dde173cf2357084ca9423950be1f2f11ab11d65d8bd30165bfb8fd4213e9/cytoolz-1.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:90e577e08d3a4308186d9e1ec06876d4756b1e8164b92971c69739ea17e15297", size = 362898, upload-time = "2024-12-13T05:46:12.771Z" }, ] +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + [[package]] name = "docc" version = "0.3.1" @@ -525,34 +626,6 @@ doc = [ { name = "docc" }, { name = "fladrif" }, ] -fill = [ - { name = "ckzg" }, - { name = "click" }, - { name = "coincurve" }, - { name = "colorlog" }, - { name = "eth-abi" }, - { name = "ethereum-hive" }, - { name = "ethereum-rlp" }, - { name = "ethereum-types" }, - { name = "gitpython" }, - { name = "joblib" }, - { name = "pydantic" }, - { name = "pyjwt" }, - { name = "pytest-custom-report" }, - { name = "pytest-html" }, - { name = "pytest-json-report" }, - { name = "pytest-metadata" }, - { name = "pytest-regex" }, - { name = "pyyaml" }, - { name = "questionary" }, - { name = "requests-unixsocket2" }, - { name = "rich" }, - { name = "semver" }, - { name = "tenacity" }, - { name = "trie" }, - { name = "types-pyyaml" }, - { name = "typing-extensions" }, -] lint = [ { name = "codespell" }, { name = "mypy" }, @@ -564,6 +637,7 @@ optimized = [ { name = "rust-pyspec-glue" }, ] test = [ + { name = "ethereum-execution-tests" }, { name = "filelock" }, { name = "gitpython" }, { name = "libcst" }, @@ -580,59 +654,160 @@ tools = [ [package.metadata] requires-dist = [ - { name = "ckzg", marker = "extra == 'fill'", specifier = ">=2.1.1" }, - { name = "click", marker = "extra == 'fill'", specifier = ">=8.1.0,<9" }, { name = "codespell", marker = "extra == 'lint'", specifier = "==2.4.1" }, { name = "coincurve", specifier = ">=20,<21" }, - { name = "coincurve", marker = "extra == 'fill'", specifier = ">=20.0.0,<21" }, - { name = "colorlog", marker = "extra == 'fill'", specifier = ">=6.7.0,<7" }, { name = "cryptography", specifier = ">=45.0.1,<46" }, { name = "docc", marker = "extra == 'doc'", specifier = ">=0.3.0,<0.4.0" }, - { name = "eth-abi", marker = "extra == 'fill'", specifier = ">=5.2.0" }, { name = "ethash", marker = "extra == 'optimized'", specifier = ">=1.1.0,<2" }, - { name = "ethereum-hive", marker = "extra == 'fill'", specifier = ">=0.1.0a1,<1.0.0" }, + { name = "ethereum-execution-tests", marker = "extra == 'test'", editable = "packages/tests" }, { name = "ethereum-rlp", specifier = ">=0.1.4,<0.2" }, - { name = "ethereum-rlp", marker = "extra == 'fill'", specifier = ">=0.1.3,<0.2" }, { name = "ethereum-types", specifier = ">=0.2.4,<0.3" }, - { name = "ethereum-types", marker = "extra == 'fill'", specifier = ">=0.2.1,<0.3" }, { name = "filelock", marker = "extra == 'test'", specifier = ">=3.15.1,<4" }, { name = "fladrif", marker = "extra == 'doc'", specifier = ">=0.2.0,<0.3.0" }, - { name = "gitpython", marker = "extra == 'fill'", specifier = ">=3.1.31,<4" }, { name = "gitpython", marker = "extra == 'test'", specifier = ">=3.1.0,<3.2" }, - { name = "joblib", marker = "extra == 'fill'", specifier = ">=1.4.2" }, { name = "libcst", marker = "extra == 'test'", specifier = ">=1.8,<2" }, { name = "libcst", marker = "extra == 'tools'", specifier = ">=1.8,<2" }, { name = "mypy", marker = "extra == 'lint'", specifier = "==1.17.0" }, { name = "platformdirs", marker = "extra == 'tools'", specifier = ">=4.2,<5" }, { name = "py-ecc", specifier = ">=8.0.0b2,<9" }, { name = "pycryptodome", specifier = ">=3.22,<4" }, - { name = "pydantic", marker = "extra == 'fill'", specifier = ">=2.11.0,<3" }, - { name = "pyjwt", marker = "extra == 'fill'", specifier = ">=2.3.0,<3" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8,<9" }, { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=4.1.0,<5" }, - { name = "pytest-custom-report", marker = "extra == 'fill'", specifier = ">=1.0.1,<2" }, - { name = "pytest-html", marker = "extra == 'fill'", specifier = ">=4.1.0,<5" }, - { name = "pytest-json-report", marker = "extra == 'fill'", specifier = ">=1.5.0,<2" }, - { name = "pytest-metadata", marker = "extra == 'fill'", specifier = ">=3,<4" }, - { name = "pytest-regex", marker = "extra == 'fill'", specifier = ">=0.2.0,<0.3" }, { name = "pytest-xdist", marker = "extra == 'test'", specifier = ">=3.3.1,<4" }, - { name = "pyyaml", marker = "extra == 'fill'", specifier = ">=6.0.2,<7" }, - { name = "questionary", marker = "extra == 'fill'", specifier = ">=2.1.0,<3" }, { name = "requests", marker = "extra == 'test'" }, { name = "requests-cache", marker = "extra == 'test'", specifier = ">=1.2.1,<2" }, - { name = "requests-unixsocket2", marker = "extra == 'fill'", specifier = ">=0.4.0" }, - { name = "rich", marker = "extra == 'fill'", specifier = ">=13.7.0,<14" }, { name = "ruff", marker = "extra == 'lint'", specifier = "==0.13.2" }, { name = "rust-pyspec-glue", marker = "extra == 'optimized'", specifier = ">=0.0.9,<0.1.0" }, - { name = "semver", marker = "extra == 'fill'", specifier = ">=3.0.1,<4" }, - { name = "tenacity", marker = "extra == 'fill'", specifier = ">8.2.0,<9" }, - { name = "trie", marker = "extra == 'fill'", specifier = ">=3.1.0,<4" }, - { name = "types-pyyaml", marker = "extra == 'fill'", specifier = ">=6.0.12.20240917,<7" }, { name = "typing-extensions", specifier = ">=4.4" }, - { name = "typing-extensions", marker = "extra == 'fill'", specifier = ">=4.12.2,<5" }, { name = "vulture", marker = "extra == 'lint'", specifier = "==2.14.0" }, ] -provides-extras = ["test", "fill", "lint", "tools", "doc", "optimized"] +provides-extras = ["test", "lint", "tools", "doc", "optimized"] + +[[package]] +name = "ethereum-execution-tests" +version = "1.0.0" +source = { editable = "packages/tests" } +dependencies = [ + { name = "ckzg" }, + { name = "click" }, + { name = "coincurve" }, + { name = "colorlog" }, + { name = "eth-abi" }, + { name = "ethereum-execution" }, + { name = "ethereum-hive" }, + { name = "ethereum-rlp" }, + { name = "ethereum-types" }, + { name = "filelock" }, + { name = "gitpython" }, + { name = "joblib" }, + { name = "pydantic" }, + { name = "pyjwt" }, + { name = "pytest" }, + { name = "pytest-custom-report" }, + { name = "pytest-html" }, + { name = "pytest-json-report" }, + { name = "pytest-metadata" }, + { name = "pytest-regex" }, + { name = "pytest-xdist" }, + { name = "pyyaml" }, + { name = "questionary" }, + { name = "requests" }, + { name = "requests-unixsocket2" }, + { name = "rich" }, + { name = "semver" }, + { name = "tenacity" }, + { name = "trie" }, + { name = "types-pyyaml" }, + { name = "typing-extensions" }, +] + +[package.optional-dependencies] +docs = [ + { name = "cairosvg" }, + { name = "codespell" }, + { name = "lxml" }, + { name = "markdown" }, + { name = "mike" }, + { name = "mkdocs" }, + { name = "mkdocs-click" }, + { name = "mkdocs-gen-files" }, + { name = "mkdocs-git-authors-plugin" }, + { name = "mkdocs-glightbox" }, + { name = "mkdocs-literate-nav" }, + { name = "mkdocs-material" }, + { name = "mkdocs-material-extensions" }, + { name = "mkdocstrings" }, + { name = "mkdocstrings-python" }, + { name = "pillow" }, + { name = "pyspelling" }, + { name = "setuptools" }, +] +lint = [ + { name = "mypy" }, + { name = "ruff" }, + { name = "types-requests" }, +] +test = [ + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "cairosvg", marker = "extra == 'docs'", specifier = ">=2.7.0,<3" }, + { name = "ckzg", specifier = ">=2.1.3,<3" }, + { name = "click", specifier = ">=8.1.0,<9" }, + { name = "codespell", marker = "extra == 'docs'", specifier = ">=2.4.1,<3" }, + { name = "coincurve", specifier = ">=20.0.0,<21" }, + { name = "colorlog", specifier = ">=6.7.0,<7" }, + { name = "eth-abi", specifier = ">=5.2.0" }, + { name = "ethereum-execution", editable = "." }, + { name = "ethereum-hive", specifier = ">=0.1.0a1,<1.0.0" }, + { name = "ethereum-rlp", specifier = ">=0.1.3,<0.2" }, + { name = "ethereum-types", specifier = ">=0.2.1,<0.3" }, + { name = "filelock", specifier = ">=3.15.1,<4" }, + { name = "gitpython", specifier = ">=3.1.31,<4" }, + { name = "joblib", specifier = ">=1.4.2" }, + { name = "lxml", marker = "extra == 'docs'", specifier = ">=6.0.0,<7" }, + { name = "markdown", marker = "extra == 'docs'", specifier = "==3.8" }, + { name = "mike", marker = "extra == 'docs'", specifier = ">=1.1.2,<2" }, + { name = "mkdocs", marker = "extra == 'docs'", specifier = ">=1.4.3,<2" }, + { name = "mkdocs-click", marker = "extra == 'docs'", specifier = ">=0.8,<1" }, + { name = "mkdocs-gen-files", marker = "extra == 'docs'", specifier = ">=0.5.0,<1" }, + { name = "mkdocs-git-authors-plugin", marker = "extra == 'docs'", specifier = ">=0.7.1,<1" }, + { name = "mkdocs-glightbox", marker = "extra == 'docs'", specifier = ">=0.3.4,<1" }, + { name = "mkdocs-literate-nav", marker = "extra == 'docs'", specifier = ">=0.6.0,<1" }, + { name = "mkdocs-material", marker = "extra == 'docs'", specifier = ">=9.1.14,<10" }, + { name = "mkdocs-material-extensions", marker = "extra == 'docs'", specifier = ">=1.1.1,<2" }, + { name = "mkdocstrings", marker = "extra == 'docs'", specifier = ">=0.21.2,<1" }, + { name = "mkdocstrings-python", marker = "extra == 'docs'", specifier = ">=1.0.0,<2" }, + { name = "mypy", marker = "extra == 'lint'", specifier = "==1.17.0" }, + { name = "pillow", marker = "extra == 'docs'", specifier = ">=10.0.1,<11" }, + { name = "pydantic", specifier = ">=2.11.0,<3" }, + { name = "pyjwt", specifier = ">=2.3.0,<3" }, + { name = "pyspelling", marker = "extra == 'docs'", specifier = ">=2.8.2,<3" }, + { name = "pytest", specifier = ">=8,<9" }, + { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=4.1.0,<5" }, + { name = "pytest-custom-report", specifier = ">=1.0.1,<2" }, + { name = "pytest-html", specifier = ">=4.1.0,<5" }, + { name = "pytest-json-report", specifier = ">=1.5.0,<2" }, + { name = "pytest-metadata", specifier = ">=3,<4" }, + { name = "pytest-regex", specifier = ">=0.2.0,<0.3" }, + { name = "pytest-xdist", specifier = ">=3.3.1,<4" }, + { name = "pyyaml", specifier = ">=6.0.2,<7" }, + { name = "questionary", specifier = ">=2.1.0,<3" }, + { name = "requests", specifier = ">=2.31.0,<3" }, + { name = "requests-unixsocket2", specifier = ">=0.4.0" }, + { name = "rich", specifier = ">=13.7.0,<14" }, + { name = "ruff", marker = "extra == 'lint'", specifier = "==0.13.2" }, + { name = "semver", specifier = ">=3.0.1,<4" }, + { name = "setuptools", marker = "extra == 'docs'", specifier = "==78.0.2" }, + { name = "tenacity", specifier = ">=9.0.0,<10" }, + { name = "trie", specifier = ">=3.1.0,<4" }, + { name = "types-pyyaml", specifier = ">=6.0.12.20240917,<7" }, + { name = "types-requests", marker = "extra == 'lint'", specifier = ">=2.31,<2.33" }, + { name = "typing-extensions", specifier = ">=4.12.2,<5" }, +] +provides-extras = ["test", "lint", "docs"] [[package]] name = "ethereum-hive" @@ -698,6 +873,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c4/53/2e6b79e51ed771be268dde26caa57c64d5552fd49019c7a66f9ee18330be/fladrif-0.2.0-py3-none-any.whl", hash = "sha256:34ce53c2084159d7d5cd2f886db62ca9db0569d7d1c17799ab99e62831d4c53b", size = 6371, upload-time = "2023-08-10T18:04:11.559Z" }, ] +[[package]] +name = "ghp-import" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/29/d40217cbe2f6b1359e00c6c307bb3fc876ba74068cbab3dde77f03ca0dc4/ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343", size = 10943, upload-time = "2022-05-02T15:47:16.11Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" }, +] + [[package]] name = "gitdb" version = "4.0.12" @@ -722,6 +909,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1d/9a/4114a9057db2f1462d5c8f8390ab7383925fe1ac012eaa42402ad65c2963/GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110", size = 207599, upload-time = "2025-01-02T07:32:40.731Z" }, ] +[[package]] +name = "griffe" +version = "1.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ec/d7/6c09dd7ce4c7837e4cdb11dce980cb45ae3cd87677298dc3b781b6bce7d3/griffe-1.14.0.tar.gz", hash = "sha256:9d2a15c1eca966d68e00517de5d69dd1bc5c9f2335ef6c1775362ba5b8651a13", size = 424684, upload-time = "2025-09-05T15:02:29.167Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/b1/9ff6578d789a89812ff21e4e0f80ffae20a65d5dd84e7a17873fe3b365be/griffe-1.14.0-py3-none-any.whl", hash = "sha256:0e9d52832cccf0f7188cfe585ba962d2674b241c01916d780925df34873bceb0", size = 144439, upload-time = "2025-09-05T15:02:27.511Z" }, +] + [[package]] name = "hexbytes" version = "1.3.1" @@ -731,6 +930,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8d/e0/3b31492b1c89da3c5a846680517871455b30c54738486fc57ac79a5761bd/hexbytes-1.3.1-py3-none-any.whl", hash = "sha256:da01ff24a1a9a2b1881c4b85f0e9f9b0f51b526b379ffa23832ae7899d29c2c7", size = 5074, upload-time = "2025-05-14T16:45:16.179Z" }, ] +[[package]] +name = "html5lib" +version = "1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/b6/b55c3f49042f1df3dcd422b7f224f939892ee94f22abcf503a9b7339eaf2/html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f", size = 272215, upload-time = "2020-06-22T23:32:38.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", size = 112173, upload-time = "2020-06-22T23:32:36.781Z" }, +] + [[package]] name = "idna" version = "3.10" @@ -840,6 +1052,117 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d3/8f/da755d6d517eb8ec9664afae967b00a9b8dd567bbbb350e261359c1b47fc/libcst-1.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:4f14f5045766646ed9e8826b959c6d07194788babed1e0ba08c94ea4f39517e3", size = 1974355, upload-time = "2025-06-13T20:56:18.064Z" }, ] +[[package]] +name = "lxml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/88/262177de60548e5a2bfc46ad28232c9e9cbde697bd94132aeb80364675cb/lxml-6.0.2.tar.gz", hash = "sha256:cd79f3367bd74b317dda655dc8fcfa304d9eb6e4fb06b7168c5cf27f96e0cd62", size = 4073426, upload-time = "2025-09-22T04:04:59.287Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/d5/becbe1e2569b474a23f0c672ead8a29ac50b2dc1d5b9de184831bda8d14c/lxml-6.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:13e35cbc684aadf05d8711a5d1b5857c92e5e580efa9a0d2be197199c8def607", size = 8634365, upload-time = "2025-09-22T04:00:45.672Z" }, + { url = "https://files.pythonhosted.org/packages/28/66/1ced58f12e804644426b85d0bb8a4478ca77bc1761455da310505f1a3526/lxml-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b1675e096e17c6fe9c0e8c81434f5736c0739ff9ac6123c87c2d452f48fc938", size = 4650793, upload-time = "2025-09-22T04:00:47.783Z" }, + { url = "https://files.pythonhosted.org/packages/11/84/549098ffea39dfd167e3f174b4ce983d0eed61f9d8d25b7bf2a57c3247fc/lxml-6.0.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ac6e5811ae2870953390452e3476694196f98d447573234592d30488147404d", size = 4944362, upload-time = "2025-09-22T04:00:49.845Z" }, + { url = "https://files.pythonhosted.org/packages/ac/bd/f207f16abf9749d2037453d56b643a7471d8fde855a231a12d1e095c4f01/lxml-6.0.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5aa0fc67ae19d7a64c3fe725dc9a1bb11f80e01f78289d05c6f62545affec438", size = 5083152, upload-time = "2025-09-22T04:00:51.709Z" }, + { url = "https://files.pythonhosted.org/packages/15/ae/bd813e87d8941d52ad5b65071b1affb48da01c4ed3c9c99e40abb266fbff/lxml-6.0.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de496365750cc472b4e7902a485d3f152ecf57bd3ba03ddd5578ed8ceb4c5964", size = 5023539, upload-time = "2025-09-22T04:00:53.593Z" }, + { url = "https://files.pythonhosted.org/packages/02/cd/9bfef16bd1d874fbe0cb51afb00329540f30a3283beb9f0780adbb7eec03/lxml-6.0.2-cp311-cp311-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:200069a593c5e40b8f6fc0d84d86d970ba43138c3e68619ffa234bc9bb806a4d", size = 5344853, upload-time = "2025-09-22T04:00:55.524Z" }, + { url = "https://files.pythonhosted.org/packages/b8/89/ea8f91594bc5dbb879734d35a6f2b0ad50605d7fb419de2b63d4211765cc/lxml-6.0.2-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d2de809c2ee3b888b59f995625385f74629707c9355e0ff856445cdcae682b7", size = 5225133, upload-time = "2025-09-22T04:00:57.269Z" }, + { url = "https://files.pythonhosted.org/packages/b9/37/9c735274f5dbec726b2db99b98a43950395ba3d4a1043083dba2ad814170/lxml-6.0.2-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:b2c3da8d93cf5db60e8858c17684c47d01fee6405e554fb55018dd85fc23b178", size = 4677944, upload-time = "2025-09-22T04:00:59.052Z" }, + { url = "https://files.pythonhosted.org/packages/20/28/7dfe1ba3475d8bfca3878365075abe002e05d40dfaaeb7ec01b4c587d533/lxml-6.0.2-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:442de7530296ef5e188373a1ea5789a46ce90c4847e597856570439621d9c553", size = 5284535, upload-time = "2025-09-22T04:01:01.335Z" }, + { url = "https://files.pythonhosted.org/packages/e7/cf/5f14bc0de763498fc29510e3532bf2b4b3a1c1d5d0dff2e900c16ba021ef/lxml-6.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2593c77efde7bfea7f6389f1ab249b15ed4aa5bc5cb5131faa3b843c429fbedb", size = 5067343, upload-time = "2025-09-22T04:01:03.13Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b0/bb8275ab5472f32b28cfbbcc6db7c9d092482d3439ca279d8d6fa02f7025/lxml-6.0.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3e3cb08855967a20f553ff32d147e14329b3ae70ced6edc2f282b94afbc74b2a", size = 4725419, upload-time = "2025-09-22T04:01:05.013Z" }, + { url = "https://files.pythonhosted.org/packages/25/4c/7c222753bc72edca3b99dbadba1b064209bc8ed4ad448af990e60dcce462/lxml-6.0.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2ed6c667fcbb8c19c6791bbf40b7268ef8ddf5a96940ba9404b9f9a304832f6c", size = 5275008, upload-time = "2025-09-22T04:01:07.327Z" }, + { url = "https://files.pythonhosted.org/packages/6c/8c/478a0dc6b6ed661451379447cdbec77c05741a75736d97e5b2b729687828/lxml-6.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b8f18914faec94132e5b91e69d76a5c1d7b0c73e2489ea8929c4aaa10b76bbf7", size = 5248906, upload-time = "2025-09-22T04:01:09.452Z" }, + { url = "https://files.pythonhosted.org/packages/2d/d9/5be3a6ab2784cdf9accb0703b65e1b64fcdd9311c9f007630c7db0cfcce1/lxml-6.0.2-cp311-cp311-win32.whl", hash = "sha256:6605c604e6daa9e0d7f0a2137bdc47a2e93b59c60a65466353e37f8272f47c46", size = 3610357, upload-time = "2025-09-22T04:01:11.102Z" }, + { url = "https://files.pythonhosted.org/packages/e2/7d/ca6fb13349b473d5732fb0ee3eec8f6c80fc0688e76b7d79c1008481bf1f/lxml-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e5867f2651016a3afd8dd2c8238baa66f1e2802f44bc17e236f547ace6647078", size = 4036583, upload-time = "2025-09-22T04:01:12.766Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a2/51363b5ecd3eab46563645f3a2c3836a2fc67d01a1b87c5017040f39f567/lxml-6.0.2-cp311-cp311-win_arm64.whl", hash = "sha256:4197fb2534ee05fd3e7afaab5d8bfd6c2e186f65ea7f9cd6a82809c887bd1285", size = 3680591, upload-time = "2025-09-22T04:01:14.874Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c8/8ff2bc6b920c84355146cd1ab7d181bc543b89241cfb1ebee824a7c81457/lxml-6.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:a59f5448ba2ceccd06995c95ea59a7674a10de0810f2ce90c9006f3cbc044456", size = 8661887, upload-time = "2025-09-22T04:01:17.265Z" }, + { url = "https://files.pythonhosted.org/packages/37/6f/9aae1008083bb501ef63284220ce81638332f9ccbfa53765b2b7502203cf/lxml-6.0.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e8113639f3296706fbac34a30813929e29247718e88173ad849f57ca59754924", size = 4667818, upload-time = "2025-09-22T04:01:19.688Z" }, + { url = "https://files.pythonhosted.org/packages/f1/ca/31fb37f99f37f1536c133476674c10b577e409c0a624384147653e38baf2/lxml-6.0.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a8bef9b9825fa8bc816a6e641bb67219489229ebc648be422af695f6e7a4fa7f", size = 4950807, upload-time = "2025-09-22T04:01:21.487Z" }, + { url = "https://files.pythonhosted.org/packages/da/87/f6cb9442e4bada8aab5ae7e1046264f62fdbeaa6e3f6211b93f4c0dd97f1/lxml-6.0.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:65ea18d710fd14e0186c2f973dc60bb52039a275f82d3c44a0e42b43440ea534", size = 5109179, upload-time = "2025-09-22T04:01:23.32Z" }, + { url = "https://files.pythonhosted.org/packages/c8/20/a7760713e65888db79bbae4f6146a6ae5c04e4a204a3c48896c408cd6ed2/lxml-6.0.2-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c371aa98126a0d4c739ca93ceffa0fd7a5d732e3ac66a46e74339acd4d334564", size = 5023044, upload-time = "2025-09-22T04:01:25.118Z" }, + { url = "https://files.pythonhosted.org/packages/a2/b0/7e64e0460fcb36471899f75831509098f3fd7cd02a3833ac517433cb4f8f/lxml-6.0.2-cp312-cp312-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:700efd30c0fa1a3581d80a748157397559396090a51d306ea59a70020223d16f", size = 5359685, upload-time = "2025-09-22T04:01:27.398Z" }, + { url = "https://files.pythonhosted.org/packages/b9/e1/e5df362e9ca4e2f48ed6411bd4b3a0ae737cc842e96877f5bf9428055ab4/lxml-6.0.2-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c33e66d44fe60e72397b487ee92e01da0d09ba2d66df8eae42d77b6d06e5eba0", size = 5654127, upload-time = "2025-09-22T04:01:29.629Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d1/232b3309a02d60f11e71857778bfcd4acbdb86c07db8260caf7d008b08f8/lxml-6.0.2-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90a345bbeaf9d0587a3aaffb7006aa39ccb6ff0e96a57286c0cb2fd1520ea192", size = 5253958, upload-time = "2025-09-22T04:01:31.535Z" }, + { url = "https://files.pythonhosted.org/packages/35/35/d955a070994725c4f7d80583a96cab9c107c57a125b20bb5f708fe941011/lxml-6.0.2-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:064fdadaf7a21af3ed1dcaa106b854077fbeada827c18f72aec9346847cd65d0", size = 4711541, upload-time = "2025-09-22T04:01:33.801Z" }, + { url = "https://files.pythonhosted.org/packages/1e/be/667d17363b38a78c4bd63cfd4b4632029fd68d2c2dc81f25ce9eb5224dd5/lxml-6.0.2-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fbc74f42c3525ac4ffa4b89cbdd00057b6196bcefe8bce794abd42d33a018092", size = 5267426, upload-time = "2025-09-22T04:01:35.639Z" }, + { url = "https://files.pythonhosted.org/packages/ea/47/62c70aa4a1c26569bc958c9ca86af2bb4e1f614e8c04fb2989833874f7ae/lxml-6.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6ddff43f702905a4e32bc24f3f2e2edfe0f8fde3277d481bffb709a4cced7a1f", size = 5064917, upload-time = "2025-09-22T04:01:37.448Z" }, + { url = "https://files.pythonhosted.org/packages/bd/55/6ceddaca353ebd0f1908ef712c597f8570cc9c58130dbb89903198e441fd/lxml-6.0.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6da5185951d72e6f5352166e3da7b0dc27aa70bd1090b0eb3f7f7212b53f1bb8", size = 4788795, upload-time = "2025-09-22T04:01:39.165Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e8/fd63e15da5e3fd4c2146f8bbb3c14e94ab850589beab88e547b2dbce22e1/lxml-6.0.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:57a86e1ebb4020a38d295c04fc79603c7899e0df71588043eb218722dabc087f", size = 5676759, upload-time = "2025-09-22T04:01:41.506Z" }, + { url = "https://files.pythonhosted.org/packages/76/47/b3ec58dc5c374697f5ba37412cd2728f427d056315d124dd4b61da381877/lxml-6.0.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:2047d8234fe735ab77802ce5f2297e410ff40f5238aec569ad7c8e163d7b19a6", size = 5255666, upload-time = "2025-09-22T04:01:43.363Z" }, + { url = "https://files.pythonhosted.org/packages/19/93/03ba725df4c3d72afd9596eef4a37a837ce8e4806010569bedfcd2cb68fd/lxml-6.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f91fd2b2ea15a6800c8e24418c0775a1694eefc011392da73bc6cef2623b322", size = 5277989, upload-time = "2025-09-22T04:01:45.215Z" }, + { url = "https://files.pythonhosted.org/packages/c6/80/c06de80bfce881d0ad738576f243911fccf992687ae09fd80b734712b39c/lxml-6.0.2-cp312-cp312-win32.whl", hash = "sha256:3ae2ce7d6fedfb3414a2b6c5e20b249c4c607f72cb8d2bb7cc9c6ec7c6f4e849", size = 3611456, upload-time = "2025-09-22T04:01:48.243Z" }, + { url = "https://files.pythonhosted.org/packages/f7/d7/0cdfb6c3e30893463fb3d1e52bc5f5f99684a03c29a0b6b605cfae879cd5/lxml-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:72c87e5ee4e58a8354fb9c7c84cbf95a1c8236c127a5d1b7683f04bed8361e1f", size = 4011793, upload-time = "2025-09-22T04:01:50.042Z" }, + { url = "https://files.pythonhosted.org/packages/ea/7b/93c73c67db235931527301ed3785f849c78991e2e34f3fd9a6663ffda4c5/lxml-6.0.2-cp312-cp312-win_arm64.whl", hash = "sha256:61cb10eeb95570153e0c0e554f58df92ecf5109f75eacad4a95baa709e26c3d6", size = 3672836, upload-time = "2025-09-22T04:01:52.145Z" }, + { url = "https://files.pythonhosted.org/packages/53/fd/4e8f0540608977aea078bf6d79f128e0e2c2bba8af1acf775c30baa70460/lxml-6.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9b33d21594afab46f37ae58dfadd06636f154923c4e8a4d754b0127554eb2e77", size = 8648494, upload-time = "2025-09-22T04:01:54.242Z" }, + { url = "https://files.pythonhosted.org/packages/5d/f4/2a94a3d3dfd6c6b433501b8d470a1960a20ecce93245cf2db1706adf6c19/lxml-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c8963287d7a4c5c9a432ff487c52e9c5618667179c18a204bdedb27310f022f", size = 4661146, upload-time = "2025-09-22T04:01:56.282Z" }, + { url = "https://files.pythonhosted.org/packages/25/2e/4efa677fa6b322013035d38016f6ae859d06cac67437ca7dc708a6af7028/lxml-6.0.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1941354d92699fb5ffe6ed7b32f9649e43c2feb4b97205f75866f7d21aa91452", size = 4946932, upload-time = "2025-09-22T04:01:58.989Z" }, + { url = "https://files.pythonhosted.org/packages/ce/0f/526e78a6d38d109fdbaa5049c62e1d32fdd70c75fb61c4eadf3045d3d124/lxml-6.0.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb2f6ca0ae2d983ded09357b84af659c954722bbf04dea98030064996d156048", size = 5100060, upload-time = "2025-09-22T04:02:00.812Z" }, + { url = "https://files.pythonhosted.org/packages/81/76/99de58d81fa702cc0ea7edae4f4640416c2062813a00ff24bd70ac1d9c9b/lxml-6.0.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb2a12d704f180a902d7fa778c6d71f36ceb7b0d317f34cdc76a5d05aa1dd1df", size = 5019000, upload-time = "2025-09-22T04:02:02.671Z" }, + { url = "https://files.pythonhosted.org/packages/b5/35/9e57d25482bc9a9882cb0037fdb9cc18f4b79d85df94fa9d2a89562f1d25/lxml-6.0.2-cp313-cp313-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:6ec0e3f745021bfed19c456647f0298d60a24c9ff86d9d051f52b509663feeb1", size = 5348496, upload-time = "2025-09-22T04:02:04.904Z" }, + { url = "https://files.pythonhosted.org/packages/a6/8e/cb99bd0b83ccc3e8f0f528e9aa1f7a9965dfec08c617070c5db8d63a87ce/lxml-6.0.2-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:846ae9a12d54e368933b9759052d6206a9e8b250291109c48e350c1f1f49d916", size = 5643779, upload-time = "2025-09-22T04:02:06.689Z" }, + { url = "https://files.pythonhosted.org/packages/d0/34/9e591954939276bb679b73773836c6684c22e56d05980e31d52a9a8deb18/lxml-6.0.2-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef9266d2aa545d7374938fb5c484531ef5a2ec7f2d573e62f8ce722c735685fd", size = 5244072, upload-time = "2025-09-22T04:02:08.587Z" }, + { url = "https://files.pythonhosted.org/packages/8d/27/b29ff065f9aaca443ee377aff699714fcbffb371b4fce5ac4ca759e436d5/lxml-6.0.2-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:4077b7c79f31755df33b795dc12119cb557a0106bfdab0d2c2d97bd3cf3dffa6", size = 4718675, upload-time = "2025-09-22T04:02:10.783Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/f756f9c2cd27caa1a6ef8c32ae47aadea697f5c2c6d07b0dae133c244fbe/lxml-6.0.2-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a7c5d5e5f1081955358533be077166ee97ed2571d6a66bdba6ec2f609a715d1a", size = 5255171, upload-time = "2025-09-22T04:02:12.631Z" }, + { url = "https://files.pythonhosted.org/packages/61/46/bb85ea42d2cb1bd8395484fd72f38e3389611aa496ac7772da9205bbda0e/lxml-6.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8f8d0cbd0674ee89863a523e6994ac25fd5be9c8486acfc3e5ccea679bad2679", size = 5057175, upload-time = "2025-09-22T04:02:14.718Z" }, + { url = "https://files.pythonhosted.org/packages/95/0c/443fc476dcc8e41577f0af70458c50fe299a97bb6b7505bb1ae09aa7f9ac/lxml-6.0.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2cbcbf6d6e924c28f04a43f3b6f6e272312a090f269eff68a2982e13e5d57659", size = 4785688, upload-time = "2025-09-22T04:02:16.957Z" }, + { url = "https://files.pythonhosted.org/packages/48/78/6ef0b359d45bb9697bc5a626e1992fa5d27aa3f8004b137b2314793b50a0/lxml-6.0.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dfb874cfa53340009af6bdd7e54ebc0d21012a60a4e65d927c2e477112e63484", size = 5660655, upload-time = "2025-09-22T04:02:18.815Z" }, + { url = "https://files.pythonhosted.org/packages/ff/ea/e1d33808f386bc1339d08c0dcada6e4712d4ed8e93fcad5f057070b7988a/lxml-6.0.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb8dae0b6b8b7f9e96c26fdd8121522ce5de9bb5538010870bd538683d30e9a2", size = 5247695, upload-time = "2025-09-22T04:02:20.593Z" }, + { url = "https://files.pythonhosted.org/packages/4f/47/eba75dfd8183673725255247a603b4ad606f4ae657b60c6c145b381697da/lxml-6.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:358d9adae670b63e95bc59747c72f4dc97c9ec58881d4627fe0120da0f90d314", size = 5269841, upload-time = "2025-09-22T04:02:22.489Z" }, + { url = "https://files.pythonhosted.org/packages/76/04/5c5e2b8577bc936e219becb2e98cdb1aca14a4921a12995b9d0c523502ae/lxml-6.0.2-cp313-cp313-win32.whl", hash = "sha256:e8cd2415f372e7e5a789d743d133ae474290a90b9023197fd78f32e2dc6873e2", size = 3610700, upload-time = "2025-09-22T04:02:24.465Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0a/4643ccc6bb8b143e9f9640aa54e38255f9d3b45feb2cbe7ae2ca47e8782e/lxml-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:b30d46379644fbfc3ab81f8f82ae4de55179414651f110a1514f0b1f8f6cb2d7", size = 4010347, upload-time = "2025-09-22T04:02:26.286Z" }, + { url = "https://files.pythonhosted.org/packages/31/ef/dcf1d29c3f530577f61e5fe2f1bd72929acf779953668a8a47a479ae6f26/lxml-6.0.2-cp313-cp313-win_arm64.whl", hash = "sha256:13dcecc9946dca97b11b7c40d29fba63b55ab4170d3c0cf8c0c164343b9bfdcf", size = 3671248, upload-time = "2025-09-22T04:02:27.918Z" }, + { url = "https://files.pythonhosted.org/packages/03/15/d4a377b385ab693ce97b472fe0c77c2b16ec79590e688b3ccc71fba19884/lxml-6.0.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:b0c732aa23de8f8aec23f4b580d1e52905ef468afb4abeafd3fec77042abb6fe", size = 8659801, upload-time = "2025-09-22T04:02:30.113Z" }, + { url = "https://files.pythonhosted.org/packages/c8/e8/c128e37589463668794d503afaeb003987373c5f94d667124ffd8078bbd9/lxml-6.0.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4468e3b83e10e0317a89a33d28f7aeba1caa4d1a6fd457d115dd4ffe90c5931d", size = 4659403, upload-time = "2025-09-22T04:02:32.119Z" }, + { url = "https://files.pythonhosted.org/packages/00/ce/74903904339decdf7da7847bb5741fc98a5451b42fc419a86c0c13d26fe2/lxml-6.0.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:abd44571493973bad4598a3be7e1d807ed45aa2adaf7ab92ab7c62609569b17d", size = 4966974, upload-time = "2025-09-22T04:02:34.155Z" }, + { url = "https://files.pythonhosted.org/packages/1f/d3/131dec79ce61c5567fecf82515bd9bc36395df42501b50f7f7f3bd065df0/lxml-6.0.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:370cd78d5855cfbffd57c422851f7d3864e6ae72d0da615fca4dad8c45d375a5", size = 5102953, upload-time = "2025-09-22T04:02:36.054Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ea/a43ba9bb750d4ffdd885f2cd333572f5bb900cd2408b67fdda07e85978a0/lxml-6.0.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:901e3b4219fa04ef766885fb40fa516a71662a4c61b80c94d25336b4934b71c0", size = 5055054, upload-time = "2025-09-22T04:02:38.154Z" }, + { url = "https://files.pythonhosted.org/packages/60/23/6885b451636ae286c34628f70a7ed1fcc759f8d9ad382d132e1c8d3d9bfd/lxml-6.0.2-cp314-cp314-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:a4bf42d2e4cf52c28cc1812d62426b9503cdb0c87a6de81442626aa7d69707ba", size = 5352421, upload-time = "2025-09-22T04:02:40.413Z" }, + { url = "https://files.pythonhosted.org/packages/48/5b/fc2ddfc94ddbe3eebb8e9af6e3fd65e2feba4967f6a4e9683875c394c2d8/lxml-6.0.2-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2c7fdaa4d7c3d886a42534adec7cfac73860b89b4e5298752f60aa5984641a0", size = 5673684, upload-time = "2025-09-22T04:02:42.288Z" }, + { url = "https://files.pythonhosted.org/packages/29/9c/47293c58cc91769130fbf85531280e8cc7868f7fbb6d92f4670071b9cb3e/lxml-6.0.2-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:98a5e1660dc7de2200b00d53fa00bcd3c35a3608c305d45a7bbcaf29fa16e83d", size = 5252463, upload-time = "2025-09-22T04:02:44.165Z" }, + { url = "https://files.pythonhosted.org/packages/9b/da/ba6eceb830c762b48e711ded880d7e3e89fc6c7323e587c36540b6b23c6b/lxml-6.0.2-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:dc051506c30b609238d79eda75ee9cab3e520570ec8219844a72a46020901e37", size = 4698437, upload-time = "2025-09-22T04:02:46.524Z" }, + { url = "https://files.pythonhosted.org/packages/a5/24/7be3f82cb7990b89118d944b619e53c656c97dc89c28cfb143fdb7cd6f4d/lxml-6.0.2-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8799481bbdd212470d17513a54d568f44416db01250f49449647b5ab5b5dccb9", size = 5269890, upload-time = "2025-09-22T04:02:48.812Z" }, + { url = "https://files.pythonhosted.org/packages/1b/bd/dcfb9ea1e16c665efd7538fc5d5c34071276ce9220e234217682e7d2c4a5/lxml-6.0.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9261bb77c2dab42f3ecd9103951aeca2c40277701eb7e912c545c1b16e0e4917", size = 5097185, upload-time = "2025-09-22T04:02:50.746Z" }, + { url = "https://files.pythonhosted.org/packages/21/04/a60b0ff9314736316f28316b694bccbbabe100f8483ad83852d77fc7468e/lxml-6.0.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:65ac4a01aba353cfa6d5725b95d7aed6356ddc0a3cd734de00124d285b04b64f", size = 4745895, upload-time = "2025-09-22T04:02:52.968Z" }, + { url = "https://files.pythonhosted.org/packages/d6/bd/7d54bd1846e5a310d9c715921c5faa71cf5c0853372adf78aee70c8d7aa2/lxml-6.0.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b22a07cbb82fea98f8a2fd814f3d1811ff9ed76d0fc6abc84eb21527596e7cc8", size = 5695246, upload-time = "2025-09-22T04:02:54.798Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/5643d6ab947bc371da21323acb2a6e603cedbe71cb4c99c8254289ab6f4e/lxml-6.0.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:d759cdd7f3e055d6bc8d9bec3ad905227b2e4c785dc16c372eb5b5e83123f48a", size = 5260797, upload-time = "2025-09-22T04:02:57.058Z" }, + { url = "https://files.pythonhosted.org/packages/33/da/34c1ec4cff1eea7d0b4cd44af8411806ed943141804ac9c5d565302afb78/lxml-6.0.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:945da35a48d193d27c188037a05fec5492937f66fb1958c24fc761fb9d40d43c", size = 5277404, upload-time = "2025-09-22T04:02:58.966Z" }, + { url = "https://files.pythonhosted.org/packages/82/57/4eca3e31e54dc89e2c3507e1cd411074a17565fa5ffc437c4ae0a00d439e/lxml-6.0.2-cp314-cp314-win32.whl", hash = "sha256:be3aaa60da67e6153eb15715cc2e19091af5dc75faef8b8a585aea372507384b", size = 3670072, upload-time = "2025-09-22T04:03:38.05Z" }, + { url = "https://files.pythonhosted.org/packages/e3/e0/c96cf13eccd20c9421ba910304dae0f619724dcf1702864fd59dd386404d/lxml-6.0.2-cp314-cp314-win_amd64.whl", hash = "sha256:fa25afbadead523f7001caf0c2382afd272c315a033a7b06336da2637d92d6ed", size = 4080617, upload-time = "2025-09-22T04:03:39.835Z" }, + { url = "https://files.pythonhosted.org/packages/d5/5d/b3f03e22b3d38d6f188ef044900a9b29b2fe0aebb94625ce9fe244011d34/lxml-6.0.2-cp314-cp314-win_arm64.whl", hash = "sha256:063eccf89df5b24e361b123e257e437f9e9878f425ee9aae3144c77faf6da6d8", size = 3754930, upload-time = "2025-09-22T04:03:41.565Z" }, + { url = "https://files.pythonhosted.org/packages/5e/5c/42c2c4c03554580708fc738d13414801f340c04c3eff90d8d2d227145275/lxml-6.0.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:6162a86d86893d63084faaf4ff937b3daea233e3682fb4474db07395794fa80d", size = 8910380, upload-time = "2025-09-22T04:03:01.645Z" }, + { url = "https://files.pythonhosted.org/packages/bf/4f/12df843e3e10d18d468a7557058f8d3733e8b6e12401f30b1ef29360740f/lxml-6.0.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:414aaa94e974e23a3e92e7ca5b97d10c0cf37b6481f50911032c69eeb3991bba", size = 4775632, upload-time = "2025-09-22T04:03:03.814Z" }, + { url = "https://files.pythonhosted.org/packages/e4/0c/9dc31e6c2d0d418483cbcb469d1f5a582a1cd00a1f4081953d44051f3c50/lxml-6.0.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:48461bd21625458dd01e14e2c38dd0aea69addc3c4f960c30d9f59d7f93be601", size = 4975171, upload-time = "2025-09-22T04:03:05.651Z" }, + { url = "https://files.pythonhosted.org/packages/e7/2b/9b870c6ca24c841bdd887504808f0417aa9d8d564114689266f19ddf29c8/lxml-6.0.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:25fcc59afc57d527cfc78a58f40ab4c9b8fd096a9a3f964d2781ffb6eb33f4ed", size = 5110109, upload-time = "2025-09-22T04:03:07.452Z" }, + { url = "https://files.pythonhosted.org/packages/bf/0c/4f5f2a4dd319a178912751564471355d9019e220c20d7db3fb8307ed8582/lxml-6.0.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5179c60288204e6ddde3f774a93350177e08876eaf3ab78aa3a3649d43eb7d37", size = 5041061, upload-time = "2025-09-22T04:03:09.297Z" }, + { url = "https://files.pythonhosted.org/packages/12/64/554eed290365267671fe001a20d72d14f468ae4e6acef1e179b039436967/lxml-6.0.2-cp314-cp314t-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:967aab75434de148ec80597b75062d8123cadf2943fb4281f385141e18b21338", size = 5306233, upload-time = "2025-09-22T04:03:11.651Z" }, + { url = "https://files.pythonhosted.org/packages/7a/31/1d748aa275e71802ad9722df32a7a35034246b42c0ecdd8235412c3396ef/lxml-6.0.2-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d100fcc8930d697c6561156c6810ab4a508fb264c8b6779e6e61e2ed5e7558f9", size = 5604739, upload-time = "2025-09-22T04:03:13.592Z" }, + { url = "https://files.pythonhosted.org/packages/8f/41/2c11916bcac09ed561adccacceaedd2bf0e0b25b297ea92aab99fd03d0fa/lxml-6.0.2-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ca59e7e13e5981175b8b3e4ab84d7da57993eeff53c07764dcebda0d0e64ecd", size = 5225119, upload-time = "2025-09-22T04:03:15.408Z" }, + { url = "https://files.pythonhosted.org/packages/99/05/4e5c2873d8f17aa018e6afde417c80cc5d0c33be4854cce3ef5670c49367/lxml-6.0.2-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:957448ac63a42e2e49531b9d6c0fa449a1970dbc32467aaad46f11545be9af1d", size = 4633665, upload-time = "2025-09-22T04:03:17.262Z" }, + { url = "https://files.pythonhosted.org/packages/0f/c9/dcc2da1bebd6275cdc723b515f93edf548b82f36a5458cca3578bc899332/lxml-6.0.2-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b7fc49c37f1786284b12af63152fe1d0990722497e2d5817acfe7a877522f9a9", size = 5234997, upload-time = "2025-09-22T04:03:19.14Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e2/5172e4e7468afca64a37b81dba152fc5d90e30f9c83c7c3213d6a02a5ce4/lxml-6.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e19e0643cc936a22e837f79d01a550678da8377d7d801a14487c10c34ee49c7e", size = 5090957, upload-time = "2025-09-22T04:03:21.436Z" }, + { url = "https://files.pythonhosted.org/packages/a5/b3/15461fd3e5cd4ddcb7938b87fc20b14ab113b92312fc97afe65cd7c85de1/lxml-6.0.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:1db01e5cf14345628e0cbe71067204db658e2fb8e51e7f33631f5f4735fefd8d", size = 4764372, upload-time = "2025-09-22T04:03:23.27Z" }, + { url = "https://files.pythonhosted.org/packages/05/33/f310b987c8bf9e61c4dd8e8035c416bd3230098f5e3cfa69fc4232de7059/lxml-6.0.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:875c6b5ab39ad5291588aed6925fac99d0097af0dd62f33c7b43736043d4a2ec", size = 5634653, upload-time = "2025-09-22T04:03:25.767Z" }, + { url = "https://files.pythonhosted.org/packages/70/ff/51c80e75e0bc9382158133bdcf4e339b5886c6ee2418b5199b3f1a61ed6d/lxml-6.0.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:cdcbed9ad19da81c480dfd6dd161886db6096083c9938ead313d94b30aadf272", size = 5233795, upload-time = "2025-09-22T04:03:27.62Z" }, + { url = "https://files.pythonhosted.org/packages/56/4d/4856e897df0d588789dd844dbed9d91782c4ef0b327f96ce53c807e13128/lxml-6.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:80dadc234ebc532e09be1975ff538d154a7fa61ea5031c03d25178855544728f", size = 5257023, upload-time = "2025-09-22T04:03:30.056Z" }, + { url = "https://files.pythonhosted.org/packages/0f/85/86766dfebfa87bea0ab78e9ff7a4b4b45225df4b4d3b8cc3c03c5cd68464/lxml-6.0.2-cp314-cp314t-win32.whl", hash = "sha256:da08e7bb297b04e893d91087df19638dc7a6bb858a954b0cc2b9f5053c922312", size = 3911420, upload-time = "2025-09-22T04:03:32.198Z" }, + { url = "https://files.pythonhosted.org/packages/fe/1a/b248b355834c8e32614650b8008c69ffeb0ceb149c793961dd8c0b991bb3/lxml-6.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:252a22982dca42f6155125ac76d3432e548a7625d56f5a273ee78a5057216eca", size = 4406837, upload-time = "2025-09-22T04:03:34.027Z" }, + { url = "https://files.pythonhosted.org/packages/92/aa/df863bcc39c5e0946263454aba394de8a9084dbaff8ad143846b0d844739/lxml-6.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:bb4c1847b303835d89d785a18801a883436cdfd5dc3d62947f9c49e24f0f5a2c", size = 3822205, upload-time = "2025-09-22T04:03:36.249Z" }, + { url = "https://files.pythonhosted.org/packages/0b/11/29d08bc103a62c0eba8016e7ed5aeebbf1e4312e83b0b1648dd203b0e87d/lxml-6.0.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1c06035eafa8404b5cf475bb37a9f6088b0aca288d4ccc9d69389750d5543700", size = 3949829, upload-time = "2025-09-22T04:04:45.608Z" }, + { url = "https://files.pythonhosted.org/packages/12/b3/52ab9a3b31e5ab8238da241baa19eec44d2ab426532441ee607165aebb52/lxml-6.0.2-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c7d13103045de1bdd6fe5d61802565f1a3537d70cd3abf596aa0af62761921ee", size = 4226277, upload-time = "2025-09-22T04:04:47.754Z" }, + { url = "https://files.pythonhosted.org/packages/a0/33/1eaf780c1baad88224611df13b1c2a9dfa460b526cacfe769103ff50d845/lxml-6.0.2-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a3c150a95fbe5ac91de323aa756219ef9cf7fde5a3f00e2281e30f33fa5fa4f", size = 4330433, upload-time = "2025-09-22T04:04:49.907Z" }, + { url = "https://files.pythonhosted.org/packages/7a/c1/27428a2ff348e994ab4f8777d3a0ad510b6b92d37718e5887d2da99952a2/lxml-6.0.2-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60fa43be34f78bebb27812ed90f1925ec99560b0fa1decdb7d12b84d857d31e9", size = 4272119, upload-time = "2025-09-22T04:04:51.801Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d0/3020fa12bcec4ab62f97aab026d57c2f0cfd480a558758d9ca233bb6a79d/lxml-6.0.2-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21c73b476d3cfe836be731225ec3421fa2f048d84f6df6a8e70433dff1376d5a", size = 4417314, upload-time = "2025-09-22T04:04:55.024Z" }, + { url = "https://files.pythonhosted.org/packages/6c/77/d7f491cbc05303ac6801651aabeb262d43f319288c1ea96c66b1d2692ff3/lxml-6.0.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:27220da5be049e936c3aca06f174e8827ca6445a4353a1995584311487fc4e3e", size = 3518768, upload-time = "2025-09-22T04:04:57.097Z" }, +] + +[[package]] +name = "markdown" +version = "3.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2f/15/222b423b0b88689c266d9eac4e61396fe2cc53464459d6a37618ac863b24/markdown-3.8.tar.gz", hash = "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f", size = 360906, upload-time = "2025-04-11T14:42:50.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/3f/afe76f8e2246ffbc867440cbcf90525264df0e658f8a5ca1f872b3f6192a/markdown-3.8-py3-none-any.whl", hash = "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc", size = 106210, upload-time = "2025-04-11T14:42:49.178Z" }, +] + [[package]] name = "markdown-it-py" version = "3.0.0" @@ -909,6 +1232,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] +[[package]] +name = "mergedeep" +version = "1.3.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/41/580bb4006e3ed0361b8151a01d324fb03f420815446c7def45d02f74c270/mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", size = 4661, upload-time = "2021-02-05T18:55:30.623Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307", size = 6354, upload-time = "2021-02-05T18:55:29.583Z" }, +] + +[[package]] +name = "mike" +version = "1.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jinja2" }, + { name = "mkdocs" }, + { name = "pyyaml" }, + { name = "verspec" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2d/76/2d89ba71dcf8e7a74b5e152fc8e86fe7c1f37bd86563fa8dea927f521425/mike-1.1.2.tar.gz", hash = "sha256:56c3f1794c2d0b5fdccfa9b9487beb013ca813de2e3ad0744724e9d34d40b77b", size = 28626, upload-time = "2021-10-04T05:23:46.59Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl", hash = "sha256:4c307c28769834d78df10f834f57f810f04ca27d248f80a75f49c6fa2d1527ca", size = 26933, upload-time = "2021-10-04T05:23:44.604Z" }, +] + [[package]] name = "mistletoe" version = "1.4.0" @@ -918,6 +1265,181 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/0f/b5e545f0c7962be90366af3418989b12cf441d9da1e5d89d88f2f3e5cf8f/mistletoe-1.4.0-py3-none-any.whl", hash = "sha256:44a477803861de1237ba22e375c6b617690a31d2902b47279d1f8f7ed498a794", size = 51304, upload-time = "2024-07-14T10:17:33.243Z" }, ] +[[package]] +name = "mkdocs" +version = "1.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "ghp-import" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "markupsafe" }, + { name = "mergedeep" }, + { name = "mkdocs-get-deps" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "pyyaml" }, + { name = "pyyaml-env-tag" }, + { name = "watchdog" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/c6/bbd4f061bd16b378247f12953ffcb04786a618ce5e904b8c5a01a0309061/mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2", size = 3889159, upload-time = "2024-08-30T12:24:06.899Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/5b/dbc6a8cddc9cfa9c4971d59fb12bb8d42e161b7e7f8cc89e49137c5b279c/mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e", size = 3864451, upload-time = "2024-08-30T12:24:05.054Z" }, +] + +[[package]] +name = "mkdocs-autorefs" +version = "1.4.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown" }, + { name = "markupsafe" }, + { name = "mkdocs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/51/fa/9124cd63d822e2bcbea1450ae68cdc3faf3655c69b455f3a7ed36ce6c628/mkdocs_autorefs-1.4.3.tar.gz", hash = "sha256:beee715b254455c4aa93b6ef3c67579c399ca092259cc41b7d9342573ff1fc75", size = 55425, upload-time = "2025-08-26T14:23:17.223Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/4d/7123b6fa2278000688ebd338e2a06d16870aaf9eceae6ba047ea05f92df1/mkdocs_autorefs-1.4.3-py3-none-any.whl", hash = "sha256:469d85eb3114801d08e9cc55d102b3ba65917a869b893403b8987b601cf55dc9", size = 25034, upload-time = "2025-08-26T14:23:15.906Z" }, +] + +[[package]] +name = "mkdocs-click" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "markdown" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/c7/8c25f3a3b379def41e6d0bb5c4beeab7aa8a394b17e749f498504102cfa5/mkdocs_click-0.9.0.tar.gz", hash = "sha256:6050917628d4740517541422b607404d044117bc31b770c4f9e9e1939a50c908", size = 18720, upload-time = "2025-04-07T16:59:36.387Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/fc/9124ab36e2341e78d8d9c669511bd70f52ea0de8105760c31fabec1f9396/mkdocs_click-0.9.0-py3-none-any.whl", hash = "sha256:5208e828f4f68f63c847c1ef7be48edee9964090390afc8f5b3d4cbe5ea9bbed", size = 15104, upload-time = "2025-04-07T16:59:34.807Z" }, +] + +[[package]] +name = "mkdocs-gen-files" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mkdocs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/85/2d634462fd59136197d3126ca431ffb666f412e3db38fd5ce3a60566303e/mkdocs_gen_files-0.5.0.tar.gz", hash = "sha256:4c7cf256b5d67062a788f6b1d035e157fc1a9498c2399be9af5257d4ff4d19bc", size = 7539, upload-time = "2023-04-27T19:48:04.894Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/0f/1e55b3fd490ad2cecb6e7b31892d27cb9fc4218ec1dab780440ba8579e74/mkdocs_gen_files-0.5.0-py3-none-any.whl", hash = "sha256:7ac060096f3f40bd19039e7277dd3050be9a453c8ac578645844d4d91d7978ea", size = 8380, upload-time = "2023-04-27T19:48:07.059Z" }, +] + +[[package]] +name = "mkdocs-get-deps" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mergedeep" }, + { name = "platformdirs" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/f5/ed29cd50067784976f25ed0ed6fcd3c2ce9eb90650aa3b2796ddf7b6870b/mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c", size = 10239, upload-time = "2023-11-20T17:51:09.981Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/d4/029f984e8d3f3b6b726bd33cafc473b75e9e44c0f7e80a5b29abc466bdea/mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134", size = 9521, upload-time = "2023-11-20T17:51:08.587Z" }, +] + +[[package]] +name = "mkdocs-git-authors-plugin" +version = "0.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mkdocs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/64/f1/b784c631b812aab80030db80127a576b68a84caac5229836fb7fcc00e055/mkdocs_git_authors_plugin-0.10.0.tar.gz", hash = "sha256:29d1973b2835663d79986fb756e02f1f0ff3fe35c278e993206bd3c550c205e4", size = 23432, upload-time = "2025-06-10T05:42:40.94Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/bc/a4166201c2789657c4d370bfcd71a5107edec185ae245675c8b9a6719243/mkdocs_git_authors_plugin-0.10.0-py3-none-any.whl", hash = "sha256:28421a99c3e872a8e205674bb80ec48524838243e5f59eaf9bd97df103e38901", size = 21899, upload-time = "2025-06-10T05:42:39.244Z" }, +] + +[[package]] +name = "mkdocs-glightbox" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "selectolax" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/72/c03e9d8d2dbe098d7ce5d51309933a1d3aea268965ed097ab16f4b54de15/mkdocs_glightbox-0.5.1.tar.gz", hash = "sha256:7d78a5b045f2479f61b0bbb17742ba701755c56b013e70ac189c9d87a91e80bf", size = 480028, upload-time = "2025-09-04T13:10:29.679Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/cf/e9a0ce9da269746906fdc595c030f6df66793dad1487abd1699af2ba44f1/mkdocs_glightbox-0.5.1-py3-none-any.whl", hash = "sha256:f47af0daff164edf8d36e553338425be3aab6e34b987d9cbbc2ae7819a98cb01", size = 26431, upload-time = "2025-09-04T13:10:27.933Z" }, +] + +[[package]] +name = "mkdocs-literate-nav" +version = "0.6.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mkdocs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f6/5f/99aa379b305cd1c2084d42db3d26f6de0ea9bf2cc1d10ed17f61aff35b9a/mkdocs_literate_nav-0.6.2.tar.gz", hash = "sha256:760e1708aa4be86af81a2b56e82c739d5a8388a0eab1517ecfd8e5aa40810a75", size = 17419, upload-time = "2025-03-18T21:53:09.711Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/84/b5b14d2745e4dd1a90115186284e9ee1b4d0863104011ab46abb7355a1c3/mkdocs_literate_nav-0.6.2-py3-none-any.whl", hash = "sha256:0a6489a26ec7598477b56fa112056a5e3a6c15729f0214bea8a4dbc55bd5f630", size = 13261, upload-time = "2025-03-18T21:53:08.1Z" }, +] + +[[package]] +name = "mkdocs-material" +version = "9.6.21" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "backrefs" }, + { name = "colorama" }, + { name = "jinja2" }, + { name = "markdown" }, + { name = "mkdocs" }, + { name = "mkdocs-material-extensions" }, + { name = "paginate" }, + { name = "pygments" }, + { name = "pymdown-extensions" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ff/d5/ab83ca9aa314954b0a9e8849780bdd01866a3cfcb15ffb7e3a61ca06ff0b/mkdocs_material-9.6.21.tar.gz", hash = "sha256:b01aa6d2731322438056f360f0e623d3faae981f8f2d8c68b1b973f4f2657870", size = 4043097, upload-time = "2025-09-30T19:11:27.517Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/4f/98681c2030375fe9b057dbfb9008b68f46c07dddf583f4df09bf8075e37f/mkdocs_material-9.6.21-py3-none-any.whl", hash = "sha256:aa6a5ab6fb4f6d381588ac51da8782a4d3757cb3d1b174f81a2ec126e1f22c92", size = 9203097, upload-time = "2025-09-30T19:11:24.063Z" }, +] + +[[package]] +name = "mkdocs-material-extensions" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/9b/9b4c96d6593b2a541e1cb8b34899a6d021d208bb357042823d4d2cabdbe7/mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443", size = 11847, upload-time = "2023-11-22T19:09:45.208Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/54/662a4743aa81d9582ee9339d4ffa3c8fd40a4965e033d77b9da9774d3960/mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31", size = 8728, upload-time = "2023-11-22T19:09:43.465Z" }, +] + +[[package]] +name = "mkdocstrings" +version = "0.30.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jinja2" }, + { name = "markdown" }, + { name = "markupsafe" }, + { name = "mkdocs" }, + { name = "mkdocs-autorefs" }, + { name = "pymdown-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c5/33/2fa3243439f794e685d3e694590d28469a9b8ea733af4b48c250a3ffc9a0/mkdocstrings-0.30.1.tar.gz", hash = "sha256:84a007aae9b707fb0aebfc9da23db4b26fc9ab562eb56e335e9ec480cb19744f", size = 106350, upload-time = "2025-09-19T10:49:26.446Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/2c/f0dc4e1ee7f618f5bff7e05898d20bf8b6e7fa612038f768bfa295f136a4/mkdocstrings-0.30.1-py3-none-any.whl", hash = "sha256:41bd71f284ca4d44a668816193e4025c950b002252081e387433656ae9a70a82", size = 36704, upload-time = "2025-09-19T10:49:24.805Z" }, +] + +[[package]] +name = "mkdocstrings-python" +version = "1.18.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "griffe" }, + { name = "mkdocs-autorefs" }, + { name = "mkdocstrings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/ae/58ab2bfbee2792e92a98b97e872f7c003deb903071f75d8d83aa55db28fa/mkdocstrings_python-1.18.2.tar.gz", hash = "sha256:4ad536920a07b6336f50d4c6d5603316fafb1172c5c882370cbbc954770ad323", size = 207972, upload-time = "2025-08-28T16:11:19.847Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/8f/ce008599d9adebf33ed144e7736914385e8537f5fc686fdb7cceb8c22431/mkdocstrings_python-1.18.2-py3-none-any.whl", hash = "sha256:944fe6deb8f08f33fa936d538233c4036e9f53e840994f6146e8e94eb71b600d", size = 138215, upload-time = "2025-08-28T16:11:18.176Z" }, +] + [[package]] name = "mypy" version = "1.17.0" @@ -968,6 +1490,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, ] +[[package]] +name = "paginate" +version = "0.5.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/46/68dde5b6bc00c1296ec6466ab27dddede6aec9af1b99090e1107091b3b84/paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945", size = 19252, upload-time = "2024-08-25T14:17:24.139Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/96/04b8e52da071d28f5e21a805b19cb9390aa17a47462ac87f5e2696b9566d/paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591", size = 13746, upload-time = "2024-08-25T14:17:22.55Z" }, +] + [[package]] name = "parsimonious" version = "0.10.0" @@ -989,6 +1520,47 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, ] +[[package]] +name = "pillow" +version = "10.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/74/ad3d526f3bf7b6d3f408b73fde271ec69dfac8b81341a318ce825f2b3812/pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", size = 46555059, upload-time = "2024-07-01T09:48:43.583Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c", size = 3509265, upload-time = "2024-07-01T09:45:49.812Z" }, + { url = "https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be", size = 3375655, upload-time = "2024-07-01T09:45:52.462Z" }, + { url = "https://files.pythonhosted.org/packages/73/d5/c4011a76f4207a3c151134cd22a1415741e42fa5ddecec7c0182887deb3d/pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3", size = 4340304, upload-time = "2024-07-01T09:45:55.006Z" }, + { url = "https://files.pythonhosted.org/packages/ac/10/c67e20445a707f7a610699bba4fe050583b688d8cd2d202572b257f46600/pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6", size = 4452804, upload-time = "2024-07-01T09:45:58.437Z" }, + { url = "https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe", size = 4365126, upload-time = "2024-07-01T09:46:00.713Z" }, + { url = "https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319", size = 4533541, upload-time = "2024-07-01T09:46:03.235Z" }, + { url = "https://files.pythonhosted.org/packages/f4/7c/01b8dbdca5bc6785573f4cee96e2358b0918b7b2c7b60d8b6f3abf87a070/pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d", size = 4471616, upload-time = "2024-07-01T09:46:05.356Z" }, + { url = "https://files.pythonhosted.org/packages/c8/57/2899b82394a35a0fbfd352e290945440e3b3785655a03365c0ca8279f351/pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696", size = 4600802, upload-time = "2024-07-01T09:46:08.145Z" }, + { url = "https://files.pythonhosted.org/packages/4d/d7/a44f193d4c26e58ee5d2d9db3d4854b2cfb5b5e08d360a5e03fe987c0086/pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496", size = 2235213, upload-time = "2024-07-01T09:46:10.211Z" }, + { url = "https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91", size = 2554498, upload-time = "2024-07-01T09:46:12.685Z" }, + { url = "https://files.pythonhosted.org/packages/d4/c8/310ac16ac2b97e902d9eb438688de0d961660a87703ad1561fd3dfbd2aa0/pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22", size = 2243219, upload-time = "2024-07-01T09:46:14.83Z" }, + { url = "https://files.pythonhosted.org/packages/05/cb/0353013dc30c02a8be34eb91d25e4e4cf594b59e5a55ea1128fde1e5f8ea/pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94", size = 3509350, upload-time = "2024-07-01T09:46:17.177Z" }, + { url = "https://files.pythonhosted.org/packages/e7/cf/5c558a0f247e0bf9cec92bff9b46ae6474dd736f6d906315e60e4075f737/pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597", size = 3374980, upload-time = "2024-07-01T09:46:19.169Z" }, + { url = "https://files.pythonhosted.org/packages/84/48/6e394b86369a4eb68b8a1382c78dc092245af517385c086c5094e3b34428/pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80", size = 4343799, upload-time = "2024-07-01T09:46:21.883Z" }, + { url = "https://files.pythonhosted.org/packages/3b/f3/a8c6c11fa84b59b9df0cd5694492da8c039a24cd159f0f6918690105c3be/pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca", size = 4459973, upload-time = "2024-07-01T09:46:24.321Z" }, + { url = "https://files.pythonhosted.org/packages/7d/1b/c14b4197b80150fb64453585247e6fb2e1d93761fa0fa9cf63b102fde822/pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef", size = 4370054, upload-time = "2024-07-01T09:46:26.825Z" }, + { url = "https://files.pythonhosted.org/packages/55/77/40daddf677897a923d5d33329acd52a2144d54a9644f2a5422c028c6bf2d/pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a", size = 4539484, upload-time = "2024-07-01T09:46:29.355Z" }, + { url = "https://files.pythonhosted.org/packages/40/54/90de3e4256b1207300fb2b1d7168dd912a2fb4b2401e439ba23c2b2cabde/pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b", size = 4477375, upload-time = "2024-07-01T09:46:31.756Z" }, + { url = "https://files.pythonhosted.org/packages/13/24/1bfba52f44193860918ff7c93d03d95e3f8748ca1de3ceaf11157a14cf16/pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9", size = 4608773, upload-time = "2024-07-01T09:46:33.73Z" }, + { url = "https://files.pythonhosted.org/packages/55/04/5e6de6e6120451ec0c24516c41dbaf80cce1b6451f96561235ef2429da2e/pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42", size = 2235690, upload-time = "2024-07-01T09:46:36.587Z" }, + { url = "https://files.pythonhosted.org/packages/74/0a/d4ce3c44bca8635bd29a2eab5aa181b654a734a29b263ca8efe013beea98/pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a", size = 2554951, upload-time = "2024-07-01T09:46:38.777Z" }, + { url = "https://files.pythonhosted.org/packages/b5/ca/184349ee40f2e92439be9b3502ae6cfc43ac4b50bc4fc6b3de7957563894/pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9", size = 2243427, upload-time = "2024-07-01T09:46:43.15Z" }, + { url = "https://files.pythonhosted.org/packages/c3/00/706cebe7c2c12a6318aabe5d354836f54adff7156fd9e1bd6c89f4ba0e98/pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3", size = 3525685, upload-time = "2024-07-01T09:46:45.194Z" }, + { url = "https://files.pythonhosted.org/packages/cf/76/f658cbfa49405e5ecbfb9ba42d07074ad9792031267e782d409fd8fe7c69/pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb", size = 3374883, upload-time = "2024-07-01T09:46:47.331Z" }, + { url = "https://files.pythonhosted.org/packages/46/2b/99c28c4379a85e65378211971c0b430d9c7234b1ec4d59b2668f6299e011/pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70", size = 4339837, upload-time = "2024-07-01T09:46:49.647Z" }, + { url = "https://files.pythonhosted.org/packages/f1/74/b1ec314f624c0c43711fdf0d8076f82d9d802afd58f1d62c2a86878e8615/pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be", size = 4455562, upload-time = "2024-07-01T09:46:51.811Z" }, + { url = "https://files.pythonhosted.org/packages/4a/2a/4b04157cb7b9c74372fa867096a1607e6fedad93a44deeff553ccd307868/pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0", size = 4366761, upload-time = "2024-07-01T09:46:53.961Z" }, + { url = "https://files.pythonhosted.org/packages/ac/7b/8f1d815c1a6a268fe90481232c98dd0e5fa8c75e341a75f060037bd5ceae/pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc", size = 4536767, upload-time = "2024-07-01T09:46:56.664Z" }, + { url = "https://files.pythonhosted.org/packages/e5/77/05fa64d1f45d12c22c314e7b97398ffb28ef2813a485465017b7978b3ce7/pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a", size = 4477989, upload-time = "2024-07-01T09:46:58.977Z" }, + { url = "https://files.pythonhosted.org/packages/12/63/b0397cfc2caae05c3fb2f4ed1b4fc4fc878f0243510a7a6034ca59726494/pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309", size = 4610255, upload-time = "2024-07-01T09:47:01.189Z" }, + { url = "https://files.pythonhosted.org/packages/7b/f9/cfaa5082ca9bc4a6de66ffe1c12c2d90bf09c309a5f52b27759a596900e7/pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", size = 2235603, upload-time = "2024-07-01T09:47:03.918Z" }, + { url = "https://files.pythonhosted.org/packages/01/6a/30ff0eef6e0c0e71e55ded56a38d4859bf9d3634a94a88743897b5f96936/pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", size = 2554972, upload-time = "2024-07-01T09:47:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/48/2c/2e0a52890f269435eee38b21c8218e102c621fe8d8df8b9dd06fabf879ba/pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", size = 2243375, upload-time = "2024-07-01T09:47:09.065Z" }, +] + [[package]] name = "platformdirs" version = "4.3.8" @@ -1169,6 +1741,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" }, ] +[[package]] +name = "pymdown-extensions" +version = "10.16.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/b3/6d2b3f149bc5413b0a29761c2c5832d8ce904a1d7f621e86616d96f505cc/pymdown_extensions-10.16.1.tar.gz", hash = "sha256:aace82bcccba3efc03e25d584e6a22d27a8e17caa3f4dd9f207e49b787aa9a91", size = 853277, upload-time = "2025-07-28T16:19:34.167Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/06/43084e6cbd4b3bc0e80f6be743b2e79fbc6eed8de9ad8c629939fa55d972/pymdown_extensions-10.16.1-py3-none-any.whl", hash = "sha256:d6ba157a6c03146a7fb122b2b9a121300056384eafeec9c9f9e584adfdb2a32d", size = 266178, upload-time = "2025-07-28T16:19:31.401Z" }, +] + +[[package]] +name = "pyspelling" +version = "2.11" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "html5lib" }, + { name = "lxml" }, + { name = "markdown" }, + { name = "pyyaml" }, + { name = "soupsieve" }, + { name = "wcmatch" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/67/94/7975a04dd17c815b45f5f75fa07a49770b5f230320672dea155ea0a3ca14/pyspelling-2.11.tar.gz", hash = "sha256:94cc6efa979c26779601ad666f8d986adf52d247b313337ad67aac7163749d0e", size = 149444, upload-time = "2025-08-27T15:37:59.626Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/53/3d/8e0b77306de02d45ce8dec40fc999c8723e4c9735c5576db0f2026c63bab/pyspelling-2.11-py3-none-any.whl", hash = "sha256:2690a233131e7d6c3a3d47b15beb1452826b3b0702d5f241a2bcbec0102f3893", size = 45362, upload-time = "2025-08-27T15:37:58.054Z" }, +] + [[package]] name = "pytest" version = "8.4.1" @@ -1273,6 +1876,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, ] +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + [[package]] name = "pyyaml" version = "6.0.2" @@ -1308,6 +1923,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, ] +[[package]] +name = "pyyaml-env-tag" +version = "1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/2e/79c822141bfd05a853236b504869ebc6b70159afc570e1d5a20641782eaa/pyyaml_env_tag-1.1.tar.gz", hash = "sha256:2eb38b75a2d21ee0475d6d97ec19c63287a7e140231e4214969d0eac923cd7ff", size = 5737, upload-time = "2025-05-13T15:24:01.64Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/11/432f32f8097b03e3cd5fe57e88efb685d964e2e5178a48ed61e841f7fdce/pyyaml_env_tag-1.1-py3-none-any.whl", hash = "sha256:17109e1a528561e32f026364712fee1264bc2ea6715120891174ed1b980d2e04", size = 4722, upload-time = "2025-05-13T15:23:59.629Z" }, +] + [[package]] name = "pyyaml-ft" version = "8.0.0" @@ -1516,6 +2143,44 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/75/5f/786896acb270b7d418a62d1b639341527cfe48049f35093343b6011e992c/rust_pyspec_glue-0.0.9-py3-none-manylinux_2_34_x86_64.whl", hash = "sha256:8c059a4a35229abf4ea719e35894b7d490dfdb0f26790d2a3608511e0861c2c6", size = 493646, upload-time = "2025-01-17T16:14:31.374Z" }, ] +[[package]] +name = "selectolax" +version = "0.3.29" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/b9/b5a23e29d5e54c590eaad18bdbb1ced13b869b111e03d12ee0ae9eecf9b8/selectolax-0.3.29.tar.gz", hash = "sha256:28696fa4581765c705e15d05dfba464334f5f9bcb3eac9f25045f815aec6fbc1", size = 4691626, upload-time = "2025-04-30T15:17:37.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/5d/ca72f7adddae4b2b128394a7559739a6a12c156d29b55968cfcfe07fac4d/selectolax-0.3.29-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d6a1cd0518fa7656ea1683c4b2d3b5a98306753f364da9f673517847e1680a3e", size = 3649215, upload-time = "2025-04-30T15:15:59.57Z" }, + { url = "https://files.pythonhosted.org/packages/08/c6/ca984f90b12fb10790cc56c2670f1b5f09884ed2f2012a219094b38cbcb4/selectolax-0.3.29-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3e5354d805dd76b4b38002f58e6ae2e7b429ac311bf3601992a6662d2bc86911", size = 2091848, upload-time = "2025-04-30T15:16:01.73Z" }, + { url = "https://files.pythonhosted.org/packages/98/7f/c999ae6d9bfbaac3e8dea3dbb5ca6bdf61c220828e80a6c339e89f9db777/selectolax-0.3.29-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7073e3bcdc60ebdb5f8777c79b465471ec000ab556134da4e00f037d3321a2ec", size = 5638593, upload-time = "2025-04-30T15:16:03.594Z" }, + { url = "https://files.pythonhosted.org/packages/d6/32/ffd89376a888c24ecaf01fcffc5fe97b82ae03ab163158f51a559f1ebad5/selectolax-0.3.29-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47587db7cef411d22f8224cf2926aacdb326c4c838d386035229f16ccc2d8d26", size = 5668207, upload-time = "2025-04-30T15:16:05.564Z" }, + { url = "https://files.pythonhosted.org/packages/3a/5c/2de0c7b8be75ad52d44706c67946181b972f27641ab4f6a1f27f46d2a603/selectolax-0.3.29-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:21de62b5093b1cb6c5d4cab0bef5f708b9ee1483b640d42be9d955becfcd287a", size = 5276654, upload-time = "2025-04-30T15:16:07.143Z" }, + { url = "https://files.pythonhosted.org/packages/29/29/152bb745b24072d3eecd3b395c756e74763111b9bbd265604f5b96b9a1aa/selectolax-0.3.29-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:af5cd03298cd75cb0fbf712d6ae4f8aca9c13a226d2821ca82f51cc9b33b032f", size = 5543731, upload-time = "2025-04-30T15:16:09.733Z" }, + { url = "https://files.pythonhosted.org/packages/04/1d/df65baaf16ece393f9f1a7c55f015510634adbb163ce72adcafaddf5cf9c/selectolax-0.3.29-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3f58dca53d2d3dc18dfd2cb9210a5625f32598db24e3f857f5be58f21a8f3b88", size = 5275005, upload-time = "2025-04-30T15:16:11.958Z" }, + { url = "https://files.pythonhosted.org/packages/5d/74/e56fd6f9b3087947b812f3862df3265bf5e21396d9673d076e999b1086cf/selectolax-0.3.29-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a6d8e02c6b9ba951d7b5a5dd2788a1d4bbdedc89782a4de165f1a87c4168ac", size = 5617441, upload-time = "2025-04-30T15:16:14.15Z" }, + { url = "https://files.pythonhosted.org/packages/63/d6/243049029bfc937b9f02faf4a4494e693575046414a475bf28ed9632b768/selectolax-0.3.29-cp311-cp311-win32.whl", hash = "sha256:912a1fc03157ebd066d8f59ae9ca2412ef95c7101a51590327c23071b02c97c7", size = 1701370, upload-time = "2025-04-30T15:16:16.339Z" }, + { url = "https://files.pythonhosted.org/packages/c9/7f/baba8c5ce941c8cbd2dfb0c9f2253ba2d8c2d5d0fddda4f5a87eceb2484f/selectolax-0.3.29-cp311-cp311-win_amd64.whl", hash = "sha256:a3d44a295416b79815d2858ed4ccb71bf3b63087483a5d3705daa837c9dcf44d", size = 1808251, upload-time = "2025-04-30T15:16:18.289Z" }, + { url = "https://files.pythonhosted.org/packages/30/ac/ca4332eecc19124782f6f0d7cb28c331da2e9d9cf25287ba2b3b6a00cea1/selectolax-0.3.29-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:6d3f373efd1db18ac9b2222de2668aaa366a1f0b560241eab128f3ca68e8add1", size = 3656166, upload-time = "2025-04-30T15:16:19.907Z" }, + { url = "https://files.pythonhosted.org/packages/b8/46/2dcae03a94f80f3e0d339c149de8110b5abe1230668b015fd338d9e71a27/selectolax-0.3.29-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:97b9971bb37b54ef4440134f22792d15c9ee12d890a526a7fe0b376502240143", size = 2095991, upload-time = "2025-04-30T15:16:21.654Z" }, + { url = "https://files.pythonhosted.org/packages/1e/bd/95f15396e5f30898227d84a7ec6a39d9a9b34005f0e9f8f38e7fee21ab66/selectolax-0.3.29-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd99ff0f5a6c017c471635d4ee45b61d25f24689331e407147b2cf5e36892480", size = 5844493, upload-time = "2025-04-30T15:16:23.268Z" }, + { url = "https://files.pythonhosted.org/packages/36/25/64c60da9aec81f2992355b0a3ce00ea1ed99e6f5499868016d6972bd4948/selectolax-0.3.29-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8377c317bf1d5fd6ccc56dfb5a0928bbcbea3e800b7af54761cfbbb99dc94cb9", size = 5881062, upload-time = "2025-04-30T15:16:24.891Z" }, + { url = "https://files.pythonhosted.org/packages/b6/81/94105217f91f7c6a98ac3164210cba0c6aa8da91cb85405292a6d70e39c3/selectolax-0.3.29-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5388c56456272b2c241fc1906db9cc993984cafdad936cb5e061e3af0c44144e", size = 5470368, upload-time = "2025-04-30T15:16:26.457Z" }, + { url = "https://files.pythonhosted.org/packages/51/6e/40bc259f13e5d3dd0bb8ddd1d55ef099244db2568ffb82fd9d489984d61a/selectolax-0.3.29-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e9e4690894f406863e25ba49da27e1a6fda9bfc21b0b315c399d3093be080e81", size = 5693476, upload-time = "2025-04-30T15:16:28.386Z" }, + { url = "https://files.pythonhosted.org/packages/58/bd/2668ee1d5471ad88daf83ca484515ba46774fc9c951d6c4c0beffea89952/selectolax-0.3.29-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:deeab93386b6c9a75052515f5b9e7e3dd623c585871c0c2b3126970ff902603b", size = 5449747, upload-time = "2025-04-30T15:16:30.626Z" }, + { url = "https://files.pythonhosted.org/packages/a1/b5/1c61839ae5af70a8291c643982a99f051b543df90b220b98db1b26bd4899/selectolax-0.3.29-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6abdd8357f1c105c1add01a9f0373511fa832548b2e2778b00a8ba2a4508d6ed", size = 5786843, upload-time = "2025-04-30T15:16:32.231Z" }, + { url = "https://files.pythonhosted.org/packages/67/08/ca42c100ab90168c123e6b521e38cb7618b697a693fdb77e42dabb0670fd/selectolax-0.3.29-cp312-cp312-win32.whl", hash = "sha256:9c969626b2295702076f50aac91e44c3bba639fa2e1a612bf6ae254bf29b4d57", size = 1697859, upload-time = "2025-04-30T15:16:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/5c/22/9524af51d950cc718bd4406f3bed05acbfcb321a4a308ec85b96ccdaa1ef/selectolax-0.3.29-cp312-cp312-win_amd64.whl", hash = "sha256:e7f4cc1b7ce9691559decfd5db7cc500e71a9f6ccfe76c054f284c184a1d1dc9", size = 1804145, upload-time = "2025-04-30T15:16:35.12Z" }, + { url = "https://files.pythonhosted.org/packages/c0/a7/083a00aa9cb6bef0317baba4269841c366652558d77189275bed2da6aa81/selectolax-0.3.29-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e3112f05a34bf36d36ecc51520b1d98c4667b54a3f123dffef5072273e89a360", size = 3651407, upload-time = "2025-04-30T15:16:37.282Z" }, + { url = "https://files.pythonhosted.org/packages/7e/cd/6c89ac27961ef5f5e9b40eda0d0653b9c95c93485fb8a554bf093eac1c77/selectolax-0.3.29-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:38462ae369897f71da287f1282079c11f1b878b99a4d1d509d1116ce05226d88", size = 2092649, upload-time = "2025-04-30T15:16:38.817Z" }, + { url = "https://files.pythonhosted.org/packages/3e/12/82710124b7b52613fdb9d5c14494a41785eb83e1c93ec7e1d1814c2ce292/selectolax-0.3.29-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdd1e63735f2fb8485fb6b9f4fe30d6c030930f438f46a4a62bd9886ab3c7fd9", size = 5821738, upload-time = "2025-04-30T15:16:40.747Z" }, + { url = "https://files.pythonhosted.org/packages/8b/08/8ceb3eb7fee9743026a4481fccb771f257c82b2c853a1a30271902234eab/selectolax-0.3.29-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea52e0c128e8e89f98ab0ccaabbc853677de5730729a3351da595976131b66e0", size = 5856069, upload-time = "2025-04-30T15:16:42.496Z" }, + { url = "https://files.pythonhosted.org/packages/47/6c/ec2b7aff0f6202e4157415d76bd588108cc518374bf53afa81c122691780/selectolax-0.3.29-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0933659b4250b91317ccd78167e6804389cdaf7ed86c5d034b058a550d23110f", size = 5443255, upload-time = "2025-04-30T15:16:44.083Z" }, + { url = "https://files.pythonhosted.org/packages/cd/90/d5fea46ff191d02c2380a779b119ea6799751b79fcddb2bb230b21b38fc5/selectolax-0.3.29-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0c9005e9089a6b0c6fb6a9f691ddbbb10a3a23ebeff54393980340f3dbcdb99", size = 5637529, upload-time = "2025-04-30T15:16:46.175Z" }, + { url = "https://files.pythonhosted.org/packages/9d/83/7f876a515f5af31f7b948cf10951be896fe6deeff2b9b713640c8ec82fd3/selectolax-0.3.29-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ac940963c52f13cdf5d7266a979744949b660d367ce669efa073b557f6e09a18", size = 5379121, upload-time = "2025-04-30T15:16:47.909Z" }, + { url = "https://files.pythonhosted.org/packages/57/cb/7dc739a484b1a17ccf92a23dfe558ae615c232bd81e78a72049c25d1ff66/selectolax-0.3.29-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:484274f73839f9a143f4c13ce1b0a0123b5d64be22f967a1dc202a9a78687d67", size = 5727944, upload-time = "2025-04-30T15:16:49.52Z" }, + { url = "https://files.pythonhosted.org/packages/b7/09/95da4d2919d99a6090327390b84bc5440133196351e5e04c24cccda06cbb/selectolax-0.3.29-cp313-cp313-win32.whl", hash = "sha256:29e71fbd58b90d2920ef91a940680cb5331710fe397925ce9d10c3f2f086bf27", size = 1697529, upload-time = "2025-04-30T15:16:51.123Z" }, + { url = "https://files.pythonhosted.org/packages/0e/17/5a3951da22a4ad8f959088ddc370c68b28dad03190d91fcd137a52410fb9/selectolax-0.3.29-cp313-cp313-win_amd64.whl", hash = "sha256:e13befacff5f78102aa11465055ecb6d4b35f89663e36f271f2b506bcab14112", size = 1803334, upload-time = "2025-04-30T15:16:53.775Z" }, +] + [[package]] name = "semver" version = "3.0.4" @@ -1525,6 +2190,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746", size = 17912, upload-time = "2025-01-24T13:19:24.949Z" }, ] +[[package]] +name = "setuptools" +version = "78.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/f4/aa8d364f0dc1f33b2718938648c31202e2db5cd6479a73f0a9ca5a88372d/setuptools-78.0.2.tar.gz", hash = "sha256:137525e6afb9022f019d6e884a319017f9bf879a0d8783985d32cbc8683cab93", size = 1367747, upload-time = "2025-03-24T19:50:41.896Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/db/2fd473dfe436ad19fda190f4079162d400402aedfcc41e048d38c0a375c6/setuptools-78.0.2-py3-none-any.whl", hash = "sha256:4a612c80e1f1d71b80e4906ce730152e8dec23df439f82731d9d0b608d7b700d", size = 1255965, upload-time = "2025-03-24T19:50:39.943Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + [[package]] name = "smmap" version = "5.0.2" @@ -1543,13 +2226,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, ] +[[package]] +name = "soupsieve" +version = "2.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/e6/21ccce3262dd4889aa3332e5a119a3491a95e8f60939870a3a035aabac0d/soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f", size = 103472, upload-time = "2025-08-27T15:39:51.78Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/a0/bb38d3b76b8cae341dad93a2dd83ab7462e6dbcdd84d43f54ee60a8dc167/soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c", size = 36679, upload-time = "2025-08-27T15:39:50.179Z" }, +] + [[package]] name = "tenacity" -version = "8.5.0" +version = "9.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a3/4d/6a19536c50b849338fcbe9290d562b52cbdcf30d8963d3588a68a4107df1/tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78", size = 47309, upload-time = "2024-07-05T07:25:31.836Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/d4/2b0cd0fe285e14b36db076e78c93766ff1d529d70408bd1d2a5a84f1d929/tenacity-9.1.2.tar.gz", hash = "sha256:1169d376c297e7de388d18b4481760d478b0e99a777cad3a9c86e556f4b697cb", size = 48036, upload-time = "2025-04-02T08:25:09.966Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687", size = 28165, upload-time = "2024-07-05T07:25:29.591Z" }, + { url = "https://files.pythonhosted.org/packages/e5/30/643397144bfbfec6f6ef821f36f33e57d35946c44a2352d3c9f0ae847619/tenacity-9.1.2-py3-none-any.whl", hash = "sha256:f77bf36710d8b73a50b2dd155c97b870017ad21afe6ab300326b0371b3b05138", size = 28248, upload-time = "2025-04-02T08:25:07.678Z" }, +] + +[[package]] +name = "tinycss2" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" }, ] [[package]] @@ -1625,6 +2329,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/35/3e/0346d09d6e338401ebf406f12eaf9d0b54b315b86f1ec29e34f1a0aedae9/types_pyyaml-6.0.12.20250809-py3-none-any.whl", hash = "sha256:032b6003b798e7de1a1ddfeefee32fac6486bdfe4845e0ae0e7fb3ee4512b52f", size = 20277, upload-time = "2025-08-09T03:14:34.055Z" }, ] +[[package]] +name = "types-requests" +version = "2.32.4.20250913" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/27/489922f4505975b11de2b5ad07b4fe1dca0bca9be81a703f26c5f3acfce5/types_requests-2.32.4.20250913.tar.gz", hash = "sha256:abd6d4f9ce3a9383f269775a9835a4c24e5cd6b9f647d64f88aa4613c33def5d", size = 23113, upload-time = "2025-09-13T02:40:02.309Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/20/9a227ea57c1285986c4cf78400d0a91615d25b24e257fd9e2969606bdfae/types_requests-2.32.4.20250913-py3-none-any.whl", hash = "sha256:78c9c1fffebbe0fa487a418e0fa5252017e9c60d1a2da394077f1780f655d7e1", size = 20658, upload-time = "2025-09-13T02:40:01.115Z" }, +] + [[package]] name = "typing-extensions" version = "4.14.1" @@ -1660,11 +2376,20 @@ wheels = [ [[package]] name = "urllib3" -version = "1.26.20" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e4/e8/6ff5e6bc22095cfc59b6ea711b687e2b7ed4bdb373f7eeec370a97d7392f/urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32", size = 307380, upload-time = "2024-08-29T15:43:11.37Z" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/cf/8435d5a7159e2a9c83a95896ed596f68cf798005fe107cc655b5c5c14704/urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", size = 144225, upload-time = "2024-08-29T15:43:08.921Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + +[[package]] +name = "verspec" +version = "0.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/44/8126f9f0c44319b2efc65feaad589cadef4d77ece200ae3c9133d58464d0/verspec-0.1.0.tar.gz", hash = "sha256:c4504ca697b2056cdb4bfa7121461f5a0e81809255b41c03dda4ba823637c01e", size = 27123, upload-time = "2020-11-30T02:24:09.646Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl", hash = "sha256:741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31", size = 19640, upload-time = "2020-11-30T02:24:08.387Z" }, ] [[package]] @@ -1676,6 +2401,45 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/56/0cc15b8ff2613c1d5c3dc1f3f576ede1c43868c1bc2e5ccaa2d4bcd7974d/vulture-2.14-py2.py3-none-any.whl", hash = "sha256:d9a90dba89607489548a49d557f8bac8112bd25d3cbc8aeef23e860811bd5ed9", size = 28915, upload-time = "2024-12-08T17:39:40.573Z" }, ] +[[package]] +name = "watchdog" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/db/7d/7f3d619e951c88ed75c6037b246ddcf2d322812ee8ea189be89511721d54/watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282", size = 131220, upload-time = "2024-11-01T14:07:13.037Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/24/d9be5cd6642a6aa68352ded4b4b10fb0d7889cb7f45814fb92cecd35f101/watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c", size = 96393, upload-time = "2024-11-01T14:06:31.756Z" }, + { url = "https://files.pythonhosted.org/packages/63/7a/6013b0d8dbc56adca7fdd4f0beed381c59f6752341b12fa0886fa7afc78b/watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2", size = 88392, upload-time = "2024-11-01T14:06:32.99Z" }, + { url = "https://files.pythonhosted.org/packages/d1/40/b75381494851556de56281e053700e46bff5b37bf4c7267e858640af5a7f/watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c", size = 89019, upload-time = "2024-11-01T14:06:34.963Z" }, + { url = "https://files.pythonhosted.org/packages/39/ea/3930d07dafc9e286ed356a679aa02d777c06e9bfd1164fa7c19c288a5483/watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948", size = 96471, upload-time = "2024-11-01T14:06:37.745Z" }, + { url = "https://files.pythonhosted.org/packages/12/87/48361531f70b1f87928b045df868a9fd4e253d9ae087fa4cf3f7113be363/watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860", size = 88449, upload-time = "2024-11-01T14:06:39.748Z" }, + { url = "https://files.pythonhosted.org/packages/5b/7e/8f322f5e600812e6f9a31b75d242631068ca8f4ef0582dd3ae6e72daecc8/watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0", size = 89054, upload-time = "2024-11-01T14:06:41.009Z" }, + { url = "https://files.pythonhosted.org/packages/68/98/b0345cabdce2041a01293ba483333582891a3bd5769b08eceb0d406056ef/watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c", size = 96480, upload-time = "2024-11-01T14:06:42.952Z" }, + { url = "https://files.pythonhosted.org/packages/85/83/cdf13902c626b28eedef7ec4f10745c52aad8a8fe7eb04ed7b1f111ca20e/watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134", size = 88451, upload-time = "2024-11-01T14:06:45.084Z" }, + { url = "https://files.pythonhosted.org/packages/fe/c4/225c87bae08c8b9ec99030cd48ae9c4eca050a59bf5c2255853e18c87b50/watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b", size = 89057, upload-time = "2024-11-01T14:06:47.324Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c7/ca4bf3e518cb57a686b2feb4f55a1892fd9a3dd13f470fca14e00f80ea36/watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13", size = 79079, upload-time = "2024-11-01T14:06:59.472Z" }, + { url = "https://files.pythonhosted.org/packages/5c/51/d46dc9332f9a647593c947b4b88e2381c8dfc0942d15b8edc0310fa4abb1/watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379", size = 79078, upload-time = "2024-11-01T14:07:01.431Z" }, + { url = "https://files.pythonhosted.org/packages/d4/57/04edbf5e169cd318d5f07b4766fee38e825d64b6913ca157ca32d1a42267/watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e", size = 79076, upload-time = "2024-11-01T14:07:02.568Z" }, + { url = "https://files.pythonhosted.org/packages/ab/cc/da8422b300e13cb187d2203f20b9253e91058aaf7db65b74142013478e66/watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f", size = 79077, upload-time = "2024-11-01T14:07:03.893Z" }, + { url = "https://files.pythonhosted.org/packages/2c/3b/b8964e04ae1a025c44ba8e4291f86e97fac443bca31de8bd98d3263d2fcf/watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26", size = 79078, upload-time = "2024-11-01T14:07:05.189Z" }, + { url = "https://files.pythonhosted.org/packages/62/ae/a696eb424bedff7407801c257d4b1afda455fe40821a2be430e173660e81/watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c", size = 79077, upload-time = "2024-11-01T14:07:06.376Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2", size = 79078, upload-time = "2024-11-01T14:07:07.547Z" }, + { url = "https://files.pythonhosted.org/packages/07/f6/d0e5b343768e8bcb4cda79f0f2f55051bf26177ecd5651f84c07567461cf/watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a", size = 79065, upload-time = "2024-11-01T14:07:09.525Z" }, + { url = "https://files.pythonhosted.org/packages/db/d9/c495884c6e548fce18a8f40568ff120bc3a4b7b99813081c8ac0c936fa64/watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680", size = 79070, upload-time = "2024-11-01T14:07:10.686Z" }, + { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, +] + +[[package]] +name = "wcmatch" +version = "10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bracex" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/3e/c0bdc27cf06f4e47680bd5803a07cb3dfd17de84cde92dd217dcb9e05253/wcmatch-10.1.tar.gz", hash = "sha256:f11f94208c8c8484a16f4f48638a85d771d9513f4ab3f37595978801cb9465af", size = 117421, upload-time = "2025-06-22T19:14:02.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl", hash = "sha256:5848ace7dbb0476e5e55ab63c6bbd529745089343427caa5537f230cc01beb8a", size = 39854, upload-time = "2025-06-22T19:14:00.978Z" }, +] + [[package]] name = "wcwidth" version = "0.2.13" @@ -1684,3 +2448,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc wheels = [ { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, ] + +[[package]] +name = "webencodings" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, +] From f48ad3d5b56d21bd6f3c1343e59e2b5127586d11 Mon Sep 17 00:00:00 2001 From: Sam Wilson Date: Wed, 8 Oct 2025 13:42:14 -0400 Subject: [PATCH 102/102] Add package directory to tox.ini --- .../src/ethereum_clis/clis/execution_specs.py | 24 ++++++++----------- .../src/pytest_plugins/execute/pre_alloc.py | 2 +- .../src/pytest_plugins/filler/pre_alloc.py | 2 +- tox.ini | 8 +++---- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/packages/tests/src/ethereum_clis/clis/execution_specs.py b/packages/tests/src/ethereum_clis/clis/execution_specs.py index ad0ed97408..1a97b049b6 100644 --- a/packages/tests/src/ethereum_clis/clis/execution_specs.py +++ b/packages/tests/src/ethereum_clis/clis/execution_specs.py @@ -1,14 +1,20 @@ """ Ethereum Specs EVM Transition Tool Interface. """ + import json import tempfile from io import StringIO from typing import Any, ClassVar, Dict, Optional -from ethereum_clis.file_utils import dump_files_to_directory -from ethereum_clis.transition_tool import TransitionTool, model_dump_config +import ethereum +from ethereum_spec_tools.evm_tools import create_parser +from ethereum_spec_tools.evm_tools.t8n import T8N +from ethereum_spec_tools.evm_tools.utils import get_supported_forks + from ethereum_clis.cli_types import TransitionToolOutput +from ethereum_clis.file_utils import dump_files_to_directory +from ethereum_clis.transition_tool import model_dump_config from ethereum_test_exceptions import ( BlockException, ExceptionBase, @@ -16,12 +22,6 @@ TransactionException, ) from ethereum_test_forks import Fork -from pytest_plugins.custom_logging import get_logger - -import ethereum -from ethereum_spec_tools.evm_tools import create_parser -from ethereum_spec_tools.evm_tools.t8n import T8N -from ethereum_spec_tools.evm_tools.utils import get_supported_forks from ..transition_tool import TransitionTool @@ -59,9 +59,7 @@ def evaluate( """ del slow_request request_data = transition_tool_data.get_request_data() - request_data_json = request_data.model_dump( - mode="json", **model_dump_config - ) + request_data_json = request_data.model_dump(mode="json", **model_dump_config) t8n_args = [ "t8n", @@ -127,9 +125,7 @@ def evaluate( ) if self.trace: - self.collect_traces( - output.result.receipts, temp_dir, debug_output_path - ) + self.collect_traces(output.result.receipts, temp_dir, debug_output_path) temp_dir.cleanup() return output diff --git a/packages/tests/src/pytest_plugins/execute/pre_alloc.py b/packages/tests/src/pytest_plugins/execute/pre_alloc.py index e7af7ddc80..434d4a7a4a 100644 --- a/packages/tests/src/pytest_plugins/execute/pre_alloc.py +++ b/packages/tests/src/pytest_plugins/execute/pre_alloc.py @@ -548,7 +548,7 @@ def pre( request: pytest.FixtureRequest, ) -> Generator[Alloc, None, None]: """Return default pre allocation for all tests (Empty alloc).""" - # FIXME: Static tests dont have a fork so we need to get it from the node. + # FIXME: Static tests don't have a fork so we need to get it from the node. actual_fork = fork if actual_fork is None: assert hasattr(request.node, "fork") diff --git a/packages/tests/src/pytest_plugins/filler/pre_alloc.py b/packages/tests/src/pytest_plugins/filler/pre_alloc.py index 244f28a4b2..e7a5809251 100644 --- a/packages/tests/src/pytest_plugins/filler/pre_alloc.py +++ b/packages/tests/src/pytest_plugins/filler/pre_alloc.py @@ -438,7 +438,7 @@ def pre( request: pytest.FixtureRequest, ) -> Alloc: """Return default pre allocation for all tests (Empty alloc).""" - # FIXME: Static tests dont have a fork so we need to get it from the node. + # FIXME: Static tests don't have a fork so we need to get it from the node. actual_fork = fork if actual_fork is None: assert hasattr(request.node, "fork") diff --git a/tox.ini b/tox.ini index b5be296e52..977d8ff681 100644 --- a/tox.ini +++ b/tox.ini @@ -15,10 +15,10 @@ extras = test doc commands = - codespell -I whitelist.txt src tests --skip 'tests/eest' - ruff check src tests --exclude tests/eest - ruff format src tests --check --exclude tests/eest - mypy src tests --exclude "tests/json_infra/fixtures/*|tests/eest/*" --namespace-packages + codespell -I whitelist.txt src tests packages --skip 'tests/eest' + ruff check src tests packages --exclude tests/eest + ruff format src tests packages --check --exclude tests/eest + mypy src tests --exclude "tests/json_infra/fixtures/*|tests/eest/*" --namespace-packages # TODO: add packages directory ethereum-spec-lint uv lock --check