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)
This commit is contained in:
dapplion
2026-06-09 20:46:24 +02:00
parent 3f550adf63
commit a5e289623c
3 changed files with 31 additions and 8 deletions

View File

@@ -693,12 +693,21 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
/// 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())
}
}
}

View File

@@ -1061,6 +1061,15 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
block_slot: Slot,
lookup_peers: Arc<RwLock<HashSet<PeerId>>>,
) -> Result<LookupRequestResult<DataColumnSidecarList<T::EthSpec>>, RpcRequestSendError> {
if self
.spec()
.fork_name_at_slot::<T::EthSpec>(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)

View File

@@ -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)
}