Merge branch 'unstable' of https://github.com/sigp/lighthouse into gloas-payload-processing

This commit is contained in:
Eitan Seri- Levi
2026-02-24 10:47:12 -08:00
20 changed files with 353 additions and 497 deletions

View File

@@ -51,7 +51,9 @@
use crate::beacon_snapshot::PreProcessingSnapshot;
use crate::blob_verification::GossipBlobError;
use crate::block_verification_types::{AsBlock, BlockImportData, RpcBlock};
use crate::data_availability_checker::{AvailabilityCheckError, MaybeAvailableBlock};
use crate::data_availability_checker::{
AvailabilityCheckError, AvailableBlock, AvailableBlockData, MaybeAvailableBlock,
};
use crate::data_column_verification::GossipDataColumnError;
use crate::execution_payload::{
AllowOptimisticImport, NotifyExecutionLayer, PayloadNotifier,
@@ -334,6 +336,15 @@ pub enum BlockError {
max_blobs_at_epoch: usize,
block: usize,
},
/// The bid's parent_block_root does not match the block's parent_root.
///
/// ## Peer scoring
///
/// The block is invalid and the peer should be penalized.
BidParentRootMismatch {
bid_parent_root: Hash256,
block_parent_root: Hash256,
},
}
/// Which specific signature(s) are invalid in a SignedBeaconBlock
@@ -888,15 +899,15 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
// Do not gossip blocks that claim to contain more blobs than the max allowed
// at the given block epoch.
if let Ok(commitments) = block.message().body().blob_kzg_commitments() {
if let Some(blob_kzg_commitments_len) = block.message().blob_kzg_commitments_len() {
let max_blobs_at_epoch = chain
.spec
.max_blobs_per_block(block.slot().epoch(T::EthSpec::slots_per_epoch()))
as usize;
if commitments.len() > max_blobs_at_epoch {
if blob_kzg_commitments_len > max_blobs_at_epoch {
return Err(BlockError::InvalidBlobCount {
max_blobs_at_epoch,
block: commitments.len(),
block: blob_kzg_commitments_len,
});
}
}
@@ -933,6 +944,24 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
let block_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch());
let (parent_block, block) =
verify_parent_block_is_known::<T>(&fork_choice_read_lock, block)?;
// [New in Gloas]: Verify bid.parent_block_root matches block.parent_root.
if let Ok(bid) = block.message().body().signed_execution_payload_bid()
&& bid.message.parent_block_root != block.message().parent_root()
{
return Err(BlockError::BidParentRootMismatch {
bid_parent_root: bid.message.parent_block_root,
block_parent_root: block.message().parent_root(),
});
}
// TODO(gloas) The following validation can only be completed once fork choice has been implemented:
// The block's parent execution payload (defined by bid.parent_block_hash) has been seen
// (via gossip or non-gossip sources) (a client MAY queue blocks for processing
// once the parent payload is retrieved). If execution_payload verification of block's execution
// payload parent by an execution node is complete, verify the block's execution payload
// parent (defined by bid.parent_block_hash) passes all validation.
drop(fork_choice_read_lock);
// Track the number of skip slots between the block and its parent.
@@ -1039,8 +1068,15 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
});
}
// Validate the block's execution_payload (if any).
validate_execution_payload_for_gossip(&parent_block, block.message(), chain)?;
// [New in Gloas]: Skip payload validation checks. The payload now arrives separately
// via `ExecutionPayloadEnvelope`.
if !chain
.spec
.fork_name_at_slot::<T::EthSpec>(block.slot())
.gloas_enabled()
{
validate_execution_payload_for_gossip(&parent_block, block.message(), chain)?;
}
// Beacon API block_gossip events
if let Some(event_handler) = chain.event_handler.as_ref()
@@ -1212,15 +1248,35 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
let result = info_span!("signature_verify").in_scope(|| signature_verifier.verify());
match result {
Ok(_) => Ok(Self {
block: MaybeAvailableBlock::AvailabilityPending {
Ok(_) => {
// gloas blocks are always available.
let maybe_available = if chain
.spec
.fork_name_at_slot::<T::EthSpec>(block.slot())
.gloas_enabled()
{
MaybeAvailableBlock::Available(
AvailableBlock::new(
block,
AvailableBlockData::NoData,
&chain.data_availability_checker,
chain.spec.clone(),
)
.map_err(BlockError::AvailabilityCheck)?,
)
} else {
MaybeAvailableBlock::AvailabilityPending {
block_root: from.block_root,
block,
}
};
Ok(Self {
block: maybe_available,
block_root: from.block_root,
block,
},
block_root: from.block_root,
parent: Some(parent),
consensus_context,
}),
parent: Some(parent),
consensus_context,
})
}
Err(_) => Err(BlockError::InvalidSignature(
InvalidSignature::BlockBodySignatures,
)),