Remove merge transition code (#8761)

Co-Authored-By: dapplion <35266934+dapplion@users.noreply.github.com>
This commit is contained in:
Lion - dapplion
2026-02-24 20:20:28 -07:00
committed by GitHub
parent e59f1f03ef
commit d6bf53834f
39 changed files with 581 additions and 2433 deletions

View File

@@ -12,19 +12,19 @@ use crate::{
ExecutionPayloadError,
};
use execution_layer::{
BlockProposalContents, BlockProposalContentsType, BuilderParams, NewPayloadRequest,
PayloadAttributes, PayloadParameters, PayloadStatus,
BlockProposalContentsType, BuilderParams, NewPayloadRequest, PayloadAttributes,
PayloadParameters, PayloadStatus,
};
use fork_choice::{InvalidationOperation, PayloadVerificationStatus};
use proto_array::{Block as ProtoBlock, ExecutionStatus};
use slot_clock::SlotClock;
use state_processing::per_block_processing::{
compute_timestamp_at_slot, get_expected_withdrawals, is_execution_enabled,
is_merge_transition_complete, partially_verify_execution_payload,
partially_verify_execution_payload,
};
use std::sync::Arc;
use tokio::task::JoinHandle;
use tracing::{Instrument, debug, debug_span, warn};
use tracing::{Instrument, debug_span, warn};
use tree_hash::TreeHash;
use types::execution::BlockProductionVersion;
use types::*;
@@ -32,12 +32,6 @@ use types::*;
pub type PreparePayloadResult<E> = Result<BlockProposalContentsType<E>, BlockProductionError>;
pub type PreparePayloadHandle<E> = JoinHandle<Option<PreparePayloadResult<E>>>;
#[derive(PartialEq)]
pub enum AllowOptimisticImport {
Yes,
No,
}
/// Signal whether the execution payloads of new blocks should be
/// immediately verified with the EL or imported optimistically without
/// any EL communication.
@@ -218,78 +212,6 @@ async fn notify_new_payload<T: BeaconChainTypes>(
}
}
/// Verify that the block which triggers the merge is valid to be imported to fork choice.
///
/// ## Errors
///
/// Will return an error when using a pre-merge fork `state`. Ensure to only run this function
/// after the merge fork.
///
/// ## Specification
///
/// Equivalent to the `validate_merge_block` function in the merge Fork Choice Changes:
///
/// https://github.com/ethereum/consensus-specs/blob/v1.1.5/specs/merge/fork-choice.md#validate_merge_block
pub async fn validate_merge_block<T: BeaconChainTypes>(
chain: &Arc<BeaconChain<T>>,
block: BeaconBlockRef<'_, T::EthSpec>,
allow_optimistic_import: AllowOptimisticImport,
) -> Result<(), BlockError> {
let spec = &chain.spec;
let block_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch());
let execution_payload = block.execution_payload()?;
if spec.terminal_block_hash != ExecutionBlockHash::zero() {
if block_epoch < spec.terminal_block_hash_activation_epoch {
return Err(ExecutionPayloadError::InvalidActivationEpoch {
activation_epoch: spec.terminal_block_hash_activation_epoch,
epoch: block_epoch,
}
.into());
}
if execution_payload.parent_hash() != spec.terminal_block_hash {
return Err(ExecutionPayloadError::InvalidTerminalBlockHash {
terminal_block_hash: spec.terminal_block_hash,
payload_parent_hash: execution_payload.parent_hash(),
}
.into());
}
return Ok(());
}
let execution_layer = chain
.execution_layer
.as_ref()
.ok_or(ExecutionPayloadError::NoExecutionConnection)?;
let is_valid_terminal_pow_block = execution_layer
.is_valid_terminal_pow_block_hash(execution_payload.parent_hash(), spec)
.await
.map_err(ExecutionPayloadError::from)?;
match is_valid_terminal_pow_block {
Some(true) => Ok(()),
Some(false) => Err(ExecutionPayloadError::InvalidTerminalPoWBlock {
parent_hash: execution_payload.parent_hash(),
}
.into()),
None => {
if allow_optimistic_import == AllowOptimisticImport::Yes {
debug!(
block_hash = ?execution_payload.parent_hash(),
msg = "the terminal block/parent was unavailable",
"Optimistically importing merge transition block"
);
Ok(())
} else {
Err(ExecutionPayloadError::UnverifiedNonOptimisticCandidate.into())
}
}
}
}
/// Validate the gossip block's execution_payload according to the checks described here:
/// https://github.com/ethereum/consensus-specs/blob/dev/specs/merge/p2p-interface.md#beacon_block
pub fn validate_execution_payload_for_gossip<T: BeaconChainTypes>(
@@ -305,14 +227,14 @@ pub fn validate_execution_payload_for_gossip<T: BeaconChainTypes>(
// Only apply this validation if this is a Bellatrix beacon block.
if let Ok(execution_payload) = block.body().execution_payload() {
// This logic should match `is_execution_enabled`. We use only the execution block hash of
// the parent here in order to avoid loading the parent state during gossip verification.
// Check parent execution status to determine if we should validate the payload.
// We use only the execution status of the parent here to avoid loading the parent state
// during gossip verification.
let is_merge_transition_complete = match parent_block.execution_status {
// Optimistically declare that an "unknown" status block has completed the merge.
let parent_has_execution = match parent_block.execution_status {
// Parent has valid or optimistic execution status.
ExecutionStatus::Valid(_) | ExecutionStatus::Optimistic(_) => true,
// It's impossible for an irrelevant block to have completed the merge. It is pre-merge
// by definition.
// Pre-merge blocks have irrelevant execution status.
ExecutionStatus::Irrelevant(_) => false,
// If the parent has an invalid payload then it's impossible to build a valid block upon
// it. Reject the block.
@@ -323,7 +245,7 @@ pub fn validate_execution_payload_for_gossip<T: BeaconChainTypes>(
}
};
if is_merge_transition_complete || !execution_payload.is_default_with_empty_roots() {
if parent_has_execution || !execution_payload.is_default_with_empty_roots() {
let expected_timestamp = chain
.slot_clock
.start_of(block.slot())
@@ -372,7 +294,6 @@ pub fn get_execution_payload<T: BeaconChainTypes>(
// task.
let spec = &chain.spec;
let current_epoch = state.current_epoch();
let is_merge_transition_complete = is_merge_transition_complete(state);
let timestamp =
compute_timestamp_at_slot(state, state.slot(), spec).map_err(BeaconStateError::from)?;
let random = *state.get_randao_mix(current_epoch)?;
@@ -399,7 +320,6 @@ pub fn get_execution_payload<T: BeaconChainTypes>(
async move {
prepare_execution_payload::<T>(
&chain,
is_merge_transition_complete,
timestamp,
random,
proposer_index,
@@ -423,8 +343,6 @@ pub fn get_execution_payload<T: BeaconChainTypes>(
/// Prepares an execution payload for inclusion in a block.
///
/// Will return `Ok(None)` if the Bellatrix fork has occurred, but a terminal block has not been found.
///
/// ## Errors
///
/// Will return an error when using a pre-Bellatrix fork `state`. Ensure to only run this function
@@ -438,7 +356,6 @@ pub fn get_execution_payload<T: BeaconChainTypes>(
#[allow(clippy::too_many_arguments)]
pub async fn prepare_execution_payload<T>(
chain: &Arc<BeaconChain<T>>,
is_merge_transition_complete: bool,
timestamp: u64,
random: Hash256,
proposer_index: u64,
@@ -453,7 +370,6 @@ pub async fn prepare_execution_payload<T>(
where
T: BeaconChainTypes,
{
let current_epoch = builder_params.slot.epoch(T::EthSpec::slots_per_epoch());
let spec = &chain.spec;
let fork = spec.fork_name_at_slot::<T::EthSpec>(builder_params.slot);
let execution_layer = chain
@@ -461,42 +377,7 @@ where
.as_ref()
.ok_or(BlockProductionError::ExecutionLayerMissing)?;
let parent_hash = if !is_merge_transition_complete {
let is_terminal_block_hash_set = spec.terminal_block_hash != ExecutionBlockHash::zero();
let is_activation_epoch_reached =
current_epoch >= spec.terminal_block_hash_activation_epoch;
if is_terminal_block_hash_set && !is_activation_epoch_reached {
// Use the "empty" payload if there's a terminal block hash, but we haven't reached the
// terminal block epoch yet.
return Ok(BlockProposalContentsType::Full(
BlockProposalContents::Payload {
payload: FullPayload::default_at_fork(fork)?,
block_value: Uint256::ZERO,
},
));
}
let terminal_pow_block_hash = execution_layer
.get_terminal_pow_block_hash(spec, timestamp)
.await
.map_err(BlockProductionError::TerminalPoWBlockLookupFailed)?;
if let Some(terminal_pow_block_hash) = terminal_pow_block_hash {
terminal_pow_block_hash
} else {
// If the merge transition hasn't occurred yet and the EL hasn't found the terminal
// block, return an "empty" payload.
return Ok(BlockProposalContentsType::Full(
BlockProposalContents::Payload {
payload: FullPayload::default_at_fork(fork)?,
block_value: Uint256::ZERO,
},
));
}
} else {
latest_execution_payload_header_block_hash
};
let parent_hash = latest_execution_payload_header_block_hash;
// Try to obtain the fork choice update parameters from the cached head.
//