mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 20:57:10 +00:00
intro single_envelope_lookup.rs
This commit is contained in:
@@ -103,14 +103,18 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
ExecutedEnvelope::AvailabilityPending {
|
||||
signed_envelope,
|
||||
import_data,
|
||||
payload_verification_outcome,
|
||||
payload_verification_outcome: _,
|
||||
} => {
|
||||
self.import_pending_execution_payload_envelope(
|
||||
signed_envelope,
|
||||
import_data,
|
||||
payload_verification_outcome,
|
||||
)
|
||||
.await
|
||||
// The envelope has been executed but data columns have not yet arrived.
|
||||
// Do not import — return MissingComponents so callers know to fetch columns.
|
||||
// TODO(gloas): once an envelope DA checker exists, cache the envelope here
|
||||
// (analogous to `data_availability_checker.put_executed_block`) so that
|
||||
// import is driven automatically when columns arrive.
|
||||
let slot = signed_envelope.slot();
|
||||
let block_root = import_data.block_root;
|
||||
Ok(AvailabilityProcessingStatus::MissingComponents(
|
||||
slot, block_root,
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4007,8 +4007,11 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
|
||||
block_root: *block_root,
|
||||
});
|
||||
}
|
||||
Ok(AvailabilityProcessingStatus::MissingComponents(_, _)) => {
|
||||
// Nothing to do
|
||||
Ok(AvailabilityProcessingStatus::MissingComponents(_slot, _block_root)) => {
|
||||
// TODO(gloas): wire this into the envelope DA checker once it exists, analogous to
|
||||
// how `process_availability` drives block import once blobs/columns arrive. Until
|
||||
// then gossip envelopes with missing columns will be stuck until columns arrive via
|
||||
// gossip or engineGetBlobs.
|
||||
}
|
||||
Err(e) => match e {
|
||||
EnvelopeError::ExecutionPayloadError(epe) if !epe.penalize_peer() => {}
|
||||
|
||||
@@ -54,6 +54,7 @@ use types::{EthSpec, SignedBeaconBlock};
|
||||
pub mod common;
|
||||
pub mod parent_chain;
|
||||
mod single_block_lookup;
|
||||
mod single_envelope_lookup;
|
||||
|
||||
/// The maximum depth we will search for a parent block. In principle we should have sync'd any
|
||||
/// canonical chain to its head once the peer connects. A chain should not appear where it's depth
|
||||
@@ -645,6 +646,31 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
self.on_processing_result_inner::<CustodyRequestState<T::EthSpec>>(id, result, cx)
|
||||
}
|
||||
BlockProcessType::SinglePayloadEnvelope { id, block_root } => {
|
||||
// When envelope processing returns `MissingComponents`, the envelope has been
|
||||
// executed but data columns are not yet available. Transition the lookup to fetch
|
||||
// custody columns instead of retrying the envelope or erroring.
|
||||
if matches!(
|
||||
&result,
|
||||
BlockProcessingResult::Ok(
|
||||
AvailabilityProcessingStatus::MissingComponents { .. }
|
||||
)
|
||||
) && let Some(lookup) = self.single_block_lookups.get_mut(&id)
|
||||
&& lookup.transition_envelope_to_custody()
|
||||
{
|
||||
debug!(
|
||||
?block_root,
|
||||
"Envelope processed, transitioning to custody column lookup"
|
||||
);
|
||||
let lookup_result = lookup.continue_requests(cx);
|
||||
self.on_lookup_result(
|
||||
id,
|
||||
lookup_result,
|
||||
"envelope_to_custody_transition",
|
||||
cx,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let result = self
|
||||
.on_processing_result_inner::<EnvelopeRequestState<T::EthSpec>>(id, result, cx);
|
||||
// On successful envelope import, unblock child lookups waiting for this envelope
|
||||
|
||||
@@ -78,8 +78,8 @@ pub struct SingleBlockLookup<T: BeaconChainTypes> {
|
||||
/// than the lifetime of a custody request.
|
||||
#[educe(Debug(method(fmt_peer_set_as_len)))]
|
||||
peers: Arc<RwLock<HashSet<PeerId>>>,
|
||||
block_root: Hash256,
|
||||
awaiting_parent: Option<AwaitingParent>,
|
||||
pub(super) block_root: Hash256,
|
||||
pub(super) awaiting_parent: Option<AwaitingParent>,
|
||||
created: Instant,
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
@@ -120,21 +120,6 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an envelope-only lookup. The block is already imported, we just need the envelope.
|
||||
pub fn new_envelope_only(block_root: Hash256, peers: &[PeerId], id: Id) -> Self {
|
||||
let mut lookup = Self::new(block_root, peers, id, None);
|
||||
// Block is already imported, mark as completed
|
||||
lookup
|
||||
.block_request_state
|
||||
.state
|
||||
.on_completed_request("block already imported")
|
||||
.expect("block state starts as AwaitingDownload");
|
||||
lookup.component_requests =
|
||||
ComponentRequests::ActiveEnvelopeRequest(EnvelopeRequestState::new(block_root));
|
||||
lookup
|
||||
}
|
||||
|
||||
/// Reset the status of all internal requests
|
||||
pub fn reset_requests(&mut self) {
|
||||
self.block_request_state = BlockRequestState::new(self.block_root);
|
||||
match &self.component_requests {
|
||||
@@ -174,24 +159,11 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the parent root if awaiting a parent envelope.
|
||||
pub fn awaiting_parent_envelope(&self) -> Option<Hash256> {
|
||||
match self.awaiting_parent {
|
||||
Some(AwaitingParent::Envelope(root)) => Some(root),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark this lookup as awaiting a parent block to be imported before processing.
|
||||
pub fn set_awaiting_parent(&mut self, parent_root: Hash256) {
|
||||
self.awaiting_parent = Some(AwaitingParent::Block(parent_root));
|
||||
}
|
||||
|
||||
/// Mark this lookup as awaiting a parent envelope to be imported before processing.
|
||||
pub fn set_awaiting_parent_envelope(&mut self, parent_root: Hash256) {
|
||||
self.awaiting_parent = Some(AwaitingParent::Envelope(parent_root));
|
||||
}
|
||||
|
||||
/// Mark this lookup as no longer awaiting any parent.
|
||||
pub fn resolve_awaiting_parent(&mut self) {
|
||||
self.awaiting_parent = None;
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
//! Envelope-specific extensions to `SingleBlockLookup`.
|
||||
//!
|
||||
//! Envelope-only lookups are created when a block's parent is known and imported but its
|
||||
//! execution payload envelope has not yet been received. The block download step is skipped
|
||||
//! (marked complete immediately), and only the envelope — and possibly subsequent custody
|
||||
//! columns — are fetched.
|
||||
|
||||
use super::single_block_lookup::{
|
||||
AwaitingParent, ComponentRequests, CustodyRequestState, EnvelopeRequestState, SingleBlockLookup,
|
||||
};
|
||||
use beacon_chain::BeaconChainTypes;
|
||||
use lighthouse_network::PeerId;
|
||||
use lighthouse_network::service::api_types::Id;
|
||||
use store::Hash256;
|
||||
|
||||
impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
||||
/// Create an envelope-only lookup. The block is already imported; only the envelope (and
|
||||
/// potentially custody columns) need to be fetched.
|
||||
pub fn new_envelope_only(block_root: Hash256, peers: &[PeerId], id: Id) -> Self {
|
||||
let mut lookup = Self::new(block_root, peers, id, None);
|
||||
// Block is already imported — advance past the download step immediately.
|
||||
lookup
|
||||
.block_request_state
|
||||
.state
|
||||
.on_completed_request("block already imported")
|
||||
.expect("block state starts as AwaitingDownload");
|
||||
lookup.component_requests =
|
||||
ComponentRequests::ActiveEnvelopeRequest(EnvelopeRequestState::new(block_root));
|
||||
lookup
|
||||
}
|
||||
|
||||
/// Transition from `ActiveEnvelopeRequest` to `ActiveCustodyRequest`.
|
||||
///
|
||||
/// Called when envelope processing returns `MissingComponents`: the envelope has been executed
|
||||
/// but data columns have not yet arrived and must be fetched separately.
|
||||
/// Returns `true` if the transition was made, `false` if state was not an envelope request.
|
||||
pub fn transition_envelope_to_custody(&mut self) -> bool {
|
||||
if matches!(
|
||||
self.component_requests,
|
||||
ComponentRequests::ActiveEnvelopeRequest(_)
|
||||
) {
|
||||
self.component_requests =
|
||||
ComponentRequests::ActiveCustodyRequest(CustodyRequestState::new(self.block_root));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the parent root if this lookup is awaiting a parent envelope.
|
||||
pub fn awaiting_parent_envelope(&self) -> Option<Hash256> {
|
||||
match self.awaiting_parent {
|
||||
Some(AwaitingParent::Envelope(root)) => Some(root),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark this lookup as awaiting a parent envelope before processing can resume.
|
||||
pub fn set_awaiting_parent_envelope(&mut self, parent_root: Hash256) {
|
||||
self.awaiting_parent = Some(AwaitingParent::Envelope(parent_root));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user