mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-19 21:04:41 +00:00
Verify merge block in block_verification
This commit is contained in:
@@ -58,7 +58,9 @@ use safe_arith::ArithError;
|
||||
use slog::{debug, error, Logger};
|
||||
use slot_clock::SlotClock;
|
||||
use ssz::Encode;
|
||||
use state_processing::per_block_processing::is_execution_enabled;
|
||||
use state_processing::per_block_processing::{
|
||||
is_execution_enabled, is_merge_block, is_merge_complete,
|
||||
};
|
||||
use state_processing::{
|
||||
block_signature_verifier::{BlockSignatureVerifier, Error as BlockSignatureVerifierError},
|
||||
per_block_processing, per_slot_processing,
|
||||
@@ -286,6 +288,20 @@ pub enum ExecutionPayloadError {
|
||||
///
|
||||
/// The block is invalid and the peer is faulty
|
||||
TransactionDataExceedsSizeLimit,
|
||||
/// The execution payload references an execution block that cannot trigger the merge.
|
||||
///
|
||||
/// ## Peer scoring
|
||||
///
|
||||
/// The block is invalid and the peer sent us a block that passes gossip propagation conditions,
|
||||
/// but is invalid upon further verification.
|
||||
InvalidTerminalPoWBlock,
|
||||
/// The execution payload references execution blocks that are unavailable on our execution
|
||||
/// nodes.
|
||||
///
|
||||
/// ## Peer scoring
|
||||
///
|
||||
/// It's not clear if the peer is invalid or if it's on a different execution fork to us.
|
||||
TerminalPoWBlockNotFound,
|
||||
}
|
||||
|
||||
impl From<execution_layer::Error> for ExecutionPayloadError {
|
||||
@@ -1079,6 +1095,44 @@ impl<'a, T: BeaconChainTypes> FullyVerifiedBlock<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
// If this block triggers the merge, check to ensure that it references valid execution
|
||||
// blocks.
|
||||
//
|
||||
// The specification defines this check inside `on_block` in the fork-choice specification,
|
||||
// however we perform the block here for two reasons:
|
||||
//
|
||||
// - There's no point in importing a block that will fail fork choice, so it's best to fail
|
||||
// early.
|
||||
// - Doing the check here means we can keep our fork-choice implementation "pure". I.e., no
|
||||
// calls to remote servers.
|
||||
if is_merge_block(&state, block.message().body()) {
|
||||
let execution_layer = chain
|
||||
.execution_layer
|
||||
.as_ref()
|
||||
.ok_or(ExecutionPayloadError::NoExecutionConnection)?;
|
||||
let execution_payload =
|
||||
block
|
||||
.message()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.ok_or_else(|| InconsistentFork {
|
||||
fork_at_slot: eth2::types::ForkName::Merge,
|
||||
object_fork: block.message().body().fork_name(),
|
||||
})?;
|
||||
|
||||
let is_valid_terminal_pow_block = execution_layer
|
||||
.block_on(|execution_layer| {
|
||||
execution_layer.is_valid_terminal_pow_block_hash(execution_payload.parent_hash)
|
||||
})
|
||||
.map_err(ExecutionPayloadError::from)?;
|
||||
|
||||
match is_valid_terminal_pow_block {
|
||||
Some(true) => Ok(()),
|
||||
Some(false) => Err(ExecutionPayloadError::InvalidTerminalPoWBlock),
|
||||
None => Err(ExecutionPayloadError::TerminalPoWBlockNotFound),
|
||||
}?;
|
||||
}
|
||||
|
||||
// This is the soonest we can run these checks as they must be called AFTER per_slot_processing
|
||||
let execute_payload_handle = if is_execution_enabled(&state, block.message().body()) {
|
||||
let execution_layer = chain
|
||||
|
||||
Reference in New Issue
Block a user