From 12831a888f4d563474c14c60244be6192c199339 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Tue, 13 Aug 2024 17:00:38 +0200 Subject: [PATCH 1/4] Ensure EL block hash is updated when beacon parent root is overridden Because beacon parent root is hashed into the EL block hash, need to recompute the EL block hash whenever parent beacon block is set. This is only used seldomly as part of testing. --- .../test/helpers/execution_payload.py | 28 ++++++++++++++++--- .../test/phase0/fork_choice/test_on_block.py | 8 ++++++ .../test/phase0/sanity/test_blocks.py | 13 ++++++--- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 1fbb12d7ba..2d32ecb871 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -204,18 +204,20 @@ def get_consolidation_request_rlp_bytes(consolidation_request): return b"\x02" + encode(values, sedes) -def compute_el_block_hash(spec, payload, pre_state): +def compute_el_block_hash_with_parent_root(spec, payload, parent_beacon_block_root): + if payload == spec.ExecutionPayload(): + return spec.Hash32() + transactions_trie_root = compute_trie_root_from_indexed_data(payload.transactions) withdrawals_trie_root = None - parent_beacon_block_root = None requests_trie_root = None if is_post_capella(spec): withdrawals_encoded = [get_withdrawal_rlp(withdrawal) for withdrawal in payload.withdrawals] withdrawals_trie_root = compute_trie_root_from_indexed_data(withdrawals_encoded) - if is_post_deneb(spec): - parent_beacon_block_root = pre_state.latest_block_header.hash_tree_root() + if not is_post_deneb(spec): + parent_beacon_block_root = None if is_post_electra(spec): requests_encoded = [] requests_encoded += [get_deposit_request_rlp_bytes(request) for request in payload.deposit_requests] @@ -236,6 +238,24 @@ def compute_el_block_hash(spec, payload, pre_state): ) +def compute_el_block_hash(spec, payload, pre_state): + parent_beacon_block_root = None + + if is_post_deneb(spec): + previous_block_header = pre_state.latest_block_header.copy() + if previous_block_header.state_root == spec.Root(): + previous_block_header.state_root = pre_state.hash_tree_root() + parent_beacon_block_root = previous_block_header.hash_tree_root() + + return compute_el_block_hash_with_parent_root( + spec, payload, parent_beacon_block_root) + + +def compute_el_block_hash_for_block(spec, block): + return compute_el_block_hash_with_parent_root( + spec, block.body.execution_payload, block.parent_root) + + def build_empty_post_eip7732_execution_payload_header(spec, state): if not is_post_eip7732(spec): return 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..3a3f60a438 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,9 @@ transition_unsigned_block, sign_block, ) +from eth2spec.test.helpers.execution_payload import ( + compute_el_block_hash_for_block, +) from eth2spec.test.helpers.fork_choice import ( get_genesis_forkchoice_store_and_block, on_tick_and_append_step, @@ -28,6 +31,9 @@ is_ready_to_justify, find_next_justifying_slot, ) +from eth2spec.test.helpers.forks import ( + is_post_bellatrix, +) from eth2spec.test.helpers.state import ( next_epoch, next_slots, @@ -152,6 +158,8 @@ 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): + block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, block) signed_block = sign_block(spec, state, block) 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..148cb939d5 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, + compute_el_block_hash_for_block, +) from eth2spec.test.helpers.voluntary_exits import prepare_signed_exits from eth2spec.test.helpers.multi_operations import ( run_slash_and_exit, @@ -158,7 +161,7 @@ def process_and_sign_block_without_header_validations(spec, state, block): if is_post_altair(spec): spec.process_sync_aggregate(state, block.body.sync_aggregate) - # Insert post-state rot + # Insert post-state root block.state_root = state.hash_tree_root() # Sign block @@ -197,11 +200,13 @@ def test_invalid_parent_from_same_slot(spec, state): signed_parent_block = state_transition_and_sign_block(spec, state, parent_block) child_block = parent_block.copy() - child_block.parent_root = state.latest_block_header.hash_tree_root() - if is_post_bellatrix(spec): 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): + child_block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, child_block) + # Show that normal path through transition fails failed_state = state.copy() expect_assertion_error( From 890810a3a5e39f1f026d0afc6a0366fa1592def3 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 14 Aug 2024 20:05:45 +0200 Subject: [PATCH 2/4] More fixes --- .../test/phase0/block_processing/test_process_block_header.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py index 5188d8f91b..1b33b71645 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py +++ b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py @@ -65,6 +65,8 @@ def test_invalid_proposer_index(spec, state): def test_invalid_parent_root(spec, state): block = build_empty_block_for_next_slot(spec, state) block.parent_root = b'\12' * 32 # invalid prev root + if is_post_bellatrix(spec): + block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, block) yield from run_block_header_processing(spec, state, block, valid=False) @@ -81,6 +83,8 @@ def test_invalid_multiple_blocks_single_slot(spec, state): child_block = block.copy() child_block.parent_root = block.hash_tree_root() + if is_post_bellatrix(spec): + child_block.body.execution_payload.block_hash = compute_el_block_hash_for_block(spec, child_block) yield from run_block_header_processing(spec, state, child_block, prepare_state=False, valid=False) From db1cecbe1a348364476e2c602f0e00dfab047eb5 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 14 Aug 2024 20:46:34 +0200 Subject: [PATCH 3/4] Imports --- .../test/phase0/block_processing/test_process_block_header.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py index 1b33b71645..a1f1e09a0b 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py +++ b/tests/core/pyspec/eth2spec/test/phase0/block_processing/test_process_block_header.py @@ -2,6 +2,8 @@ from eth2spec.test.context import spec_state_test, expect_assertion_error, with_all_phases from eth2spec.test.helpers.block import build_empty_block_for_next_slot +from eth2spec.test.helpers.execution_payload import compute_el_block_hash_for_block +from eth2spec.test.helpers.forks import is_post_bellatrix from eth2spec.test.helpers.state import next_slot From 0cf18359344311b36c5de33182a072ec59f33781 Mon Sep 17 00:00:00 2001 From: Justin Traglia <95511699+jtraglia@users.noreply.github.com> Date: Wed, 18 Sep 2024 07:35:01 -0500 Subject: [PATCH 4/4] Fix merge mistake --- .../pyspec/eth2spec/test/helpers/execution_payload.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index d2a97bf277..4bad581eef 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -198,20 +198,12 @@ def compute_el_block_hash_with_parent_root(spec, payload, parent_beacon_block_ro transactions_trie_root = compute_trie_root_from_indexed_data(payload.transactions) withdrawals_trie_root = None - requests_trie_root = None if is_post_capella(spec): withdrawals_encoded = [get_withdrawal_rlp(withdrawal) for withdrawal in payload.withdrawals] withdrawals_trie_root = compute_trie_root_from_indexed_data(withdrawals_encoded) if not is_post_deneb(spec): parent_beacon_block_root = None - if is_post_electra(spec): - requests_encoded = [] - requests_encoded += [get_deposit_request_rlp_bytes(request) for request in payload.deposit_requests] - requests_encoded += [get_withdrawal_request_rlp_bytes(request) for request in payload.withdrawal_requests] - requests_encoded += [get_consolidation_request_rlp_bytes(request) for request in payload.consolidation_requests] - - requests_trie_root = compute_trie_root_from_indexed_data(requests_encoded) payload_header = get_execution_payload_header(spec, payload)