diff --git a/specs/merge/fork-choice.md b/specs/merge/fork-choice.md index 42c61b83d..eec084f62 100644 --- a/specs/merge/fork-choice.md +++ b/specs/merge/fork-choice.md @@ -16,6 +16,7 @@ - [`PowBlock`](#powblock) - [`get_pow_block`](#get_pow_block) - [`is_valid_terminal_pow_block`](#is_valid_terminal_pow_block) + - [`validate_merge_block`](#validate_merge_block) - [Updated fork-choice handlers](#updated-fork-choice-handlers) - [`on_block`](#on_block) @@ -103,6 +104,30 @@ def is_valid_terminal_pow_block(block: PowBlock, parent: PowBlock) -> bool: return is_total_difficulty_reached and is_parent_total_difficulty_valid ``` +### `validate_merge_block` + +```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. + """ + pow_block = get_pow_block(block.body.execution_payload.parent_hash) + # Check if `pow_block` is unavailable + assert pow_block is not None + pow_parent = get_pow_block(pow_block.parent_hash) + # Check if `pow_parent` is unavailable + 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) + + # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached. + if TERMINAL_BLOCK_HASH != Hash32(): + assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH +``` + ## Updated fork-choice handlers ### `on_block` @@ -137,17 +162,7 @@ def on_block(store: Store, signed_block: SignedBeaconBlock) -> None: # [New in Merge] if is_merge_block(pre_state, block.body): - # Check the parent PoW block of execution payload is a valid terminal PoW block. - # Note: unavailable PoW block(s) may later become available. - # Nodes should queue such beacon blocks for later processing. - pow_block = get_pow_block(block.body.execution_payload.parent_hash) - assert pow_block is not None - pow_parent = get_pow_block(pow_block.parent_hash) - assert pow_parent is not None - assert is_valid_terminal_pow_block(pow_block, pow_parent) - # If `TERMINAL_BLOCK_HASH` is used as an override, the activation epoch must be reached. - if TERMINAL_BLOCK_HASH != Hash32(): - assert compute_epoch_at_slot(block.slot) >= TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH + validate_merge_block(block) # Add new block to the store store.blocks[hash_tree_root(block)] = block