From a5e289623ca7908d3f1c5390fed285ddcf4ce43e Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 9 Jun 2026 20:46:24 +0200 Subject: [PATCH] Fix Gloas no-full-child lookup completion; gate wrong-data test by depth - custody_lookup_request: under Gloas with no FULL-child peer to serve columns, park the data request (Pending) so the lookup completes on block import instead of stranding - has_no_peers: once the Gloas block request is complete, evaluate only the gloas child peers - bad_peer_wrong_data_response: the wrong-sidecar penalty is only attributable under Gloas at depth >= 2 (the tip has no FULL-child peer) --- .../sync/block_lookups/single_block_lookup.rs | 21 +++++++++++++------ .../network/src/sync/network_context.rs | 9 ++++++++ beacon_node/network/src/sync/tests/lookups.rs | 9 ++++++-- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/beacon_node/network/src/sync/block_lookups/single_block_lookup.rs b/beacon_node/network/src/sync/block_lookups/single_block_lookup.rs index 59d025b5b3..20fbe55010 100644 --- a/beacon_node/network/src/sync/block_lookups/single_block_lookup.rs +++ b/beacon_node/network/src/sync/block_lookups/single_block_lookup.rs @@ -693,12 +693,21 @@ impl SingleBlockLookup { /// Returns true if this lookup has zero peers pub fn has_no_peers(&self) -> bool { - self.peers.read().is_empty() - && self - .gloas_child_peers - .read() - .values() - .all(|set| set.read().is_empty()) + if self.block_request.is_complete() + && let Some(block) = self.block_request.state.peek_downloaded_data() + && block.fork_name_unchecked().gloas_enabled() + { + // Gloas block request complete, the main peer set is irrelevant. Check only the gloas + // child peers + self.get_data_peers(block).read().is_empty() + } else { + self.peers.read().is_empty() + && self + .gloas_child_peers + .read() + .values() + .all(|set| set.read().is_empty()) + } } } diff --git a/beacon_node/network/src/sync/network_context.rs b/beacon_node/network/src/sync/network_context.rs index ff4e751ce2..e3741c51b1 100644 --- a/beacon_node/network/src/sync/network_context.rs +++ b/beacon_node/network/src/sync/network_context.rs @@ -1061,6 +1061,15 @@ impl SyncNetworkContext { block_slot: Slot, lookup_peers: Arc>>, ) -> Result>, RpcRequestSendError> { + if self + .spec() + .fork_name_at_slot::(block_slot) + .gloas_enabled() + && lookup_peers.read().is_empty() + { + return Ok(LookupRequestResult::Pending("no peers")); + } + let custody_indexes_imported = self .chain .cached_data_column_indexes(&block_root, block_slot) diff --git a/beacon_node/network/src/sync/tests/lookups.rs b/beacon_node/network/src/sync/tests/lookups.rs index 8e29dbeada..bebac21e73 100644 --- a/beacon_node/network/src/sync/tests/lookups.rs +++ b/beacon_node/network/src/sync/tests/lookups.rs @@ -2205,8 +2205,13 @@ async fn bad_peer_wrong_data_response(depth: usize) { r.build_chain_and_trigger_last_block(depth).await; r.simulate(SimulateConfig::new().return_wrong_sidecar_for_block_once()) .await; - // We register a penalty, retry and complete sync successfully - r.assert_penalties(&["UnrequestedBlockRoot"]); + // We register a penalty, retry and complete sync successfully. Under Gloas the tip block + // (depth 1) has no attributable FULL-child peer so no custody request is made and no penalty + // is possible; at depth >= 2 the parent's columns are served by the tip (its FULL child), so + // the wrong-sidecar penalty is attributable. + if !r.is_after_gloas() || depth >= 2 { + r.assert_penalties(&["UnrequestedBlockRoot"]); + } r.assert_successful_lookup_sync(); // TODO(tree-sync) Assert that a single lookup is created (no drops) }