From 714db1e257fec7f61106372308501fe35d4c3f09 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 15 Jul 2024 11:33:57 -0300 Subject: [PATCH 01/73] refactor genesis state for eip7732 --- specs/_features/eip7732/beacon-chain.md | 62 +++++++++++++++++++ .../bellatrix/genesis/test_initialization.py | 5 +- .../pyspec/eth2spec/test/helpers/genesis.py | 21 ++++++- 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/specs/_features/eip7732/beacon-chain.md b/specs/_features/eip7732/beacon-chain.md index fdcb2b3008..abce7250b6 100644 --- a/specs/_features/eip7732/beacon-chain.md +++ b/specs/_features/eip7732/beacon-chain.md @@ -714,3 +714,65 @@ def validate_merge_block(block: BeaconBlock) -> None: # Check if `pow_block` is a valid terminal PoW block assert is_valid_terminal_pow_block(pow_block, pow_parent) ``` + +## Testing + +*Note*: The function `initialize_beacon_state_from_eth1` is modified for pure EIP-7732 testing only. +Modifications include: +1. Use `EIP7732_FORK_VERSION` as the previous and current fork version. + +```python +def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32, + eth1_timestamp: uint64, + deposits: Sequence[Deposit], + execution_payload_header: ExecutionPayloadHeader=ExecutionPayloadHeader() + ) -> BeaconState: + fork = Fork( + previous_version=EIP7732_FORK_VERSION, # [Modified in EIP-7732] + current_version=EIP7732_FORK_VERSION, # [Modified in EIP-7732] + epoch=GENESIS_EPOCH, + ) + state = BeaconState( + genesis_time=eth1_timestamp + GENESIS_DELAY, + fork=fork, + eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))), + latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())), + randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy + deposit_requests_start_index=UNSET_DEPOSIT_REQUESTS_START_INDEX, # [New in Electra:EIP6110] + ) + + # Process deposits + leaves = list(map(lambda deposit: deposit.data, deposits)) + for index, deposit in enumerate(deposits): + deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1]) + state.eth1_data.deposit_root = hash_tree_root(deposit_data_list) + process_deposit(state, deposit) + + # Process deposit balance updates + for deposit in state.pending_balance_deposits: + increase_balance(state, deposit.index, deposit.amount) + state.pending_balance_deposits = [] + + # Process activations + for index, validator in enumerate(state.validators): + balance = state.balances[index] + # [Modified in Electra:EIP7251] + validator.effective_balance = min( + balance - balance % EFFECTIVE_BALANCE_INCREMENT, get_validator_max_effective_balance(validator)) + if validator.effective_balance >= MIN_ACTIVATION_BALANCE: + validator.activation_eligibility_epoch = GENESIS_EPOCH + validator.activation_epoch = GENESIS_EPOCH + + # Set genesis validators root for domain separation and chain versioning + state.genesis_validators_root = hash_tree_root(state.validators) + + # Fill in sync committees + # Note: A duplicate committee is assigned for the current and next committee at genesis + state.current_sync_committee = get_next_sync_committee(state) + state.next_sync_committee = get_next_sync_committee(state) + + # Initialize the execution payload header + state.latest_execution_payload_header = execution_payload_header + + return state +``` diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/genesis/test_initialization.py b/tests/core/pyspec/eth2spec/test/bellatrix/genesis/test_initialization.py index 140d8708ca..b4d0f86dab 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/genesis/test_initialization.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/genesis/test_initialization.py @@ -107,7 +107,10 @@ def test_initialize_post_transition(spec): # initialize beacon_state *with* an execution_payload_header yield 'execution_payload_header', 'meta', True - genesis_execution_payload_header = get_sample_genesis_execution_payload_header(spec) + genesis_execution_payload_header = get_sample_genesis_execution_payload_header( + spec, + spec.compute_start_slot_at_epoch(spec.GENESIS_EPOCH) + ) state = spec.initialize_beacon_state_from_eth1( eth1_block_hash, eth1_timestamp, diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index 95c1e97e55..f80565499f 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -6,12 +6,12 @@ compute_el_header_block_hash, ) from eth2spec.test.helpers.forks import ( - is_post_altair, is_post_bellatrix, is_post_capella, is_post_deneb, is_post_electra, is_post_whisk, + is_post_altair, is_post_bellatrix, is_post_capella, is_post_deneb, + is_post_electra, is_post_whisk, is_post_eip7732 ) from eth2spec.test.helpers.keys import pubkeys from eth2spec.test.helpers.whisk import compute_whisk_initial_tracker_cached, compute_whisk_initial_k_commitment_cached - def build_mock_validator(spec, i: int, balance: int): active_pubkey = pubkeys[i] withdrawal_pubkey = pubkeys[-1 - i] @@ -45,10 +45,24 @@ def build_mock_validator(spec, i: int, balance: int): return validator -def get_sample_genesis_execution_payload_header(spec, +def get_post_eip7732_genesis_execution_payload_header(spec, slot, eth1_block_hash): + header = spec.ExecutionPayloadHeader( + parent_block_hash=b'\x30' * 32, + parent_block_root=b'\x00' * 32, + block_hash=eth1_block_hash, + gas_limit=30000000, + slot=slot, + blob_kzg_commitments_root=b'\x20' * 32, + ) + return header + + +def get_sample_genesis_execution_payload_header(spec, slot, eth1_block_hash=None): if eth1_block_hash is None: eth1_block_hash = b'\x55' * 32 + if is_post_eip7732(spec): + return get_post_eip7732_genesis_execution_payload_header(spec, slot, eth1_block_hash) payload_header = spec.ExecutionPayloadHeader( parent_hash=b'\x30' * 32, fee_recipient=b'\x42' * 20, @@ -146,6 +160,7 @@ def create_genesis_state(spec, validator_balances, activation_threshold): # Initialize the execution payload header (with block number and genesis time set to 0) state.latest_execution_payload_header = get_sample_genesis_execution_payload_header( spec, + spec.compute_start_slot_at_epoch(spec.GENESIS_EPOCH), eth1_block_hash=eth1_block_hash, ) From 0ae49b0e096381af56c116018b18fb36fb28e65e Mon Sep 17 00:00:00 2001 From: Potuz Date: Thu, 4 Jul 2024 13:23:32 -0300 Subject: [PATCH 02/73] Revert "Disable eip7732 tests like whisk-style" This reverts commit aac95e2dc4ce4666febc2eac4e0216c8b8b2cda5. --- .circleci/config.yml | 13 +++++++++++++ .github/workflows/run-tests.yml | 2 +- .../core/pyspec/eth2spec/test/helpers/constants.py | 6 ++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7ac281dea9..9c998f2311 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -194,6 +194,19 @@ jobs: command: make citest fork=eip7594 - store_test_results: path: tests/core/pyspec/test-reports + test-eip7732: + docker: + - image: circleci/python:3.9 + working_directory: ~/specs-repo + steps: + - restore_cache: + key: v3-specs-repo-{{ .Branch }}-{{ .Revision }} + - restore_pyspec_cached_venv + - run: + name: Run py-tests + command: make citest fork=eip7732 + - store_test_results: + path: tests/core/pyspec/test-reports table_of_contents: docker: - image: circleci/node:10.16.3 diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 83926c47c5..63d5ff7889 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -74,7 +74,7 @@ jobs: needs: [lint,codespell,table_of_contents] strategy: matrix: - version: ["phase0", "altair", "bellatrix", "capella", "deneb", "electra", "whisk", "eip7594"] + version: ["phase0", "altair", "bellatrix", "capella", "deneb", "electra", "whisk", "eip7594", "eip7732"] steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/tests/core/pyspec/eth2spec/test/helpers/constants.py b/tests/core/pyspec/eth2spec/test/helpers/constants.py index 7e5d0a0f4c..ecb290c04b 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/constants.py +++ b/tests/core/pyspec/eth2spec/test/helpers/constants.py @@ -38,13 +38,14 @@ ELECTRA, # Experimental patches EIP7594, + EIP7732, ) # The forks that have light client specs LIGHT_CLIENT_TESTING_FORKS = (*[item for item in MAINNET_FORKS if item != PHASE0], ELECTRA) # The forks that output to the test vectors. -TESTGEN_FORKS = (*MAINNET_FORKS, ELECTRA, EIP7594, WHISK) +TESTGEN_FORKS = (*MAINNET_FORKS, ELECTRA, EIP7594, WHISK, EIP7732) # Forks allowed in the test runner `--fork` flag, to fail fast in case of typos -ALLOWED_TEST_RUNNER_FORKS = (*ALL_PHASES, WHISK, EIP7732) +ALLOWED_TEST_RUNNER_FORKS = (*ALL_PHASES, WHISK) # NOTE: the same definition as in `pysetup/md_doc_paths.py` PREVIOUS_FORK_OF = { @@ -69,6 +70,7 @@ BELLATRIX: CAPELLA, CAPELLA: DENEB, DENEB: ELECTRA, + ELECTRA: EIP7732, } ALL_PRE_POST_FORKS = POST_FORK_OF.items() From 2be168c2a2689182cc4aacad4d425715f3f279ff Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 21 Aug 2024 16:25:36 -0300 Subject: [PATCH 03/73] Fixes some more python tests - Disables blocks with blobs in deneb tests - Correctly starts forkchoice on `get_forkchoice_store` --- tests/core/pyspec/eth2spec/test/context.py | 31 +++++++++++++++++-- .../eth2spec/test/deneb/sanity/test_blocks.py | 20 ++++++------ .../pyspec/eth2spec/test/helpers/genesis.py | 1 + 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 8b2e8de6d3..ca13723f0c 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -8,7 +8,7 @@ from .exceptions import SkippedTest from .helpers.constants import ( PHASE0, ALTAIR, BELLATRIX, CAPELLA, DENEB, ELECTRA, - EIP7594, + EIP7594, EIP7732, WHISK, MINIMAL, ALL_PHASES, @@ -422,7 +422,8 @@ def with_all_phases(fn): def with_all_phases_from(earliest_phase, all_phases=ALL_PHASES): """ - A decorator factory for running a tests with every phase except the ones listed + A decorator factory for running a tests with every phase starting at `earliest_phase` + excluding the ones listed. """ def decorator(fn): return with_phases([phase for phase in all_phases if is_post_fork(phase, earliest_phase)])(fn) @@ -436,6 +437,30 @@ def with_all_phases_from_except(earliest_phase, except_phases=None): return with_all_phases_from(earliest_phase, [phase for phase in ALL_PHASES if phase not in except_phases]) +def with_all_phases_from_to(earliest_phase, latest_phase, all_phases=ALL_PHASES): + """ + A decorator factory for running a tests with every phase starting at `earliest_phase` + and ending at `latest_phase` excluding the ones listed. + """ + def decorator(fn): + return with_phases([phase for phase in all_phases if + is_post_fork(phase, earliest_phase) and not + is_post_fork(phase, latest_phase)])(fn) + return decorator + + +def with_all_phases_from_to_except(earliest_phase, latest_phase, except_phases=None): + """ + A decorator factory for running a tests with every phase starting at `earliest_phase` + and ending at `latest_phase` excluding the ones listed. + """ + def decorator(fn): + return with_phases([phase for phase in ALL_PHASES if phase not in except_phases and + is_post_fork(phase, earliest_phase) and not + is_post_fork(phase, latest_phase)])(fn) + return decorator + + def with_all_phases_except(exclusion_phases): """ A decorator factory for running a tests with every phase except the ones listed @@ -560,6 +585,8 @@ def wrapper(*args, spec: Spec, **kw): with_whisk_and_later = with_all_phases_from(WHISK, all_phases=ALLOWED_TEST_RUNNER_FORKS) with_eip7594_and_later = with_all_phases_from(EIP7594, all_phases=ALLOWED_TEST_RUNNER_FORKS) +with_deneb_and_before_eip7732 = with_all_phases_from_to(DENEB, EIP7732) + class quoted_str(str): pass diff --git a/tests/core/pyspec/eth2spec/test/deneb/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/deneb/sanity/test_blocks.py index 94db2c34fc..eeeacb6dff 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/deneb/sanity/test_blocks.py @@ -8,7 +8,7 @@ ) from eth2spec.test.context import ( spec_state_test, - with_deneb_and_later, + with_deneb_and_before_eip7732, ) from eth2spec.test.helpers.execution_payload import ( compute_el_block_hash, @@ -51,55 +51,55 @@ def run_block_with_blobs(spec, state, blob_count, tx_count=1, blob_gas_used=1, e yield 'post', state if valid else None -@with_deneb_and_later +@with_deneb_and_before_eip7732 @spec_state_test def test_zero_blob(spec, state): yield from run_block_with_blobs(spec, state, blob_count=0) -@with_deneb_and_later +@with_deneb_and_before_eip7732 @spec_state_test def test_one_blob(spec, state): yield from run_block_with_blobs(spec, state, blob_count=1) -@with_deneb_and_later +@with_deneb_and_before_eip7732 @spec_state_test def test_one_blob_two_txs(spec, state): yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=2) -@with_deneb_and_later +@with_deneb_and_before_eip7732 @spec_state_test def test_one_blob_max_txs(spec, state): yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=spec.MAX_BLOBS_PER_BLOCK) -@with_deneb_and_later +@with_deneb_and_before_eip7732 @spec_state_test def test_invalid_one_blob_max_plus_one_txs(spec, state): yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=spec.MAX_BLOBS_PER_BLOCK + 1, valid=False) -@with_deneb_and_later +@with_deneb_and_before_eip7732 @spec_state_test def test_max_blobs_per_block(spec, state): yield from run_block_with_blobs(spec, state, blob_count=spec.MAX_BLOBS_PER_BLOCK) -@with_deneb_and_later +@with_deneb_and_before_eip7732 @spec_state_test def test_invalid_max_blobs_per_block_two_txs(spec, state): yield from run_block_with_blobs(spec, state, blob_count=spec.MAX_BLOBS_PER_BLOCK, tx_count=2, valid=False) -@with_deneb_and_later +@with_deneb_and_before_eip7732 @spec_state_test def test_invalid_exceed_max_blobs_per_block(spec, state): yield from run_block_with_blobs(spec, state, blob_count=spec.MAX_BLOBS_PER_BLOCK + 1, valid=False) -@with_deneb_and_later +@with_deneb_and_before_eip7732 @spec_state_test def test_mix_blob_tx_and_non_blob_tx(spec, state): yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=1, non_blob_tx_count=1) diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index f80565499f..7aae9404f1 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -12,6 +12,7 @@ from eth2spec.test.helpers.keys import pubkeys from eth2spec.test.helpers.whisk import compute_whisk_initial_tracker_cached, compute_whisk_initial_k_commitment_cached + def build_mock_validator(spec, i: int, balance: int): active_pubkey = pubkeys[i] withdrawal_pubkey = pubkeys[-1 - i] From 7e092f62419309adf296d9fdd27a358878195070 Mon Sep 17 00:00:00 2001 From: Potuz Date: Thu, 4 Jul 2024 15:16:07 -0300 Subject: [PATCH 04/73] deal with new get_head reply --- .../capella/block_processing/test_process_withdrawals.py | 6 +++++- tests/core/pyspec/eth2spec/test/helpers/fork_choice.py | 7 +++++++ .../eth2spec/test/phase0/fork_choice/test_ex_ante.py | 8 +++++++- .../phase0/unittests/fork_choice/test_on_attestation.py | 9 +++++++-- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py index 891ad35ed6..b8a342f4ea 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py @@ -11,6 +11,7 @@ build_empty_execution_payload, compute_el_block_hash, ) +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.random import ( randomize_state, ) @@ -77,7 +78,10 @@ def run_withdrawals_processing(spec, state, execution_payload, num_expected_with yield 'post', None return - spec.process_withdrawals(state, execution_payload) + if is_post_eip7732: + spec.process_withdrawals(state) + else: + spec.process_withdrawals(state, execution_payload) yield 'post', state diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 8598870fb6..76495f9d42 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -2,6 +2,7 @@ from eth_utils import encode_hex from eth2spec.test.exceptions import BlockNotFoundException +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.attestations import ( next_epoch_with_attestations, next_slots_with_attestations, @@ -267,6 +268,12 @@ def add_attester_slashing(spec, store, attester_slashing, test_steps, valid=True def get_formatted_head_output(spec, store): head = spec.get_head(store) + if is_post_eip7732: + return { + 'slot': int(head.slot), + 'root': encode_hex(head.root), + } + slot = store.blocks[head].slot return { 'slot': int(slot), diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py index 9978f7d46c..5b7fb5ca88 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py @@ -11,6 +11,7 @@ build_empty_block, ) from eth2spec.test.helpers.constants import MAINNET +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.fork_choice import ( get_genesis_forkchoice_store_and_block, on_tick_and_append_step, @@ -28,7 +29,12 @@ def _apply_base_block_a(spec, state, store, test_steps): block = build_empty_block(spec, state, slot=state.slot + 1) signed_block_a = state_transition_and_sign_block(spec, state, block) yield from tick_and_add_block(spec, store, signed_block_a, test_steps) - assert spec.get_head(store) == signed_block_a.message.hash_tree_root() + head = spec.get_head(store) + expected_root = signed_block_a.message.hash_tree_root() + if is_post_eip7732: + assert head.root == expected_root + else: + assert spec.get_head(store) == signed_block_a.message.hash_tree_root() @with_altair_and_later diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py index e3ec931b32..d7c5462ae0 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py @@ -2,7 +2,7 @@ from eth2spec.test.helpers.block import build_empty_block_for_next_slot from eth2spec.test.helpers.attestations import get_valid_attestation, sign_attestation from eth2spec.test.helpers.constants import ALL_PHASES -from eth2spec.test.helpers.forks import is_post_electra +from eth2spec.test.helpers.forks import is_post_electra, is_post_eip7732 from eth2spec.test.helpers.state import transition_to, state_transition_and_sign_block, next_epoch, next_slot from eth2spec.test.helpers.fork_choice import get_genesis_forkchoice_store @@ -20,7 +20,12 @@ def run_on_attestation(spec, state, store, attestation, valid=True): spec.on_attestation(store, attestation) sample_index = indexed_attestation.attesting_indices[0] - if spec.fork in ALL_PHASES: + if is_post_eip7732: + latest_message = spec.LatestMessage( + slot=attestation.data.slot, + root=attestation.data.beacon_block_root, + ) + elif spec.fork in ALL_PHASES: latest_message = spec.LatestMessage( epoch=attestation.data.target.epoch, root=attestation.data.beacon_block_root, From 800b27fafa2b4515f09a9dd73d1d35027bdc6dba Mon Sep 17 00:00:00 2001 From: Potuz Date: Fri, 5 Jul 2024 08:16:42 -0300 Subject: [PATCH 05/73] skip electra tests with a payload --- .../block_processing/test_process_withdrawals.py | 5 ++++- tests/core/pyspec/eth2spec/test/context.py | 1 + .../eth2spec/test/electra/sanity/blocks/test_blocks.py | 10 +++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py index b8a342f4ea..c3841480ca 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py @@ -74,7 +74,10 @@ def run_withdrawals_processing(spec, state, execution_payload, num_expected_with yield 'execution_payload', execution_payload if not valid: - expect_assertion_error(lambda: spec.process_withdrawals(state, execution_payload)) + if is_post_eip7732: + expect_assertion_error(lambda: spec.process_withdrawals(state)) + else: + expect_assertion_error(lambda: spec.process_withdrawals(state, execution_payload)) yield 'post', None return diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index ca13723f0c..4e9b948fd5 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -586,6 +586,7 @@ def wrapper(*args, spec: Spec, **kw): with_eip7594_and_later = with_all_phases_from(EIP7594, all_phases=ALLOWED_TEST_RUNNER_FORKS) with_deneb_and_before_eip7732 = with_all_phases_from_to(DENEB, EIP7732) +with_electra_and_before_eip7732 = with_all_phases_from_to(ELECTRA, EIP7732) class quoted_str(str): diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py index 9fa4d609fc..72d6937309 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py @@ -3,7 +3,7 @@ ) from eth2spec.test.context import ( spec_state_test, - with_electra_and_later, + with_electra_and_before_eip7732, ) from eth2spec.test.helpers.bls_to_execution_changes import ( get_signed_address_change, @@ -22,7 +22,7 @@ ) -@with_electra_and_later +@with_electra_and_before_eip7732 @spec_state_test def test_basic_el_withdrawal_request(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit @@ -51,7 +51,7 @@ def test_basic_el_withdrawal_request(spec, state): assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_electra_and_later +@with_electra_and_before_eip7732 @spec_state_test def test_basic_btec_and_el_withdrawal_request_in_same_block(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit @@ -93,7 +93,7 @@ def test_basic_btec_and_el_withdrawal_request_in_same_block(spec, state): assert is_execution_address and is_correct_source_address -@with_electra_and_later +@with_electra_and_before_eip7732 @spec_state_test def test_basic_btec_before_el_withdrawal_request(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit @@ -140,7 +140,7 @@ def test_basic_btec_before_el_withdrawal_request(spec, state): assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_electra_and_later +@with_electra_and_before_eip7732 @spec_state_test def test_cl_exit_and_el_withdrawal_request_in_same_block(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit From f45e829049f4f4fab6b4093e3d89c83a16b7fdde Mon Sep 17 00:00:00 2001 From: Potuz Date: Fri, 5 Jul 2024 09:09:07 -0300 Subject: [PATCH 06/73] run_execution_payload_processing post eip-7732 --- specs/_features/eip7732/beacon-chain.md | 15 +++++++ .../test_process_execution_payload.py | 39 ++++++++++++++++--- .../test/helpers/execution_payload.py | 7 +++- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/specs/_features/eip7732/beacon-chain.md b/specs/_features/eip7732/beacon-chain.md index abce7250b6..73d0831f31 100644 --- a/specs/_features/eip7732/beacon-chain.md +++ b/specs/_features/eip7732/beacon-chain.md @@ -717,6 +717,8 @@ def validate_merge_block(block: BeaconBlock) -> None: ## Testing +### Modified `initialize_beacon_state_from_eth1` + *Note*: The function `initialize_beacon_state_from_eth1` is modified for pure EIP-7732 testing only. Modifications include: 1. Use `EIP7732_FORK_VERSION` as the previous and current fork version. @@ -776,3 +778,16 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash32, return state ``` + +### Modified `is_merge_transition_complete` + +The function `is_merge_transition_complete` is modified for test purposes only to include the hash tree root of the empty KZG commitment list + +```python +def is_merge_transition_complete(state: BeaconState) -> bool: + header = ExecutionPayloadHeader() + kzgs = List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]() + header.blob_kzg_commitments_root = kzgs.hash_tree_root() + + return state.latest_execution_payload_header != header +``` diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py index 325431e7a9..6dd1765d16 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py @@ -15,8 +15,9 @@ with_bellatrix_and_later, with_phases, ) +from eth2spec.test.helpers.keys import privkeys from eth2spec.test.helpers.state import next_slot - +from eth2spec.test.helpers.forks import is_post_eip7732 def run_execution_payload_processing(spec, state, execution_payload, valid=True, execution_valid=True): """ @@ -28,11 +29,31 @@ def run_execution_payload_processing(spec, state, execution_payload, valid=True, If ``valid == False``, run expecting ``AssertionError`` """ # Before Deneb, only `body.execution_payload` matters. `BeaconBlockBody` is just a wrapper. - body = spec.BeaconBlockBody(execution_payload=execution_payload) + # after EIP-7732 the execution payload is no longer in the body + if is_post_eip7732(spec): + envelope = spec.ExecutionPayloadEnvelope( + payload=execution_payload, + beacon_block_root=state.latest_block_header.hash_tree_root(), + payload_withheld=False, + state_root=state.hash_tree_root(), + ) + privkey = privkeys[0] + signature = spec.get_execution_payload_envelope_signature( + state, + envelope, + privkey, + ) + signed_envelope = spec.SignedExecutionPayloadEnvelope( + message=envelope, + signature=signature, + ) + else: + body = spec.BeaconBlockBody(execution_payload=execution_payload) yield 'pre', state yield 'execution', {'execution_valid': execution_valid} - yield 'body', body + if not is_post_eip7732(spec): + yield 'body', body called_new_block = False @@ -40,15 +61,21 @@ class TestEngine(spec.NoopExecutionEngine): def verify_and_notify_new_payload(self, new_payload_request) -> bool: nonlocal called_new_block, execution_valid called_new_block = True - assert new_payload_request.execution_payload == body.execution_payload + assert new_payload_request.execution_payload == execution_payload return execution_valid if not valid: - expect_assertion_error(lambda: spec.process_execution_payload(state, body, TestEngine())) + if is_post_eip7732(spec): + expect_assertion_error(lambda: spec.process_execution_payload(state, signed_envelope, TestEngine())) + else: + expect_assertion_error(lambda: spec.process_execution_payload(state, body, TestEngine())) yield 'post', None return - spec.process_execution_payload(state, body, TestEngine()) + if is_post_eip7732(spec): + spec.process_execution_payload(state, signed_envelope, TestEngine()) + else: + spec.process_execution_payload(state, body, TestEngine()) # Make sure we called the engine assert called_new_block diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 1fbb12d7ba..d87727d3f7 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -335,7 +335,12 @@ def build_randomized_execution_payload(spec, state, rng): def build_state_with_incomplete_transition(spec, state): - state = build_state_with_execution_payload_header(spec, state, spec.ExecutionPayloadHeader()) + header = spec.ExecutionPayloadHeader() + if is_post_eip7732: + kzgs = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() + header.blob_kzg_commitments_root = kzgs.hash_tree_root() + + state = build_state_with_execution_payload_header(spec, state, header) assert not spec.is_merge_transition_complete(state) return state From de7bf8d5fbd507772ecbf06ed4c5d1a69a17d99d Mon Sep 17 00:00:00 2001 From: Potuz Date: Fri, 5 Jul 2024 10:58:25 -0300 Subject: [PATCH 07/73] construct the header correctly --- .../test_process_execution_payload.py | 11 +++++++++-- .../eth2spec/test/helpers/execution_payload.py | 15 ++++++--------- .../core/pyspec/eth2spec/test/helpers/genesis.py | 7 ++++++- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py index 6dd1765d16..93a991bed4 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py @@ -35,8 +35,11 @@ def run_execution_payload_processing(spec, state, execution_payload, valid=True, payload=execution_payload, beacon_block_root=state.latest_block_header.hash_tree_root(), payload_withheld=False, - state_root=state.hash_tree_root(), ) + post_state = state.copy() + post_state.latest_block_hash = execution_payload.block_hash + post_state.latest_full_slot = state.slot + envelope.state_root = post_state.hash_tree_root() privkey = privkeys[0] signature = spec.get_execution_payload_envelope_signature( state, @@ -82,7 +85,11 @@ def verify_and_notify_new_payload(self, new_payload_request) -> bool: yield 'post', state - assert state.latest_execution_payload_header == get_execution_payload_header(spec, body.execution_payload) + if is_post_eip7732(spec): + assert state.latest_full_slot == state.slot + assert state.latest_block_hash == execution_payload.block_hash + else: + assert state.latest_execution_payload_header == get_execution_payload_header(spec, state, body.execution_payload) def run_success_test(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index d87727d3f7..4a195c06f7 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -15,17 +15,15 @@ ) -def get_execution_payload_header(spec, execution_payload): +def get_execution_payload_header(spec, state, execution_payload): if is_post_eip7732(spec): return spec.ExecutionPayloadHeader( parent_block_hash=execution_payload.parent_hash, - parent_block_root=spec.Root(), # TODO: Fix this + parent_block_root=state.latest_block_header.hash_tree_root(), block_hash=execution_payload.block_hash, gas_limit=execution_payload.gas_limit, - builder_index=spec.ValidatorIndex(0), # TODO: Fix this - slot=spec.Slot(0), # TODO: Fix this - value=spec.Gwei(0), # TODO: Fix this - blob_kzg_commitments_root=spec.Root() # TODO: Fix this + slot=state.slot, + blob_kzg_commitments_root=state.latest_execution_payload_header.blob_kzg_commitments_root, ) payload_header = spec.ExecutionPayloadHeader( @@ -224,7 +222,7 @@ def compute_el_block_hash(spec, payload, pre_state): requests_trie_root = compute_trie_root_from_indexed_data(requests_encoded) - payload_header = get_execution_payload_header(spec, payload) + payload_header = get_execution_payload_header(spec, spec.BeaconState(), payload) return compute_el_header_block_hash( spec, @@ -348,7 +346,7 @@ def build_state_with_incomplete_transition(spec, state): def build_state_with_complete_transition(spec, state): pre_state_payload = build_empty_execution_payload(spec, state) - payload_header = get_execution_payload_header(spec, pre_state_payload) + payload_header = get_execution_payload_header(spec, state, pre_state_payload) state = build_state_with_execution_payload_header(spec, state, payload_header) assert spec.is_merge_transition_complete(state) @@ -359,7 +357,6 @@ def build_state_with_complete_transition(spec, state): def build_state_with_execution_payload_header(spec, state, execution_payload_header): pre_state = state.copy() pre_state.latest_execution_payload_header = execution_payload_header - return pre_state diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index 7aae9404f1..304145f4ee 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -47,13 +47,14 @@ def build_mock_validator(spec, i: int, balance: int): def get_post_eip7732_genesis_execution_payload_header(spec, slot, eth1_block_hash): + kzgs = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() header = spec.ExecutionPayloadHeader( parent_block_hash=b'\x30' * 32, parent_block_root=b'\x00' * 32, block_hash=eth1_block_hash, gas_limit=30000000, slot=slot, - blob_kzg_commitments_root=b'\x20' * 32, + blob_kzg_commitments_root=kzgs.hash_tree_root(), ) return header @@ -190,4 +191,8 @@ def create_genesis_state(spec, validator_balances, activation_threshold): state.pending_partial_withdrawals = [] state.pending_consolidations = [] + if is_post_eip7732(spec): + withdrawals = spec.List[spec.Withdrawal, spec.MAX_WITHDRAWALS_PER_PAYLOAD]() + state.latest_withdrawals_root = withdrawals.hash_tree_root() + return state From 5bb0dd879cd6dc0306aafedd1c4378682f1fc967 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 8 Jul 2024 14:39:31 -0300 Subject: [PATCH 08/73] get sample sidecars for eip 7732 --- .../deneb/unittests/validator/test_validator.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py index 6724e8304a..d3875e3435 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py @@ -6,6 +6,7 @@ from eth2spec.test.helpers.execution_payload import ( compute_el_block_hash, ) +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.sharding import ( get_sample_opaque_tx, ) @@ -24,13 +25,21 @@ def _get_sample_sidecars(spec, state, rng): opaque_tx_2, blobs_2, blob_kzg_commitments_2, proofs_2 = get_sample_opaque_tx(spec, blob_count=blob_count, rng=rng) assert opaque_tx_1 != opaque_tx_2 - block.body.blob_kzg_commitments = blob_kzg_commitments_1 + blob_kzg_commitments_2 - block.body.execution_payload.transactions = [opaque_tx_1, opaque_tx_2] - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + blob_kzg_commitments = blob_kzg_commitments_1 + blob_kzg_commitments_2 + if is_post_eip7732(spec): + kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK](blob_kzg_commitments) + kzg_root = kzg_list.hash_tree_root() + block.body.signed_execution_payload_header.message.blob_kzg_commitments_root = kzg_root + else: + block.body.blob_kzg_commitments = blob_kzg_commitments_1 + blob_kzg_commitments_2 + block.body.execution_payload.transactions = [opaque_tx_1, opaque_tx_2] + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) blobs = blobs_1 + blobs_2 proofs = proofs_1 + proofs_2 signed_block = sign_block(spec, state, block, proposer_index=0) + if is_post_eip7732(spec): + return spec.get_blob_sidecars(signed_block, blobs, blob_kzg_commitments, proofs) return spec.get_blob_sidecars(signed_block, blobs, proofs) From 62f4cd2f70d4dfa45c9406e4472873a8a3e0d135 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 8 Jul 2024 09:29:38 -0300 Subject: [PATCH 09/73] use right sidecar proofs in tests --- .../test/deneb/unittests/validator/test_validator.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py index d3875e3435..fee4f7dda2 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py @@ -25,10 +25,11 @@ def _get_sample_sidecars(spec, state, rng): opaque_tx_2, blobs_2, blob_kzg_commitments_2, proofs_2 = get_sample_opaque_tx(spec, blob_count=blob_count, rng=rng) assert opaque_tx_1 != opaque_tx_2 - blob_kzg_commitments = blob_kzg_commitments_1 + blob_kzg_commitments_2 if is_post_eip7732(spec): - kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK](blob_kzg_commitments) - kzg_root = kzg_list.hash_tree_root() + blob_kzg_commitments = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]( + blob_kzg_commitments_1 + blob_kzg_commitments_2 + ) + kzg_root = blob_kzg_commitments.hash_tree_root() block.body.signed_execution_payload_header.message.blob_kzg_commitments_root = kzg_root else: block.body.blob_kzg_commitments = blob_kzg_commitments_1 + blob_kzg_commitments_2 From 0731099c535bc28d384464bc53b58cdb2e3955d2 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 8 Jul 2024 13:33:17 -0300 Subject: [PATCH 10/73] fixed gindex --- pysetup/spec_builders/eip7732.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pysetup/spec_builders/eip7732.py b/pysetup/spec_builders/eip7732.py index 0c335fe1d9..c3a763b09c 100644 --- a/pysetup/spec_builders/eip7732.py +++ b/pysetup/spec_builders/eip7732.py @@ -37,9 +37,3 @@ def deprecate_constants(cls) -> Set[str]: return set([ 'EXECUTION_PAYLOAD_GINDEX', ]) - - @classmethod - def deprecate_presets(cls) -> Set[str]: - return set([ - 'KZG_COMMITMENT_INCLUSION_PROOF_DEPTH', - ]) From ebeed79a932eeafde0937499a6fc5faaae7113be Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 8 Jul 2024 10:56:06 -0300 Subject: [PATCH 11/73] keep deprecated kzg --- pysetup/spec_builders/eip7732.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pysetup/spec_builders/eip7732.py b/pysetup/spec_builders/eip7732.py index c3a763b09c..0c335fe1d9 100644 --- a/pysetup/spec_builders/eip7732.py +++ b/pysetup/spec_builders/eip7732.py @@ -37,3 +37,9 @@ def deprecate_constants(cls) -> Set[str]: return set([ 'EXECUTION_PAYLOAD_GINDEX', ]) + + @classmethod + def deprecate_presets(cls) -> Set[str]: + return set([ + 'KZG_COMMITMENT_INCLUSION_PROOF_DEPTH', + ]) From fa5cc0a142d9d023f2d5c49a3e96a0149f8e1a6c Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 8 Jul 2024 14:40:22 -0300 Subject: [PATCH 12/73] fix merkle proof tester --- .../merkle_proof/test_single_merkle_proof.py | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py b/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py index 1dda310123..906a08d5dc 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py +++ b/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py @@ -12,6 +12,7 @@ from eth2spec.test.helpers.execution_payload import ( compute_el_block_hash, ) +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.sharding import ( get_sample_opaque_tx, ) @@ -34,22 +35,49 @@ def _run_blob_kzg_commitment_merkle_proof_test(spec, state, rng=None): mode=RandomizationMode, chaos=True, ) - block.body.blob_kzg_commitments = blob_kzg_commitments - block.body.execution_payload.transactions = [opaque_tx] - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + if is_post_eip7732(spec): + blob_kzg_commitments = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]( + blob_kzg_commitments + ) + kzg_root = blob_kzg_commitments.hash_tree_root() + block.body.signed_execution_payload_header.message.blob_kzg_commitments_root = kzg_root + else: + block.body.blob_kzg_commitments = blob_kzg_commitments + block.body.execution_payload.transactions = [opaque_tx] + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) + signed_block = sign_block(spec, state, block, proposer_index=0) - blob_sidecars = spec.get_blob_sidecars(signed_block, blobs, proofs) + if is_post_eip7732(spec): + blob_sidecars = spec.get_blob_sidecars(signed_block, blobs, blob_kzg_commitments, proofs) + else: + blob_sidecars = spec.get_blob_sidecars(signed_block, blobs, proofs) blob_index = 0 blob_sidecar = blob_sidecars[blob_index] yield "object", block.body kzg_commitment_inclusion_proof = blob_sidecar.kzg_commitment_inclusion_proof - gindex = spec.get_generalized_index(spec.BeaconBlockBody, 'blob_kzg_commitments', blob_index) + + if is_post_eip7732(spec): + inner_gindex = spec.get_generalized_index( + spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK], + blob_index + ) + outer_gindex = spec.get_generalized_index( + spec.BeaconBlockBody, + "signed_execution_payload_header", + "message", + "blob_kzg_commitments_root", + ) + gindex = spec.concat_generalized_indices(outer_gindex, inner_gindex) + else: + gindex = spec.get_generalized_index(spec.BeaconBlockBody, 'blob_kzg_commitments', blob_index) + yield "proof", { "leaf": "0x" + blob_sidecar.kzg_commitment.hash_tree_root().hex(), "leaf_index": gindex, "branch": ['0x' + root.hex() for root in kzg_commitment_inclusion_proof] } + assert spec.is_valid_merkle_branch( leaf=blob_sidecar.kzg_commitment.hash_tree_root(), branch=blob_sidecar.kzg_commitment_inclusion_proof, From 4ee48056271aa9b4069e22a6fd0c090edf6b79cb Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 8 Jul 2024 14:41:51 -0300 Subject: [PATCH 13/73] fix validate_merge_block --- specs/_features/eip7732/fork-choice.md | 31 ++++++++ .../test_process_execution_payload.py | 4 +- .../unittests/test_validate_merge_block.py | 79 +++++++++++++++---- .../test_process_execution_payload.py | 45 +++++++++-- .../merkle_proof/test_single_merkle_proof.py | 2 +- .../test/helpers/execution_payload.py | 4 +- 6 files changed, 141 insertions(+), 24 deletions(-) diff --git a/specs/_features/eip7732/fork-choice.md b/specs/_features/eip7732/fork-choice.md index 0eb49ddfc1..1155354d1d 100644 --- a/specs/_features/eip7732/fork-choice.md +++ b/specs/_features/eip7732/fork-choice.md @@ -561,3 +561,34 @@ def on_payload_attestation_message( store.payload_withhold_boost_root = block.parent_root store.payload_withhold_boost_full = is_parent_node_full(store, block) ``` + +### Modified `validate_merge_block` + +The function `validate_merge_block` is modified for test purposes + +```python +def validate_merge_block(block: BeaconBlock) -> None: + """ + Check the parent PoW block of execution payload is a valid terminal PoW block. + + Note: Unavailable PoW block(s) may later become available, + and a client software MAY delay a call to ``validate_merge_block`` + until the PoW block(s) become available. + """ + if TERMINAL_BLOCK_HASH != Hash32(): + # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached. + assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH + assert block.body.signed_execution_payload_header.message.parent_block_hash == TERMINAL_BLOCK_HASH + return + + pow_block = get_pow_block(block.body.signed_execution_payload_header.message.parent_block_hash) + # Check if `pow_block` is available + assert pow_block is not None + pow_parent = get_pow_block(pow_block.parent_hash) + # Check if `pow_parent` is available + assert pow_parent is not None + # Check if `pow_block` is a valid terminal PoW block + assert is_valid_terminal_pow_block(pow_block, pow_parent) + + + diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py index 93a991bed4..92d39653b5 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py @@ -19,6 +19,7 @@ from eth2spec.test.helpers.state import next_slot from eth2spec.test.helpers.forks import is_post_eip7732 + def run_execution_payload_processing(spec, state, execution_payload, valid=True, execution_valid=True): """ Run ``process_execution_payload``, yielding: @@ -89,7 +90,8 @@ def verify_and_notify_new_payload(self, new_payload_request) -> bool: assert state.latest_full_slot == state.slot assert state.latest_block_hash == execution_payload.block_hash else: - assert state.latest_execution_payload_header == get_execution_payload_header(spec, state, body.execution_payload) + assert state.latest_execution_payload_header == get_execution_payload_header( + spec, state, body.execution_payload) def run_success_test(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_validate_merge_block.py b/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_validate_merge_block.py index d519dfac0f..925a04489b 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_validate_merge_block.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_validate_merge_block.py @@ -4,11 +4,13 @@ build_empty_block_for_next_slot, ) from eth2spec.test.helpers.execution_payload import ( + build_empty_execution_payload, compute_el_block_hash, ) from eth2spec.test.helpers.pow_block import ( prepare_random_pow_chain, ) +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.context import ( spec_state_test, with_bellatrix_and_later, @@ -59,8 +61,15 @@ def test_validate_merge_block_success(spec, state): pow_chain.head(-1).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1) pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.parent_hash = pow_chain.head().block_hash - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + if is_post_eip7732(spec): + payload = build_empty_execution_payload(spec, state) + block.body.signed_execution_payload_header.message.parent_block_hash = pow_chain.head().block_hash + block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash( + spec, payload, state) + else: + block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + run_validate_merge_block(spec, pow_chain, block) @@ -80,8 +89,15 @@ def test_validate_merge_block_fail_parent_block_lookup(spec, state): pow_chain = prepare_random_pow_chain(spec, 1) pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.parent_hash = pow_chain.head().block_hash - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + if is_post_eip7732(spec): + payload = build_empty_execution_payload(spec, state) + block.body.signed_execution_payload_header.message.parent_block_hash = pow_chain.head().block_hash + block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash( + spec, payload, state) + else: + block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + run_validate_merge_block(spec, pow_chain, block, valid=False) @@ -92,8 +108,15 @@ def test_validate_merge_block_fail_after_terminal(spec, state): pow_chain.head(-1).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY + uint256(1) block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.parent_hash = pow_chain.head().block_hash - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + if is_post_eip7732(spec): + payload = build_empty_execution_payload(spec, state) + block.body.signed_execution_payload_header.message.parent_block_hash = pow_chain.head().block_hash + block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash( + spec, payload, state) + else: + block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + run_validate_merge_block(spec, pow_chain, block, valid=False) @@ -109,8 +132,15 @@ def test_validate_merge_block_tbh_override_success(spec, state): pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1) pow_chain.head().block_hash = TERMINAL_BLOCK_HASH block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.parent_hash = pow_chain.head().block_hash - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + if is_post_eip7732(spec): + payload = build_empty_execution_payload(spec, state) + block.body.signed_execution_payload_header.message.parent_block_hash = pow_chain.head().block_hash + block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash( + spec, payload, state) + else: + block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + run_validate_merge_block(spec, pow_chain, block) @@ -125,8 +155,15 @@ def test_validate_merge_block_fail_parent_hash_is_not_tbh(spec, state): pow_chain.head(-1).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1) pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.parent_hash = pow_chain.head().block_hash - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + if is_post_eip7732(spec): + payload = build_empty_execution_payload(spec, state) + block.body.signed_execution_payload_header.message.parent_block_hash = pow_chain.head().block_hash + block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash( + spec, payload, state) + else: + block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + run_validate_merge_block(spec, pow_chain, block, valid=False) @@ -142,8 +179,15 @@ def test_validate_merge_block_terminal_block_hash_fail_activation_not_reached(sp pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY pow_chain.head().block_hash = TERMINAL_BLOCK_HASH block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.parent_hash = pow_chain.head().block_hash - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + if is_post_eip7732(spec): + payload = build_empty_execution_payload(spec, state) + block.body.signed_execution_payload_header.message.parent_block_hash = pow_chain.head().block_hash + block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash( + spec, payload, state) + else: + block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + run_validate_merge_block(spec, pow_chain, block, valid=False) @@ -158,6 +202,13 @@ def test_validate_merge_block_fail_activation_not_reached_parent_hash_is_not_tbh pow_chain.head(-1).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1) pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = build_empty_block_for_next_slot(spec, state) - block.body.execution_payload.parent_hash = pow_chain.head().block_hash - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + if is_post_eip7732(spec): + payload = build_empty_execution_payload(spec, state) + block.body.signed_execution_payload_header.message.parent_block_hash = pow_chain.head().block_hash + block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash( + spec, payload, state) + else: + block.body.execution_payload.parent_hash = pow_chain.head().block_hash + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) + run_validate_merge_block(spec, pow_chain, block, valid=False) diff --git a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py index 85175a3b9c..12eb02efb4 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py @@ -10,6 +10,8 @@ expect_assertion_error, with_deneb_and_later ) +from eth2spec.test.helpers.keys import privkeys +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.sharding import ( get_sample_opaque_tx, ) @@ -25,11 +27,39 @@ def run_execution_payload_processing(spec, state, execution_payload, blob_kzg_co - post-state ('post'). If ``valid == False``, run expecting ``AssertionError`` """ + + # after EIP-7732 the execution payload is no longer in the body + if is_post_eip7732(spec): + envelope = spec.ExecutionPayloadEnvelope( + payload=execution_payload, + beacon_block_root=state.latest_block_header.hash_tree_root(), + payload_withheld=False, + ) + post_state = state.copy() + post_state.latest_block_hash = execution_payload.block_hash + post_state.latest_full_slot = state.slot + envelope.state_root = post_state.hash_tree_root() + privkey = privkeys[0] + signature = spec.get_execution_payload_envelope_signature( + state, + envelope, + privkey, + ) + signed_envelope = spec.SignedExecutionPayloadEnvelope( + message=envelope, + signature=signature, + ) + else: + body = spec.BeaconBlockBody( + blob_kzg_commitments=blob_kzg_commitments, + execution_payload=execution_payload, + ) + # Before Deneb, only `body.execution_payload` matters. `BeaconBlockBody` is just a wrapper. - body = spec.BeaconBlockBody( - blob_kzg_commitments=blob_kzg_commitments, - execution_payload=execution_payload - ) + body = spec.BeaconBlockBody() + if not is_post_eip7732(spec): + body.blob_kzg_commitments = blob_kzg_commitments + body.execution_payload = execution_payload yield 'pre', state yield 'execution', {'execution_valid': execution_valid} @@ -41,11 +71,14 @@ class TestEngine(spec.NoopExecutionEngine): def verify_and_notify_new_payload(self, new_payload_request) -> bool: nonlocal called_new_block, execution_valid called_new_block = True - assert new_payload_request.execution_payload == body.execution_payload + assert new_payload_request.execution_payload == execution_payload return execution_valid if not valid: - expect_assertion_error(lambda: spec.process_execution_payload(state, body, TestEngine())) + if is_post_eip7732(spec): + expect_assertion_error(lambda: spec.process_execution_payload(state, signed_envelope, body, TestEngine())) + else: + expect_assertion_error(lambda: spec.process_execution_payload(state, body, TestEngine())) yield 'post', None return diff --git a/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py b/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py index 906a08d5dc..0bccb3cb3a 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py +++ b/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py @@ -67,7 +67,7 @@ def _run_blob_kzg_commitment_merkle_proof_test(spec, state, rng=None): "signed_execution_payload_header", "message", "blob_kzg_commitments_root", - ) + ) gindex = spec.concat_generalized_indices(outer_gindex, inner_gindex) else: gindex = spec.get_generalized_index(spec.BeaconBlockBody, 'blob_kzg_commitments', blob_index) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 4a195c06f7..e5ed4d1f3c 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -335,8 +335,8 @@ def build_randomized_execution_payload(spec, state, rng): def build_state_with_incomplete_transition(spec, state): header = spec.ExecutionPayloadHeader() if is_post_eip7732: - kzgs = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() - header.blob_kzg_commitments_root = kzgs.hash_tree_root() + kzgs = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() + header.blob_kzg_commitments_root = kzgs.hash_tree_root() state = build_state_with_execution_payload_header(spec, state, header) assert not spec.is_merge_transition_complete(state) From b9644a673da6eec517c897418ed8b2e9916aaf0a Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 8 Jul 2024 14:56:34 -0300 Subject: [PATCH 14/73] fix test_config_invariants --- .../deneb/unittests/test_config_invariants.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py index 1f44257856..0bfc0957a2 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py @@ -3,7 +3,7 @@ spec_test, with_deneb_and_later, ) - +from eth2spec.test.helpers.forks import is_post_eip7732 @with_deneb_and_later @spec_test @@ -24,5 +24,19 @@ def test_networking(spec): # Start with the same size, but `BLOB_SIDECAR_SUBNET_COUNT` could potentially increase later. assert spec.config.BLOB_SIDECAR_SUBNET_COUNT == spec.config.MAX_BLOBS_PER_BLOCK for i in range(spec.MAX_BLOB_COMMITMENTS_PER_BLOCK): - gindex = spec.get_generalized_index(spec.BeaconBlockBody, 'blob_kzg_commitments', i) - assert spec.floorlog2(gindex) == spec.KZG_COMMITMENT_INCLUSION_PROOF_DEPTH + if is_post_eip7732(spec): + inner_gindex = spec.get_generalized_index( + spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK], + i + ) + outer_gindex = spec.get_generalized_index( + spec.BeaconBlockBody, + "signed_execution_payload_header", + "message", + "blob_kzg_commitments_root", + ) + gindex = spec.concat_generalized_indices(outer_gindex, inner_gindex) + assert spec.floorlog2(gindex) == spec.KZG_COMMITMENT_INCLUSION_PROOF_DEPTH_EIP7732 + else: + gindex = spec.get_generalized_index(spec.BeaconBlockBody, 'blob_kzg_commitments', i) + assert spec.floorlog2(gindex) == spec.KZG_COMMITMENT_INCLUSION_PROOF_DEPTH From 8caa39e6d76d297c3123b35df8bbc4e29304fec8 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 8 Jul 2024 15:08:33 -0300 Subject: [PATCH 15/73] use full latest block for genesis --- tests/core/pyspec/eth2spec/test/helpers/genesis.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index 304145f4ee..5c39604943 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -194,5 +194,6 @@ def create_genesis_state(spec, validator_balances, activation_threshold): if is_post_eip7732(spec): withdrawals = spec.List[spec.Withdrawal, spec.MAX_WITHDRAWALS_PER_PAYLOAD]() state.latest_withdrawals_root = withdrawals.hash_tree_root() + state.latest_block_hash = state.latest_execution_payload_header.block_hash # last block is full return state From 789322f234127fea022f0ec2be28fce2eb1cb5d1 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 8 Jul 2024 15:59:06 -0300 Subject: [PATCH 16/73] fix test_process_execution_payload --- .../test_process_execution_payload.py | 23 +++++++++++++++++-- .../test/helpers/execution_payload.py | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py index 12eb02efb4..54764ddd6b 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py @@ -82,14 +82,21 @@ def verify_and_notify_new_payload(self, new_payload_request) -> bool: yield 'post', None return - spec.process_execution_payload(state, body, TestEngine()) + if is_post_eip7732(spec): + spec.process_execution_payload(state, signed_envelope, TestEngine()) + else: + spec.process_execution_payload(state, body, TestEngine()) # Make sure we called the engine assert called_new_block yield 'post', state - assert state.latest_execution_payload_header == get_execution_payload_header(spec, body.execution_payload) + if is_post_eip7732(spec): + assert state.latest_block_hash == execution_payload.block_hash + assert state.latest_full_slot == state.slot + else: + assert state.latest_execution_payload_header == get_execution_payload_header(spec, state, execution_payload) """ @@ -113,6 +120,7 @@ def test_incorrect_blob_tx_type(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -130,6 +138,7 @@ def test_incorrect_transaction_length_1_extra_byte(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -147,6 +156,7 @@ def test_incorrect_transaction_length_1_byte_short(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -164,6 +174,7 @@ def test_incorrect_transaction_length_empty(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -181,6 +192,7 @@ def test_incorrect_transaction_length_32_extra_bytes(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -197,6 +209,7 @@ def test_no_transactions_with_commitments(spec, state): execution_payload.transactions = [] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -214,6 +227,7 @@ def test_incorrect_commitment(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -231,6 +245,7 @@ def test_incorrect_commitments_order(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -245,6 +260,7 @@ def test_incorrect_block_hash(spec, state): execution_payload.block_hash = b'\x12' * 32 # incorrect block hash # CL itself doesn't verify EL block hash + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -262,6 +278,7 @@ def test_zeroed_commitment(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -278,6 +295,7 @@ def test_invalid_correct_input__execution_invalid(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments, valid=False, execution_valid=False) @@ -292,4 +310,5 @@ def test_invalid_exceed_max_blobs_per_block(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments, valid=False) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index e5ed4d1f3c..2c1e5201f3 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -280,6 +280,7 @@ def build_empty_execution_payload(spec, state, randao_mix=None): logs_bloom=spec.ByteVector[spec.BYTES_PER_LOGS_BLOOM](), # TODO: zeroed logs bloom for empty logs ok? prev_randao=randao_mix, gas_used=0, # empty block, 0 gas + gas_limit=latest.gas_limit, timestamp=timestamp, extra_data=spec.ByteList[spec.MAX_EXTRA_DATA_BYTES](), transactions=empty_txs, From 43e9f2d32fa32ced82d8d56b5cd6231afaeef6a1 Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 9 Jul 2024 09:59:31 -0300 Subject: [PATCH 17/73] skip invalid withdrawal tests --- .../test_process_withdrawals.py | 57 ++++++++++--------- tests/core/pyspec/eth2spec/test/context.py | 2 +- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py index c3841480ca..c27243bde3 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py @@ -5,6 +5,7 @@ expect_assertion_error, with_presets, with_capella_and_later, + with_capella_until_eip7732, ) from eth2spec.test.helpers.constants import MAINNET, MINIMAL from eth2spec.test.helpers.execution_payload import ( @@ -254,7 +255,7 @@ def test_success_all_partially_withdrawable(spec, state): # Failure cases in which the number of withdrawals in the execution_payload is incorrect # -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_non_withdrawable_non_empty_withdrawals(spec, state): next_slot(spec, state) @@ -271,7 +272,7 @@ def test_invalid_non_withdrawable_non_empty_withdrawals(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_one_expected_full_withdrawal_and_none_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), num_full_withdrawals=1) @@ -284,7 +285,7 @@ def test_invalid_one_expected_full_withdrawal_and_none_in_withdrawals(spec, stat yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_one_expected_partial_withdrawal_and_none_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), num_partial_withdrawals=1) @@ -297,7 +298,7 @@ def test_invalid_one_expected_partial_withdrawal_and_none_in_withdrawals(spec, s yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_one_expected_full_withdrawal_and_duplicate_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), num_full_withdrawals=2) @@ -310,7 +311,7 @@ def test_invalid_one_expected_full_withdrawal_and_duplicate_in_withdrawals(spec, yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_two_expected_partial_withdrawal_and_duplicate_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), num_partial_withdrawals=2) @@ -323,7 +324,7 @@ def test_invalid_two_expected_partial_withdrawal_and_duplicate_in_withdrawals(sp yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_max_per_slot_full_withdrawals_and_one_less_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -337,7 +338,7 @@ def test_invalid_max_per_slot_full_withdrawals_and_one_less_in_withdrawals(spec, yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_max_per_slot_partial_withdrawals_and_one_less_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -351,7 +352,7 @@ def test_invalid_max_per_slot_partial_withdrawals_and_one_less_in_withdrawals(sp yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_a_lot_fully_withdrawable_too_few_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -365,7 +366,7 @@ def test_invalid_a_lot_fully_withdrawable_too_few_in_withdrawals(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -379,7 +380,7 @@ def test_invalid_a_lot_partially_withdrawable_too_few_in_withdrawals(spec, state yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -398,7 +399,7 @@ def test_invalid_a_lot_mixed_withdrawable_in_queue_too_few_in_withdrawals(spec, # Failure cases in which the withdrawals in the execution_payload are incorrect # -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_incorrect_withdrawal_index(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -412,7 +413,7 @@ def test_invalid_incorrect_withdrawal_index(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_incorrect_address_full(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -426,7 +427,7 @@ def test_invalid_incorrect_address_full(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_incorrect_address_partial(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -440,7 +441,7 @@ def test_invalid_incorrect_address_partial(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_incorrect_amount_full(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), num_full_withdrawals=1) @@ -453,7 +454,7 @@ def test_invalid_incorrect_amount_full(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_incorrect_amount_partial(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), num_full_withdrawals=1) @@ -466,7 +467,7 @@ def test_invalid_incorrect_amount_partial(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_one_of_many_incorrectly_full(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -486,7 +487,7 @@ def test_invalid_one_of_many_incorrectly_full(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_one_of_many_incorrectly_partial(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -506,7 +507,7 @@ def test_invalid_one_of_many_incorrectly_partial(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_many_incorrectly_full(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -526,7 +527,7 @@ def test_invalid_many_incorrectly_full(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, valid=False) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_many_incorrectly_partial(spec, state): prepare_expected_withdrawals(spec, state, rng=random.Random(42), @@ -550,7 +551,7 @@ def test_invalid_many_incorrectly_partial(spec, state): # More full withdrawal cases # -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_withdrawable_epoch_but_0_balance(spec, state): current_epoch = spec.get_current_epoch(state) @@ -564,7 +565,7 @@ def test_withdrawable_epoch_but_0_balance(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_withdrawable_epoch_but_0_effective_balance_0_balance(spec, state): current_epoch = spec.get_current_epoch(state) @@ -578,7 +579,7 @@ def test_withdrawable_epoch_but_0_effective_balance_0_balance(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_withdrawable_epoch_but_0_effective_balance_nonzero_balance(spec, state): current_epoch = spec.get_current_epoch(state) @@ -592,7 +593,7 @@ def test_withdrawable_epoch_but_0_effective_balance_nonzero_balance(spec, state) yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=1) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_no_withdrawals_but_some_next_epoch(spec, state): current_epoch = spec.get_current_epoch(state) @@ -606,7 +607,7 @@ def test_no_withdrawals_but_some_next_epoch(spec, state): yield from run_withdrawals_processing(spec, state, execution_payload, num_expected_withdrawals=0) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_all_withdrawal(spec, state): # Make all validators withdrawable @@ -642,25 +643,25 @@ def run_random_full_withdrawals_test(spec, state, rng): yield from run_withdrawals_processing(spec, state, execution_payload) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_random_full_withdrawals_0(spec, state): yield from run_random_full_withdrawals_test(spec, state, random.Random(444)) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_random_full_withdrawals_1(spec, state): yield from run_random_full_withdrawals_test(spec, state, random.Random(420)) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_random_full_withdrawals_2(spec, state): yield from run_random_full_withdrawals_test(spec, state, random.Random(200)) -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_random_full_withdrawals_3(spec, state): yield from run_random_full_withdrawals_test(spec, state, random.Random(2000000)) diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 4e9b948fd5..79230a905a 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -587,7 +587,7 @@ def wrapper(*args, spec: Spec, **kw): with_deneb_and_before_eip7732 = with_all_phases_from_to(DENEB, EIP7732) with_electra_and_before_eip7732 = with_all_phases_from_to(ELECTRA, EIP7732) - +with_capella_until_eip7732 = with_all_phases_from_to(CAPELLA, EIP7732) class quoted_str(str): pass From f5d61ceb2f3ae15af63b1b41adf072009f72c705 Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 9 Jul 2024 10:03:51 -0300 Subject: [PATCH 18/73] skip invalid bellatrix tests --- .../test/bellatrix/sanity/test_blocks.py | 5 +++-- tests/core/pyspec/eth2spec/test/context.py | 5 +++-- .../eth2spec/test/deneb/sanity/test_blocks.py | 20 +++++++++---------- .../test/electra/sanity/blocks/test_blocks.py | 10 +++++----- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py index 6ac76ca596..bf6ad6ea3e 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py @@ -12,12 +12,13 @@ from eth2spec.test.context import ( BELLATRIX, with_bellatrix_and_later, + with_bellatrix_until_eip7732, with_phases, spec_state_test, ) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_empty_block_transition_no_tx(spec, state): yield 'pre', state @@ -31,7 +32,7 @@ def test_empty_block_transition_no_tx(spec, state): yield 'post', state -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_block_transition_randomized_payload(spec, state): yield 'pre', state diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 79230a905a..9c1d4e78ac 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -585,9 +585,10 @@ def wrapper(*args, spec: Spec, **kw): with_whisk_and_later = with_all_phases_from(WHISK, all_phases=ALLOWED_TEST_RUNNER_FORKS) with_eip7594_and_later = with_all_phases_from(EIP7594, all_phases=ALLOWED_TEST_RUNNER_FORKS) -with_deneb_and_before_eip7732 = with_all_phases_from_to(DENEB, EIP7732) -with_electra_and_before_eip7732 = with_all_phases_from_to(ELECTRA, EIP7732) +with_bellatrix_until_eip7732 = with_all_phases_from_to(BELLATRIX, EIP7732) with_capella_until_eip7732 = with_all_phases_from_to(CAPELLA, EIP7732) +with_deneb_until_eip7732 = with_all_phases_from_to(DENEB, EIP7732) +with_electra_until_eip7732 = with_all_phases_from_to(ELECTRA, EIP7732) class quoted_str(str): pass diff --git a/tests/core/pyspec/eth2spec/test/deneb/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/deneb/sanity/test_blocks.py index eeeacb6dff..0c24987f94 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/deneb/sanity/test_blocks.py @@ -8,7 +8,7 @@ ) from eth2spec.test.context import ( spec_state_test, - with_deneb_and_before_eip7732, + with_deneb_until_eip7732, ) from eth2spec.test.helpers.execution_payload import ( compute_el_block_hash, @@ -51,55 +51,55 @@ def run_block_with_blobs(spec, state, blob_count, tx_count=1, blob_gas_used=1, e yield 'post', state if valid else None -@with_deneb_and_before_eip7732 +@with_deneb_until_eip7732 @spec_state_test def test_zero_blob(spec, state): yield from run_block_with_blobs(spec, state, blob_count=0) -@with_deneb_and_before_eip7732 +@with_deneb_until_eip7732 @spec_state_test def test_one_blob(spec, state): yield from run_block_with_blobs(spec, state, blob_count=1) -@with_deneb_and_before_eip7732 +@with_deneb_until_eip7732 @spec_state_test def test_one_blob_two_txs(spec, state): yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=2) -@with_deneb_and_before_eip7732 +@with_deneb_until_eip7732 @spec_state_test def test_one_blob_max_txs(spec, state): yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=spec.MAX_BLOBS_PER_BLOCK) -@with_deneb_and_before_eip7732 +@with_deneb_until_eip7732 @spec_state_test def test_invalid_one_blob_max_plus_one_txs(spec, state): yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=spec.MAX_BLOBS_PER_BLOCK + 1, valid=False) -@with_deneb_and_before_eip7732 +@with_deneb_until_eip7732 @spec_state_test def test_max_blobs_per_block(spec, state): yield from run_block_with_blobs(spec, state, blob_count=spec.MAX_BLOBS_PER_BLOCK) -@with_deneb_and_before_eip7732 +@with_deneb_until_eip7732 @spec_state_test def test_invalid_max_blobs_per_block_two_txs(spec, state): yield from run_block_with_blobs(spec, state, blob_count=spec.MAX_BLOBS_PER_BLOCK, tx_count=2, valid=False) -@with_deneb_and_before_eip7732 +@with_deneb_until_eip7732 @spec_state_test def test_invalid_exceed_max_blobs_per_block(spec, state): yield from run_block_with_blobs(spec, state, blob_count=spec.MAX_BLOBS_PER_BLOCK + 1, valid=False) -@with_deneb_and_before_eip7732 +@with_deneb_until_eip7732 @spec_state_test def test_mix_blob_tx_and_non_blob_tx(spec, state): yield from run_block_with_blobs(spec, state, blob_count=1, tx_count=1, non_blob_tx_count=1) diff --git a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py index 72d6937309..58fcb7d944 100644 --- a/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/electra/sanity/blocks/test_blocks.py @@ -3,7 +3,7 @@ ) from eth2spec.test.context import ( spec_state_test, - with_electra_and_before_eip7732, + with_electra_until_eip7732, ) from eth2spec.test.helpers.bls_to_execution_changes import ( get_signed_address_change, @@ -22,7 +22,7 @@ ) -@with_electra_and_before_eip7732 +@with_electra_until_eip7732 @spec_state_test def test_basic_el_withdrawal_request(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit @@ -51,7 +51,7 @@ def test_basic_el_withdrawal_request(spec, state): assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_electra_and_before_eip7732 +@with_electra_until_eip7732 @spec_state_test def test_basic_btec_and_el_withdrawal_request_in_same_block(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit @@ -93,7 +93,7 @@ def test_basic_btec_and_el_withdrawal_request_in_same_block(spec, state): assert is_execution_address and is_correct_source_address -@with_electra_and_before_eip7732 +@with_electra_until_eip7732 @spec_state_test def test_basic_btec_before_el_withdrawal_request(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit @@ -140,7 +140,7 @@ def test_basic_btec_before_el_withdrawal_request(spec, state): assert state.validators[validator_index].exit_epoch < spec.FAR_FUTURE_EPOCH -@with_electra_and_before_eip7732 +@with_electra_until_eip7732 @spec_state_test def test_cl_exit_and_el_withdrawal_request_in_same_block(spec, state): # move state forward SHARD_COMMITTEE_PERIOD epochs to allow for exit From 5b22ff3dcf093c61c27dd11cf6bdd77e3da6ffcc Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 9 Jul 2024 10:26:44 -0300 Subject: [PATCH 19/73] skip more invalid tests --- .../test_process_execution_payload.py | 13 +++++++------ .../test_should_override_forkchoice_update.py | 6 +++--- .../eth2spec/test/bellatrix/sync/test_optimistic.py | 4 ++-- .../light_client/test_single_merkle_proof.py | 4 ++-- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py index 92d39653b5..21d28c3f08 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py @@ -13,6 +13,7 @@ expect_assertion_error, spec_state_test, with_bellatrix_and_later, + with_bellatrix_until_eip7732, with_phases, ) from eth2spec.test.helpers.keys import privkeys @@ -291,14 +292,14 @@ def run_non_empty_extra_data_test(spec, state): assert state.latest_execution_payload_header.extra_data == execution_payload.extra_data -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_non_empty_extra_data_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_non_empty_extra_data_test(spec, state) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_non_empty_extra_data_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) @@ -320,14 +321,14 @@ def run_non_empty_transactions_test(spec, state): assert state.latest_execution_payload_header.transactions_root == execution_payload.transactions.hash_tree_root() -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_non_empty_transactions_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_non_empty_extra_data_test(spec, state) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_non_empty_transactions_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) @@ -346,14 +347,14 @@ def run_zero_length_transaction_test(spec, state): assert state.latest_execution_payload_header.transactions_root == execution_payload.transactions.hash_tree_root() -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_zero_length_transaction_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_zero_length_transaction_test(spec, state) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_zero_length_transaction_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/fork_choice/test_should_override_forkchoice_update.py b/tests/core/pyspec/eth2spec/test/bellatrix/fork_choice/test_should_override_forkchoice_update.py index 6c8e33e954..dbbeb6ae0f 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/fork_choice/test_should_override_forkchoice_update.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/fork_choice/test_should_override_forkchoice_update.py @@ -1,6 +1,6 @@ from eth2spec.test.context import ( spec_state_test, - with_bellatrix_and_later, + with_bellatrix_until_eip7732, with_presets, ) from eth2spec.test.helpers.constants import ( @@ -28,7 +28,7 @@ ) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test @with_presets([MINIMAL], reason="too slow") def test_should_override_forkchoice_update__false(spec, state): @@ -73,7 +73,7 @@ def test_should_override_forkchoice_update__false(spec, state): yield 'steps', test_steps -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_should_override_forkchoice_update__true(spec, state): test_steps = [] diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/sync/test_optimistic.py b/tests/core/pyspec/eth2spec/test/bellatrix/sync/test_optimistic.py index 2d1aaced91..9eb45ff394 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/sync/test_optimistic.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/sync/test_optimistic.py @@ -1,6 +1,6 @@ from eth2spec.test.context import ( spec_state_test, - with_bellatrix_and_later, + with_bellatrix_until_eip7732, ) from eth2spec.test.helpers.attestations import ( state_transition_with_full_block, @@ -28,7 +28,7 @@ ) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_from_syncing_to_invalid(spec, state): test_steps = [] diff --git a/tests/core/pyspec/eth2spec/test/capella/light_client/test_single_merkle_proof.py b/tests/core/pyspec/eth2spec/test/capella/light_client/test_single_merkle_proof.py index 7f414ab285..7c39236fe8 100644 --- a/tests/core/pyspec/eth2spec/test/capella/light_client/test_single_merkle_proof.py +++ b/tests/core/pyspec/eth2spec/test/capella/light_client/test_single_merkle_proof.py @@ -1,6 +1,6 @@ from eth2spec.test.context import ( spec_state_test, - with_capella_and_later, + with_capella_until_eip7732, with_test_suite_name, ) from eth2spec.test.helpers.attestations import ( @@ -9,7 +9,7 @@ @with_test_suite_name("BeaconBlockBody") -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_execution_merkle_proof(spec, state): block = state_transition_with_full_block(spec, state, True, False) From 7f52e6ddfeb85c464574fdcd57bff18ebf06d668 Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 9 Jul 2024 10:38:19 -0300 Subject: [PATCH 20/73] skip some more tests and fix bellatrix execution_payload --- .../block_processing/test_process_execution_payload.py | 5 +++++ .../test/bellatrix/unittests/test_transition.py | 5 +++-- .../pyspec/eth2spec/test/capella/sanity/test_blocks.py | 10 ++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py index 21d28c3f08..096e457cd1 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py @@ -365,6 +365,11 @@ def run_randomized_non_validated_execution_fields_test(spec, state, rng, executi next_slot(spec, state) execution_payload = build_randomized_execution_payload(spec, state, rng) + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash + state.latest_execution_payload_header.gas_limit = execution_payload.gas_limit + state.latest_block_hash = execution_payload.parent_hash + yield from run_execution_payload_processing( spec, state, execution_payload, diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_transition.py b/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_transition.py index 4a7c5d4a17..f90f1447ca 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_transition.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/unittests/test_transition.py @@ -5,7 +5,8 @@ ) from eth2spec.test.context import ( spec_state_test, - with_bellatrix_and_later + with_bellatrix_and_later, + with_bellatrix_until_eip7732, ) @@ -32,7 +33,7 @@ def test_success_merge_complete(spec, state): ] -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_is_merge_block_and_is_execution_enabled(spec, state): for result in expected_results: diff --git a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py index dabc2be18b..dd25e9c934 100644 --- a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py @@ -3,6 +3,7 @@ from eth2spec.test.helpers.forks import is_post_electra from eth2spec.test.context import ( with_capella_and_later, + with_capella_until_eip7732, spec_state_test, with_presets, ) @@ -38,7 +39,7 @@ # `is_execution_enabled` has been removed from Capella # -@with_capella_and_later +@with_capella_until_eip7732 @spec_state_test def test_invalid_is_execution_enabled_false(spec, state): # Set `latest_execution_payload_header` to empty @@ -308,7 +309,12 @@ def test_withdrawal_success_two_blocks(spec, state): block = build_empty_block_for_next_slot(spec, state) signed_block_2 = state_transition_and_sign_block(spec, state, block) - assert state.next_withdrawal_index == pre_next_withdrawal_index + spec.MAX_WITHDRAWALS_PER_PAYLOAD * 2 + # after EIP-7732 the second block does not perform any withdrawals because + # there was no payload processed + if is_post_eip7732(spec): + assert state.next_withdrawal_index == pre_next_withdrawal_index + spec.MAX_WITHDRAWALS_PER_PAYLOAD + else: + assert state.next_withdrawal_index == pre_next_withdrawal_index + spec.MAX_WITHDRAWALS_PER_PAYLOAD * 2 yield 'blocks', [signed_block_1, signed_block_2] yield 'post', state From ab221ff08987044f3fe2a08eaef757a11f098818 Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 21 Aug 2024 16:28:24 -0300 Subject: [PATCH 21/73] skip several more tests --- .../test_process_execution_payload.py | 12 ++++++------ .../test/bellatrix/genesis/test_initialization.py | 5 +++++ .../eth2spec/test/capella/sanity/test_blocks.py | 2 +- .../test_process_execution_payload.py | 2 +- .../test/deneb/fork_choice/test_on_block.py | 13 +++++++------ 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py index 096e457cd1..2963c7a5c4 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py @@ -102,7 +102,7 @@ def run_success_test(spec, state): yield from run_execution_payload_processing(spec, state, execution_payload) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_success_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) @@ -110,7 +110,7 @@ def test_success_first_payload(spec, state): yield from run_success_test(spec, state) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_success_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) @@ -126,14 +126,14 @@ def run_gap_slot_test(spec, state): yield from run_execution_payload_processing(spec, state, execution_payload) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_success_first_payload_with_gap_slot(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_gap_slot_test(spec, state) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_success_regular_payload_with_gap_slot(spec, state): state = build_state_with_complete_transition(spec, state) @@ -148,14 +148,14 @@ def run_bad_execution_test(spec, state): yield from run_execution_payload_processing(spec, state, execution_payload, valid=False, execution_valid=False) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_invalid_bad_execution_first_payload(spec, state): state = build_state_with_incomplete_transition(spec, state) yield from run_bad_execution_test(spec, state) -@with_bellatrix_and_later +@with_bellatrix_until_eip7732 @spec_state_test def test_invalid_bad_execution_regular_payload(spec, state): state = build_state_with_complete_transition(spec, state) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/genesis/test_initialization.py b/tests/core/pyspec/eth2spec/test/bellatrix/genesis/test_initialization.py index b4d0f86dab..a1f8eccfcf 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/genesis/test_initialization.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/genesis/test_initialization.py @@ -10,6 +10,7 @@ from eth2spec.test.helpers.deposits import ( prepare_full_genesis_deposits, ) +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.genesis import ( get_sample_genesis_execution_payload_header, ) @@ -72,6 +73,10 @@ def test_initialize_pre_transition_empty_payload(spec): # initialize beacon_state *with* an *empty* execution_payload_header yield 'execution_payload_header', 'meta', True execution_payload_header = spec.ExecutionPayloadHeader() + if is_post_eip7732(spec): + kzgs = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() + execution_payload_header.blob_kzg_commitments_root = kzgs.hash_tree_root() + state = spec.initialize_beacon_state_from_eth1( eth1_block_hash, eth1_timestamp, diff --git a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py index dd25e9c934..3c11049273 100644 --- a/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/capella/sanity/test_blocks.py @@ -1,6 +1,6 @@ import random from eth2spec.test.helpers.constants import MINIMAL -from eth2spec.test.helpers.forks import is_post_electra +from eth2spec.test.helpers.forks import is_post_electra, is_post_eip7732 from eth2spec.test.context import ( with_capella_and_later, with_capella_until_eip7732, diff --git a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py index 54764ddd6b..e554d93fe3 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py @@ -76,7 +76,7 @@ def verify_and_notify_new_payload(self, new_payload_request) -> bool: if not valid: if is_post_eip7732(spec): - expect_assertion_error(lambda: spec.process_execution_payload(state, signed_envelope, body, TestEngine())) + expect_assertion_error(lambda: spec.process_execution_payload(state, signed_envelope, TestEngine())) else: expect_assertion_error(lambda: spec.process_execution_payload(state, body, TestEngine())) yield 'post', None diff --git a/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py index a7e7f784e4..8bf7988091 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py @@ -2,12 +2,13 @@ from eth2spec.test.context import ( spec_state_test, - with_all_phases_from_except, + with_all_phases_from_to_except, ) from eth2spec.test.helpers.constants import ( DENEB, EIP7594, + EIP7732, ) from eth2spec.test.helpers.block import ( @@ -39,7 +40,7 @@ def get_block_with_blob(spec, state, rng=None): return block, blobs, blob_kzg_proofs -@with_all_phases_from_except(DENEB, [EIP7594]) +@with_all_phases_from_to_except(DENEB, EIP7732, [EIP7594]) @spec_state_test def test_simple_blob_data(spec, state): rng = Random(1234) @@ -74,7 +75,7 @@ def test_simple_blob_data(spec, state): yield 'steps', test_steps -@with_all_phases_from_except(DENEB, [EIP7594]) +@with_all_phases_from_to_except(DENEB, EIP7732, [EIP7594]) @spec_state_test def test_invalid_incorrect_proof(spec, state): rng = Random(1234) @@ -102,7 +103,7 @@ def test_invalid_incorrect_proof(spec, state): yield 'steps', test_steps -@with_all_phases_from_except(DENEB, [EIP7594]) +@with_all_phases_from_to_except(DENEB, EIP7732, [EIP7594]) @spec_state_test def test_invalid_data_unavailable(spec, state): rng = Random(1234) @@ -130,7 +131,7 @@ def test_invalid_data_unavailable(spec, state): yield 'steps', test_steps -@with_all_phases_from_except(DENEB, [EIP7594]) +@with_all_phases_from_to_except(DENEB, EIP7732, [EIP7594]) @spec_state_test def test_invalid_wrong_proofs_length(spec, state): rng = Random(1234) @@ -158,7 +159,7 @@ def test_invalid_wrong_proofs_length(spec, state): yield 'steps', test_steps -@with_all_phases_from_except(DENEB, [EIP7594]) +@with_all_phases_from_to_except(DENEB, EIP7732, [EIP7594]) @spec_state_test def test_invalid_wrong_blobs_length(spec, state): rng = Random(1234) From 3de46b72f69ccd4c6c6cdc8d0d89fa8795d0d54c Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 9 Jul 2024 14:12:47 -0300 Subject: [PATCH 22/73] fix deneb process_execution_payload --- .../deneb/block_processing/test_process_execution_payload.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py index e554d93fe3..ec05197ee1 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py @@ -34,7 +34,10 @@ def run_execution_payload_processing(spec, state, execution_payload, blob_kzg_co payload=execution_payload, beacon_block_root=state.latest_block_header.hash_tree_root(), payload_withheld=False, + blob_kzg_commitments=blob_kzg_commitments, ) + kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK](blob_kzg_commitments) + state.latest_execution_payload_header.blob_kzg_commitments_root = kzg_list.hash_tree_root() post_state = state.copy() post_state.latest_block_hash = execution_payload.block_hash post_state.latest_full_slot = state.slot From f7d7e1a4b37e683731d0483034c8c82596711ea1 Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 9 Jul 2024 14:30:23 -0300 Subject: [PATCH 23/73] fix get_head --- .../eth2spec/test/phase0/fork_choice/test_get_head.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 886fcbd209..ccacc2f10f 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -25,7 +25,7 @@ apply_next_epoch_with_attestations, ) from eth2spec.test.helpers.forks import ( - is_post_altair, + is_post_altair, is_post_eip7732, ) from eth2spec.test.helpers.state import ( next_slots, @@ -44,7 +44,11 @@ def test_genesis(spec, state): yield 'anchor_block', anchor_block anchor_root = get_anchor_root(spec, state) - assert spec.get_head(store) == anchor_root + head = spec.get_head(store) + if is_post_eip7732(spec): + assert head.root == anchor_root + else: + assert head == anchor_root test_steps.append({ 'checks': { 'genesis_time': int(store.genesis_time), From e94a337dd78799c68472492cdfb6f2473ff6fc2b Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 15 Jul 2024 09:57:41 -0300 Subject: [PATCH 24/73] Fix execution payload testing in 7732 --- .../test_process_execution_payload.py | 6 ++++- .../pyspec/eth2spec/test/helpers/block.py | 1 + .../test/helpers/execution_payload.py | 3 ++- .../eth2spec/test/helpers/fork_choice.py | 10 ++++++-- .../pyspec/eth2spec/test/helpers/genesis.py | 6 ++++- .../pyspec/eth2spec/test/helpers/state.py | 17 ++++++++++++- .../test/phase0/fork_choice/test_get_head.py | 24 ++++++++++++------- 7 files changed, 52 insertions(+), 15 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py index ec05197ee1..38bfccc3a7 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py @@ -32,13 +32,17 @@ def run_execution_payload_processing(spec, state, execution_payload, blob_kzg_co if is_post_eip7732(spec): envelope = spec.ExecutionPayloadEnvelope( payload=execution_payload, - beacon_block_root=state.latest_block_header.hash_tree_root(), payload_withheld=False, blob_kzg_commitments=blob_kzg_commitments, ) kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK](blob_kzg_commitments) state.latest_execution_payload_header.blob_kzg_commitments_root = kzg_list.hash_tree_root() post_state = state.copy() + previous_state_root = state.hash_tree_root() + if post_state.latest_block_header.state_root == spec.Root(): + post_state.latest_block_header.state_root = previous_state_root + envelope.beacon_block_root = post_state.latest_block_header.hash_tree_root() + post_state.latest_block_hash = execution_payload.block_hash post_state.latest_full_slot = state.slot envelope.state_root = post_state.hash_tree_root() diff --git a/tests/core/pyspec/eth2spec/test/helpers/block.py b/tests/core/pyspec/eth2spec/test/helpers/block.py index 96a0155732..73cc6bab18 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/block.py +++ b/tests/core/pyspec/eth2spec/test/helpers/block.py @@ -1,3 +1,4 @@ +from eth_utils import encode_hex from eth2spec.test.helpers.execution_payload import build_empty_execution_payload from eth2spec.test.helpers.execution_payload import build_empty_signed_execution_payload_header from eth2spec.test.helpers.forks import is_post_whisk, is_post_altair, is_post_bellatrix, is_post_eip7732 diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 2c1e5201f3..9d5e80ddab 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -238,6 +238,7 @@ def build_empty_post_eip7732_execution_payload_header(spec, state): if not is_post_eip7732(spec): return parent_block_root = hash_tree_root(state.latest_block_header) + kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() return spec.ExecutionPayloadHeader( parent_block_hash=state.latest_block_hash, parent_block_root=parent_block_root, @@ -246,7 +247,7 @@ def build_empty_post_eip7732_execution_payload_header(spec, state): builder_index=spec.ValidatorIndex(0), slot=state.slot, value=spec.Gwei(0), - blob_kzg_commitments_root=spec.Root() + blob_kzg_commitments_root=kzg_list.hash_tree_root(), ) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 76495f9d42..878095c956 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -122,7 +122,12 @@ def get_genesis_forkchoice_store(spec, genesis_state): def get_genesis_forkchoice_store_and_block(spec, genesis_state): assert genesis_state.slot == spec.GENESIS_SLOT genesis_block = spec.BeaconBlock(state_root=genesis_state.hash_tree_root()) - return spec.get_forkchoice_store(genesis_state, genesis_block), genesis_block + if is_post_eip7732(spec): + genesis_block.body.signed_execution_payload_header.message.block_hash = genesis_state.latest_block_hash + store = spec.get_forkchoice_store(genesis_state, genesis_block) + if is_post_eip7732(spec): + store.execution_payload_states = store.block_states.copy() + return store, genesis_block def get_block_file_name(block): @@ -161,7 +166,8 @@ def run_on_block(spec, store, signed_block, valid=True): assert False spec.on_block(store, signed_block) - assert store.blocks[signed_block.message.hash_tree_root()] == signed_block.message + root = signed_block.message.hash_tree_root() + assert store.blocks[root] == signed_block.message def add_block(spec, diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index 5c39604943..4984eb7dbc 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -117,6 +117,10 @@ def create_genesis_state(spec, validator_balances, activation_threshold): previous_version = getattr(spec.config, f"{previous_fork.upper()}_FORK_VERSION") current_version = getattr(spec.config, f"{spec.fork.upper()}_FORK_VERSION") + genesis_block_body = spec.BeaconBlockBody() + if is_post_eip7732(spec): + genesis_block_body.signed_execution_payload_header.message.block_hash = eth1_block_hash + state = spec.BeaconState( genesis_time=0, eth1_deposit_index=len(validator_balances), @@ -130,7 +134,7 @@ def create_genesis_state(spec, validator_balances, activation_threshold): current_version=current_version, epoch=spec.GENESIS_EPOCH, ), - latest_block_header=spec.BeaconBlockHeader(body_root=spec.hash_tree_root(spec.BeaconBlockBody())), + latest_block_header=spec.BeaconBlockHeader(body_root=spec.hash_tree_root(genesis_block_body)), randao_mixes=[eth1_block_hash] * spec.EPOCHS_PER_HISTORICAL_VECTOR, ) diff --git a/tests/core/pyspec/eth2spec/test/helpers/state.py b/tests/core/pyspec/eth2spec/test/helpers/state.py index 07e7bfb478..168d8b5184 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/state.py +++ b/tests/core/pyspec/eth2spec/test/helpers/state.py @@ -1,6 +1,7 @@ +from eth_utils import encode_hex from eth2spec.test.context import expect_assertion_error from eth2spec.test.helpers.block import apply_empty_block, sign_block, transition_unsigned_block -from eth2spec.test.helpers.forks import is_post_altair +from eth2spec.test.helpers.forks import is_post_altair, is_post_eip7732 from eth2spec.test.helpers.voluntary_exits import get_unslashed_exited_validators @@ -91,6 +92,20 @@ def get_state_root(spec, state, slot) -> bytes: return state.state_roots[slot % spec.SLOTS_PER_HISTORICAL_ROOT] +def payload_state_transition(spec, store, state, block): + if is_post_eip7732(spec): + # cache the latest block header + previous_state_root = state.hash_tree_root() + if state.latest_block_header.state_root == spec.Root(): + state.latest_block_header.state_root = previous_state_root + # also perform the state transition as if the payload was revealed + state.latest_block_hash = block.body.signed_execution_payload_header.message.block_hash + state.latest_full_slot = block.slot + root = block.hash_tree_root() + store.execution_payload_states[root] = store.block_states[root].copy() + return state + + def state_transition_and_sign_block(spec, state, block, expect_fail=False): """ State transition via the provided ``block`` diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index ccacc2f10f..6dd34541cd 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -1,5 +1,6 @@ import random +from eth_utils import encode_hex from eth2spec.test.context import ( spec_state_test, with_altair_and_later, @@ -30,9 +31,16 @@ from eth2spec.test.helpers.state import ( next_slots, next_epoch, + payload_state_transition, state_transition_and_sign_block, ) +def check_head_against_root(spec, store, root): + head = spec.get_head(store) + if is_post_eip7732(spec): + assert head.root == root + else: + assert head == root @with_altair_and_later @spec_state_test @@ -44,11 +52,8 @@ def test_genesis(spec, state): yield 'anchor_block', anchor_block anchor_root = get_anchor_root(spec, state) - head = spec.get_head(store) - if is_post_eip7732(spec): - assert head.root == anchor_root - else: - assert head == anchor_root + check_head_against_root(spec, store, anchor_root) + test_steps.append({ 'checks': { 'genesis_time': int(store.genesis_time), @@ -72,20 +77,21 @@ def test_chain_no_attestations(spec, state): yield 'anchor_block', anchor_block anchor_root = get_anchor_root(spec, state) - assert spec.get_head(store) == anchor_root + check_head_against_root(spec, store, anchor_root) output_head_check(spec, store, test_steps) - + # On receiving a block of `GENESIS_SLOT + 1` slot block_1 = build_empty_block_for_next_slot(spec, state) signed_block_1 = state_transition_and_sign_block(spec, state, block_1) yield from tick_and_add_block(spec, store, signed_block_1, test_steps) - + payload_state_transition(spec, store, state, signed_block_1.message) + # On receiving a block of next epoch block_2 = build_empty_block_for_next_slot(spec, state) signed_block_2 = state_transition_and_sign_block(spec, state, block_2) yield from tick_and_add_block(spec, store, signed_block_2, test_steps) - assert spec.get_head(store) == spec.hash_tree_root(block_2) + check_head_against_root(spec, store, spec.hash_tree_root(block_2)) output_head_check(spec, store, test_steps) yield 'steps', test_steps From f3238a095f650169b39465e32c3adb790bebb995 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 15 Jul 2024 11:09:01 -0300 Subject: [PATCH 25/73] Use full nodes --- tests/core/pyspec/eth2spec/test/helpers/fork_choice.py | 2 +- tests/core/pyspec/eth2spec/test/helpers/state.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 878095c956..358ea7ac36 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -54,7 +54,7 @@ def get_anchor_root(spec, state): def tick_and_add_block(spec, store, signed_block, test_steps, valid=True, merge_block=False, block_not_found=False, is_optimistic=False, blob_data=None): - pre_state = store.block_states[signed_block.message.parent_root] + pre_state = store.execution_payload_states[signed_block.message.parent_root] if merge_block: assert spec.is_merge_transition_block(pre_state, signed_block.message.body) diff --git a/tests/core/pyspec/eth2spec/test/helpers/state.py b/tests/core/pyspec/eth2spec/test/helpers/state.py index 168d8b5184..82d714bec2 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/state.py +++ b/tests/core/pyspec/eth2spec/test/helpers/state.py @@ -102,7 +102,7 @@ def payload_state_transition(spec, store, state, block): state.latest_block_hash = block.body.signed_execution_payload_header.message.block_hash state.latest_full_slot = block.slot root = block.hash_tree_root() - store.execution_payload_states[root] = store.block_states[root].copy() + store.execution_payload_states[root] = state.copy() return state From ba8bb951bf1c20710300cb4a043e7e7c0db865f9 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 15 Jul 2024 12:01:02 -0300 Subject: [PATCH 26/73] some forkchoice fixes --- .../test/phase0/fork_choice/test_get_head.py | 51 ++++++----- .../test/phase0/fork_choice/test_on_block.py | 87 ++++++++++++++----- 2 files changed, 94 insertions(+), 44 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 6dd34541cd..79be7c4b47 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -108,7 +108,7 @@ def test_split_tie_breaker_no_attestations(spec, state): yield 'anchor_state', state yield 'anchor_block', anchor_block anchor_root = get_anchor_root(spec, state) - assert spec.get_head(store) == anchor_root + check_head_against_root(spec, store, anchor_root) output_head_check(spec, store, test_steps) # Create block at slot 1 @@ -127,10 +127,13 @@ def test_split_tie_breaker_no_attestations(spec, state): on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_1, test_steps) + post_state_1 = state.copy() + payload_state_transition(spec, store, state, signed_block_1.message) yield from add_block(spec, store, signed_block_2, test_steps) + payload_state_transition(spec, store, post_state_1, signed_block_2.message) highest_root = max(spec.hash_tree_root(block_1), spec.hash_tree_root(block_2)) - assert spec.get_head(store) == highest_root + check_head_against_root(spec, store, highest_root) output_head_check(spec, store, test_steps) yield 'steps', test_steps @@ -147,7 +150,7 @@ def test_shorter_chain_but_heavier_weight(spec, state): yield 'anchor_state', state yield 'anchor_block', anchor_block anchor_root = get_anchor_root(spec, state) - assert spec.get_head(store) == anchor_root + check_head_against_root(spec, store, anchor_root) output_head_check(spec, store, test_steps) # build longer tree @@ -156,6 +159,7 @@ def test_shorter_chain_but_heavier_weight(spec, state): long_block = build_empty_block_for_next_slot(spec, long_state) signed_long_block = state_transition_and_sign_block(spec, long_state, long_block) yield from tick_and_add_block(spec, store, signed_long_block, test_steps) + payload_state_transition(spec, store, long_state, signed_long_block.message) # build short tree short_state = genesis_state.copy() @@ -163,14 +167,15 @@ def test_shorter_chain_but_heavier_weight(spec, state): short_block.body.graffiti = b'\x42' * 32 signed_short_block = state_transition_and_sign_block(spec, short_state, short_block) yield from tick_and_add_block(spec, store, signed_short_block, test_steps) + payload_state_transition(spec, store, short_state, signed_short_block.message) # Since the long chain has higher proposer_score at slot 1, the latest long block is the head - assert spec.get_head(store) == spec.hash_tree_root(long_block) + check_head_against_root(spec, store, spec.hash_tree_root(long_block)) short_attestation = get_valid_attestation(spec, short_state, short_block.slot, signed=True) yield from tick_and_run_on_attestation(spec, store, short_attestation, test_steps) - assert spec.get_head(store) == spec.hash_tree_root(short_block) + check_head_against_root(spec, store, spec.hash_tree_root(short_block)) output_head_check(spec, store, test_steps) yield 'steps', test_steps @@ -186,7 +191,7 @@ def test_filtered_block_tree(spec, state): yield 'anchor_state', state yield 'anchor_block', anchor_block anchor_root = get_anchor_root(spec, state) - assert spec.get_head(store) == anchor_root + check_head_against_root(spec, store, anchor_root) output_head_check(spec, store, test_steps) # transition state past initial couple of epochs @@ -201,12 +206,13 @@ def test_filtered_block_tree(spec, state): on_tick_and_append_step(spec, store, current_time, test_steps) for signed_block in signed_blocks: yield from add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, state, signed_block.message) assert store.justified_checkpoint == state.current_justified_checkpoint # the last block in the branch should be the head expected_head_root = spec.hash_tree_root(signed_blocks[-1].message) - assert spec.get_head(store) == expected_head_root + check_head_against_root(spec, store, expected_head_root) output_head_check(spec, store, test_steps) # @@ -242,12 +248,13 @@ def test_filtered_block_tree(spec, state): # include rogue block and associated attestations in the store yield from add_block(spec, store, signed_rogue_block, test_steps) + payload_state_transition(spec, store, non_viable_state, rogue_block.message) for attestation in attestations: yield from tick_and_run_on_attestation(spec, store, attestation, test_steps) # ensure that get_head still returns the head from the previous branch - assert spec.get_head(store) == expected_head_root + check_head_against_root(spec, store, expected_head_root) output_head_check(spec, store, test_steps) yield 'steps', test_steps @@ -264,7 +271,7 @@ def test_proposer_boost_correct_head(spec, state): yield 'anchor_state', state yield 'anchor_block', anchor_block anchor_root = get_anchor_root(spec, state) - assert spec.get_head(store) == anchor_root + check_head_against_root(spec, store, anchor_root) output_head_check(spec, store, test_steps) # Build block that serves as head ONLY on timely arrival, and ONLY in that slot @@ -291,19 +298,19 @@ def test_proposer_boost_correct_head(spec, state): # Process block_2 yield from add_block(spec, store, signed_block_2, test_steps) assert store.proposer_boost_root == spec.Root() - assert spec.get_head(store) == spec.hash_tree_root(block_2) + check_head_against_root(spec, store, spec.hash_tree_root(block_2)) # Process block_1 on timely arrival # The head should temporarily change to block_1 yield from add_block(spec, store, signed_block_1, test_steps) assert store.proposer_boost_root == spec.hash_tree_root(block_1) - assert spec.get_head(store) == spec.hash_tree_root(block_1) + check_head_against_root(spec, store, spec.hash_tree_root(block_1)) # After block_1.slot, the head should revert to block_2 time = store.genesis_time + (block_1.slot + 1) * spec.config.SECONDS_PER_SLOT on_tick_and_append_step(spec, store, time, test_steps) assert store.proposer_boost_root == spec.Root() - assert spec.get_head(store) == spec.hash_tree_root(block_2) + check_head_against_root(spec, store, spec.hash_tree_root(block_2)) output_head_check(spec, store, test_steps) yield 'steps', test_steps @@ -320,7 +327,7 @@ def test_discard_equivocations_on_attester_slashing(spec, state): yield 'anchor_state', state yield 'anchor_block', anchor_block anchor_root = get_anchor_root(spec, state) - assert spec.get_head(store) == anchor_root + check_head_against_root(spec, store, anchor_root) output_head_check(spec, store, test_steps) # Build block that serves as head before discarding equivocations @@ -360,23 +367,23 @@ def test_discard_equivocations_on_attester_slashing(spec, state): # Process block_2 yield from add_block(spec, store, signed_block_2, test_steps) assert store.proposer_boost_root == spec.Root() - assert spec.get_head(store) == spec.hash_tree_root(block_2) + check_head_against_root(spec, store, spec.hash_tree_root(block_2)) # Process block_1 # The head should remain block_2 yield from add_block(spec, store, signed_block_1, test_steps) assert store.proposer_boost_root == spec.Root() - assert spec.get_head(store) == spec.hash_tree_root(block_2) + check_head_against_root(spec, store, spec.hash_tree_root(block_2)) # Process attestation # The head should change to block_1 yield from add_attestation(spec, store, attestation, test_steps) - assert spec.get_head(store) == spec.hash_tree_root(block_1) + check_head_against_root(spec, store, spec.hash_tree_root(block_1)) # Process attester_slashing # The head should revert to block_2 yield from add_attester_slashing(spec, store, attester_slashing, test_steps) - assert spec.get_head(store) == spec.hash_tree_root(block_2) + check_head_against_root(spec, store, spec.hash_tree_root(block_2)) output_head_check(spec, store, test_steps) yield 'steps', test_steps @@ -462,7 +469,7 @@ def test_discard_equivocations_slashed_validator_censoring(spec, state): on_tick_and_append_step(spec, store, current_time, test_steps) # Check that block with higher root wins - assert spec.get_head(store) == block_high_root + check_head_against_root(spec, store, block_high_root) # Create attestation for block with lower root attestation = get_valid_attestation(spec, block_low_root_post_state, slot=eqv_slot, index=0, signed=True) @@ -473,7 +480,7 @@ def test_discard_equivocations_slashed_validator_censoring(spec, state): # Add attestation to the store yield from add_attestation(spec, store, attestation, test_steps) # Check that block with higher root still wins - assert spec.get_head(store) == block_high_root + check_head_against_root(spec, store, block_high_root) output_head_check(spec, store, test_steps) yield 'steps', test_steps @@ -550,7 +557,7 @@ def test_voting_source_within_two_epoch(spec, state): last_fork_block_root, store.finalized_checkpoint.epoch ) - assert spec.get_head(store) == last_fork_block_root + check_head_against_root(spec, store, last_fork_block_root) yield 'steps', test_steps @@ -634,7 +641,7 @@ def test_voting_source_beyond_two_epoch(spec, state): last_fork_block_root, store.finalized_checkpoint.epoch ) - assert spec.get_head(store) == correct_head + check_head_against_root(spec, store, correct_head) yield 'steps', test_steps @@ -739,7 +746,7 @@ def test_incorrect_finalized(spec, state): store.finalized_checkpoint.epoch ) assert spec.get_head(store) != last_fork_block_root - assert spec.get_head(store) == head_root + check_head_against_root(spec, store, head_root) yield 'steps', test_steps """ diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index cd41350496..5a15975209 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -18,6 +18,7 @@ transition_unsigned_block, sign_block, ) +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.fork_choice import ( get_genesis_forkchoice_store_and_block, on_tick_and_append_step, @@ -62,14 +63,14 @@ def test_basic(spec, state): block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) # On receiving a block of next epoch store.time = current_time + spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH block = build_empty_block(spec, state, state.slot + spec.SLOTS_PER_EPOCH) signed_block = state_transition_and_sign_block(spec, state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) yield 'steps', test_steps @@ -96,7 +97,7 @@ def test_on_block_checkpoints(spec, state): state, store, last_signed_block = yield from apply_next_epoch_with_attestations( spec, state, store, True, False, test_steps=test_steps) last_block_root = hash_tree_root(last_signed_block.message) - assert spec.get_head(store) == last_block_root + check_head_against_root(spec, store, last_block_root) # Forward 1 epoch next_epoch(spec, state) @@ -109,7 +110,7 @@ def test_on_block_checkpoints(spec, state): block = build_empty_block_for_next_slot(spec, fin_state) signed_block = state_transition_and_sign_block(spec, fin_state.copy(), block) yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) yield 'steps', test_steps @@ -469,14 +470,28 @@ def test_proposer_boost(spec, state): on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block, test_steps) assert store.proposer_boost_root == spec.hash_tree_root(block) - assert spec.get_weight(store, spec.hash_tree_root(block)) > 0 + if is_post_eip7732(spec): + node = spec.ChildNode( + root=spec.hash_tree_root(block), + slot=block.slot, + ) + assert spec.get_weight(store, node) > 0 + else: + assert spec.get_weight(store, spec.hash_tree_root(block)) > 0 # Ensure that boost is removed after slot is over time = (store.genesis_time + block.slot * spec.config.SECONDS_PER_SLOT + spec.config.SECONDS_PER_SLOT) on_tick_and_append_step(spec, store, time, test_steps) assert store.proposer_boost_root == spec.Root() - assert spec.get_weight(store, spec.hash_tree_root(block)) == 0 + if is_post_eip7732(spec): + node = spec.ChildNode( + root=spec.hash_tree_root(block), + slot=block.slot, + ) + assert spec.get_weight(store, node) > 0 + else: + assert spec.get_weight(store, spec.hash_tree_root(block)) == 0 next_slots(spec, state, 3) block = build_empty_block_for_next_slot(spec, state) @@ -487,14 +502,28 @@ def test_proposer_boost(spec, state): on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block, test_steps) assert store.proposer_boost_root == spec.hash_tree_root(block) - assert spec.get_weight(store, spec.hash_tree_root(block)) > 0 + if is_post_eip7732(spec): + node = spec.ChildNode( + root=spec.hash_tree_root(block), + slot=block.slot, + ) + assert spec.get_weight(store, node) > 0 + else: + assert spec.get_weight(store, spec.hash_tree_root(block)) > 0 # Ensure that boost is removed after slot is over time = (store.genesis_time + block.slot * spec.config.SECONDS_PER_SLOT + spec.config.SECONDS_PER_SLOT) on_tick_and_append_step(spec, store, time, test_steps) assert store.proposer_boost_root == spec.Root() - assert spec.get_weight(store, spec.hash_tree_root(block)) == 0 + if is_post_eip7732(spec): + node = spec.ChildNode( + root=spec.hash_tree_root(block), + slot=block.slot, + ) + assert spec.get_weight(store, node) > 0 + else: + assert spec.get_weight(store, spec.hash_tree_root(block)) == 0 test_steps.append({ 'checks': { @@ -564,7 +593,14 @@ def test_proposer_boost_is_first_block(spec, state): yield from add_block(spec, store, signed_block_a, test_steps) # `proposer_boost_root` is now `block_a` assert store.proposer_boost_root == spec.hash_tree_root(block_a) - assert spec.get_weight(store, spec.hash_tree_root(block_a)) > 0 + if is_post_eip7732(spec): + node = spec.ChildNode( + root=spec.hash_tree_root(block_a), + slot=block_a.slot, + ) + assert spec.get_weight(store, node) > 0 + else: + assert spec.get_weight(store, spec.hash_tree_root(block_a)) > 0 test_steps.append({ 'checks': { 'proposer_boost_root': encode_hex(store.proposer_boost_root), @@ -579,7 +615,14 @@ def test_proposer_boost_is_first_block(spec, state): yield from add_block(spec, store, signed_block_b, test_steps) # `proposer_boost_root` is still `block_a` assert store.proposer_boost_root == spec.hash_tree_root(block_a) - assert spec.get_weight(store, spec.hash_tree_root(block_b)) == 0 + if is_post_eip7732(spec): + node = spec.ChildNode( + root=spec.hash_tree_root(block_b), + slot=block_b.slot, + ) + assert spec.get_weight(store, node) > 0 + else: + assert spec.get_weight(store, spec.hash_tree_root(block_b)) == 0 test_steps.append({ 'checks': { 'proposer_boost_root': encode_hex(store.proposer_boost_root), @@ -656,7 +699,7 @@ def test_justification_withholding(spec, state): yield from tick_and_add_block(spec, store, signed_block, test_steps) assert state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 - assert spec.get_head(store) == hash_tree_root(honest_block) + check_head_against_root(spec, store, hash_tree_root(honest_block)) assert is_ready_to_justify(spec, honest_state) # ------------ @@ -666,7 +709,7 @@ def test_justification_withholding(spec, state): yield from tick_and_add_block(spec, store, attacker_signed_blocks[-1], test_steps) assert store.finalized_checkpoint.epoch == 3 assert store.justified_checkpoint.epoch == 4 - assert spec.get_head(store) == hash_tree_root(honest_block) + check_head_against_root(spec, store, hash_tree_root(honest_block)) yield 'steps', test_steps @@ -712,7 +755,7 @@ def test_justification_withholding_reverse_order(spec, state): assert attacker_state.current_justified_checkpoint.epoch == 3 assert spec.get_current_epoch(attacker_state) == 4 attackers_head = hash_tree_root(attacker_signed_blocks[-1].message) - assert spec.get_head(store) == attackers_head + check_head_against_root(spec, store, attackers_head) # ------------ @@ -743,7 +786,7 @@ def test_justification_withholding_reverse_order(spec, state): yield from tick_and_add_block(spec, store, signed_block, test_steps) assert store.finalized_checkpoint.epoch == 3 assert store.justified_checkpoint.epoch == 4 - assert spec.get_head(store) == hash_tree_root(honest_block) + check_head_against_root(spec, store, hash_tree_root(honest_block)) yield 'steps', test_steps @@ -791,7 +834,7 @@ def test_justification_update_beginning_of_epoch(spec, state): # Now add the blocks & check that justification update was triggered for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) assert store.justified_checkpoint.epoch == 4 yield 'steps', test_steps @@ -841,7 +884,7 @@ def test_justification_update_end_of_epoch(spec, state): # Now add the blocks & check that justification update was triggered for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) assert store.justified_checkpoint.epoch == 4 yield 'steps', test_steps @@ -1048,7 +1091,7 @@ def test_justified_update_not_realized_finality(spec, state): finalized_root = spec.get_head(store) finalized_block = store.blocks[finalized_root] assert spec.compute_epoch_at_slot(finalized_block.slot) == 4 - assert spec.get_head(store) == finalized_root + check_head_against_root(spec, store, finalized_root) # Copy the post-state to use later another_state = state.copy() @@ -1124,7 +1167,7 @@ def test_justified_update_monotonic(spec, state): finalized_root = spec.get_head(store) finalized_block = store.blocks[finalized_root] assert spec.compute_epoch_at_slot(finalized_block.slot) == 4 - assert spec.get_head(store) == finalized_root + check_head_against_root(spec, store, finalized_root) # Copy into another variable so we can use `state` later another_state = state.copy() @@ -1203,7 +1246,7 @@ def test_justified_update_always_if_better(spec, state): finalized_root = spec.get_head(store) finalized_block = store.blocks[finalized_root] assert spec.compute_epoch_at_slot(finalized_block.slot) == 4 - assert spec.get_head(store) == finalized_root + check_head_against_root(spec, store, finalized_root) # Copy into another variable to use later another_state = state.copy() @@ -1283,7 +1326,7 @@ def test_pull_up_past_epoch_block(spec, state): # Add the previously created chain to the store and check for updates for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert store.justified_checkpoint.epoch == 4 assert store.finalized_checkpoint.epoch == 3 @@ -1332,7 +1375,7 @@ def test_not_pull_up_current_epoch_block(spec, state): # Add the previously created chain to the store and check that store does not apply pull-up updates for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert store.justified_checkpoint.epoch == 3 assert store.finalized_checkpoint.epoch == 2 @@ -1382,7 +1425,7 @@ def test_pull_up_on_tick(spec, state): # since the previous epoch was not justified for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert store.justified_checkpoint.epoch == 3 assert store.finalized_checkpoint.epoch == 2 From 7c84a5d78346ae51e65a10af5b7a98176482035c Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 15 Jul 2024 12:11:46 -0300 Subject: [PATCH 27/73] linter --- .../test/bellatrix/sanity/test_blocks.py | 1 - tests/core/pyspec/eth2spec/test/context.py | 1 + .../deneb/unittests/test_config_invariants.py | 2 +- .../pyspec/eth2spec/test/helpers/block.py | 1 - .../eth2spec/test/helpers/fork_choice.py | 8 ++++ .../pyspec/eth2spec/test/helpers/genesis.py | 2 +- .../pyspec/eth2spec/test/helpers/state.py | 1 - .../test/phase0/fork_choice/test_get_head.py | 14 ++----- .../test/phase0/fork_choice/test_on_block.py | 38 +++++++++---------- 9 files changed, 34 insertions(+), 34 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py index bf6ad6ea3e..46852af131 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/sanity/test_blocks.py @@ -11,7 +11,6 @@ ) from eth2spec.test.context import ( BELLATRIX, - with_bellatrix_and_later, with_bellatrix_until_eip7732, with_phases, spec_state_test, diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 9c1d4e78ac..5f3b00eb32 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -590,6 +590,7 @@ def wrapper(*args, spec: Spec, **kw): with_deneb_until_eip7732 = with_all_phases_from_to(DENEB, EIP7732) with_electra_until_eip7732 = with_all_phases_from_to(ELECTRA, EIP7732) + class quoted_str(str): pass diff --git a/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py index 0bfc0957a2..5da9ee4fa9 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py @@ -5,6 +5,7 @@ ) from eth2spec.test.helpers.forks import is_post_eip7732 + @with_deneb_and_later @spec_test @single_phase @@ -27,7 +28,6 @@ def test_networking(spec): if is_post_eip7732(spec): inner_gindex = spec.get_generalized_index( spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK], - i ) outer_gindex = spec.get_generalized_index( spec.BeaconBlockBody, diff --git a/tests/core/pyspec/eth2spec/test/helpers/block.py b/tests/core/pyspec/eth2spec/test/helpers/block.py index 73cc6bab18..96a0155732 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/block.py +++ b/tests/core/pyspec/eth2spec/test/helpers/block.py @@ -1,4 +1,3 @@ -from eth_utils import encode_hex from eth2spec.test.helpers.execution_payload import build_empty_execution_payload from eth2spec.test.helpers.execution_payload import build_empty_signed_execution_payload_header from eth2spec.test.helpers.forks import is_post_whisk, is_post_altair, is_post_bellatrix, is_post_eip7732 diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 358ea7ac36..583f7f4356 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -10,6 +10,14 @@ ) +def check_head_against_root(spec, store, root): + head = spec.get_head(store) + if is_post_eip7732(spec): + assert head.root == root + else: + assert head == root + + class BlobData(NamedTuple): """ The return values of ``retrieve_blobs_and_proofs`` helper. diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index 4984eb7dbc..b21d805416 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -198,6 +198,6 @@ def create_genesis_state(spec, validator_balances, activation_threshold): if is_post_eip7732(spec): withdrawals = spec.List[spec.Withdrawal, spec.MAX_WITHDRAWALS_PER_PAYLOAD]() state.latest_withdrawals_root = withdrawals.hash_tree_root() - state.latest_block_hash = state.latest_execution_payload_header.block_hash # last block is full + state.latest_block_hash = state.latest_execution_payload_header.block_hash # last block is full return state diff --git a/tests/core/pyspec/eth2spec/test/helpers/state.py b/tests/core/pyspec/eth2spec/test/helpers/state.py index 82d714bec2..7fc099904f 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/state.py +++ b/tests/core/pyspec/eth2spec/test/helpers/state.py @@ -1,4 +1,3 @@ -from eth_utils import encode_hex from eth2spec.test.context import expect_assertion_error from eth2spec.test.helpers.block import apply_empty_block, sign_block, transition_unsigned_block from eth2spec.test.helpers.forks import is_post_altair, is_post_eip7732 diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 79be7c4b47..44f3821ce2 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -1,6 +1,5 @@ import random -from eth_utils import encode_hex from eth2spec.test.context import ( spec_state_test, with_altair_and_later, @@ -15,6 +14,7 @@ from eth2spec.test.helpers.fork_choice import ( add_attester_slashing, add_block, + check_head_against_root, get_anchor_root, get_genesis_forkchoice_store_and_block, get_formatted_head_output, @@ -26,7 +26,7 @@ apply_next_epoch_with_attestations, ) from eth2spec.test.helpers.forks import ( - is_post_altair, is_post_eip7732, + is_post_altair, ) from eth2spec.test.helpers.state import ( next_slots, @@ -35,12 +35,6 @@ state_transition_and_sign_block, ) -def check_head_against_root(spec, store, root): - head = spec.get_head(store) - if is_post_eip7732(spec): - assert head.root == root - else: - assert head == root @with_altair_and_later @spec_state_test @@ -79,13 +73,13 @@ def test_chain_no_attestations(spec, state): anchor_root = get_anchor_root(spec, state) check_head_against_root(spec, store, anchor_root) output_head_check(spec, store, test_steps) - + # On receiving a block of `GENESIS_SLOT + 1` slot block_1 = build_empty_block_for_next_slot(spec, state) signed_block_1 = state_transition_and_sign_block(spec, state, block_1) yield from tick_and_add_block(spec, store, signed_block_1, test_steps) payload_state_transition(spec, store, state, signed_block_1.message) - + # On receiving a block of next epoch block_2 = build_empty_block_for_next_slot(spec, state) signed_block_2 = state_transition_and_sign_block(spec, state, block_2) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 5a15975209..1db8cd35bc 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -20,6 +20,7 @@ ) from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.fork_choice import ( + check_head_against_root, get_genesis_forkchoice_store_and_block, on_tick_and_append_step, add_block, @@ -35,7 +36,6 @@ state_transition_and_sign_block, ) - rng = random.Random(2020) @@ -472,9 +472,9 @@ def test_proposer_boost(spec, state): assert store.proposer_boost_root == spec.hash_tree_root(block) if is_post_eip7732(spec): node = spec.ChildNode( - root=spec.hash_tree_root(block), - slot=block.slot, - ) + root=spec.hash_tree_root(block), + slot=block.slot, + ) assert spec.get_weight(store, node) > 0 else: assert spec.get_weight(store, spec.hash_tree_root(block)) > 0 @@ -486,9 +486,9 @@ def test_proposer_boost(spec, state): assert store.proposer_boost_root == spec.Root() if is_post_eip7732(spec): node = spec.ChildNode( - root=spec.hash_tree_root(block), - slot=block.slot, - ) + root=spec.hash_tree_root(block), + slot=block.slot, + ) assert spec.get_weight(store, node) > 0 else: assert spec.get_weight(store, spec.hash_tree_root(block)) == 0 @@ -504,9 +504,9 @@ def test_proposer_boost(spec, state): assert store.proposer_boost_root == spec.hash_tree_root(block) if is_post_eip7732(spec): node = spec.ChildNode( - root=spec.hash_tree_root(block), - slot=block.slot, - ) + root=spec.hash_tree_root(block), + slot=block.slot, + ) assert spec.get_weight(store, node) > 0 else: assert spec.get_weight(store, spec.hash_tree_root(block)) > 0 @@ -518,9 +518,9 @@ def test_proposer_boost(spec, state): assert store.proposer_boost_root == spec.Root() if is_post_eip7732(spec): node = spec.ChildNode( - root=spec.hash_tree_root(block), - slot=block.slot, - ) + root=spec.hash_tree_root(block), + slot=block.slot, + ) assert spec.get_weight(store, node) > 0 else: assert spec.get_weight(store, spec.hash_tree_root(block)) == 0 @@ -595,9 +595,9 @@ def test_proposer_boost_is_first_block(spec, state): assert store.proposer_boost_root == spec.hash_tree_root(block_a) if is_post_eip7732(spec): node = spec.ChildNode( - root=spec.hash_tree_root(block_a), - slot=block_a.slot, - ) + root=spec.hash_tree_root(block_a), + slot=block_a.slot, + ) assert spec.get_weight(store, node) > 0 else: assert spec.get_weight(store, spec.hash_tree_root(block_a)) > 0 @@ -617,9 +617,9 @@ def test_proposer_boost_is_first_block(spec, state): assert store.proposer_boost_root == spec.hash_tree_root(block_a) if is_post_eip7732(spec): node = spec.ChildNode( - root=spec.hash_tree_root(block_b), - slot=block_b.slot, - ) + root=spec.hash_tree_root(block_b), + slot=block_b.slot, + ) assert spec.get_weight(store, node) > 0 else: assert spec.get_weight(store, spec.hash_tree_root(block_b)) == 0 From 34a21f4c5c0677decdcb114b0b152e89f1bad074 Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 16 Jul 2024 16:23:34 -0300 Subject: [PATCH 28/73] fix test_networking --- .../eth2spec/test/deneb/unittests/test_config_invariants.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py b/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py index 5da9ee4fa9..a901adcb58 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py +++ b/tests/core/pyspec/eth2spec/test/deneb/unittests/test_config_invariants.py @@ -28,6 +28,7 @@ def test_networking(spec): if is_post_eip7732(spec): inner_gindex = spec.get_generalized_index( spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK], + i ) outer_gindex = spec.get_generalized_index( spec.BeaconBlockBody, From 6c5f1cb8d375ac243cced66aee9b9861a2af1db8 Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 16 Jul 2024 16:53:28 -0300 Subject: [PATCH 29/73] fix test_discard_equivocations_on_attester_slashing --- .../test/phase0/fork_choice/test_ex_ante.py | 37 ++++++++++--------- .../test/phase0/fork_choice/test_get_head.py | 17 +++++---- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py index 5b7fb5ca88..ee85d6a22b 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py @@ -13,6 +13,7 @@ from eth2spec.test.helpers.constants import MAINNET from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.fork_choice import ( + check_head_against_root, get_genesis_forkchoice_store_and_block, on_tick_and_append_step, add_attestation, @@ -34,7 +35,7 @@ def _apply_base_block_a(spec, state, store, test_steps): if is_post_eip7732: assert head.root == expected_root else: - assert spec.get_head(store) == signed_block_a.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_a.message.hash_tree_root()) @with_altair_and_later @@ -91,15 +92,15 @@ def _filter_participant_set(participants): time = state_c.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Block B received at N+2 — C is head due to proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Attestation_1 received at N+2 — C is head yield from add_attestation(spec, store, attestation, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) yield 'steps', test_steps @@ -168,11 +169,11 @@ def test_ex_ante_attestations_is_greater_than_proposer_boost_with_boost(spec, st time = state_c.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Block B received at N+2 — C is head due to proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Attestation_set_1 at slot `N + 1` voting for block B proposer_boost_root = signed_block_b.message.hash_tree_root() @@ -192,7 +193,7 @@ def _filter_participant_set(participants): # Attestation_set_1 received at N+2 — B is head because B's attestation_score > C's proposer_score. # (B's proposer_score = C's attestation_score = 0) yield from add_attestation(spec, store, attestation, test_steps) - assert spec.get_head(store) == signed_block_b.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_b.message.hash_tree_root()) yield 'steps', test_steps @@ -245,17 +246,17 @@ def test_ex_ante_sandwich_without_attestations(spec, state): time = state_c.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Block B received at N+2 — C is head, it has proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Block D received at N+3 - D is head, it has proposer score boost time = state_d.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_d, test_steps) - assert spec.get_head(store) == signed_block_d.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_d.message.hash_tree_root()) yield 'steps', test_steps @@ -322,21 +323,21 @@ def _filter_participant_set(participants): time = state_c.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Block B received at N+2 — C is head, it has proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Attestation_1 received at N+3 — C is head time = state_d.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_attestation(spec, store, attestation, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Block D received at N+3 - D is head, it has proposer score boost yield from add_block(spec, store, signed_block_d, test_steps) - assert spec.get_head(store) == signed_block_d.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_d.message.hash_tree_root()) yield 'steps', test_steps @@ -392,11 +393,11 @@ def test_ex_ante_sandwich_with_boost_not_sufficient(spec, state): time = state_c.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Block B received at N+2 — C is head, it has proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Attestation_set_1 at N+2 voting for block C proposer_boost_root = signed_block_c.message.hash_tree_root() @@ -418,10 +419,10 @@ def _filter_participant_set(participants): time = state_d.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_attestation(spec, store, attestation, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) # Block D received at N+3 - C is head, D's boost not sufficient! yield from add_block(spec, store, signed_block_d, test_steps) - assert spec.get_head(store) == signed_block_c.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) yield 'steps', test_steps diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 44f3821ce2..67047f05ae 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -326,7 +326,7 @@ def test_discard_equivocations_on_attester_slashing(spec, state): # Build block that serves as head before discarding equivocations state_1 = genesis_state.copy() - next_slots(spec, state_1, 3) + next_slots(spec, state_1, 2) block_1 = build_empty_block_for_next_slot(spec, state_1) signed_block_1 = state_transition_and_sign_block(spec, state_1, block_1) @@ -345,7 +345,7 @@ def test_discard_equivocations_on_attester_slashing(spec, state): # Build block that serves as head after discarding equivocations state_2 = genesis_state.copy() - next_slots(spec, state_2, 2) + next_slots(spec, state_2, 3) block_2 = build_empty_block_for_next_slot(spec, state_2) signed_block_2 = state_transition_and_sign_block(spec, state_2.copy(), block_2) rng = random.Random(1001) @@ -358,14 +358,15 @@ def test_discard_equivocations_on_attester_slashing(spec, state): time = store.genesis_time + (block_eqv.slot + 2) * spec.config.SECONDS_PER_SLOT on_tick_and_append_step(spec, store, time, test_steps) - # Process block_2 - yield from add_block(spec, store, signed_block_2, test_steps) - assert store.proposer_boost_root == spec.Root() - check_head_against_root(spec, store, spec.hash_tree_root(block_2)) - # Process block_1 - # The head should remain block_2 yield from add_block(spec, store, signed_block_1, test_steps) + payload_state_transition(spec, store, state_1, signed_block_1.message) + assert store.proposer_boost_root == spec.Root() + check_head_against_root(spec, store, spec.hash_tree_root(block_1)) + + # Process block_2 head should switch to block_2 + yield from add_block(spec, store, signed_block_2, test_steps) + payload_state_transition(spec, store, state_2, signed_block_2.message) assert store.proposer_boost_root == spec.Root() check_head_against_root(spec, store, spec.hash_tree_root(block_2)) From 936a3d627445cee434b8c07d330b2c80fddd0288 Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 16 Jul 2024 17:00:04 -0300 Subject: [PATCH 30/73] test_on_block_finalized_skip_slots --- tests/core/pyspec/eth2spec/test/helpers/fork_choice.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 583f7f4356..2bd592ec42 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -8,6 +8,7 @@ next_slots_with_attestations, state_transition_with_full_block, ) +from eth2spec.test.helpers.state import payload_state_transition def check_head_against_root(spec, store, root): @@ -336,6 +337,7 @@ def apply_next_epoch_with_attestations(spec, for signed_block in new_signed_blocks: block = signed_block.message yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, state, signed_block.message) block_root = block.hash_tree_root() assert store.blocks[block_root] == block last_signed_block = signed_block @@ -358,6 +360,7 @@ def apply_next_slots_with_attestations(spec, for signed_block in new_signed_blocks: block = signed_block.message yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, state, signed_block.message) block_root = block.hash_tree_root() assert store.blocks[block_root] == block last_signed_block = signed_block From 6c50e2650d97ebb613c59a3a0b28a85d598de5ad Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 16 Jul 2024 17:27:16 -0300 Subject: [PATCH 31/73] fix test_discard_equivocations_slashed_validator_censoring --- .../eth2spec/test/phase0/fork_choice/test_get_head.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 67047f05ae..09d9c62580 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -27,6 +27,7 @@ ) from eth2spec.test.helpers.forks import ( is_post_altair, + is_post_eip7732, ) from eth2spec.test.helpers.state import ( next_slots, @@ -418,11 +419,15 @@ def test_discard_equivocations_slashed_validator_censoring(spec, state): anchor_state = state.copy() # Generate an anchor block with correct state root anchor_block = spec.BeaconBlock(state_root=anchor_state.hash_tree_root()) + if is_post_eip7732(spec): + anchor_block.body.signed_execution_payload_header.message.block_hash = anchor_state.latest_block_hash yield 'anchor_state', anchor_state yield 'anchor_block', anchor_block # Get a new store with the anchor state & anchor block store = spec.get_forkchoice_store(anchor_state, anchor_block) + if is_post_eip7732(spec): + store.execution_payload_states = store.block_states.copy() # Now generate the store checks current_time = anchor_state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time @@ -446,7 +451,9 @@ def test_discard_equivocations_slashed_validator_censoring(spec, state): # Add both blocks to the store yield from tick_and_add_block(spec, store, signed_block_1, test_steps) + payload_state_transition(spec, store, state_1, signed_block_1.message) yield from tick_and_add_block(spec, store, signed_block_2, test_steps) + payload_state_transition(spec, store, state_2, signed_block_2.message) # Find out which block will win in tie breaking if spec.hash_tree_root(block_1) < spec.hash_tree_root(block_2): From ef4659bea72c4d6607e91db4abd04a2c42b8ccaa Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 16 Jul 2024 17:44:05 -0300 Subject: [PATCH 32/73] bad state in test_filtered_block_tree --- .../pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 09d9c62580..cce3cd3b76 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -243,7 +243,7 @@ def test_filtered_block_tree(spec, state): # include rogue block and associated attestations in the store yield from add_block(spec, store, signed_rogue_block, test_steps) - payload_state_transition(spec, store, non_viable_state, rogue_block.message) + payload_state_transition(spec, store, non_viable_state, signed_rogue_block.message) for attestation in attestations: yield from tick_and_run_on_attestation(spec, store, attestation, test_steps) From 3906e58309c3d8e37358d1796b1e732991535429 Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 16 Jul 2024 18:03:47 -0300 Subject: [PATCH 33/73] more head checks --- .../fork_choice/test_get_proposer_head.py | 2 +- .../test/phase0/fork_choice/test_reorg.py | 36 +++++++++++-------- .../phase0/fork_choice/test_withholding.py | 24 ++++++------- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_proposer_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_proposer_head.py index 81e5b4f563..da8c55d152 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_proposer_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_proposer_head.py @@ -41,7 +41,7 @@ def test_basic_is_head_root(spec, state): block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) # Proposer of next slot head_root = spec.get_head(store) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py index 983a8ee661..acaf5f171f 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py @@ -15,6 +15,7 @@ build_empty_block, build_empty_block_for_next_slot, ) +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.fork_choice import ( get_genesis_forkchoice_store_and_block, on_tick_and_append_step, @@ -23,6 +24,7 @@ apply_next_epoch_with_attestations, find_next_justifying_slot, is_ready_to_justify, + payload_state_transition, ) from eth2spec.test.helpers.state import ( state_transition_and_sign_block, @@ -75,7 +77,7 @@ def test_simple_attempted_reorg_without_enough_ffg_votes(spec, state): assert spec.compute_epoch_at_slot(justifying_slot) == spec.get_current_epoch(state) for signed_block in signed_blocks[:-2]: yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) state = store.block_states[spec.get_head(store)].copy() assert state.current_justified_checkpoint.epoch == 3 next_slot(spec, state) @@ -129,7 +131,7 @@ def test_simple_attempted_reorg_without_enough_ffg_votes(spec, state): signed_block_y = signed_blocks_of_y.pop(0) yield from tick_and_add_block(spec, store, signed_block_y, test_steps) # chain `y` remains the winner since it arrives earlier than `z` - assert spec.get_head(store) == signed_block_y.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) assert len(signed_blocks_of_y) == len(signed_blocks_of_z) == 0 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 4 @@ -141,14 +143,14 @@ def test_simple_attempted_reorg_without_enough_ffg_votes(spec, state): assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 4 # chain `y` reminds the winner - assert spec.get_head(store) == signed_block_y.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) # to next block next_epoch(spec, state) current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, current_time, test_steps) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 - assert spec.get_head(store) == signed_block_y.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 yield 'steps', test_steps @@ -193,8 +195,12 @@ def _run_delayed_justification(spec, state, attemped_reorg, is_justifying_previo assert spec.compute_epoch_at_slot(justifying_slot) == spec.get_current_epoch(state) for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, state, signed_block.message) spec.get_head(store) == signed_block.message.hash_tree_root() - state = store.block_states[spec.get_head(store)].copy() + if is_post_eip7732(spec): + state = store.execution_payload_states[spec.get_head(store).root].copy() + else: + state = store.block_states[spec.get_head(store)].copy() if is_justifying_previous_epoch: assert state.current_justified_checkpoint.epoch == 2 else: @@ -209,7 +215,7 @@ def _run_delayed_justification(spec, state, attemped_reorg, is_justifying_previo else: signed_block_y = state_transition_with_full_block(spec, state, True, True) yield from tick_and_add_block(spec, store, signed_block_y, test_steps) - assert spec.get_head(store) == signed_block_y.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) if is_justifying_previous_epoch: assert store.justified_checkpoint.epoch == 2 else: @@ -222,7 +228,7 @@ def _run_delayed_justification(spec, state, attemped_reorg, is_justifying_previo current_time = temp_state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, current_time, test_steps) yield from add_attestations(spec, store, attestations_for_y, test_steps) - assert spec.get_head(store) == signed_block_y.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) if attemped_reorg: # add chain z @@ -241,7 +247,7 @@ def _run_delayed_justification(spec, state, attemped_reorg, is_justifying_previo on_tick_and_append_step(spec, store, current_time, test_steps) # no reorg - assert spec.get_head(store) == signed_block_y.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) if is_justifying_previous_epoch: assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 else: @@ -389,7 +395,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 assert y_voting_source_epoch == 3 assert y_voting_source_epoch == store.justified_checkpoint.epoch - assert spec.get_head(store) == signed_block_y.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) if enough_ffg: assert is_ready_to_justify(spec, state) @@ -409,7 +415,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif assert y_voting_source_epoch == 2 assert y_voting_source_epoch != store.justified_checkpoint.epoch assert not (y_voting_source_epoch + 2 >= spec.compute_epoch_at_slot(spec.get_current_slot(store))) - assert spec.get_head(store) == signed_block_z.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_z.message.hash_tree_root()) else: if enough_ffg: # y is not filtered out & wins the LMD competition, so y should be the head @@ -417,13 +423,13 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif assert y_voting_source_epoch == 3 assert y_voting_source_epoch != store.justified_checkpoint.epoch assert y_voting_source_epoch + 2 >= spec.compute_epoch_at_slot(spec.get_current_slot(store)) - assert spec.get_head(store) == signed_block_y.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) else: # y is not filtered out & wins the LMD competition, so y should be the head assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 assert y_voting_source_epoch == 3 assert y_voting_source_epoch == store.justified_checkpoint.epoch - assert spec.get_head(store) == signed_block_y.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) # to next epoch next_epoch(spec, state) @@ -438,7 +444,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif assert y_voting_source_epoch == 2 assert y_voting_source_epoch != store.justified_checkpoint.epoch assert not (y_voting_source_epoch + 2 >= spec.compute_epoch_at_slot(spec.get_current_slot(store))) - assert spec.get_head(store) == signed_block_z.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_z.message.hash_tree_root()) else: if enough_ffg: # y is filtered out & so z should be the head @@ -446,13 +452,13 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif assert y_voting_source_epoch == 3 assert y_voting_source_epoch != store.justified_checkpoint.epoch assert not (y_voting_source_epoch + 2 >= spec.compute_epoch_at_slot(spec.get_current_slot(store))) - assert spec.get_head(store) == signed_block_z.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_z.message.hash_tree_root()) else: # y is not filtered out & wins the LMD competition, so y should be the head assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 assert y_voting_source_epoch == 3 assert y_voting_source_epoch == store.justified_checkpoint.epoch - assert spec.get_head(store) == signed_block_y.message.hash_tree_root() + check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) yield 'steps', test_steps diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py index 61926875ad..a25bfa1b66 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py @@ -62,8 +62,8 @@ def test_withholding_attack(spec, state): signed_attack_block = signed_blocks[-1] for signed_block in signed_blocks[:-1]: yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() - assert spec.get_head(store) == signed_blocks[-2].message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + check_head_against_root(spec, store, signed_blocks[-2].message.hash_tree_root()) state = store.block_states[spec.get_head(store)].copy() assert spec.compute_epoch_at_slot(state.slot) == 4 assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 4 @@ -83,20 +83,20 @@ def test_withholding_attack(spec, state): signed_honest_block = state_transition_and_sign_block(spec, state, honest_block) # Add the honest block to the store yield from tick_and_add_block(spec, store, signed_honest_block, test_steps) - assert spec.get_head(store) == signed_honest_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_honest_block.message.hash_tree_root()) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 # Tick to the next slot so proposer boost is not a factor in choosing the head current_time = (honest_block.slot + 1) * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, current_time, test_steps) - assert spec.get_head(store) == signed_honest_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_honest_block.message.hash_tree_root()) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 # Upon revealing the withheld attack block, the honest block should still be the head yield from tick_and_add_block(spec, store, signed_attack_block, test_steps) - assert spec.get_head(store) == signed_honest_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_honest_block.message.hash_tree_root()) # As a side effect of the pull-up logic, the attack block is pulled up and store.justified_checkpoint is updated assert store.justified_checkpoint.epoch == 4 @@ -105,7 +105,7 @@ def test_withholding_attack(spec, state): current_time = slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, current_time, test_steps) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 6 - assert spec.get_head(store) == signed_honest_block.message.hash_tree_root() + check_head_against_root(spec, store, signed_honest_block.message.hash_tree_root()) yield 'steps', test_steps @@ -149,8 +149,8 @@ def test_withholding_attack_unviable_honest_chain(spec, state): signed_attack_block = signed_blocks[-1] for signed_block in signed_blocks[:-1]: yield from tick_and_add_block(spec, store, signed_block, test_steps) - assert spec.get_head(store) == signed_block.message.hash_tree_root() - assert spec.get_head(store) == signed_blocks[-2].message.hash_tree_root() + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + check_head_against_root(spec, store, signed_blocks[-2].message.hash_tree_root()) state = store.block_states[spec.get_head(store)].copy() assert spec.compute_epoch_at_slot(state.slot) == 5 assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 @@ -176,14 +176,14 @@ def test_withholding_attack_unviable_honest_chain(spec, state): current_epoch = spec.compute_epoch_at_slot(spec.get_current_slot(store)) assert current_epoch == 6 # assert store.voting_source[honest_block_root].epoch == 3 - assert spec.get_head(store) == honest_block_root + check_head_against_root(spec, store, honest_block_root) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 6 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 # Tick to the next slot so proposer boost is not a factor in choosing the head current_time = (honest_block.slot + 1) * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, current_time, test_steps) - assert spec.get_head(store) == honest_block_root + check_head_against_root(spec, store, honest_block_root) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 6 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 @@ -192,7 +192,7 @@ def test_withholding_attack_unviable_honest_chain(spec, state): # The attack block is pulled up and store.justified_checkpoint is updated assert store.justified_checkpoint.epoch == 5 attack_block_root = signed_attack_block.message.hash_tree_root() - assert spec.get_head(store) == attack_block_root + check_head_against_root(spec, store, attack_block_root) # After going to the next epoch, the honest block should become the head slot = spec.get_current_slot(store) + spec.SLOTS_PER_EPOCH - (state.slot % spec.SLOTS_PER_EPOCH) @@ -200,6 +200,6 @@ def test_withholding_attack_unviable_honest_chain(spec, state): on_tick_and_append_step(spec, store, current_time, test_steps) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 7 # assert store.voting_source[honest_block_root].epoch == 5 - assert spec.get_head(store) == honest_block_root + check_head_against_root(spec, store, honest_block_root) yield 'steps', test_steps From 81009f6417832a8d447ff9a72e7ad4eda9a3f9d7 Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 17 Jul 2024 08:42:11 -0300 Subject: [PATCH 34/73] skip honest reorg tests --- tests/core/pyspec/eth2spec/test/context.py | 1 + .../test/phase0/fork_choice/test_get_proposer_head.py | 8 ++++---- .../eth2spec/test/phase0/fork_choice/test_withholding.py | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/context.py b/tests/core/pyspec/eth2spec/test/context.py index 5f3b00eb32..28a247861d 100644 --- a/tests/core/pyspec/eth2spec/test/context.py +++ b/tests/core/pyspec/eth2spec/test/context.py @@ -585,6 +585,7 @@ def wrapper(*args, spec: Spec, **kw): with_whisk_and_later = with_all_phases_from(WHISK, all_phases=ALLOWED_TEST_RUNNER_FORKS) with_eip7594_and_later = with_all_phases_from(EIP7594, all_phases=ALLOWED_TEST_RUNNER_FORKS) +with_altair_until_eip7732 = with_all_phases_from_to(ALTAIR, EIP7732) with_bellatrix_until_eip7732 = with_all_phases_from_to(BELLATRIX, EIP7732) with_capella_until_eip7732 = with_all_phases_from_to(CAPELLA, EIP7732) with_deneb_until_eip7732 = with_all_phases_from_to(DENEB, EIP7732) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_proposer_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_proposer_head.py index da8c55d152..b24e9a65b3 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_proposer_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_proposer_head.py @@ -1,7 +1,7 @@ from eth_utils import encode_hex from eth2spec.test.context import ( spec_state_test, - with_altair_and_later, + with_altair_until_eip7732, ) from eth2spec.test.helpers.attestations import ( get_valid_attestations_at_slot, @@ -25,7 +25,7 @@ ) -@with_altair_and_later +@with_altair_until_eip7732 @spec_state_test def test_basic_is_head_root(spec, state): test_steps = [] @@ -41,7 +41,7 @@ def test_basic_is_head_root(spec, state): block = build_empty_block_for_next_slot(spec, state) signed_block = state_transition_and_sign_block(spec, state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps) - check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + assert spec.get_head(store) == signed_block.message.hash_tree_root() # Proposer of next slot head_root = spec.get_head(store) @@ -65,7 +65,7 @@ def test_basic_is_head_root(spec, state): yield 'steps', test_steps -@with_altair_and_later +@with_altair_until_eip7732 @spec_state_test def test_basic_is_parent_root(spec, state): test_steps = [] diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py index a25bfa1b66..bd7d7d22f9 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py @@ -13,6 +13,7 @@ build_empty_block_for_next_slot, ) from eth2spec.test.helpers.fork_choice import ( + check_head_against_root, get_genesis_forkchoice_store_and_block, on_tick_and_append_step, tick_and_add_block, From 341da172e44899af1a8f9a160bac324d5d1914df Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 17 Jul 2024 08:54:58 -0300 Subject: [PATCH 35/73] fix test_invalid_parent_from_same_slot --- .../eth2spec/test/phase0/sanity/test_blocks.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py index 41ba2e8b71..11f2add340 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py @@ -20,7 +20,10 @@ from eth2spec.test.helpers.proposer_slashings import get_valid_proposer_slashing, check_proposer_slashing_effect from eth2spec.test.helpers.attestations import get_valid_attestation from eth2spec.test.helpers.deposits import prepare_state_and_deposit -from eth2spec.test.helpers.execution_payload import build_empty_execution_payload +from eth2spec.test.helpers.execution_payload import ( + build_empty_execution_payload, + build_empty_signed_execution_payload_header, +) from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits from eth2spec.test.helpers.multi_operations import ( run_slash_and_exit, @@ -36,6 +39,7 @@ is_post_bellatrix, is_post_electra, is_post_capella, + is_post_eip7732, ) from eth2spec.test.context import ( spec_test, spec_state_test, dump_skipping_message, @@ -147,7 +151,7 @@ def process_and_sign_block_without_header_validations(spec, state, block): state_root=spec.Bytes32(), body_root=block.body.hash_tree_root(), ) - if is_post_bellatrix(spec): + if is_post_bellatrix(spec) and not is_post_eip7732(spec): if spec.is_execution_enabled(state, block.body): spec.process_execution_payload(state, block.body, spec.EXECUTION_ENGINE) @@ -199,7 +203,9 @@ def test_invalid_parent_from_same_slot(spec, state): child_block = parent_block.copy() child_block.parent_root = state.latest_block_header.hash_tree_root() - if is_post_bellatrix(spec): + if is_post_eip7732(spec): + child_block.body.signed_execution_payload_header = build_empty_signed_execution_payload_header(spec, state) + elif is_post_bellatrix(spec): child_block.body.execution_payload = build_empty_execution_payload(spec, state) # Show that normal path through transition fails From d69802396b298b7d7e9a71f3b5e12f4cffb1f1bd Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 17 Jul 2024 09:27:28 -0300 Subject: [PATCH 36/73] fix payload transitions in test_reorg.py --- .../eth2spec/test/phase0/fork_choice/test_reorg.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py index acaf5f171f..3e62b85c27 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py @@ -17,6 +17,7 @@ ) from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.fork_choice import ( + check_head_against_root, get_genesis_forkchoice_store_and_block, on_tick_and_append_step, add_attestations, @@ -298,6 +299,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif block_a = build_empty_block_for_next_slot(spec, state) signed_block_a = state_transition_and_sign_block(spec, state, block_a) yield from tick_and_add_block(spec, store, signed_block_a, test_steps) + payload_state_transition(spec, store, state, signed_block_a.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 3 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 2 else: @@ -306,10 +308,12 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif spec, state, store, True, True, test_steps=test_steps) signed_block_a = state_transition_with_full_block(spec, state, True, True) yield from tick_and_add_block(spec, store, signed_block_a, test_steps) + payload_state_transition(spec, store, state, signed_block_a.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 4 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 - spec.get_head(store) == signed_block_a.message.hash_tree_root() - state = store.block_states[spec.get_head(store)].copy() + root_a = signed_block_a.message.hash_tree_root() + check_head_against_root(spec, store, root_a) + state = store.block_states[root_a].copy() state_a = state.copy() if is_justifying_previous_epoch: @@ -363,8 +367,10 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif # apply chain y, the empty chain if slot <= last_slot_of_y and len(signed_blocks_of_y) > 0: signed_block_y = signed_blocks_of_y.pop(0) + state_of_y = states_of_empty_chain.pop(0) assert signed_block_y.message.slot == slot yield from tick_and_add_block(spec, store, signed_block_y, test_steps) + payload_state_transition(spec, store, state_of_y, signed_block_y.message) # apply chain z, a fork chain that includes these attestations_for_y block = build_empty_block(spec, state, slot=slot) @@ -378,6 +384,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif signed_block_z = state_transition_and_sign_block(spec, state, block) if signed_block_y != signed_block_z: yield from tick_and_add_block(spec, store, signed_block_z, test_steps) + payload_state_transition(spec, store, state, signed_block_z.message) if is_ready_to_justify(spec, state): break From f9408f52191b6a2165e95c37b8a651699196638d Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 17 Jul 2024 09:30:56 -0300 Subject: [PATCH 37/73] fix payload transition in test_voting_source_beyond_two_epoch --- .../pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index cce3cd3b76..383d9f0cca 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -625,6 +625,7 @@ def test_voting_source_beyond_two_epoch(spec, state): # Now add the fork to the store for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, state, signed_block.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 6 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 5 assert store.finalized_checkpoint.epoch == 4 From 54b9f10e4b398d4455376d69316f1db9d687975f Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 09:28:06 -0300 Subject: [PATCH 38/73] Remove state from payload_state_transition --- .../eth2spec/test/helpers/fork_choice.py | 12 +++++++--- .../pyspec/eth2spec/test/helpers/state.py | 13 +++++++--- .../test/phase0/fork_choice/test_get_head.py | 24 +++++++++---------- .../test/phase0/fork_choice/test_reorg.py | 10 ++++---- .../phase0/fork_choice/test_withholding.py | 16 +++++++++---- 5 files changed, 47 insertions(+), 28 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 2bd592ec42..715bfbb0bc 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -8,7 +8,10 @@ next_slots_with_attestations, state_transition_with_full_block, ) -from eth2spec.test.helpers.state import payload_state_transition +from eth2spec.test.helpers.state import ( + payload_state_transition, + payload_state_transition_no_store, +) def check_head_against_root(spec, store, root): @@ -337,7 +340,7 @@ def apply_next_epoch_with_attestations(spec, for signed_block in new_signed_blocks: block = signed_block.message yield from tick_and_add_block(spec, store, signed_block, test_steps) - payload_state_transition(spec, store, state, signed_block.message) + payload_state_transition(spec, store, signed_block.message) block_root = block.hash_tree_root() assert store.blocks[block_root] == block last_signed_block = signed_block @@ -360,7 +363,7 @@ def apply_next_slots_with_attestations(spec, for signed_block in new_signed_blocks: block = signed_block.message yield from tick_and_add_block(spec, store, signed_block, test_steps) - payload_state_transition(spec, store, state, signed_block.message) + payload_state_transition(spec, store, signed_block.message) block_root = block.hash_tree_root() assert store.blocks[block_root] == block last_signed_block = signed_block @@ -389,6 +392,7 @@ def find_next_justifying_slot(spec, signed_blocks = [] justifying_slot = None while justifying_slot is None: + previous_header_root = temp_state.latest_block_header.hash_tree_root() signed_block = state_transition_with_full_block( spec, temp_state, @@ -397,6 +401,8 @@ def find_next_justifying_slot(spec, participation_fn, ) signed_blocks.append(signed_block) + payload_state_transition_no_store(spec, temp_state, signed_block.message) + if is_ready_to_justify(spec, temp_state): justifying_slot = temp_state.slot diff --git a/tests/core/pyspec/eth2spec/test/helpers/state.py b/tests/core/pyspec/eth2spec/test/helpers/state.py index 7fc099904f..309a1e0d20 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/state.py +++ b/tests/core/pyspec/eth2spec/test/helpers/state.py @@ -91,7 +91,7 @@ def get_state_root(spec, state, slot) -> bytes: return state.state_roots[slot % spec.SLOTS_PER_HISTORICAL_ROOT] -def payload_state_transition(spec, store, state, block): +def payload_state_transition_no_store(spec, state, block): if is_post_eip7732(spec): # cache the latest block header previous_state_root = state.hash_tree_root() @@ -100,8 +100,15 @@ def payload_state_transition(spec, store, state, block): # also perform the state transition as if the payload was revealed state.latest_block_hash = block.body.signed_execution_payload_header.message.block_hash state.latest_full_slot = block.slot - root = block.hash_tree_root() - store.execution_payload_states[root] = state.copy() + return state + + +def payload_state_transition(spec, store, block): + root = block.hash_tree_root() + state = store.block_states[root].copy() + if is_post_eip7732(spec): + payload_state_transition_no_store(spec, state, block) + store.execution_payload_states[root] = state return state diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 383d9f0cca..65580be6f3 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -79,7 +79,7 @@ def test_chain_no_attestations(spec, state): block_1 = build_empty_block_for_next_slot(spec, state) signed_block_1 = state_transition_and_sign_block(spec, state, block_1) yield from tick_and_add_block(spec, store, signed_block_1, test_steps) - payload_state_transition(spec, store, state, signed_block_1.message) + payload_state_transition(spec, store, signed_block_1.message) # On receiving a block of next epoch block_2 = build_empty_block_for_next_slot(spec, state) @@ -123,9 +123,9 @@ def test_split_tie_breaker_no_attestations(spec, state): yield from add_block(spec, store, signed_block_1, test_steps) post_state_1 = state.copy() - payload_state_transition(spec, store, state, signed_block_1.message) + payload_state_transition(spec, store, signed_block_1.message) yield from add_block(spec, store, signed_block_2, test_steps) - payload_state_transition(spec, store, post_state_1, signed_block_2.message) + payload_state_transition(spec, store, signed_block_2.message) highest_root = max(spec.hash_tree_root(block_1), spec.hash_tree_root(block_2)) check_head_against_root(spec, store, highest_root) @@ -154,7 +154,7 @@ def test_shorter_chain_but_heavier_weight(spec, state): long_block = build_empty_block_for_next_slot(spec, long_state) signed_long_block = state_transition_and_sign_block(spec, long_state, long_block) yield from tick_and_add_block(spec, store, signed_long_block, test_steps) - payload_state_transition(spec, store, long_state, signed_long_block.message) + payload_state_transition(spec, store, signed_long_block.message) # build short tree short_state = genesis_state.copy() @@ -162,7 +162,7 @@ def test_shorter_chain_but_heavier_weight(spec, state): short_block.body.graffiti = b'\x42' * 32 signed_short_block = state_transition_and_sign_block(spec, short_state, short_block) yield from tick_and_add_block(spec, store, signed_short_block, test_steps) - payload_state_transition(spec, store, short_state, signed_short_block.message) + payload_state_transition(spec, store, signed_short_block.message) # Since the long chain has higher proposer_score at slot 1, the latest long block is the head check_head_against_root(spec, store, spec.hash_tree_root(long_block)) @@ -201,7 +201,7 @@ def test_filtered_block_tree(spec, state): on_tick_and_append_step(spec, store, current_time, test_steps) for signed_block in signed_blocks: yield from add_block(spec, store, signed_block, test_steps) - payload_state_transition(spec, store, state, signed_block.message) + payload_state_transition(spec, store, signed_block.message) assert store.justified_checkpoint == state.current_justified_checkpoint @@ -243,7 +243,7 @@ def test_filtered_block_tree(spec, state): # include rogue block and associated attestations in the store yield from add_block(spec, store, signed_rogue_block, test_steps) - payload_state_transition(spec, store, non_viable_state, signed_rogue_block.message) + payload_state_transition(spec, store, signed_rogue_block.message) for attestation in attestations: yield from tick_and_run_on_attestation(spec, store, attestation, test_steps) @@ -361,13 +361,13 @@ def test_discard_equivocations_on_attester_slashing(spec, state): # Process block_1 yield from add_block(spec, store, signed_block_1, test_steps) - payload_state_transition(spec, store, state_1, signed_block_1.message) + payload_state_transition(spec, store, signed_block_1.message) assert store.proposer_boost_root == spec.Root() check_head_against_root(spec, store, spec.hash_tree_root(block_1)) # Process block_2 head should switch to block_2 yield from add_block(spec, store, signed_block_2, test_steps) - payload_state_transition(spec, store, state_2, signed_block_2.message) + payload_state_transition(spec, store, signed_block_2.message) assert store.proposer_boost_root == spec.Root() check_head_against_root(spec, store, spec.hash_tree_root(block_2)) @@ -451,9 +451,9 @@ def test_discard_equivocations_slashed_validator_censoring(spec, state): # Add both blocks to the store yield from tick_and_add_block(spec, store, signed_block_1, test_steps) - payload_state_transition(spec, store, state_1, signed_block_1.message) + payload_state_transition(spec, store, signed_block_1.message) yield from tick_and_add_block(spec, store, signed_block_2, test_steps) - payload_state_transition(spec, store, state_2, signed_block_2.message) + payload_state_transition(spec, store, signed_block_2.message) # Find out which block will win in tie breaking if spec.hash_tree_root(block_1) < spec.hash_tree_root(block_2): @@ -625,7 +625,7 @@ def test_voting_source_beyond_two_epoch(spec, state): # Now add the fork to the store for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) - payload_state_transition(spec, store, state, signed_block.message) + payload_state_transition(spec, store, signed_block.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 6 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 5 assert store.finalized_checkpoint.epoch == 4 diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py index 3e62b85c27..5908db901a 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py @@ -196,7 +196,7 @@ def _run_delayed_justification(spec, state, attemped_reorg, is_justifying_previo assert spec.compute_epoch_at_slot(justifying_slot) == spec.get_current_epoch(state) for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) - payload_state_transition(spec, store, state, signed_block.message) + payload_state_transition(spec, store, signed_block.message) spec.get_head(store) == signed_block.message.hash_tree_root() if is_post_eip7732(spec): state = store.execution_payload_states[spec.get_head(store).root].copy() @@ -299,7 +299,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif block_a = build_empty_block_for_next_slot(spec, state) signed_block_a = state_transition_and_sign_block(spec, state, block_a) yield from tick_and_add_block(spec, store, signed_block_a, test_steps) - payload_state_transition(spec, store, state, signed_block_a.message) + payload_state_transition(spec, store, signed_block_a.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 3 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 2 else: @@ -308,7 +308,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif spec, state, store, True, True, test_steps=test_steps) signed_block_a = state_transition_with_full_block(spec, state, True, True) yield from tick_and_add_block(spec, store, signed_block_a, test_steps) - payload_state_transition(spec, store, state, signed_block_a.message) + payload_state_transition(spec, store, signed_block_a.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 4 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 root_a = signed_block_a.message.hash_tree_root() @@ -370,7 +370,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif state_of_y = states_of_empty_chain.pop(0) assert signed_block_y.message.slot == slot yield from tick_and_add_block(spec, store, signed_block_y, test_steps) - payload_state_transition(spec, store, state_of_y, signed_block_y.message) + payload_state_transition(spec, store, signed_block_y.message) # apply chain z, a fork chain that includes these attestations_for_y block = build_empty_block(spec, state, slot=slot) @@ -384,7 +384,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif signed_block_z = state_transition_and_sign_block(spec, state, block) if signed_block_y != signed_block_z: yield from tick_and_add_block(spec, store, signed_block_z, test_steps) - payload_state_transition(spec, store, state, signed_block_z.message) + payload_state_transition(spec, store, signed_block_z.message) if is_ready_to_justify(spec, state): break diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py index bd7d7d22f9..d863d54123 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py @@ -1,3 +1,4 @@ +from eth_utils import encode_hex from eth2spec.test.context import ( spec_state_test, with_altair_and_later, @@ -16,6 +17,7 @@ check_head_against_root, get_genesis_forkchoice_store_and_block, on_tick_and_append_step, + payload_state_transition, tick_and_add_block, apply_next_epoch_with_attestations, find_next_justifying_slot, @@ -62,10 +64,12 @@ def test_withholding_attack(spec, state): assert len(signed_blocks) > 1 signed_attack_block = signed_blocks[-1] for signed_block in signed_blocks[:-1]: - yield from tick_and_add_block(spec, store, signed_block, test_steps) - check_head_against_root(spec, store, signed_block.message.hash_tree_root()) - check_head_against_root(spec, store, signed_blocks[-2].message.hash_tree_root()) - state = store.block_states[spec.get_head(store)].copy() + current_root = signed_block.message.hash_tree_root() + state = yield from tick_and_add_block(spec, store, signed_block, test_steps) + state = payload_state_transition(spec, store, signed_block.message) + check_head_against_root(spec, store, current_root) + head_root = signed_blocks[-2].message.hash_tree_root() + check_head_against_root(spec, store, head_root) assert spec.compute_epoch_at_slot(state.slot) == 4 assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 4 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 @@ -74,16 +78,18 @@ def test_withholding_attack(spec, state): next_epoch(spec, state) assert spec.compute_epoch_at_slot(state.slot) == 5 assert state.current_justified_checkpoint.epoch == 3 - # Create two block in the honest chain with full attestations, and add to the store + # Create two blocks in the honest chain with full attestations, and add to the store for _ in range(2): signed_block = state_transition_with_full_block(spec, state, True, False) yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) # Create final block in the honest chain that includes the justifying attestations from the attack block honest_block = build_empty_block_for_next_slot(spec, state) honest_block.body.attestations = signed_attack_block.message.body.attestations signed_honest_block = state_transition_and_sign_block(spec, state, honest_block) # Add the honest block to the store yield from tick_and_add_block(spec, store, signed_honest_block, test_steps) + payload_state_transition(spec, store, signed_honest_block.message) check_head_against_root(spec, store, signed_honest_block.message.hash_tree_root()) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 From 04eae5b54b5f7c12df02c643a65d69ed906997ad Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 09:37:39 -0300 Subject: [PATCH 39/73] fix test_on_block --- .../pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 1db8cd35bc..f3f709f821 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -33,6 +33,7 @@ from eth2spec.test.helpers.state import ( next_epoch, next_slots, + payload_state_transition, state_transition_and_sign_block, ) @@ -956,6 +957,7 @@ def test_incompatible_justification_update_start_of_epoch(spec, state): # Now add the blocks & check that justification update was triggered for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) finalized_checkpoint_block = spec.get_checkpoint_block( store, last_block_root, From 5aae7f237b63346ce56c1bacbcfdea6b792eaaf2 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 09:50:26 -0300 Subject: [PATCH 40/73] add more fixes to test_on_block.py --- .../test/phase0/fork_choice/test_on_block.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index f3f709f821..d57a56e964 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -1043,6 +1043,7 @@ def test_incompatible_justification_update_end_of_epoch(spec, state): # Now add the blocks & check that justification update was triggered for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) finalized_checkpoint_block = spec.get_checkpoint_block( store, last_block_root, @@ -1124,6 +1125,7 @@ def test_justified_update_not_realized_finality(spec, state): # Now add the blocks & check that justification update was triggered for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) assert store.justified_checkpoint.epoch == 6 assert store.finalized_checkpoint.epoch == 4 last_block = signed_blocks[-1] @@ -1191,6 +1193,7 @@ def test_justified_update_monotonic(spec, state): # Now add the blocks & check that justification update was triggered for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 7 assert store.justified_checkpoint.epoch == 6 assert store.finalized_checkpoint.epoch == 2 @@ -1245,7 +1248,10 @@ def test_justified_update_always_if_better(spec, state): assert store.finalized_checkpoint.epoch == 2 # We'll eventually make the current head block the finalized block - finalized_root = spec.get_head(store) + if is_post_eip7732(spec): + finalized_root = spec.get_head(store).root + else: + finalized_root = spec.get_head(store) finalized_block = store.blocks[finalized_root] assert spec.compute_epoch_at_slot(finalized_block.slot) == 4 check_head_against_root(spec, store, finalized_root) @@ -1278,6 +1284,7 @@ def test_justified_update_always_if_better(spec, state): # Now add the blocks & check that justification update was triggered for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 7 assert store.justified_checkpoint.epoch == 6 assert store.finalized_checkpoint.epoch == 4 @@ -1329,6 +1336,7 @@ def test_pull_up_past_epoch_block(spec, state): for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert store.justified_checkpoint.epoch == 4 assert store.finalized_checkpoint.epoch == 3 @@ -1378,6 +1386,7 @@ def test_not_pull_up_current_epoch_block(spec, state): for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert store.justified_checkpoint.epoch == 3 assert store.finalized_checkpoint.epoch == 2 @@ -1428,6 +1437,7 @@ def test_pull_up_on_tick(spec, state): for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert store.justified_checkpoint.epoch == 3 assert store.finalized_checkpoint.epoch == 2 From c7e2b5c509e121bb09b2d305afcdb87b64252144 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 10:09:26 -0300 Subject: [PATCH 41/73] fix test_justification_withholding_reverse_order --- .../eth2spec/test/phase0/fork_choice/test_get_head.py | 4 +++- .../eth2spec/test/phase0/fork_choice/test_on_block.py | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 65580be6f3..dc058a16f9 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -85,8 +85,8 @@ def test_chain_no_attestations(spec, state): block_2 = build_empty_block_for_next_slot(spec, state) signed_block_2 = state_transition_and_sign_block(spec, state, block_2) yield from tick_and_add_block(spec, store, signed_block_2, test_steps) - check_head_against_root(spec, store, spec.hash_tree_root(block_2)) + payload_state_transition(spec, store, signed_block_2.message) output_head_check(spec, store, test_steps) yield 'steps', test_steps @@ -543,6 +543,7 @@ def test_voting_source_within_two_epoch(spec, state): # Now add the fork to the store for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 4 assert store.finalized_checkpoint.epoch == 3 @@ -723,6 +724,7 @@ def test_incorrect_finalized(spec, state): # Now add the fork to the store for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 7 assert store.justified_checkpoint.epoch == 6 assert store.finalized_checkpoint.epoch == 3 diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index d57a56e964..dc952dbf98 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -682,6 +682,7 @@ def test_justification_withholding(spec, state): for signed_block in honest_signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) last_honest_block = honest_signed_blocks[-1].message honest_state = store.block_states[hash_tree_root(last_honest_block)].copy() @@ -698,6 +699,7 @@ def test_justification_withholding(spec, state): honest_block.body.attestations = attacker_signed_blocks[-1].message.body.attestations signed_block = state_transition_and_sign_block(spec, honest_state, honest_block) yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) assert state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 check_head_against_root(spec, store, hash_tree_root(honest_block)) @@ -708,6 +710,7 @@ def test_justification_withholding(spec, state): # When the attacker's block is received, the honest block is still the head # This relies on the honest block's LMD score increasing due to proposer boost yield from tick_and_add_block(spec, store, attacker_signed_blocks[-1], test_steps) + payload_state_transition(spec, store, attacker_signed_blocks[-1].message) assert store.finalized_checkpoint.epoch == 3 assert store.justified_checkpoint.epoch == 4 check_head_against_root(spec, store, hash_tree_root(honest_block)) @@ -751,6 +754,7 @@ def test_justification_withholding_reverse_order(spec, state): assert len(signed_blocks) == 1 attacker_signed_blocks += signed_blocks yield from tick_and_add_block(spec, store, signed_blocks[0], test_steps) + payload_state_transition(spec, store, signed_blocks[0].message) assert attacker_state.finalized_checkpoint.epoch == 2 assert attacker_state.current_justified_checkpoint.epoch == 3 @@ -785,6 +789,7 @@ def test_justification_withholding_reverse_order(spec, state): # When the honest block is received, the honest block becomes the head # This relies on the honest block's LMD score increasing due to proposer boost yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) assert store.finalized_checkpoint.epoch == 3 assert store.justified_checkpoint.epoch == 4 check_head_against_root(spec, store, hash_tree_root(honest_block)) @@ -835,6 +840,7 @@ def test_justification_update_beginning_of_epoch(spec, state): # Now add the blocks & check that justification update was triggered for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) assert store.justified_checkpoint.epoch == 4 @@ -886,6 +892,7 @@ def test_justification_update_end_of_epoch(spec, state): for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block.message) assert store.justified_checkpoint.epoch == 4 yield 'steps', test_steps From 35a1a34eed8ae2f43e8eb5e20fa41e7ceba5a395 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 11:07:00 -0300 Subject: [PATCH 42/73] more payload transition additions --- .../eth2spec/test/helpers/fork_choice.py | 1 + .../test/phase0/fork_choice/test_ex_ante.py | 14 +++++++++++++ .../test/phase0/fork_choice/test_on_block.py | 20 +++++++++++++++++-- .../test/phase0/fork_choice/test_reorg.py | 7 +++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 715bfbb0bc..1ba550c913 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -169,6 +169,7 @@ def on_tick_and_append_step(spec, store, time, test_steps): def run_on_block(spec, store, signed_block, valid=True): + print("In run_on_block: ", encode_hex(signed_block.message.hash_tree_root())) if not valid: try: spec.on_block(store, signed_block) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py index ee85d6a22b..deca9d400b 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py @@ -30,6 +30,7 @@ def _apply_base_block_a(spec, state, store, test_steps): block = build_empty_block(spec, state, slot=state.slot + 1) signed_block_a = state_transition_and_sign_block(spec, state, block) yield from tick_and_add_block(spec, store, signed_block_a, test_steps) + payload_state_transition(spec, store, signed_block_a.message) head = spec.get_head(store) expected_root = signed_block_a.message.hash_tree_root() if is_post_eip7732: @@ -93,10 +94,12 @@ def _filter_participant_set(participants): on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_c.message) # Block B received at N+2 — C is head due to proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_b.message) # Attestation_1 received at N+2 — C is head yield from add_attestation(spec, store, attestation, test_steps) @@ -170,10 +173,12 @@ def test_ex_ante_attestations_is_greater_than_proposer_boost_with_boost(spec, st on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_c.message) # Block B received at N+2 — C is head due to proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_c.message) # Attestation_set_1 at slot `N + 1` voting for block B proposer_boost_root = signed_block_b.message.hash_tree_root() @@ -247,16 +252,19 @@ def test_ex_ante_sandwich_without_attestations(spec, state): on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_c.message) # Block B received at N+2 — C is head, it has proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_b.message) # Block D received at N+3 - D is head, it has proposer score boost time = state_d.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_d, test_steps) check_head_against_root(spec, store, signed_block_d.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_d.message) yield 'steps', test_steps @@ -324,10 +332,12 @@ def _filter_participant_set(participants): on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_c.message) # Block B received at N+2 — C is head, it has proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_b.message) # Attestation_1 received at N+3 — C is head time = state_d.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time @@ -338,6 +348,7 @@ def _filter_participant_set(participants): # Block D received at N+3 - D is head, it has proposer score boost yield from add_block(spec, store, signed_block_d, test_steps) check_head_against_root(spec, store, signed_block_d.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_d.message) yield 'steps', test_steps @@ -394,10 +405,12 @@ def test_ex_ante_sandwich_with_boost_not_sufficient(spec, state): on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_c, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_c.message) # Block B received at N+2 — C is head, it has proposer score boost yield from add_block(spec, store, signed_block_b, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_b.message) # Attestation_set_1 at N+2 voting for block C proposer_boost_root = signed_block_c.message.hash_tree_root() @@ -424,5 +437,6 @@ def _filter_participant_set(participants): # Block D received at N+3 - C is head, D's boost not sufficient! yield from add_block(spec, store, signed_block_d, test_steps) check_head_against_root(spec, store, signed_block_c.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block_d.message) yield 'steps', test_steps diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index dc952dbf98..2431b60bf1 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -65,6 +65,7 @@ def test_basic(spec, state): signed_block = state_transition_and_sign_block(spec, state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block.message) # On receiving a block of next epoch store.time = current_time + spec.config.SECONDS_PER_SLOT * spec.SLOTS_PER_EPOCH @@ -72,6 +73,7 @@ def test_basic(spec, state): signed_block = state_transition_and_sign_block(spec, state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block.message) yield 'steps', test_steps @@ -112,6 +114,7 @@ def test_on_block_checkpoints(spec, state): signed_block = state_transition_and_sign_block(spec, fin_state.copy(), block) yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block.message) yield 'steps', test_steps @@ -237,6 +240,7 @@ def test_on_block_finalized_skip_slots(spec, state): block = build_empty_block_for_next_slot(spec, target_state) signed_block = state_transition_and_sign_block(spec, target_state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) yield 'steps', test_steps @@ -432,6 +436,7 @@ def test_new_finalized_slot_is_justified_checkpoint_ancestor(spec, state): pre_store_justified_checkpoint_root = store.justified_checkpoint.root for block in all_blocks: yield from tick_and_add_block(spec, store, block, test_steps) + payload_state_transition(spec, store, block.message) ancestor_at_finalized_slot = spec.get_checkpoint_block( store, @@ -470,6 +475,7 @@ def test_proposer_boost(spec, state): spec.config.SECONDS_PER_SLOT // spec.INTERVALS_PER_SLOT - 1) on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) assert store.proposer_boost_root == spec.hash_tree_root(block) if is_post_eip7732(spec): node = spec.ChildNode( @@ -502,6 +508,7 @@ def test_proposer_boost(spec, state): time = (store.genesis_time + block.slot * spec.config.SECONDS_PER_SLOT) on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) assert store.proposer_boost_root == spec.hash_tree_root(block) if is_post_eip7732(spec): node = spec.ChildNode( @@ -557,6 +564,7 @@ def test_proposer_boost_root_same_slot_untimely_block(spec, state): spec.config.SECONDS_PER_SLOT // spec.INTERVALS_PER_SLOT) on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) assert store.proposer_boost_root == spec.Root() @@ -592,6 +600,7 @@ def test_proposer_boost_is_first_block(spec, state): spec.config.SECONDS_PER_SLOT // spec.INTERVALS_PER_SLOT - 1) on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_a, test_steps) + payload_state_transition(spec, store, signed_block_a.message) # `proposer_boost_root` is now `block_a` assert store.proposer_boost_root == spec.hash_tree_root(block_a) if is_post_eip7732(spec): @@ -614,6 +623,7 @@ def test_proposer_boost_is_first_block(spec, state): block_b.body.graffiti = b'\x34' * 32 signed_block_b = state_transition_and_sign_block(spec, state, block_b) yield from add_block(spec, store, signed_block_b, test_steps) + payload_state_transition(spec, store, signed_block_b.message) # `proposer_boost_root` is still `block_a` assert store.proposer_boost_root == spec.hash_tree_root(block_a) if is_post_eip7732(spec): @@ -1098,7 +1108,10 @@ def test_justified_update_not_realized_finality(spec, state): assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 # We'll make the current head block the finalized block - finalized_root = spec.get_head(store) + if is_post_eip7732(spec): + finalized_root = spec.get_head(store).root + else: + finalized_root = spec.get_head(store) finalized_block = store.blocks[finalized_root] assert spec.compute_epoch_at_slot(finalized_block.slot) == 4 check_head_against_root(spec, store, finalized_root) @@ -1175,7 +1188,10 @@ def test_justified_update_monotonic(spec, state): assert store.finalized_checkpoint.epoch == 2 # We'll eventually make the current head block the finalized block - finalized_root = spec.get_head(store) + if is_post_eip7732(spec): + finalized_root = spec.get_head(store).root + else: + finalized_root = spec.get_head(store) finalized_block = store.blocks[finalized_root] assert spec.compute_epoch_at_slot(finalized_block.slot) == 4 check_head_against_root(spec, store, finalized_root) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py index 5908db901a..d555ede183 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py @@ -79,6 +79,7 @@ def test_simple_attempted_reorg_without_enough_ffg_votes(spec, state): for signed_block in signed_blocks[:-2]: yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block.message) state = store.block_states[spec.get_head(store)].copy() assert state.current_justified_checkpoint.epoch == 3 next_slot(spec, state) @@ -120,17 +121,21 @@ def test_simple_attempted_reorg_without_enough_ffg_votes(spec, state): # (i) slot block_a.slot + 1 signed_block_y = signed_blocks_of_y.pop(0) yield from tick_and_add_block(spec, store, signed_block_y, test_steps) + payload_state_transition(spec, store, signed_block_y.message) # apply block of chain `z` signed_block_z = signed_blocks_of_z.pop(0) yield from tick_and_add_block(spec, store, signed_block_z, test_steps) + payload_state_transition(spec, store, signed_block_z.message) # (ii) slot block_a.slot + 2 # apply block of chain `z` signed_block_z = signed_blocks_of_z.pop(0) yield from tick_and_add_block(spec, store, signed_block_z, test_steps) + payload_state_transition(spec, store, signed_block_z.message) # apply block of chain `y` signed_block_y = signed_blocks_of_y.pop(0) yield from tick_and_add_block(spec, store, signed_block_y, test_steps) + payload_state_transition(spec, store, signed_block_y.message) # chain `y` remains the winner since it arrives earlier than `z` check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) assert len(signed_blocks_of_y) == len(signed_blocks_of_z) == 0 @@ -216,6 +221,7 @@ def _run_delayed_justification(spec, state, attemped_reorg, is_justifying_previo else: signed_block_y = state_transition_with_full_block(spec, state, True, True) yield from tick_and_add_block(spec, store, signed_block_y, test_steps) + payload_state_transition(spec, store, signed_block_y.message) check_head_against_root(spec, store, signed_block_y.message.hash_tree_root()) if is_justifying_previous_epoch: assert store.justified_checkpoint.epoch == 2 @@ -240,6 +246,7 @@ def _run_delayed_justification(spec, state, attemped_reorg, is_justifying_previo assert spec.compute_epoch_at_slot(block_z.slot) == 5 signed_block_z = state_transition_and_sign_block(spec, state, block_z) yield from tick_and_add_block(spec, store, signed_block_z, test_steps) + payload_state_transition(spec, store, signed_block_z.message) else: # next epoch state = state_b.copy() From 58898594d0e2f59ef1caf7e1b9e0459ae0dc812c Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 11:31:52 -0300 Subject: [PATCH 43/73] fix test_justified_update_monotonic --- tests/core/pyspec/eth2spec/test/helpers/fork_choice.py | 1 - .../eth2spec/test/phase0/fork_choice/test_ex_ante.py | 1 + .../eth2spec/test/phase0/fork_choice/test_on_block.py | 2 ++ .../eth2spec/test/phase0/fork_choice/test_reorg.py | 9 +++++++-- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 1ba550c913..715bfbb0bc 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -169,7 +169,6 @@ def on_tick_and_append_step(spec, store, time, test_steps): def run_on_block(spec, store, signed_block, valid=True): - print("In run_on_block: ", encode_hex(signed_block.message.hash_tree_root())) if not valid: try: spec.on_block(store, signed_block) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py index deca9d400b..89d19beb9c 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py @@ -22,6 +22,7 @@ ) from eth2spec.test.helpers.state import ( state_transition_and_sign_block, + payload_state_transition, ) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 2431b60bf1..f5cb77e6cb 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -1223,6 +1223,8 @@ def test_justified_update_monotonic(spec, state): last_block = signed_blocks[-1] last_block_root = last_block.message.hash_tree_root() ancestor_at_finalized_slot = spec.get_ancestor(store, last_block_root, finalized_block.slot) + if is_post_eip7732(spec): + ancestor_at_finalized_slot = ancestor_at_finalized_slot.root assert ancestor_at_finalized_slot == finalized_root # Create a fork with lower justification that also finalizes our chosen block diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py index d555ede183..d3fd527f5f 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py @@ -80,7 +80,13 @@ def test_simple_attempted_reorg_without_enough_ffg_votes(spec, state): yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) payload_state_transition(spec, store, signed_block.message) - state = store.block_states[spec.get_head(store)].copy() + if is_post_eip7732(spec): + head_root = spec.get_head(store).root + state = store.execution_payload_states[head_root].copy() + else: + head_root = spec.get_head(store) + state = store.block_states[head_root].copy() + assert state.current_justified_checkpoint.epoch == 3 next_slot(spec, state) state_a = state.copy() @@ -202,7 +208,6 @@ def _run_delayed_justification(spec, state, attemped_reorg, is_justifying_previo for signed_block in signed_blocks: yield from tick_and_add_block(spec, store, signed_block, test_steps) payload_state_transition(spec, store, signed_block.message) - spec.get_head(store) == signed_block.message.hash_tree_root() if is_post_eip7732(spec): state = store.execution_payload_states[spec.get_head(store).root].copy() else: From 5e353b65e8df3cb74168d616a03d6defafc8fb3e Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 11:36:03 -0300 Subject: [PATCH 44/73] fix test_justified_update_not_realized_finality --- .../pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index f5cb77e6cb..5cee2822ce 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -1151,6 +1151,9 @@ def test_justified_update_not_realized_finality(spec, state): last_block = signed_blocks[-1] last_block_root = last_block.message.hash_tree_root() ancestor_at_finalized_slot = spec.get_ancestor(store, last_block_root, finalized_block.slot) + if is_post_eip7732(spec): + ancestor_at_finalized_slot = ancestor_at_finalized_slot.root + assert ancestor_at_finalized_slot == store.finalized_checkpoint.root yield 'steps', test_steps From 7c74ab2b7b47ab632eb4a6d8b28ac2f6b6cbd6b6 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 13:27:42 -0300 Subject: [PATCH 45/73] fix test_filtered_block_tree --- tests/core/pyspec/eth2spec/test/helpers/attestations.py | 7 ++++++- tests/core/pyspec/eth2spec/test/helpers/fork_choice.py | 1 + .../eth2spec/test/phase0/fork_choice/test_get_head.py | 6 +++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/attestations.py b/tests/core/pyspec/eth2spec/test/helpers/attestations.py index 19c3b7c25a..d3d23a5233 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/attestations.py +++ b/tests/core/pyspec/eth2spec/test/helpers/attestations.py @@ -3,7 +3,11 @@ from typing import List from eth2spec.test.context import expect_assertion_error -from eth2spec.test.helpers.state import state_transition_and_sign_block, next_epoch, next_slot +from eth2spec.test.helpers.state import ( + payload_state_transition_no_store, + state_transition_and_sign_block, + next_epoch, next_slot, +) from eth2spec.test.helpers.block import build_empty_block_for_next_slot from eth2spec.test.helpers.forks import is_post_altair, is_post_deneb, is_post_electra from eth2spec.test.helpers.keys import privkeys @@ -262,6 +266,7 @@ def next_slots_with_attestations(spec, participation_fn, ) signed_blocks.append(signed_block) + payload_state_transition_no_store(spec, post_state, signed_block.message) return state, signed_blocks, post_state diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 715bfbb0bc..f32156d5c1 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -17,6 +17,7 @@ def check_head_against_root(spec, store, root): head = spec.get_head(store) if is_post_eip7732(spec): + print("Obtained head: ", encode_hex(head.root)) assert head.root == root else: assert head == root diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index dc058a16f9..f294cc517d 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -1,5 +1,6 @@ import random +from eth_utils import encode_hex from eth2spec.test.context import ( spec_state_test, with_altair_and_later, @@ -216,7 +217,10 @@ def test_filtered_block_tree(spec, state): # # build a chain without attestations off of previous justified block - non_viable_state = store.block_states[store.justified_checkpoint.root].copy() + if is_post_eip7732(spec): + non_viable_state = store.execution_payload_states[store.justified_checkpoint.root].copy() + else: + non_viable_state = store.block_states[store.justified_checkpoint.root].copy() # ensure that next wave of votes are for future epoch next_epoch(spec, non_viable_state) From 49e68f2cfe3e30cb334d5b7a1bee938e37ce2415 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 15:31:43 -0300 Subject: [PATCH 46/73] fix attestation helpers --- .../pyspec/eth2spec/test/helpers/fork_choice.py | 17 ++++++++++++++--- .../test/phase0/fork_choice/test_on_block.py | 8 ++++++-- .../test/phase0/fork_choice/test_reorg.py | 5 ++++- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index f32156d5c1..ccf4f92810 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -17,7 +17,6 @@ def check_head_against_root(spec, store, root): head = spec.get_head(store) if is_post_eip7732(spec): - print("Obtained head: ", encode_hex(head.root)) assert head.root == root else: assert head == root @@ -183,6 +182,12 @@ def run_on_block(spec, store, signed_block, valid=True): assert store.blocks[root] == signed_block.message +def get_store_full_state(spec, store, root): + if is_post_eip7732(spec): + return store.execution_payload_states[root] + return store.block_states[root] + + def add_block(spec, store, signed_block, @@ -346,7 +351,10 @@ def apply_next_epoch_with_attestations(spec, assert store.blocks[block_root] == block last_signed_block = signed_block - assert store.block_states[block_root].hash_tree_root() == post_state.hash_tree_root() + if is_post_eip7732(spec): + assert store.execution_payload_states[block_root].hash_tree_root() == post_state.hash_tree_root() + else: + assert store.block_states[block_root].hash_tree_root() == post_state.hash_tree_root() return post_state, store, last_signed_block @@ -369,7 +377,10 @@ def apply_next_slots_with_attestations(spec, assert store.blocks[block_root] == block last_signed_block = signed_block - assert store.block_states[block_root].hash_tree_root() == post_state.hash_tree_root() + if is_post_eip7732(spec): + assert store.execution_payload_states[block_root].hash_tree_root() == post_state.hash_tree_root() + else: + assert store.block_states[block_root].hash_tree_root() == post_state.hash_tree_root() return post_state, store, last_signed_block diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 5cee2822ce..806b71fbfe 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -107,9 +107,12 @@ def test_on_block_checkpoints(spec, state): on_tick_and_append_step(spec, store, store.genesis_time + state.slot * spec.config.SECONDS_PER_SLOT, test_steps) # Mock the finalized_checkpoint and build a block on it - fin_state = store.block_states[last_block_root].copy() - fin_state.finalized_checkpoint = store.block_states[last_block_root].current_justified_checkpoint.copy() + if is_post_eip7732(spec): + fin_state = store.execution_payload_states[last_block_root].copy() + else: + fin_state = store.block_states[last_block_root].copy() + fin_state.finalized_checkpoint = store.block_states[last_block_root].current_justified_checkpoint.copy() block = build_empty_block_for_next_slot(spec, fin_state) signed_block = state_transition_and_sign_block(spec, fin_state.copy(), block) yield from tick_and_add_block(spec, store, signed_block, test_steps) @@ -904,6 +907,7 @@ def test_justification_update_end_of_epoch(spec, state): check_head_against_root(spec, store, signed_block.message.hash_tree_root()) payload_state_transition(spec, store, signed_block.message) assert store.justified_checkpoint.epoch == 4 + assert 1 == 0 yield 'steps', test_steps diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py index d3fd527f5f..e8d0584513 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py @@ -19,6 +19,7 @@ from eth2spec.test.helpers.fork_choice import ( check_head_against_root, get_genesis_forkchoice_store_and_block, + get_store_full_state, on_tick_and_append_step, add_attestations, tick_and_add_block, @@ -26,6 +27,7 @@ find_next_justifying_slot, is_ready_to_justify, payload_state_transition, + payload_state_transition_no_store, ) from eth2spec.test.helpers.state import ( state_transition_and_sign_block, @@ -325,7 +327,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 root_a = signed_block_a.message.hash_tree_root() check_head_against_root(spec, store, root_a) - state = store.block_states[root_a].copy() + state = get_store_full_state(spec, store, root_a).copy() state_a = state.copy() if is_justifying_previous_epoch: @@ -358,6 +360,7 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif for slot in range(state.slot + 1, last_slot_of_y + 1): block = build_empty_block(spec, state, slot=slot) signed_block = state_transition_and_sign_block(spec, state, block) + payload_state_transition_no_store(spec, state, signed_block.message) signed_blocks_of_empty_chain.append(signed_block) states_of_empty_chain.append(state.copy()) signed_blocks_of_y.append(signed_block) From 9a923c2084a09c9390846c92d8705eecbab51036 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 15:59:32 -0300 Subject: [PATCH 47/73] get_store_full_state helper --- .../pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py | 2 ++ .../pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index f294cc517d..2585cad987 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -626,6 +626,8 @@ def test_voting_source_beyond_two_epoch(spec, state): # Store the head before adding the fork to the store correct_head = spec.get_head(store) + if is_post_eip7732(spec): + correct_head = correct_head.root # Now add the fork to the store for signed_block in signed_blocks: diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 806b71fbfe..0cb9b6469a 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -22,6 +22,7 @@ from eth2spec.test.helpers.fork_choice import ( check_head_against_root, get_genesis_forkchoice_store_and_block, + get_store_full_state, on_tick_and_append_step, add_block, tick_and_add_block, @@ -428,7 +429,7 @@ def test_new_finalized_slot_is_justified_checkpoint_ancestor(spec, state): all_blocks = [] slot = spec.compute_start_slot_at_epoch(3) block_root = spec.get_block_root_at_slot(state, slot) - another_state = store.block_states[block_root].copy() + another_state = get_store_full_state(spec, store, block_root).copy() for _ in range(2): _, signed_blocks, another_state = next_epoch_with_attestations(spec, another_state, True, True) all_blocks += signed_blocks From 7df5538b5a6b57fa5a066e5588ff3687bccfd867 Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 16:28:23 -0300 Subject: [PATCH 48/73] fix test_proposer_boost_is_first_block --- .../pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 0cb9b6469a..5aa7988f12 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -635,7 +635,7 @@ def test_proposer_boost_is_first_block(spec, state): root=spec.hash_tree_root(block_b), slot=block_b.slot, ) - assert spec.get_weight(store, node) > 0 + assert spec.get_weight(store, node) == 0 else: assert spec.get_weight(store, spec.hash_tree_root(block_b)) == 0 test_steps.append({ From 285539540b855628099c70108fd1911246b8cadf Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 16:34:21 -0300 Subject: [PATCH 49/73] fix test_justification_withholding_reverse_order --- .../pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 5aa7988f12..22f9da7870 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -783,7 +783,7 @@ def test_justification_withholding_reverse_order(spec, state): assert len(honest_signed_blocks) > 0 last_honest_block = honest_signed_blocks[-1].message - honest_state = store.block_states[hash_tree_root(last_honest_block)].copy() + honest_state = get_store_full_state(spec, store, hash_tree_root(last_honest_block)).copy() assert honest_state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2 assert honest_state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 From 8df692edd764e71d5808f5e4652596784a2c04df Mon Sep 17 00:00:00 2001 From: Potuz Date: Mon, 22 Jul 2024 16:51:16 -0300 Subject: [PATCH 50/73] fix test_proposer_boost --- .../pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 22f9da7870..b8d0709f77 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -500,7 +500,7 @@ def test_proposer_boost(spec, state): root=spec.hash_tree_root(block), slot=block.slot, ) - assert spec.get_weight(store, node) > 0 + assert spec.get_weight(store, node) == 0 else: assert spec.get_weight(store, spec.hash_tree_root(block)) == 0 @@ -533,7 +533,7 @@ def test_proposer_boost(spec, state): root=spec.hash_tree_root(block), slot=block.slot, ) - assert spec.get_weight(store, node) > 0 + assert spec.get_weight(store, node) == 0 else: assert spec.get_weight(store, spec.hash_tree_root(block)) == 0 From 89d2764d62db5540db3cbb3dfcf24fc1f61875fd Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 23 Jul 2024 11:09:30 -0300 Subject: [PATCH 51/73] fix test_justification_withholding --- .../pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index b8d0709f77..2b8dc81d92 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -699,7 +699,7 @@ def test_justification_withholding(spec, state): payload_state_transition(spec, store, signed_block.message) last_honest_block = honest_signed_blocks[-1].message - honest_state = store.block_states[hash_tree_root(last_honest_block)].copy() + honest_state = get_store_full_state(spec, store, hash_tree_root(last_honest_block)).copy() assert honest_state.finalized_checkpoint.epoch == store.finalized_checkpoint.epoch == 2 assert honest_state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 From 333002502043db51e227b33bb3cd3da6406dc3ef Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 23 Jul 2024 13:28:33 -0300 Subject: [PATCH 52/73] fix test_on_block_checkpoints --- .../pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 2b8dc81d92..47e2fdb35a 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -115,7 +115,7 @@ def test_on_block_checkpoints(spec, state): fin_state.finalized_checkpoint = store.block_states[last_block_root].current_justified_checkpoint.copy() block = build_empty_block_for_next_slot(spec, fin_state) - signed_block = state_transition_and_sign_block(spec, fin_state.copy(), block) + signed_block = state_transition_and_sign_block(spec, fin_state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) payload_state_transition(spec, store, signed_block.message) From 6e1797e3c3bde1afdade6c3d9932f16e0d3cf63b Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 23 Jul 2024 16:05:22 -0300 Subject: [PATCH 53/73] fix _run_include_votes_of_another_empty_chain --- .../eth2spec/test/phase0/fork_choice/test_get_head.py | 5 +++-- .../eth2spec/test/phase0/fork_choice/test_reorg.py | 9 ++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 2585cad987..8267d828c4 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -4,6 +4,7 @@ from eth2spec.test.context import ( spec_state_test, with_altair_and_later, + with_altair_until_eip7732, with_presets, ) from eth2spec.test.helpers.attestations import get_valid_attestation, next_epoch_with_attestations @@ -258,8 +259,8 @@ def test_filtered_block_tree(spec, state): yield 'steps', test_steps - -@with_altair_and_later +# This test is skipped in EIP-7732 because the block's slot decides first on weight ties +@with_altair_until_eip7732 @spec_state_test def test_proposer_boost_correct_head(spec, state): test_steps = [] diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py index e8d0584513..b0272a02d6 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py @@ -1,3 +1,4 @@ +from eth_utils import encode_hex from eth2spec.test.context import ( spec_state_test, with_altair_and_later, @@ -355,16 +356,14 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif signed_blocks_of_y = [] # build an empty chain to the slot prior epoch boundary - signed_blocks_of_empty_chain = [] states_of_empty_chain = [] for slot in range(state.slot + 1, last_slot_of_y + 1): block = build_empty_block(spec, state, slot=slot) signed_block = state_transition_and_sign_block(spec, state, block) payload_state_transition_no_store(spec, state, signed_block.message) - signed_blocks_of_empty_chain.append(signed_block) states_of_empty_chain.append(state.copy()) signed_blocks_of_y.append(signed_block) - signed_block_y = signed_blocks_of_empty_chain[-1] + signed_block_y = signed_blocks_of_y[-1] assert spec.compute_epoch_at_slot(signed_block_y.message.slot) == 4 # create 2/3 votes for the empty chain @@ -382,7 +381,6 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif # apply chain y, the empty chain if slot <= last_slot_of_y and len(signed_blocks_of_y) > 0: signed_block_y = signed_blocks_of_y.pop(0) - state_of_y = states_of_empty_chain.pop(0) assert signed_block_y.message.slot == slot yield from tick_and_add_block(spec, store, signed_block_y, test_steps) payload_state_transition(spec, store, signed_block_y.message) @@ -397,9 +395,10 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif ): block.body.attestations = attestations_for_y.pop(0) signed_block_z = state_transition_and_sign_block(spec, state, block) + print("Trying to import block: ", signed_block_z.message.slot) if signed_block_y != signed_block_z: yield from tick_and_add_block(spec, store, signed_block_z, test_steps) - payload_state_transition(spec, store, signed_block_z.message) + state = payload_state_transition(spec, store, signed_block_z.message).copy() if is_ready_to_justify(spec, state): break From eeb7097f03c59bee13001749259fcb8f3af01cef Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 23 Jul 2024 16:16:04 -0300 Subject: [PATCH 54/73] Fix test_simple_attempted_reorg_without_enough_ffg_votes --- .../core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py index b0272a02d6..0462252d3b 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py @@ -102,6 +102,7 @@ def test_simple_attempted_reorg_without_enough_ffg_votes(spec, state): block_y = build_empty_block_for_next_slot(spec, state) signed_block_y = state_transition_and_sign_block(spec, state, block_y) signed_blocks_of_y.append(signed_block_y) + payload_state_transition_no_store(spec, state, signed_block_y.message) # chain y has some on-chain attestations, but not enough to justify c4 signed_block_y = state_transition_with_full_block(spec, state, True, True) @@ -117,6 +118,7 @@ def test_simple_attempted_reorg_without_enough_ffg_votes(spec, state): block_z.body.attestations = [attestation] signed_block_z = state_transition_and_sign_block(spec, state, block_z) signed_blocks_of_z.append(signed_block_z) + payload_state_transition_no_store(spec, state, signed_block_z.message) # add an empty block on chain z block_z = build_empty_block_for_next_slot(spec, state) @@ -395,7 +397,6 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif ): block.body.attestations = attestations_for_y.pop(0) signed_block_z = state_transition_and_sign_block(spec, state, block) - print("Trying to import block: ", signed_block_z.message.slot) if signed_block_y != signed_block_z: yield from tick_and_add_block(spec, store, signed_block_z, test_steps) state = payload_state_transition(spec, store, signed_block_z.message).copy() From b3159091973d1f0ca06ac3dfac0e75c9d49ef1ee Mon Sep 17 00:00:00 2001 From: Potuz Date: Tue, 23 Jul 2024 16:45:55 -0300 Subject: [PATCH 55/73] some small fixes --- .../eth2spec/test/phase0/fork_choice/test_on_block.py | 2 -- .../test/phase0/fork_choice/test_withholding.py | 10 ++++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 47e2fdb35a..8b1a65ae66 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -908,8 +908,6 @@ def test_justification_update_end_of_epoch(spec, state): check_head_against_root(spec, store, signed_block.message.hash_tree_root()) payload_state_transition(spec, store, signed_block.message) assert store.justified_checkpoint.epoch == 4 - assert 1 == 0 - yield 'steps', test_steps diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py index d863d54123..27ab9bfcc9 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py @@ -65,8 +65,8 @@ def test_withholding_attack(spec, state): signed_attack_block = signed_blocks[-1] for signed_block in signed_blocks[:-1]: current_root = signed_block.message.hash_tree_root() - state = yield from tick_and_add_block(spec, store, signed_block, test_steps) - state = payload_state_transition(spec, store, signed_block.message) + yield from tick_and_add_block(spec, store, signed_block, test_steps) + payload_state_transition(spec, store, signed_block.message) check_head_against_root(spec, store, current_root) head_root = signed_blocks[-2].message.hash_tree_root() check_head_against_root(spec, store, head_root) @@ -79,10 +79,12 @@ def test_withholding_attack(spec, state): assert spec.compute_epoch_at_slot(state.slot) == 5 assert state.current_justified_checkpoint.epoch == 3 # Create two blocks in the honest chain with full attestations, and add to the store + honest_state = state.copy() for _ in range(2): - signed_block = state_transition_with_full_block(spec, state, True, False) + print("Trying slot", honest_state.slot) + signed_block = state_transition_with_full_block(spec, honest_state, True, False) yield from tick_and_add_block(spec, store, signed_block, test_steps) - payload_state_transition(spec, store, signed_block.message) + honest_state = payload_state_transition(spec, store, signed_block.message).copy() # Create final block in the honest chain that includes the justifying attestations from the attack block honest_block = build_empty_block_for_next_slot(spec, state) honest_block.body.attestations = signed_attack_block.message.body.attestations From ed33cbeb82bac98c109756f0a9892da7c860b878 Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 24 Jul 2024 11:12:01 -0300 Subject: [PATCH 56/73] fix test_withholding_attack_unviable_honest_chain --- .../eth2spec/test/helpers/fork_choice.py | 2 +- .../phase0/fork_choice/test_withholding.py | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index ccf4f92810..8b7fc899b2 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -66,7 +66,7 @@ def get_anchor_root(spec, state): def tick_and_add_block(spec, store, signed_block, test_steps, valid=True, merge_block=False, block_not_found=False, is_optimistic=False, blob_data=None): - pre_state = store.execution_payload_states[signed_block.message.parent_root] + pre_state = get_store_full_state(spec, store, signed_block.message.parent_root) if merge_block: assert spec.is_merge_transition_block(pre_state, signed_block.message.body) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py index 27ab9bfcc9..e9a2142ed8 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py @@ -13,11 +13,14 @@ from eth2spec.test.helpers.block import ( build_empty_block_for_next_slot, ) +from eth2spec.test.helpers.forks import is_post_eip7732 from eth2spec.test.helpers.fork_choice import ( check_head_against_root, get_genesis_forkchoice_store_and_block, + get_store_full_state, on_tick_and_append_step, payload_state_transition, + payload_state_transition_no_store, tick_and_add_block, apply_next_epoch_with_attestations, find_next_justifying_slot, @@ -81,7 +84,6 @@ def test_withholding_attack(spec, state): # Create two blocks in the honest chain with full attestations, and add to the store honest_state = state.copy() for _ in range(2): - print("Trying slot", honest_state.slot) signed_block = state_transition_with_full_block(spec, honest_state, True, False) yield from tick_and_add_block(spec, store, signed_block, test_steps) honest_state = payload_state_transition(spec, store, signed_block.message).copy() @@ -159,8 +161,8 @@ def test_withholding_attack_unviable_honest_chain(spec, state): for signed_block in signed_blocks[:-1]: yield from tick_and_add_block(spec, store, signed_block, test_steps) check_head_against_root(spec, store, signed_block.message.hash_tree_root()) - check_head_against_root(spec, store, signed_blocks[-2].message.hash_tree_root()) - state = store.block_states[spec.get_head(store)].copy() + payload_state_transition(spec, store, signed_block.message) + state = get_store_full_state(spec, store, signed_block.message.hash_tree_root()).copy() assert spec.compute_epoch_at_slot(state.slot) == 5 assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 5 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 @@ -169,11 +171,14 @@ def test_withholding_attack_unviable_honest_chain(spec, state): next_epoch(spec, state) assert spec.compute_epoch_at_slot(state.slot) == 6 assert state.current_justified_checkpoint.epoch == 3 - # Create two block in the honest chain with full attestations, and add to the store + # Create two blocks in the honest chain with full attestations, and add to the store for _ in range(2): signed_block = state_transition_with_full_block(spec, state, True, False) + payload_state_transition_no_store(spec, state, signed_block.message) assert state.current_justified_checkpoint.epoch == 3 yield from tick_and_add_block(spec, store, signed_block, test_steps) + check_head_against_root(spec, store, signed_block.message.hash_tree_root()) + payload_state_transition(spec, store, signed_block.message) # Create final block in the honest chain that includes the justifying attestations from the attack block honest_block = build_empty_block_for_next_slot(spec, state) honest_block.body.attestations = signed_attack_block.message.body.attestations @@ -182,6 +187,7 @@ def test_withholding_attack_unviable_honest_chain(spec, state): assert state.current_justified_checkpoint.epoch == 3 # Add the honest block to the store yield from tick_and_add_block(spec, store, signed_honest_block, test_steps) + payload_state_transition(spec, store, signed_honest_block.message) current_epoch = spec.compute_epoch_at_slot(spec.get_current_slot(store)) assert current_epoch == 6 # assert store.voting_source[honest_block_root].epoch == 3 @@ -197,10 +203,16 @@ def test_withholding_attack_unviable_honest_chain(spec, state): assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 # Upon revealing the withheld attack block, it should become the head + # Except in EIP-7732 in which it's parent becomes head because of the + # attestations during the attacker's block's committee. yield from tick_and_add_block(spec, store, signed_attack_block, test_steps) + payload_state_transition(spec, store, signed_attack_block.message) # The attack block is pulled up and store.justified_checkpoint is updated assert store.justified_checkpoint.epoch == 5 - attack_block_root = signed_attack_block.message.hash_tree_root() + if is_post_eip7732(spec): + attack_block_root = signed_attack_block.message.parent_root + else: + attack_block_root = signed_attack_block.message.hash_tree_root() check_head_against_root(spec, store, attack_block_root) # After going to the next epoch, the honest block should become the head From f31f5a24a54f9936affdd765b9b130dd57bc08ff Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 24 Jul 2024 11:33:26 -0300 Subject: [PATCH 57/73] fix test_withholding_attack --- .../eth2spec/test/phase0/fork_choice/test_withholding.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py index e9a2142ed8..83b0886a5c 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py @@ -76,6 +76,7 @@ def test_withholding_attack(spec, state): assert spec.compute_epoch_at_slot(state.slot) == 4 assert spec.compute_epoch_at_slot(spec.get_current_slot(store)) == 4 assert state.current_justified_checkpoint.epoch == store.justified_checkpoint.epoch == 3 + state = get_store_full_state(spec, store, head_root).copy() # Create an honest chain in epoch 5 that includes the justifying attestations from the attack block next_epoch(spec, state) @@ -88,9 +89,9 @@ def test_withholding_attack(spec, state): yield from tick_and_add_block(spec, store, signed_block, test_steps) honest_state = payload_state_transition(spec, store, signed_block.message).copy() # Create final block in the honest chain that includes the justifying attestations from the attack block - honest_block = build_empty_block_for_next_slot(spec, state) + honest_block = build_empty_block_for_next_slot(spec, honest_state) honest_block.body.attestations = signed_attack_block.message.body.attestations - signed_honest_block = state_transition_and_sign_block(spec, state, honest_block) + signed_honest_block = state_transition_and_sign_block(spec, honest_state, honest_block) # Add the honest block to the store yield from tick_and_add_block(spec, store, signed_honest_block, test_steps) payload_state_transition(spec, store, signed_honest_block.message) From 3046c997e613c7e81aff067d1bd6d3e6d03053e5 Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 24 Jul 2024 13:47:42 -0300 Subject: [PATCH 58/73] fix previous forks tests --- tests/core/pyspec/eth2spec/test/helpers/fork_choice.py | 3 +-- .../pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py | 2 +- .../pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py | 4 +--- .../pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py | 4 ++-- .../eth2spec/test/phase0/fork_choice/test_withholding.py | 1 - .../test/phase0/unittests/fork_choice/test_on_attestation.py | 2 +- 6 files changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 8b7fc899b2..c7ac46df75 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -292,7 +292,7 @@ def add_attester_slashing(spec, store, attester_slashing, test_steps, valid=True def get_formatted_head_output(spec, store): head = spec.get_head(store) - if is_post_eip7732: + if is_post_eip7732(spec): return { 'slot': int(head.slot), 'root': encode_hex(head.root), @@ -404,7 +404,6 @@ def find_next_justifying_slot(spec, signed_blocks = [] justifying_slot = None while justifying_slot is None: - previous_header_root = temp_state.latest_block_header.hash_tree_root() signed_block = state_transition_with_full_block( spec, temp_state, diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py index 89d19beb9c..4cf83ac07c 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_ex_ante.py @@ -34,7 +34,7 @@ def _apply_base_block_a(spec, state, store, test_steps): payload_state_transition(spec, store, signed_block_a.message) head = spec.get_head(store) expected_root = signed_block_a.message.hash_tree_root() - if is_post_eip7732: + if is_post_eip7732(spec): assert head.root == expected_root else: check_head_against_root(spec, store, signed_block_a.message.hash_tree_root()) diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py index 8267d828c4..62a378ab8e 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_get_head.py @@ -1,6 +1,4 @@ import random - -from eth_utils import encode_hex from eth2spec.test.context import ( spec_state_test, with_altair_and_later, @@ -124,7 +122,6 @@ def test_split_tie_breaker_no_attestations(spec, state): on_tick_and_append_step(spec, store, time, test_steps) yield from add_block(spec, store, signed_block_1, test_steps) - post_state_1 = state.copy() payload_state_transition(spec, store, signed_block_1.message) yield from add_block(spec, store, signed_block_2, test_steps) payload_state_transition(spec, store, signed_block_2.message) @@ -259,6 +256,7 @@ def test_filtered_block_tree(spec, state): yield 'steps', test_steps + # This test is skipped in EIP-7732 because the block's slot decides first on weight ties @with_altair_until_eip7732 @spec_state_test diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py index 0462252d3b..bc33d38728 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_reorg.py @@ -1,4 +1,3 @@ -from eth_utils import encode_hex from eth2spec.test.context import ( spec_state_test, with_altair_and_later, @@ -397,9 +396,10 @@ def _run_include_votes_of_another_empty_chain(spec, state, enough_ffg, is_justif ): block.body.attestations = attestations_for_y.pop(0) signed_block_z = state_transition_and_sign_block(spec, state, block) + payload_state_transition_no_store(spec, state, block) if signed_block_y != signed_block_z: yield from tick_and_add_block(spec, store, signed_block_z, test_steps) - state = payload_state_transition(spec, store, signed_block_z.message).copy() + payload_state_transition(spec, store, signed_block_z.message) if is_ready_to_justify(spec, state): break diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py index 83b0886a5c..2c8e71c3e6 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_withholding.py @@ -1,4 +1,3 @@ -from eth_utils import encode_hex from eth2spec.test.context import ( spec_state_test, with_altair_and_later, diff --git a/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py b/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py index d7c5462ae0..368dd9a915 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py +++ b/tests/core/pyspec/eth2spec/test/phase0/unittests/fork_choice/test_on_attestation.py @@ -20,7 +20,7 @@ def run_on_attestation(spec, state, store, attestation, valid=True): spec.on_attestation(store, attestation) sample_index = indexed_attestation.attesting_indices[0] - if is_post_eip7732: + if is_post_eip7732(spec): latest_message = spec.LatestMessage( slot=attestation.data.slot, root=attestation.data.beacon_block_root, From 97f309c9ccddf203780807f4994daeb99e9f4009 Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 24 Jul 2024 13:54:33 -0300 Subject: [PATCH 59/73] doctoc --- specs/_features/eip7732/beacon-chain.md | 3 +++ specs/_features/eip7732/fork-choice.md | 1 + 2 files changed, 4 insertions(+) diff --git a/specs/_features/eip7732/beacon-chain.md b/specs/_features/eip7732/beacon-chain.md index 73d0831f31..39277eedea 100644 --- a/specs/_features/eip7732/beacon-chain.md +++ b/specs/_features/eip7732/beacon-chain.md @@ -54,6 +54,9 @@ - [New `verify_execution_payload_envelope_signature`](#new-verify_execution_payload_envelope_signature) - [Modified `is_merge_transition_complete`](#modified-is_merge_transition_complete) - [Modified `validate_merge_block`](#modified-validate_merge_block) +- [Testing](#testing) + - [Modified `initialize_beacon_state_from_eth1`](#modified-initialize_beacon_state_from_eth1) + - [Modified `is_merge_transition_complete`](#modified-is_merge_transition_complete-1) diff --git a/specs/_features/eip7732/fork-choice.md b/specs/_features/eip7732/fork-choice.md index 1155354d1d..e9b9896629 100644 --- a/specs/_features/eip7732/fork-choice.md +++ b/specs/_features/eip7732/fork-choice.md @@ -32,6 +32,7 @@ - [`seconds_into_slot`](#seconds_into_slot) - [Modified `on_tick_per_slot`](#modified-on_tick_per_slot) - [`on_payload_attestation_message`](#on_payload_attestation_message) + - [Modified `validate_merge_block`](#modified-validate_merge_block) From 4acbaca2b94138e3efdbc8eeb1042af752cd5ede Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 24 Jul 2024 16:16:04 -0300 Subject: [PATCH 60/73] fix some capella and bellatrix tests --- .../test/capella/block_processing/test_process_withdrawals.py | 4 ++-- tests/core/pyspec/eth2spec/test/helpers/execution_payload.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py index c27243bde3..d6a872db48 100644 --- a/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/capella/block_processing/test_process_withdrawals.py @@ -75,14 +75,14 @@ def run_withdrawals_processing(spec, state, execution_payload, num_expected_with yield 'execution_payload', execution_payload if not valid: - if is_post_eip7732: + if is_post_eip7732(spec): expect_assertion_error(lambda: spec.process_withdrawals(state)) else: expect_assertion_error(lambda: spec.process_withdrawals(state, execution_payload)) yield 'post', None return - if is_post_eip7732: + if is_post_eip7732(spec): spec.process_withdrawals(state) else: spec.process_withdrawals(state, execution_payload) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 9d5e80ddab..8e154a34e0 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -336,7 +336,7 @@ def build_randomized_execution_payload(spec, state, rng): def build_state_with_incomplete_transition(spec, state): header = spec.ExecutionPayloadHeader() - if is_post_eip7732: + if is_post_eip7732(spec): kzgs = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() header.blob_kzg_commitments_root = kzgs.hash_tree_root() From 89a79cc3bec9926cfc1caa85b0b30e9a4fbbf80b Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 24 Jul 2024 17:25:46 -0300 Subject: [PATCH 61/73] fix deneb tests --- .../test_process_execution_payload.py | 57 +++++++++++++------ .../unittests/validator/test_validator.py | 2 +- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py index 38bfccc3a7..18ff48dc19 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py @@ -56,18 +56,13 @@ def run_execution_payload_processing(spec, state, execution_payload, blob_kzg_co message=envelope, signature=signature, ) + body = spec.BeaconBlockBody() else: body = spec.BeaconBlockBody( blob_kzg_commitments=blob_kzg_commitments, execution_payload=execution_payload, ) - # Before Deneb, only `body.execution_payload` matters. `BeaconBlockBody` is just a wrapper. - body = spec.BeaconBlockBody() - if not is_post_eip7732(spec): - body.blob_kzg_commitments = blob_kzg_commitments - body.execution_payload = execution_payload - yield 'pre', state yield 'execution', {'execution_valid': execution_valid} yield 'body', body @@ -127,7 +122,10 @@ def test_incorrect_blob_tx_type(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash + yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -145,7 +143,9 @@ def test_incorrect_transaction_length_1_extra_byte(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -163,7 +163,9 @@ def test_incorrect_transaction_length_1_byte_short(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -181,7 +183,9 @@ def test_incorrect_transaction_length_empty(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -199,7 +203,10 @@ def test_incorrect_transaction_length_32_extra_bytes(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -216,7 +223,9 @@ def test_no_transactions_with_commitments(spec, state): execution_payload.transactions = [] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -234,7 +243,9 @@ def test_incorrect_commitment(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -252,7 +263,9 @@ def test_incorrect_commitments_order(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -267,7 +280,9 @@ def test_incorrect_block_hash(spec, state): execution_payload.block_hash = b'\x12' * 32 # incorrect block hash # CL itself doesn't verify EL block hash - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -285,7 +300,9 @@ def test_zeroed_commitment(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -302,7 +319,9 @@ def test_invalid_correct_input__execution_invalid(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments, valid=False, execution_valid=False) @@ -317,5 +336,7 @@ def test_invalid_exceed_max_blobs_per_block(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - state.latest_execution_payload_header.block_hash = execution_payload.block_hash + ## Make the first block full in EIP-7732 + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments, valid=False) diff --git a/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py b/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py index fee4f7dda2..99a2eeffa4 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py +++ b/tests/core/pyspec/eth2spec/test/deneb/unittests/validator/test_validator.py @@ -34,7 +34,7 @@ def _get_sample_sidecars(spec, state, rng): else: block.body.blob_kzg_commitments = blob_kzg_commitments_1 + blob_kzg_commitments_2 block.body.execution_payload.transactions = [opaque_tx_1, opaque_tx_2] - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) blobs = blobs_1 + blobs_2 proofs = proofs_1 + proofs_2 From e482735eea847e762c27f7f88d4c971eeb4ed287 Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 24 Jul 2024 17:39:04 -0300 Subject: [PATCH 62/73] fix electra tests --- .../test/deneb/merkle_proof/test_single_merkle_proof.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py b/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py index 0bccb3cb3a..de420f99a4 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py +++ b/tests/core/pyspec/eth2spec/test/deneb/merkle_proof/test_single_merkle_proof.py @@ -44,7 +44,7 @@ def _run_blob_kzg_commitment_merkle_proof_test(spec, state, rng=None): else: block.body.blob_kzg_commitments = blob_kzg_commitments block.body.execution_payload.transactions = [opaque_tx] - block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload) + block.body.execution_payload.block_hash = compute_el_block_hash(spec, block.body.execution_payload, state) signed_block = sign_block(spec, state, block, proposer_index=0) if is_post_eip7732(spec): From 2f3db22cb265938a7d34d7fde20f56c824db5a4b Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 24 Jul 2024 18:02:18 -0300 Subject: [PATCH 63/73] fix linter --- .../test_process_execution_payload.py | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py index 18ff48dc19..a4c85bf5ff 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py @@ -122,7 +122,7 @@ def test_incorrect_blob_tx_type(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash @@ -143,7 +143,7 @@ def test_incorrect_transaction_length_1_extra_byte(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -163,7 +163,7 @@ def test_incorrect_transaction_length_1_byte_short(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -183,7 +183,7 @@ def test_incorrect_transaction_length_empty(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -203,8 +203,7 @@ def test_incorrect_transaction_length_32_extra_bytes(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -223,7 +222,7 @@ def test_no_transactions_with_commitments(spec, state): execution_payload.transactions = [] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -243,7 +242,7 @@ def test_incorrect_commitment(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -263,7 +262,7 @@ def test_incorrect_commitments_order(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -280,7 +279,7 @@ def test_incorrect_block_hash(spec, state): execution_payload.block_hash = b'\x12' * 32 # incorrect block hash # CL itself doesn't verify EL block hash - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -300,7 +299,7 @@ def test_zeroed_commitment(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -319,7 +318,7 @@ def test_invalid_correct_input__execution_invalid(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments, @@ -336,7 +335,7 @@ def test_invalid_exceed_max_blobs_per_block(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) - ## Make the first block full in EIP-7732 + # Make the first block full in EIP-7732 if is_post_eip7732(spec): state.latest_execution_payload_header.block_hash = execution_payload.block_hash yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments, valid=False) From 6408770e45b5c83a3357db06c0186ee2d94ea023 Mon Sep 17 00:00:00 2001 From: Potuz Date: Wed, 24 Jul 2024 18:29:08 -0300 Subject: [PATCH 64/73] enable 7732 in circleci --- .circleci/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9c998f2311..e395ed314d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -336,6 +336,9 @@ workflows: - test-eip7594: requires: - install_pyspec_test + - test-eip7732: + requires: + - install_pyspec_test - table_of_contents - codespell - lint: From 9df37db32731762069f3e83ecd150686f4b7ce60 Mon Sep 17 00:00:00 2001 From: Hsiao-Wei Wang Date: Fri, 23 Aug 2024 01:58:43 +0800 Subject: [PATCH 65/73] Update CircleCI image to Python3.12.4 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e395ed314d..e93586a44c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -196,7 +196,7 @@ jobs: path: tests/core/pyspec/test-reports test-eip7732: docker: - - image: circleci/python:3.9 + - image: cimg/python:3.12.4 working_directory: ~/specs-repo steps: - restore_cache: From 17c50ee74d85084288ef342bdc35db7a9c87b7b2 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Sun, 9 Feb 2025 21:21:07 -0600 Subject: [PATCH 66/73] Delete trailing whitespace --- specs/_features/eip7732/fork-choice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/_features/eip7732/fork-choice.md b/specs/_features/eip7732/fork-choice.md index 3d3eb276c5..4730c0681f 100644 --- a/specs/_features/eip7732/fork-choice.md +++ b/specs/_features/eip7732/fork-choice.md @@ -575,7 +575,7 @@ def on_payload_attestation_message( store.payload_withhold_boost_full = is_parent_node_full(store, block) ``` -### Modified `validate_merge_block` +### Modified `validate_merge_block` The function `validate_merge_block` is modified for test purposes From 0b8afdb232eda83583d09bb3f45e348db6caa678 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 24 Feb 2025 09:26:44 -0600 Subject: [PATCH 67/73] Fix merge conflict mistake --- tests/core/pyspec/eth2spec/test/helpers/genesis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/genesis.py b/tests/core/pyspec/eth2spec/test/helpers/genesis.py index db669108db..dd87509177 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/genesis.py +++ b/tests/core/pyspec/eth2spec/test/helpers/genesis.py @@ -8,7 +8,7 @@ ) from eth2spec.test.helpers.forks import ( is_post_altair, is_post_bellatrix, is_post_capella, is_post_deneb, - is_post_electra, is_post_whisk, is_post_eip7441, is_post_eip7732, + is_post_electra, is_post_eip7441, is_post_eip7732, ) from eth2spec.test.helpers.keys import pubkeys from eth2spec.test.helpers.eip7441 import ( From 6fc80618ee797a68ae3419dc9e5fbb4f7c34f72f Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 24 Feb 2025 14:06:45 -0600 Subject: [PATCH 68/73] Fix builder index computation --- .../pyspec/eth2spec/test/helpers/execution_payload.py | 7 +++++-- .../eth2spec/test/phase0/fork_choice/test_on_block.py | 8 +++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 2dc1519abc..9fbd356016 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -266,12 +266,15 @@ def build_empty_post_eip7732_execution_payload_header(spec, state): return parent_block_root = hash_tree_root(state.latest_block_header) kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() + epoch = spec.get_current_epoch(state) + # TODO(jtraglia): placeholder until we figure out how to compute the builder index + builder_index = spec.get_active_validator_indices(state, epoch)[0] return spec.ExecutionPayloadHeader( parent_block_hash=state.latest_block_hash, parent_block_root=parent_block_root, block_hash=spec.Hash32(), gas_limit=spec.uint64(0), - builder_index=spec.ValidatorIndex(0), + builder_index=builder_index, slot=state.slot, value=spec.Gwei(0), blob_kzg_commitments_root=kzg_list.hash_tree_root(), @@ -282,7 +285,7 @@ def build_empty_signed_execution_payload_header(spec, state): if not is_post_eip7732(spec): return message = build_empty_post_eip7732_execution_payload_header(spec, state) - privkey = privkeys[0] + privkey = privkeys[message.builder_index] signature = spec.get_execution_payload_header_signature(state, message, privkey) return spec.SignedExecutionPayloadHeader( message=message, diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index 3022b5b34b..d35067e09a 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -19,6 +19,8 @@ sign_block, ) from eth2spec.test.helpers.execution_payload import ( + build_empty_execution_payload, + compute_el_block_hash, compute_el_block_hash_for_block, ) from eth2spec.test.helpers.fork_choice import ( @@ -167,7 +169,11 @@ def test_on_block_bad_parent_root(spec, state): block.state_root = state.hash_tree_root() block.parent_root = b'\x45' * 32 - if is_post_bellatrix(spec): + if is_post_eip7732(spec): + payload = build_empty_execution_payload(spec, state) + block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash( + spec, payload, state) + elif is_post_bellatrix(spec): block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, block) signed_block = sign_block(spec, state, block) From 54ce7386b2c92336138c9689bfbe8a3581099759 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 24 Feb 2025 14:16:41 -0600 Subject: [PATCH 69/73] Build index is first active/non-slashed index --- .../core/pyspec/eth2spec/test/helpers/execution_payload.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 9fbd356016..3bec00766f 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -268,7 +268,11 @@ def build_empty_post_eip7732_execution_payload_header(spec, state): kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() epoch = spec.get_current_epoch(state) # TODO(jtraglia): placeholder until we figure out how to compute the builder index - builder_index = spec.get_active_validator_indices(state, epoch)[0] + builder_index = None + for index in spec.get_active_validator_indices(state, epoch): + if not state.validators[index].slashed: + builder_index = index + assert builder_index is not None return spec.ExecutionPayloadHeader( parent_block_hash=state.latest_block_hash, parent_block_root=parent_block_root, From 160371023a2a11ef3955cf3507e3d762652e7920 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 24 Feb 2025 14:45:51 -0600 Subject: [PATCH 70/73] Sort of fix two tests --- .../test/electra/fork_choice/test_deposit_with_reorg.py | 5 +++-- .../core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py | 7 ++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/electra/fork_choice/test_deposit_with_reorg.py b/tests/core/pyspec/eth2spec/test/electra/fork_choice/test_deposit_with_reorg.py index 74c418ad60..8efdf1fc36 100644 --- a/tests/core/pyspec/eth2spec/test/electra/fork_choice/test_deposit_with_reorg.py +++ b/tests/core/pyspec/eth2spec/test/electra/fork_choice/test_deposit_with_reorg.py @@ -4,7 +4,7 @@ from eth2spec.test.context import ( with_presets, spec_state_test, - with_electra_and_later, + with_electra_until_eip7732, ) from eth2spec.test.helpers.execution_payload import ( compute_el_block_hash_for_block, @@ -26,7 +26,8 @@ ) -@with_electra_and_later +# TODO(jtraglia): In eip7732, how do we set execution requests in the payload envelope? +@with_electra_until_eip7732 @spec_state_test @with_presets([MINIMAL], reason="too slow") def test_new_validator_deposit_with_multiple_epoch_transitions(spec, state): diff --git a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py index f0a9f6b29d..724cae6eb3 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py +++ b/tests/core/pyspec/eth2spec/test/phase0/sanity/test_blocks.py @@ -23,6 +23,7 @@ from eth2spec.test.helpers.execution_payload import ( build_empty_execution_payload, build_empty_signed_execution_payload_header, + compute_el_block_hash, compute_el_block_hash_for_block, ) from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits @@ -210,7 +211,11 @@ def test_invalid_parent_from_same_slot(spec, state): child_block.body.execution_payload = build_empty_execution_payload(spec, state) child_block.parent_root = state.latest_block_header.hash_tree_root() - if is_post_bellatrix(spec): + if is_post_eip7732(spec): + payload = build_empty_execution_payload(spec, state) + child_block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash( + spec, payload, state) + elif is_post_bellatrix(spec): child_block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, child_block) # Show that normal path through transition fails From cdb6ed471e85431a0a9daaf4f403364da0929a1f Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 24 Feb 2025 15:16:22 -0600 Subject: [PATCH 71/73] Remove eip7732 in POST_FORK_OF --- tests/core/pyspec/eth2spec/test/helpers/constants.py | 1 - .../pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/constants.py b/tests/core/pyspec/eth2spec/test/helpers/constants.py index 7c9158aa1e..c5bf965461 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/constants.py +++ b/tests/core/pyspec/eth2spec/test/helpers/constants.py @@ -69,7 +69,6 @@ BELLATRIX: CAPELLA, CAPELLA: DENEB, DENEB: ELECTRA, - ELECTRA: EIP7732, } ALL_PRE_POST_FORKS = POST_FORK_OF.items() diff --git a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py index d35067e09a..42a26dcdaf 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/phase0/fork_choice/test_on_block.py @@ -172,7 +172,7 @@ def test_on_block_bad_parent_root(spec, state): if is_post_eip7732(spec): payload = build_empty_execution_payload(spec, state) block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash( - spec, payload, state) + spec, payload, state) elif is_post_bellatrix(spec): block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, block) From 56264126278dbf20963dbf4f9f799504b09857e3 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 24 Feb 2025 15:42:59 -0600 Subject: [PATCH 72/73] Figure out some todos --- .../test_process_execution_payload.py | 2 +- .../test_process_execution_payload.py | 15 +++++++++------ .../test/deneb/fork_choice/test_on_block.py | 2 +- .../eth2spec/test/helpers/execution_payload.py | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py index 6b2c5f6fab..934c94c484 100644 --- a/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/bellatrix/block_processing/test_process_execution_payload.py @@ -42,7 +42,7 @@ def run_execution_payload_processing(spec, state, execution_payload, valid=True, post_state.latest_block_hash = execution_payload.block_hash post_state.latest_full_slot = state.slot envelope.state_root = post_state.hash_tree_root() - privkey = privkeys[0] + privkey = privkeys[envelope.builder_index] signature = spec.get_execution_payload_envelope_signature( state, envelope, diff --git a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py index 7b2bcb9e2e..7266de8ae4 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/deneb/block_processing/test_process_execution_payload.py @@ -9,7 +9,6 @@ spec_state_test, expect_assertion_error, with_deneb_and_later, - with_deneb_until_eip7732, ) from eth2spec.test.helpers.keys import privkeys from eth2spec.test.helpers.forks import is_post_eip7732 @@ -48,7 +47,7 @@ def run_execution_payload_processing(spec, state, execution_payload, blob_kzg_co post_state.latest_block_hash = execution_payload.block_hash post_state.latest_full_slot = state.slot envelope.state_root = post_state.hash_tree_root() - privkey = privkeys[0] + privkey = privkeys[envelope.builder_index] signature = spec.get_execution_payload_envelope_signature( state, envelope, @@ -250,8 +249,7 @@ def test_incorrect_commitment(spec, state): yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) -# TODO(jtraglia): Determine why this doesn't work in eip7732 -@with_deneb_until_eip7732 +@with_deneb_and_later @spec_state_test def test_no_commitments_for_transactions(spec, state): """ @@ -265,6 +263,9 @@ def test_no_commitments_for_transactions(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash + yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) @@ -288,8 +289,7 @@ def test_incorrect_commitments_order(spec, state): yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) -# TODO(jtraglia): Determine why this doesn't work in eip7732 -@with_deneb_until_eip7732 +@with_deneb_and_later @spec_state_test def test_incorrect_transaction_no_blobs_but_with_commitments(spec, state): """ @@ -305,6 +305,9 @@ def test_incorrect_transaction_no_blobs_but_with_commitments(spec, state): execution_payload.transactions = [opaque_tx] execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) + if is_post_eip7732(spec): + state.latest_execution_payload_header.block_hash = execution_payload.block_hash + # the transaction doesn't contain any blob, but commitments are provided yield from run_execution_payload_processing(spec, state, execution_payload, blob_kzg_commitments) diff --git a/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py index e530183604..41d3a5e56f 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py @@ -40,7 +40,7 @@ def get_block_with_blob(spec, state, rng=None): return block, blobs, blob_kzg_proofs -# TODO(jtraglia): use with_all_phases_from_to_except after EIP7732 is based on Fulu. +# TODO(jtraglia): Use with_all_phases_from_to_except after EIP7732 is based on Fulu. # This applies to every other test in this file too. @with_all_phases_from_except(DENEB, [FULU, EIP7732]) @spec_state_test diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 3bec00766f..8fc8794fd8 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -267,7 +267,7 @@ def build_empty_post_eip7732_execution_payload_header(spec, state): parent_block_root = hash_tree_root(state.latest_block_header) kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() epoch = spec.get_current_epoch(state) - # TODO(jtraglia): placeholder until we figure out how to compute the builder index + # TODO(jtraglia): Placeholder until we figure out how to compute the builder index. builder_index = None for index in spec.get_active_validator_indices(state, epoch): if not state.validators[index].slashed: From 896a8e9c393d29410b098f1c169394a86f7ad1f5 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 24 Feb 2025 15:48:40 -0600 Subject: [PATCH 73/73] Update some todos --- tests/core/pyspec/eth2spec/test/helpers/execution_payload.py | 1 - tests/core/pyspec/eth2spec/test/helpers/fork_transition.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 8fc8794fd8..6f01b8132e 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -267,7 +267,6 @@ def build_empty_post_eip7732_execution_payload_header(spec, state): parent_block_root = hash_tree_root(state.latest_block_header) kzg_list = spec.List[spec.KZGCommitment, spec.MAX_BLOB_COMMITMENTS_PER_BLOCK]() epoch = spec.get_current_epoch(state) - # TODO(jtraglia): Placeholder until we figure out how to compute the builder index. builder_index = None for index in spec.get_active_validator_indices(state, epoch): if not state.validators[index].slashed: diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py b/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py index 808cd79e03..b0fe953702 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_transition.py @@ -66,6 +66,7 @@ class OperationType(Enum): CONSOLIDATION_REQUEST = auto() +# TODO(jtraglia): Pretty sure this doesn't play well with eip7732. Needs some work. def _set_operations_by_dict(spec, block, operation_dict, state): for key, value in operation_dict.items(): # to handle e.g. `execution_requests.deposits` and `deposits` @@ -73,7 +74,6 @@ def _set_operations_by_dict(spec, block, operation_dict, state): for attr in key.split('.')[:-1]: obj = getattr(obj, attr) setattr(obj, key.split('.')[-1], value) - # TODO(jtraglia): Ensure this is correct. It if is_post_eip7732(spec): payload = build_empty_execution_payload(spec, state) block.body.signed_execution_payload_header.message.block_hash = compute_el_block_hash(