Make single block lookup respect earliest_available_slot for column requests (#9447)

Single block lookups do not respect the `earliest_available_slot` peers sent. This causes us to potentially request columns from peers that do not custody columns yet (but will soon).


  Pass down the block's slot and only consider peers where `earliest_available_slot <= block_slot` for custody column requests.


Co-Authored-By: Daniel Knopik <daniel@dknopik.de>
This commit is contained in:
Daniel Knopik
2026-06-17 01:54:00 +02:00
committed by GitHub
parent e0ff3b5709
commit 9de2e9e6e1
5 changed files with 121 additions and 33 deletions

View File

@@ -397,9 +397,9 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
.collect()
}
pub fn get_custodial_peers(&self, column_index: ColumnIndex) -> Vec<PeerId> {
pub fn get_custodial_peers(&self, column_index: ColumnIndex, block_slot: Slot) -> Vec<PeerId> {
self.network_globals()
.custody_peers_for_column(column_index)
.custody_peers_for_column(column_index, block_slot)
}
pub fn network_globals(&self) -> &NetworkGlobals<T::EthSpec> {
@@ -1161,6 +1161,7 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
let requester = CustodyRequester(id);
let mut request = ActiveCustodyRequest::new(
block_root,
block_slot,
CustodyId { requester },
&custody_indexes_to_fetch,
lookup_peers,

View File

@@ -13,7 +13,7 @@ use std::hash::{BuildHasher, RandomState};
use std::time::{Duration, Instant};
use std::{collections::HashMap, marker::PhantomData, sync::Arc};
use tracing::{Span, debug, debug_span, warn};
use types::{DataColumnSidecar, Hash256, data::ColumnIndex};
use types::{DataColumnSidecar, Hash256, Slot, data::ColumnIndex};
use types::{DataColumnSidecarList, EthSpec};
use super::{LookupRequestResult, PeerGroup, RpcResponseResult, SyncNetworkContext};
@@ -22,6 +22,7 @@ const MAX_STALE_NO_PEERS_DURATION: Duration = Duration::from_secs(30);
pub struct ActiveCustodyRequest<T: BeaconChainTypes> {
block_root: Hash256,
block_slot: Slot,
custody_id: CustodyId,
/// List of column indices this request needs to download to complete successfully
column_requests: FnvHashMap<ColumnIndex, ColumnRequest<T::EthSpec>>,
@@ -62,6 +63,7 @@ pub type CustodyRequestResult<E> = Result<Option<DownloadResult<DataColumnSideca
impl<T: BeaconChainTypes> ActiveCustodyRequest<T> {
pub(crate) fn new(
block_root: Hash256,
block_slot: Slot,
custody_id: CustodyId,
column_indices: &[ColumnIndex],
lookup_peers: Arc<RwLock<HashSet<PeerId>>>,
@@ -73,6 +75,7 @@ impl<T: BeaconChainTypes> ActiveCustodyRequest<T> {
);
Self {
block_root,
block_slot,
custody_id,
column_requests: HashMap::from_iter(
column_indices
@@ -365,7 +368,7 @@ impl<T: BeaconChainTypes> ActiveCustodyRequest<T> {
// We draw from the total set of peers, but prioritize those peers who we have
// received an attestation or a block from (`lookup_peers`), as the `lookup_peers` may take
// time to build up and we are likely to not find any column peers initially.
let custodial_peers = cx.get_custodial_peers(column_index);
let custodial_peers = cx.get_custodial_peers(column_index, self.block_slot);
let mut prioritized_peers = custodial_peers
.iter()
.filter(|peer| {