mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-16 02:08:29 +00:00
Merge sigp/unstable into gloas-lookup-sync-fixes
Brings in the gossip-blob deprecation (#9126) and 17 other unstable commits. Conflict resolutions (8 files): - Kept our unified `SyncMessage::UnknownParentSidecarHeader` design over unstable's separate `UnknownParentDataColumn`/`UnknownParentPartialDataColumn` variants (gossip_methods, manager, single_block_lookup, mod, tests). - Adopted unstable's gossip-blob deprecation: dropped `process_gossip_blob`, `process_gossip_verified_blob`, and the blob parent-unknown test path. - Took unstable's `process_gossip_verified_data_column` (Result-returning `to_partial`), router PayloadEnvelopesByRoot flattened match, and combined `BlockProcessType::id` arm. - Dropped unstable's gloas-lookup-sync boilerplate stubs (#9322) that duplicated our real impls: `process_lookup_envelope`, `rpc_payload_envelope_received`, `on_single_payload_envelope_response`, and the `SinglePayloadEnvelope` processing-result arm. cargo check -p network passes clean.
This commit is contained in:
@@ -203,9 +203,9 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
block_root,
|
||||
Some(block_component),
|
||||
Some(awaiting_parent),
|
||||
// On a `UnknownParentBlock` or `UnknownParentBlob` event the peer is not required
|
||||
// to have the rest of the block components (refer to decoupled blob gossip). Create
|
||||
// the lookup with zero peers to house the block components.
|
||||
// On a `UnknownParentBlock` or `UnknownParentSidecarHeader` event the peer is not
|
||||
// required to have the rest of the block components (refer to decoupled blob
|
||||
// gossip). Create the lookup with zero peers to house the block components.
|
||||
&[],
|
||||
&PeerType::PreGloas,
|
||||
new_lookup_trigger,
|
||||
|
||||
@@ -593,7 +593,7 @@ impl<T: BeaconChainTypes> CustodyBackFillSync<T> {
|
||||
Err(err) => {
|
||||
debug!(batch_epoch = %batch_id, error = ?err, "Batch download failed");
|
||||
|
||||
// If there are any coupling errors, penalize the appropriate peers
|
||||
// If there are any coupling errors, penalize the appropriate peers.
|
||||
if let RpcResponseError::BlockComponentCouplingError(coupling_error) = err
|
||||
&& let CouplingError::DataColumnPeerFailure {
|
||||
error,
|
||||
@@ -601,15 +601,19 @@ impl<T: BeaconChainTypes> CustodyBackFillSync<T> {
|
||||
exceeded_retries: _,
|
||||
} = coupling_error
|
||||
{
|
||||
let mut failed_peers = HashSet::new();
|
||||
for (column_index, faulty_peer) in faulty_peers {
|
||||
debug!(
|
||||
?error,
|
||||
?column_index,
|
||||
?faulty_peer,
|
||||
"Custody backfill sync penalizing peer"
|
||||
"Custody backfill sync: peer failed to serve column"
|
||||
);
|
||||
failed_peers.insert(faulty_peer);
|
||||
}
|
||||
for peer in failed_peers {
|
||||
network.report_peer(
|
||||
faulty_peer,
|
||||
peer,
|
||||
PeerAction::LowToleranceError,
|
||||
"Peer failed to serve column",
|
||||
);
|
||||
|
||||
@@ -198,8 +198,9 @@ pub enum BlockProcessType {
|
||||
impl BlockProcessType {
|
||||
pub fn id(&self) -> Id {
|
||||
match self {
|
||||
BlockProcessType::SingleBlock { id } | BlockProcessType::SingleBlob { id } => *id,
|
||||
BlockProcessType::SingleCustodyColumn(id)
|
||||
BlockProcessType::SingleBlock { id }
|
||||
| BlockProcessType::SingleBlob { id }
|
||||
| BlockProcessType::SingleCustodyColumn(id)
|
||||
| BlockProcessType::SinglePayloadEnvelope(id) => *id,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,7 +305,12 @@ impl<T: BeaconChainTypes> ActiveCustodyRequest<T> {
|
||||
// must have its columns in custody. In that case, set `true = enforce max_requests`
|
||||
// and downscore if data_columns_by_root does not return the expected custody
|
||||
// columns. For the rest of peers, don't downscore if columns are missing.
|
||||
lookup_peers.contains(&peer_id),
|
||||
//
|
||||
// Post-Gloas, blocks and payload envelopes are decoupled. A peer may
|
||||
// have the block but not yet imported the envelope and data columns.
|
||||
// Don't enforce max_responses in this case.
|
||||
lookup_peers.contains(&peer_id)
|
||||
&& !cx.fork_context.current_fork_name().gloas_enabled(),
|
||||
)
|
||||
.map_err(Error::SendFailed)?;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ impl<E: EthSpec> ActiveRequestItems for BlobsByRangeRequestItems<E> {
|
||||
if blob.index >= self.max_blobs_per_block {
|
||||
return Err(LookupVerifyError::UnrequestedIndex(blob.index));
|
||||
}
|
||||
|
||||
if !blob.verify_blob_sidecar_inclusion_proof() {
|
||||
return Err(LookupVerifyError::InvalidInclusionProof);
|
||||
}
|
||||
|
||||
@@ -50,9 +50,11 @@ impl<E: EthSpec> ActiveRequestItems for BlobsByRootRequestItems<E> {
|
||||
if self.request.block_root != block_root {
|
||||
return Err(LookupVerifyError::UnrequestedBlockRoot(block_root));
|
||||
}
|
||||
|
||||
if !blob.verify_blob_sidecar_inclusion_proof() {
|
||||
return Err(LookupVerifyError::InvalidInclusionProof);
|
||||
}
|
||||
|
||||
if !self.request.indices.contains(&blob.index) {
|
||||
return Err(LookupVerifyError::UnrequestedIndex(blob.index));
|
||||
}
|
||||
|
||||
@@ -1278,17 +1278,6 @@ impl TestRig {
|
||||
self.trigger_unknown_parent_block(peer_id, last_block);
|
||||
}
|
||||
|
||||
fn trigger_with_last_unknown_blob_parent(&mut self) {
|
||||
let peer_id = self.new_connected_supernode_peer();
|
||||
let blobs = self
|
||||
.get_last_block()
|
||||
.block_data()
|
||||
.blobs()
|
||||
.expect("no blobs");
|
||||
let blob = blobs.first().expect("empty blobs");
|
||||
self.trigger_unknown_parent_blob(peer_id, blob.clone());
|
||||
}
|
||||
|
||||
fn trigger_with_last_unknown_data_column_parent(&mut self) {
|
||||
let peer_id = self.new_connected_supernode_peer();
|
||||
let columns = self
|
||||
@@ -1297,7 +1286,7 @@ impl TestRig {
|
||||
.data_columns()
|
||||
.expect("No data columns");
|
||||
let column = columns.first().expect("empty columns");
|
||||
self.trigger_unknown_parent_column(peer_id, column.clone());
|
||||
self.trigger_unknown_parent_data_column(peer_id, column.clone());
|
||||
}
|
||||
|
||||
// Post-test assertions
|
||||
@@ -1501,6 +1490,10 @@ impl TestRig {
|
||||
genesis_fork().deneb_enabled().then(Self::default)
|
||||
}
|
||||
|
||||
fn new_after_fulu() -> Option<Self> {
|
||||
genesis_fork().fulu_enabled().then(Self::default)
|
||||
}
|
||||
|
||||
fn new_after_deneb_before_fulu() -> Option<Self> {
|
||||
let fork = genesis_fork();
|
||||
if fork.deneb_enabled() && !fork.fulu_enabled() {
|
||||
@@ -1536,27 +1529,18 @@ impl TestRig {
|
||||
self.send_sync_message(SyncMessage::UnknownParentBlock(peer_id, block, block_root))
|
||||
}
|
||||
|
||||
fn trigger_unknown_parent_blob(&mut self, peer_id: PeerId, blob: Arc<BlobSidecar<E>>) {
|
||||
self.send_sync_message(SyncMessage::UnknownParentSidecarHeader {
|
||||
peer_id,
|
||||
block_root: blob.block_root(),
|
||||
parent_root: blob.block_parent_root(),
|
||||
slot: blob.slot(),
|
||||
});
|
||||
}
|
||||
|
||||
fn trigger_unknown_parent_column(
|
||||
fn trigger_unknown_parent_data_column(
|
||||
&mut self,
|
||||
peer_id: PeerId,
|
||||
column: Arc<DataColumnSidecar<E>>,
|
||||
data_column: Arc<DataColumnSidecar<E>>,
|
||||
) {
|
||||
let DataColumnSidecar::Fulu(col) = column.as_ref() else {
|
||||
let DataColumnSidecar::Fulu(col) = data_column.as_ref() else {
|
||||
// Gloas data columns don't carry a parent block root, so the
|
||||
// `UnknownParentSidecarHeader` trigger doesn't apply post-Gloas. The production
|
||||
// path drops these with a `warn!` (see `manager.rs` handler). Mirror that here
|
||||
// so Gloas test paths can call the same helper as Fulu without panicking.
|
||||
self.log(&format!(
|
||||
"trigger_unknown_parent_column noop (post-Gloas column has no parent root) peer {peer_id:?}"
|
||||
"trigger_unknown_parent_data_column noop (post-Gloas column has no parent root) peer {peer_id:?}"
|
||||
));
|
||||
return;
|
||||
};
|
||||
@@ -1850,9 +1834,9 @@ impl TestRig {
|
||||
)
|
||||
.unwrap()
|
||||
{
|
||||
Availability::Available(_) => panic!("blob removed from da_checker, available"),
|
||||
Availability::Available(_) => panic!("column removed from da_checker, available"),
|
||||
Availability::MissingComponents(block_root) => {
|
||||
self.log(&format!("inserted blob to da_checker {block_root:?}"))
|
||||
self.log(&format!("inserted column to da_checker {block_root:?}"))
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -2037,9 +2021,9 @@ async fn happy_path_unknown_block_parent(depth: usize) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert that sync completes from a GossipUnknownParentBlob / UnknownDataColumnParent
|
||||
/// Assert that sync completes from an UnknownDataColumnParent
|
||||
async fn happy_path_unknown_data_parent(depth: usize) {
|
||||
let Some(mut r) = TestRig::new_after_deneb() else {
|
||||
let Some(mut r) = TestRig::new_after_fulu() else {
|
||||
return;
|
||||
};
|
||||
// Post-Gloas data columns don't carry a parent block root, so the unknown-parent-data
|
||||
@@ -2048,29 +2032,23 @@ async fn happy_path_unknown_data_parent(depth: usize) {
|
||||
return;
|
||||
}
|
||||
r.build_chain(depth).await;
|
||||
if r.is_after_fulu() {
|
||||
r.trigger_with_last_unknown_data_column_parent();
|
||||
} else if r.is_after_deneb() {
|
||||
r.trigger_with_last_unknown_blob_parent();
|
||||
}
|
||||
r.trigger_with_last_unknown_data_column_parent();
|
||||
r.simulate(SimulateConfig::happy_path()).await;
|
||||
r.assert_successful_lookup_sync_parent_trigger();
|
||||
}
|
||||
|
||||
/// Assert that multiple trigger types don't create extra lookups
|
||||
async fn happy_path_multiple_triggers(depth: usize) {
|
||||
let mut r = TestRig::default();
|
||||
let Some(mut r) = TestRig::new_after_fulu() else {
|
||||
return;
|
||||
};
|
||||
// + 1, because the unknown parent trigger needs two new blocks
|
||||
r.build_chain(depth + 1).await;
|
||||
r.trigger_with_last_block();
|
||||
r.trigger_with_last_block();
|
||||
r.trigger_with_last_unknown_block_parent();
|
||||
r.trigger_with_last_unknown_block_parent();
|
||||
if r.is_after_fulu() {
|
||||
r.trigger_with_last_unknown_data_column_parent();
|
||||
} else if r.is_after_deneb() {
|
||||
r.trigger_with_last_unknown_blob_parent();
|
||||
}
|
||||
r.trigger_with_last_unknown_data_column_parent();
|
||||
r.simulate(SimulateConfig::happy_path()).await;
|
||||
assert_eq!(r.created_lookups(), depth + 1, "Don't create extra lookups");
|
||||
r.assert_successful_lookup_sync();
|
||||
@@ -2209,18 +2187,14 @@ async fn too_many_processing_failures(depth: usize) {
|
||||
#[tokio::test]
|
||||
/// Assert that multiple trigger types don't create extra lookups
|
||||
async fn unknown_parent_does_not_add_peers_to_itself() {
|
||||
let Some(mut r) = TestRig::new_after_deneb() else {
|
||||
let Some(mut r) = TestRig::new_after_fulu() else {
|
||||
return;
|
||||
};
|
||||
// 2, because the unknown parent trigger needs two new blocks
|
||||
r.build_chain(2).await;
|
||||
r.trigger_with_last_unknown_block_parent();
|
||||
r.trigger_with_last_unknown_block_parent();
|
||||
if r.is_after_fulu() {
|
||||
r.trigger_with_last_unknown_data_column_parent();
|
||||
} else if r.is_after_deneb() {
|
||||
r.trigger_with_last_unknown_blob_parent();
|
||||
}
|
||||
r.trigger_with_last_unknown_data_column_parent();
|
||||
r.simulate(SimulateConfig::happy_path()).await;
|
||||
r.assert_peers_at_lookup_of_slot(2, 0);
|
||||
// Post-Gloas the data-column trigger is a no-op (Gloas columns don't carry a parent
|
||||
|
||||
@@ -26,7 +26,7 @@ use types::{ForkName, Hash256, MinimalEthSpec as E, SignedExecutionPayloadEnvelo
|
||||
mod lookups;
|
||||
mod range;
|
||||
|
||||
type T = Witness<ManualSlotClock, E, MemoryStore<E>, MemoryStore<E>>;
|
||||
type T = Witness<ManualSlotClock, E, MemoryStore, MemoryStore>;
|
||||
|
||||
/// This test utility enables integration testing of Lighthouse sync components.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user