Clarify import sequence of child FULL

This commit is contained in:
dapplion
2026-06-01 07:14:30 +02:00
parent a70a120d55
commit efa02ede46
7 changed files with 89 additions and 84 deletions

View File

@@ -7,9 +7,10 @@ use crate::sync::network_context::{
LookupRequestResult, PeerGroup, ReqId, RpcRequestSendError, RpcResponseError,
SendErrorProcessor, SyncNetworkContext,
};
use beacon_chain::BeaconChainTypes;
use beacon_chain::BlockProcessStatus;
use beacon_chain::ParentImportedStatus;
use beacon_chain::block_verification_types::AsBlock;
use beacon_chain::{BeaconChainTypes, ExecutionStatus};
use educe::Educe;
use lighthouse_network::service::api_types::Id;
use parking_lot::RwLock;
@@ -40,60 +41,6 @@ pub struct AwaitingParent {
}
impl AwaitingParent {
pub fn is_parent_imported<T: BeaconChainTypes>(&self, cx: &mut SyncNetworkContext<T>) -> bool {
if self.parent_is_genesis() {
// Zero hash is the parent of the genesis block — not a real block, so no
// parent-known check is needed. Fall through to send the block for processing.
return true;
}
if let Some(parent_block) = cx
.chain
.canonical_head
.fork_choice_read_lock()
.get_block(&self.parent_root)
{
if parent_block.slot == cx.spec().genesis_slot {
// The genesis block is always imported by definition
return true;
}
if let Some(gloas_bid_parent_hash) = self.gloas_bid_parent_hash {
// Post-gloas block, check if it's FULL or EMPTY
let parent_hash = match parent_block.execution_status {
ExecutionStatus::Valid(hash) => hash,
ExecutionStatus::Invalid(hash) => hash,
ExecutionStatus::Optimistic(hash) => hash,
ExecutionStatus::Irrelevant(_) => {
if let Some(hash) = parent_block.execution_payload_block_hash {
hash
} else {
// This should never happen!
return false;
}
}
};
let is_full = gloas_bid_parent_hash == parent_hash;
if is_full {
// Post-gloas block FULL, we need the payload to be imported first
cx.chain
.canonical_head
.fork_choice_read_lock()
.is_payload_received(&self.parent_root)
} else {
// Post-gloas block EMPTY, and block is imported
true
}
} else {
// Pre-gloas block
true
}
} else {
// Parent is unknown
false
}
}
pub fn parent_is_genesis(&self) -> bool {
self.parent_root == Hash256::ZERO
}
@@ -680,6 +627,16 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
self.awaiting_parent
}
/// The parent relationship implied by this lookup's downloaded block: the parent root plus
/// (post-gloas) the parent's committed payload hash taken from this block's bid. `None` until
/// the block has been downloaded. Used to donate this lookup's peers to a FULL parent's
/// payload fetch.
pub fn downloaded_parent(&self) -> Option<AwaitingParent> {
self.block_request
.peek_block()
.map(|block| AwaitingParent::from_block(block))
}
/// Mark this lookup as no longer awaiting a parent lookup. Components can be sent for
/// processing.
pub fn resolve_awaiting_parent(&mut self) {
@@ -778,15 +735,29 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
break;
}
let awaiting_parent = AwaitingParent::from_block(block);
if !awaiting_parent.is_parent_imported(cx) {
self.awaiting_parent = Some(awaiting_parent);
return Ok(LookupResult::ParentUnknown {
awaiting_parent,
block_root: self.block_root,
peers: self.all_peers(),
});
// Check if the parent block is known to fork-choice. If the block is FULL
// expect the payload to be imported too.
match cx
.chain
.canonical_head
.fork_choice_read_lock()
.is_parent_imported(block)
{
// Parent block is imported (and, if this block is FULL, its payload too):
// safe to send this block for processing.
ParentImportedStatus::Imported(_) => {}
// Parent block is unknown, or it's FULL and the parent's payload has not
// been imported yet. Park this lookup until the parent resolves.
ParentImportedStatus::UnknownBlock
| ParentImportedStatus::UnimportedPayload => {
let awaiting_parent = AwaitingParent::from_block(block);
self.awaiting_parent = Some(awaiting_parent);
return Ok(LookupResult::ParentUnknown {
awaiting_parent,
block_root: self.block_root,
peers: self.all_peers(),
});
}
}
let block = block.clone();

View File

@@ -62,7 +62,7 @@ enum RangeBlockDataRequest<E: EthSpec> {
}
#[derive(Debug)]
pub(crate) enum CouplingError {
pub enum CouplingError {
InternalError(String),
/// The peer we requested the columns from was faulty/malicious
DataColumnPeerFailure {