mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 00:42:42 +00:00
Add sync lookup custody request state (#6257)
* Add sync lookup custody request state * Review PR * clippy * Merge branch 'unstable' of https://github.com/sigp/lighthouse into peerdas-network-lookup
This commit is contained in:
@@ -6852,6 +6852,24 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
self.data_availability_checker.data_availability_boundary()
|
self.data_availability_checker.data_availability_boundary()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if epoch is within the data availability boundary
|
||||||
|
pub fn da_check_required_for_epoch(&self, epoch: Epoch) -> bool {
|
||||||
|
self.data_availability_checker
|
||||||
|
.da_check_required_for_epoch(epoch)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if we should fetch blobs for this block
|
||||||
|
pub fn should_fetch_blobs(&self, block_epoch: Epoch) -> bool {
|
||||||
|
self.da_check_required_for_epoch(block_epoch)
|
||||||
|
&& !self.spec.is_peer_das_enabled_for_epoch(block_epoch)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if we should fetch custody columns for this block
|
||||||
|
pub fn should_fetch_custody_columns(&self, block_epoch: Epoch) -> bool {
|
||||||
|
self.da_check_required_for_epoch(block_epoch)
|
||||||
|
&& self.spec.is_peer_das_enabled_for_epoch(block_epoch)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn logger(&self) -> &Logger {
|
pub fn logger(&self) -> &Logger {
|
||||||
&self.log
|
&self.log
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,6 +156,15 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the set of imported custody column indexes for `block_root`. Returns None if there is
|
||||||
|
/// no block component for `block_root`.
|
||||||
|
pub fn imported_custody_column_indexes(&self, block_root: &Hash256) -> Option<Vec<u64>> {
|
||||||
|
self.availability_cache
|
||||||
|
.peek_pending_components(block_root, |components| {
|
||||||
|
components.map(|components| components.get_cached_data_columns_indices())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a blob from the availability cache.
|
/// Get a blob from the availability cache.
|
||||||
pub fn get_blob(
|
pub fn get_blob(
|
||||||
&self,
|
&self,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use ssz_types::{FixedVector, VariableList};
|
|||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::blob_sidecar::BlobIdentifier;
|
use types::blob_sidecar::BlobIdentifier;
|
||||||
use types::{BlobSidecar, ChainSpec, Epoch, EthSpec, Hash256, SignedBeaconBlock};
|
use types::{BlobSidecar, ChainSpec, ColumnIndex, Epoch, EthSpec, Hash256, SignedBeaconBlock};
|
||||||
|
|
||||||
/// This represents the components of a partially available block
|
/// This represents the components of a partially available block
|
||||||
///
|
///
|
||||||
@@ -108,6 +108,14 @@ impl<E: EthSpec> PendingComponents<E> {
|
|||||||
self.verified_data_columns.len()
|
self.verified_data_columns.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the indices of cached custody columns
|
||||||
|
pub fn get_cached_data_columns_indices(&self) -> Vec<ColumnIndex> {
|
||||||
|
self.verified_data_columns
|
||||||
|
.iter()
|
||||||
|
.map(|d| d.index())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// Inserts a block into the cache.
|
/// Inserts a block into the cache.
|
||||||
pub fn insert_block(&mut self, block: DietAvailabilityPendingExecutedBlock<E>) {
|
pub fn insert_block(&mut self, block: DietAvailabilityPendingExecutedBlock<E>) {
|
||||||
*self.get_cached_block_mut() = Some(block)
|
*self.get_cached_block_mut() = Some(block)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::EnrExt;
|
|||||||
use crate::{Enr, GossipTopic, Multiaddr, PeerId};
|
use crate::{Enr, GossipTopic, Multiaddr, PeerId};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use types::EthSpec;
|
use types::{ChainSpec, ColumnIndex, EthSpec};
|
||||||
|
|
||||||
pub struct NetworkGlobals<E: EthSpec> {
|
pub struct NetworkGlobals<E: EthSpec> {
|
||||||
/// The current local ENR.
|
/// The current local ENR.
|
||||||
@@ -110,6 +110,13 @@ impl<E: EthSpec> NetworkGlobals<E> {
|
|||||||
std::mem::replace(&mut *self.sync_state.write(), new_state)
|
std::mem::replace(&mut *self.sync_state.write(), new_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compute custody data columns the node is assigned to custody.
|
||||||
|
pub fn custody_columns(&self, _spec: &ChainSpec) -> Vec<ColumnIndex> {
|
||||||
|
let _enr = self.local_enr();
|
||||||
|
//TODO(das): implement ENR changes
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
/// TESTING ONLY. Build a dummy NetworkGlobals instance.
|
/// TESTING ONLY. Build a dummy NetworkGlobals instance.
|
||||||
pub fn new_test_globals(trusted_peers: Vec<PeerId>, log: &slog::Logger) -> NetworkGlobals<E> {
|
pub fn new_test_globals(trusted_peers: Vec<PeerId>, log: &slog::Logger) -> NetworkGlobals<E> {
|
||||||
use crate::CombinedKeyExt;
|
use crate::CombinedKeyExt;
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
use crate::sync::block_lookups::single_block_lookup::{
|
use crate::sync::block_lookups::single_block_lookup::{
|
||||||
LookupRequestError, SingleBlockLookup, SingleLookupRequestState,
|
LookupRequestError, SingleBlockLookup, SingleLookupRequestState,
|
||||||
};
|
};
|
||||||
use crate::sync::block_lookups::{BlobRequestState, BlockRequestState, PeerId};
|
use crate::sync::block_lookups::{
|
||||||
|
BlobRequestState, BlockRequestState, CustodyRequestState, PeerId,
|
||||||
|
};
|
||||||
use crate::sync::network_context::{LookupRequestResult, SyncNetworkContext};
|
use crate::sync::network_context::{LookupRequestResult, SyncNetworkContext};
|
||||||
use beacon_chain::block_verification_types::RpcBlock;
|
use beacon_chain::block_verification_types::RpcBlock;
|
||||||
use beacon_chain::BeaconChainTypes;
|
use beacon_chain::BeaconChainTypes;
|
||||||
use lighthouse_network::service::api_types::Id;
|
use lighthouse_network::service::api_types::Id;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::blob_sidecar::FixedBlobSidecarList;
|
use types::blob_sidecar::FixedBlobSidecarList;
|
||||||
use types::SignedBeaconBlock;
|
use types::{DataColumnSidecarList, SignedBeaconBlock};
|
||||||
|
|
||||||
use super::single_block_lookup::DownloadResult;
|
use super::single_block_lookup::DownloadResult;
|
||||||
use super::SingleLookupId;
|
use super::SingleLookupId;
|
||||||
@@ -17,6 +19,7 @@ use super::SingleLookupId;
|
|||||||
pub enum ResponseType {
|
pub enum ResponseType {
|
||||||
Block,
|
Block,
|
||||||
Blob,
|
Blob,
|
||||||
|
CustodyColumn,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait unifies common single block lookup functionality across blocks and blobs. This
|
/// This trait unifies common single block lookup functionality across blocks and blobs. This
|
||||||
@@ -38,7 +41,7 @@ pub trait RequestState<T: BeaconChainTypes> {
|
|||||||
&self,
|
&self,
|
||||||
id: Id,
|
id: Id,
|
||||||
peer_id: PeerId,
|
peer_id: PeerId,
|
||||||
downloaded_block_expected_blobs: Option<usize>,
|
downloaded_block: Option<Arc<SignedBeaconBlock<T::EthSpec>>>,
|
||||||
cx: &mut SyncNetworkContext<T>,
|
cx: &mut SyncNetworkContext<T>,
|
||||||
) -> Result<LookupRequestResult, LookupRequestError>;
|
) -> Result<LookupRequestResult, LookupRequestError>;
|
||||||
|
|
||||||
@@ -73,7 +76,7 @@ impl<T: BeaconChainTypes> RequestState<T> for BlockRequestState<T::EthSpec> {
|
|||||||
&self,
|
&self,
|
||||||
id: SingleLookupId,
|
id: SingleLookupId,
|
||||||
peer_id: PeerId,
|
peer_id: PeerId,
|
||||||
_: Option<usize>,
|
_: Option<Arc<SignedBeaconBlock<T::EthSpec>>>,
|
||||||
cx: &mut SyncNetworkContext<T>,
|
cx: &mut SyncNetworkContext<T>,
|
||||||
) -> Result<LookupRequestResult, LookupRequestError> {
|
) -> Result<LookupRequestResult, LookupRequestError> {
|
||||||
cx.block_lookup_request(id, peer_id, self.requested_block_root)
|
cx.block_lookup_request(id, peer_id, self.requested_block_root)
|
||||||
@@ -121,16 +124,11 @@ impl<T: BeaconChainTypes> RequestState<T> for BlobRequestState<T::EthSpec> {
|
|||||||
&self,
|
&self,
|
||||||
id: Id,
|
id: Id,
|
||||||
peer_id: PeerId,
|
peer_id: PeerId,
|
||||||
downloaded_block_expected_blobs: Option<usize>,
|
downloaded_block: Option<Arc<SignedBeaconBlock<T::EthSpec>>>,
|
||||||
cx: &mut SyncNetworkContext<T>,
|
cx: &mut SyncNetworkContext<T>,
|
||||||
) -> Result<LookupRequestResult, LookupRequestError> {
|
) -> Result<LookupRequestResult, LookupRequestError> {
|
||||||
cx.blob_lookup_request(
|
cx.blob_lookup_request(id, peer_id, self.block_root, downloaded_block)
|
||||||
id,
|
.map_err(LookupRequestError::SendFailedNetwork)
|
||||||
peer_id,
|
|
||||||
self.block_root,
|
|
||||||
downloaded_block_expected_blobs,
|
|
||||||
)
|
|
||||||
.map_err(LookupRequestError::SendFailedNetwork)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_for_processing(
|
fn send_for_processing(
|
||||||
@@ -161,3 +159,47 @@ impl<T: BeaconChainTypes> RequestState<T> for BlobRequestState<T::EthSpec> {
|
|||||||
&mut self.state
|
&mut self.state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: BeaconChainTypes> RequestState<T> for CustodyRequestState<T::EthSpec> {
|
||||||
|
type VerifiedResponseType = DataColumnSidecarList<T::EthSpec>;
|
||||||
|
|
||||||
|
fn make_request(
|
||||||
|
&self,
|
||||||
|
id: Id,
|
||||||
|
// TODO(das): consider selecting peers that have custody but are in this set
|
||||||
|
_peer_id: PeerId,
|
||||||
|
downloaded_block: Option<Arc<SignedBeaconBlock<T::EthSpec>>>,
|
||||||
|
cx: &mut SyncNetworkContext<T>,
|
||||||
|
) -> Result<LookupRequestResult, LookupRequestError> {
|
||||||
|
cx.custody_lookup_request(id, self.block_root, downloaded_block)
|
||||||
|
.map_err(LookupRequestError::SendFailedNetwork)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_for_processing(
|
||||||
|
id: Id,
|
||||||
|
download_result: DownloadResult<Self::VerifiedResponseType>,
|
||||||
|
cx: &SyncNetworkContext<T>,
|
||||||
|
) -> Result<(), LookupRequestError> {
|
||||||
|
let DownloadResult {
|
||||||
|
value,
|
||||||
|
block_root,
|
||||||
|
seen_timestamp,
|
||||||
|
..
|
||||||
|
} = download_result;
|
||||||
|
cx.send_custody_columns_for_processing(id, block_root, value, seen_timestamp)
|
||||||
|
.map_err(LookupRequestError::SendFailedProcessor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn response_type() -> ResponseType {
|
||||||
|
ResponseType::CustodyColumn
|
||||||
|
}
|
||||||
|
fn request_state_mut(request: &mut SingleBlockLookup<T>) -> &mut Self {
|
||||||
|
&mut request.custody_request_state
|
||||||
|
}
|
||||||
|
fn get_state(&self) -> &SingleLookupRequestState<Self::VerifiedResponseType> {
|
||||||
|
&self.state
|
||||||
|
}
|
||||||
|
fn get_state_mut(&mut self) -> &mut SingleLookupRequestState<Self::VerifiedResponseType> {
|
||||||
|
&mut self.state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ use fnv::FnvHashMap;
|
|||||||
use lighthouse_network::service::api_types::SingleLookupReqId;
|
use lighthouse_network::service::api_types::SingleLookupReqId;
|
||||||
use lighthouse_network::{PeerAction, PeerId};
|
use lighthouse_network::{PeerAction, PeerId};
|
||||||
use lru_cache::LRUTimeCache;
|
use lru_cache::LRUTimeCache;
|
||||||
pub use single_block_lookup::{BlobRequestState, BlockRequestState};
|
pub use single_block_lookup::{BlobRequestState, BlockRequestState, CustodyRequestState};
|
||||||
use slog::{debug, error, warn, Logger};
|
use slog::{debug, error, warn, Logger};
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -527,7 +527,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
|||||||
// if both components have been processed.
|
// if both components have been processed.
|
||||||
request_state.on_processing_success()?;
|
request_state.on_processing_success()?;
|
||||||
|
|
||||||
if lookup.both_components_processed() {
|
if lookup.all_components_processed() {
|
||||||
// We don't request for other block components until being sure that the block has
|
// We don't request for other block components until being sure that the block has
|
||||||
// data. If we request blobs / columns to a peer we are sure those must exist.
|
// data. If we request blobs / columns to a peer we are sure those must exist.
|
||||||
// Therefore if all components are processed and we still receive `MissingComponents`
|
// Therefore if all components are processed and we still receive `MissingComponents`
|
||||||
@@ -599,6 +599,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
|||||||
match R::response_type() {
|
match R::response_type() {
|
||||||
ResponseType::Block => "lookup_block_processing_failure",
|
ResponseType::Block => "lookup_block_processing_failure",
|
||||||
ResponseType::Blob => "lookup_blobs_processing_failure",
|
ResponseType::Blob => "lookup_blobs_processing_failure",
|
||||||
|
ResponseType::CustodyColumn => "lookup_custody_processing_failure",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use std::time::{Duration, Instant};
|
|||||||
use store::Hash256;
|
use store::Hash256;
|
||||||
use strum::IntoStaticStr;
|
use strum::IntoStaticStr;
|
||||||
use types::blob_sidecar::FixedBlobSidecarList;
|
use types::blob_sidecar::FixedBlobSidecarList;
|
||||||
use types::{EthSpec, SignedBeaconBlock};
|
use types::{DataColumnSidecarList, EthSpec, SignedBeaconBlock};
|
||||||
|
|
||||||
// Dedicated enum for LookupResult to force its usage
|
// Dedicated enum for LookupResult to force its usage
|
||||||
#[must_use = "LookupResult must be handled with on_lookup_result"]
|
#[must_use = "LookupResult must be handled with on_lookup_result"]
|
||||||
@@ -63,6 +63,7 @@ pub struct SingleBlockLookup<T: BeaconChainTypes> {
|
|||||||
pub id: Id,
|
pub id: Id,
|
||||||
pub block_request_state: BlockRequestState<T::EthSpec>,
|
pub block_request_state: BlockRequestState<T::EthSpec>,
|
||||||
pub blob_request_state: BlobRequestState<T::EthSpec>,
|
pub blob_request_state: BlobRequestState<T::EthSpec>,
|
||||||
|
pub custody_request_state: CustodyRequestState<T::EthSpec>,
|
||||||
/// Peers that claim to have imported this set of block components
|
/// Peers that claim to have imported this set of block components
|
||||||
#[derivative(Debug(format_with = "fmt_peer_set_as_len"))]
|
#[derivative(Debug(format_with = "fmt_peer_set_as_len"))]
|
||||||
peers: HashSet<PeerId>,
|
peers: HashSet<PeerId>,
|
||||||
@@ -82,6 +83,7 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
|||||||
id,
|
id,
|
||||||
block_request_state: BlockRequestState::new(requested_block_root),
|
block_request_state: BlockRequestState::new(requested_block_root),
|
||||||
blob_request_state: BlobRequestState::new(requested_block_root),
|
blob_request_state: BlobRequestState::new(requested_block_root),
|
||||||
|
custody_request_state: CustodyRequestState::new(requested_block_root),
|
||||||
peers: HashSet::from_iter(peers.iter().copied()),
|
peers: HashSet::from_iter(peers.iter().copied()),
|
||||||
block_root: requested_block_root,
|
block_root: requested_block_root,
|
||||||
awaiting_parent,
|
awaiting_parent,
|
||||||
@@ -138,9 +140,10 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the block has already been downloaded.
|
/// Returns true if the block has already been downloaded.
|
||||||
pub fn both_components_processed(&self) -> bool {
|
pub fn all_components_processed(&self) -> bool {
|
||||||
self.block_request_state.state.is_processed()
|
self.block_request_state.state.is_processed()
|
||||||
&& self.blob_request_state.state.is_processed()
|
&& self.blob_request_state.state.is_processed()
|
||||||
|
&& self.custody_request_state.state.is_processed()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this request is expecting some event to make progress
|
/// Returns true if this request is expecting some event to make progress
|
||||||
@@ -148,6 +151,7 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
|||||||
self.awaiting_parent.is_some()
|
self.awaiting_parent.is_some()
|
||||||
|| self.block_request_state.state.is_awaiting_event()
|
|| self.block_request_state.state.is_awaiting_event()
|
||||||
|| self.blob_request_state.state.is_awaiting_event()
|
|| self.blob_request_state.state.is_awaiting_event()
|
||||||
|
|| self.custody_request_state.state.is_awaiting_event()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes progress on all requests of this lookup. Any error is not recoverable and must result
|
/// Makes progress on all requests of this lookup. Any error is not recoverable and must result
|
||||||
@@ -159,13 +163,12 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
|||||||
// TODO: Check what's necessary to download, specially for blobs
|
// TODO: Check what's necessary to download, specially for blobs
|
||||||
self.continue_request::<BlockRequestState<T::EthSpec>>(cx)?;
|
self.continue_request::<BlockRequestState<T::EthSpec>>(cx)?;
|
||||||
self.continue_request::<BlobRequestState<T::EthSpec>>(cx)?;
|
self.continue_request::<BlobRequestState<T::EthSpec>>(cx)?;
|
||||||
|
self.continue_request::<CustodyRequestState<T::EthSpec>>(cx)?;
|
||||||
|
|
||||||
// If all components of this lookup are already processed, there will be no future events
|
// If all components of this lookup are already processed, there will be no future events
|
||||||
// that can make progress so it must be dropped. Consider the lookup completed.
|
// that can make progress so it must be dropped. Consider the lookup completed.
|
||||||
// This case can happen if we receive the components from gossip during a retry.
|
// This case can happen if we receive the components from gossip during a retry.
|
||||||
if self.block_request_state.state.is_processed()
|
if self.all_components_processed() {
|
||||||
&& self.blob_request_state.state.is_processed()
|
|
||||||
{
|
|
||||||
Ok(LookupResult::Completed)
|
Ok(LookupResult::Completed)
|
||||||
} else {
|
} else {
|
||||||
Ok(LookupResult::Pending)
|
Ok(LookupResult::Pending)
|
||||||
@@ -179,11 +182,11 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
|||||||
) -> Result<(), LookupRequestError> {
|
) -> Result<(), LookupRequestError> {
|
||||||
let id = self.id;
|
let id = self.id;
|
||||||
let awaiting_parent = self.awaiting_parent.is_some();
|
let awaiting_parent = self.awaiting_parent.is_some();
|
||||||
let downloaded_block_expected_blobs = self
|
let downloaded_block = self
|
||||||
.block_request_state
|
.block_request_state
|
||||||
.state
|
.state
|
||||||
.peek_downloaded_data()
|
.peek_downloaded_data()
|
||||||
.map(|block| block.num_expected_blobs());
|
.cloned();
|
||||||
let block_is_processed = self.block_request_state.state.is_processed();
|
let block_is_processed = self.block_request_state.state.is_processed();
|
||||||
let request = R::request_state_mut(self);
|
let request = R::request_state_mut(self);
|
||||||
|
|
||||||
@@ -210,7 +213,7 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let request = R::request_state_mut(self);
|
let request = R::request_state_mut(self);
|
||||||
match request.make_request(id, peer_id, downloaded_block_expected_blobs, cx)? {
|
match request.make_request(id, peer_id, downloaded_block, cx)? {
|
||||||
LookupRequestResult::RequestSent(req_id) => {
|
LookupRequestResult::RequestSent(req_id) => {
|
||||||
// Lookup sync event safety: If make_request returns `RequestSent`, we are
|
// Lookup sync event safety: If make_request returns `RequestSent`, we are
|
||||||
// guaranteed that `BlockLookups::on_download_response` will be called exactly
|
// guaranteed that `BlockLookups::on_download_response` will be called exactly
|
||||||
@@ -289,6 +292,24 @@ impl<T: BeaconChainTypes> SingleBlockLookup<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The state of the block request component of a `SingleBlockLookup`.
|
||||||
|
#[derive(Derivative)]
|
||||||
|
#[derivative(Debug)]
|
||||||
|
pub struct BlockRequestState<E: EthSpec> {
|
||||||
|
#[derivative(Debug = "ignore")]
|
||||||
|
pub requested_block_root: Hash256,
|
||||||
|
pub state: SingleLookupRequestState<Arc<SignedBeaconBlock<E>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: EthSpec> BlockRequestState<E> {
|
||||||
|
pub fn new(block_root: Hash256) -> Self {
|
||||||
|
Self {
|
||||||
|
requested_block_root: block_root,
|
||||||
|
state: SingleLookupRequestState::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The state of the blob request component of a `SingleBlockLookup`.
|
/// The state of the blob request component of a `SingleBlockLookup`.
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Debug)]
|
#[derivative(Debug)]
|
||||||
@@ -307,19 +328,19 @@ impl<E: EthSpec> BlobRequestState<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The state of the block request component of a `SingleBlockLookup`.
|
/// The state of the custody request component of a `SingleBlockLookup`.
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Debug)]
|
#[derivative(Debug)]
|
||||||
pub struct BlockRequestState<E: EthSpec> {
|
pub struct CustodyRequestState<E: EthSpec> {
|
||||||
#[derivative(Debug = "ignore")]
|
#[derivative(Debug = "ignore")]
|
||||||
pub requested_block_root: Hash256,
|
pub block_root: Hash256,
|
||||||
pub state: SingleLookupRequestState<Arc<SignedBeaconBlock<E>>>,
|
pub state: SingleLookupRequestState<DataColumnSidecarList<E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: EthSpec> BlockRequestState<E> {
|
impl<E: EthSpec> CustodyRequestState<E> {
|
||||||
pub fn new(block_root: Hash256) -> Self {
|
pub fn new(block_root: Hash256) -> Self {
|
||||||
Self {
|
Self {
|
||||||
requested_block_root: block_root,
|
block_root,
|
||||||
state: SingleLookupRequestState::new(),
|
state: SingleLookupRequestState::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -723,6 +723,8 @@ impl TestRig {
|
|||||||
(ev.work_type() == beacon_processor::RPC_BLOBS).then_some(())
|
(ev.work_type() == beacon_processor::RPC_BLOBS).then_some(())
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|e| panic!("Expected blobs work event: {e}")),
|
.unwrap_or_else(|e| panic!("Expected blobs work event: {e}")),
|
||||||
|
// TODO(das): remove todo when adding tests for custody sync lookup
|
||||||
|
ResponseType::CustodyColumn => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use std::sync::Arc;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use types::blob_sidecar::FixedBlobSidecarList;
|
use types::blob_sidecar::FixedBlobSidecarList;
|
||||||
use types::{BlobSidecar, EthSpec, Hash256, SignedBeaconBlock};
|
use types::{BlobSidecar, DataColumnSidecarList, EthSpec, Hash256, SignedBeaconBlock};
|
||||||
|
|
||||||
mod requests;
|
mod requests;
|
||||||
|
|
||||||
@@ -447,16 +447,16 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
|||||||
lookup_id: SingleLookupId,
|
lookup_id: SingleLookupId,
|
||||||
peer_id: PeerId,
|
peer_id: PeerId,
|
||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
downloaded_block_expected_blobs: Option<usize>,
|
downloaded_block: Option<Arc<SignedBeaconBlock<T::EthSpec>>>,
|
||||||
) -> Result<LookupRequestResult, RpcRequestSendError> {
|
) -> Result<LookupRequestResult, RpcRequestSendError> {
|
||||||
let Some(expected_blobs) = downloaded_block_expected_blobs.or_else(|| {
|
let Some(block) = downloaded_block.or_else(|| {
|
||||||
// If the block is already being processed or fully validated, retrieve how many blobs
|
// If the block is already being processed or fully validated, retrieve how many blobs
|
||||||
// it expects. Consider any stage of the block. If the block root has been validated, we
|
// it expects. Consider any stage of the block. If the block root has been validated, we
|
||||||
// can assert that this is the correct value of `blob_kzg_commitments_count`.
|
// can assert that this is the correct value of `blob_kzg_commitments_count`.
|
||||||
match self.chain.get_block_process_status(&block_root) {
|
match self.chain.get_block_process_status(&block_root) {
|
||||||
BlockProcessStatus::Unknown => None,
|
BlockProcessStatus::Unknown => None,
|
||||||
BlockProcessStatus::NotValidated(block)
|
BlockProcessStatus::NotValidated(block)
|
||||||
| BlockProcessStatus::ExecutionValidated(block) => Some(block.num_expected_blobs()),
|
| BlockProcessStatus::ExecutionValidated(block) => Some(block.clone()),
|
||||||
}
|
}
|
||||||
}) else {
|
}) else {
|
||||||
// Wait to download the block before downloading blobs. Then we can be sure that the
|
// Wait to download the block before downloading blobs. Then we can be sure that the
|
||||||
@@ -473,6 +473,13 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
|||||||
// get dropped as completed.
|
// get dropped as completed.
|
||||||
return Ok(LookupRequestResult::Pending("waiting for block download"));
|
return Ok(LookupRequestResult::Pending("waiting for block download"));
|
||||||
};
|
};
|
||||||
|
let expected_blobs = block.num_expected_blobs();
|
||||||
|
let block_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch());
|
||||||
|
|
||||||
|
// Check if we are into peerdas
|
||||||
|
if !self.chain.should_fetch_blobs(block_epoch) {
|
||||||
|
return Ok(LookupRequestResult::NoRequestNeeded);
|
||||||
|
}
|
||||||
|
|
||||||
let imported_blob_indexes = self
|
let imported_blob_indexes = self
|
||||||
.chain
|
.chain
|
||||||
@@ -522,6 +529,76 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
|||||||
Ok(LookupRequestResult::RequestSent(req_id))
|
Ok(LookupRequestResult::RequestSent(req_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn custody_lookup_request(
|
||||||
|
&mut self,
|
||||||
|
lookup_id: SingleLookupId,
|
||||||
|
block_root: Hash256,
|
||||||
|
downloaded_block: Option<Arc<SignedBeaconBlock<T::EthSpec>>>,
|
||||||
|
) -> Result<LookupRequestResult, RpcRequestSendError> {
|
||||||
|
let Some(block) =
|
||||||
|
downloaded_block.or_else(|| match self.chain.get_block_process_status(&block_root) {
|
||||||
|
BlockProcessStatus::Unknown => None,
|
||||||
|
BlockProcessStatus::NotValidated(block)
|
||||||
|
| BlockProcessStatus::ExecutionValidated(block) => Some(block.clone()),
|
||||||
|
})
|
||||||
|
else {
|
||||||
|
// Wait to download the block before downloading columns. Then we can be sure that the
|
||||||
|
// block has data, so there's no need to do "blind" requests for all possible columns and
|
||||||
|
// latter handle the case where if the peer sent no columns, penalize.
|
||||||
|
// - if `downloaded_block_expected_blobs` is Some = block is downloading or processing.
|
||||||
|
// - if `num_expected_blobs` returns Some = block is processed.
|
||||||
|
return Ok(LookupRequestResult::Pending("waiting for block download"));
|
||||||
|
};
|
||||||
|
let expected_blobs = block.num_expected_blobs();
|
||||||
|
let block_epoch = block.slot().epoch(T::EthSpec::slots_per_epoch());
|
||||||
|
|
||||||
|
// Check if we are into peerdas
|
||||||
|
if !self.chain.should_fetch_custody_columns(block_epoch) {
|
||||||
|
return Ok(LookupRequestResult::NoRequestNeeded);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No data required for this block
|
||||||
|
if expected_blobs == 0 {
|
||||||
|
return Ok(LookupRequestResult::NoRequestNeeded);
|
||||||
|
}
|
||||||
|
|
||||||
|
let custody_indexes_imported = self
|
||||||
|
.chain
|
||||||
|
.data_availability_checker
|
||||||
|
.imported_custody_column_indexes(&block_root)
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
// TODO(das): figure out how to pass block.slot if we end up doing rotation
|
||||||
|
let custody_indexes_duty = self.network_globals().custody_columns(&self.chain.spec);
|
||||||
|
|
||||||
|
// Include only the blob indexes not yet imported (received through gossip)
|
||||||
|
let custody_indexes_to_fetch = custody_indexes_duty
|
||||||
|
.into_iter()
|
||||||
|
.filter(|index| !custody_indexes_imported.contains(index))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if custody_indexes_to_fetch.is_empty() {
|
||||||
|
// No indexes required, do not issue any request
|
||||||
|
return Ok(LookupRequestResult::NoRequestNeeded);
|
||||||
|
}
|
||||||
|
|
||||||
|
let req_id = self.next_id();
|
||||||
|
let id = SingleLookupReqId { lookup_id, req_id };
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
self.log,
|
||||||
|
"Starting custody columns request";
|
||||||
|
"block_root" => ?block_root,
|
||||||
|
"indices" => ?custody_indexes_to_fetch,
|
||||||
|
"id" => ?id
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO(das): Issue a custody request with `id` for the set of columns
|
||||||
|
// `custody_indexes_to_fetch` and block `block_root`.
|
||||||
|
|
||||||
|
Ok(LookupRequestResult::RequestSent(req_id))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_execution_engine_online(&self) -> bool {
|
pub fn is_execution_engine_online(&self) -> bool {
|
||||||
self.execution_engine_state == EngineState::Online
|
self.execution_engine_state == EngineState::Online
|
||||||
}
|
}
|
||||||
@@ -776,6 +853,26 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn send_custody_columns_for_processing(
|
||||||
|
&self,
|
||||||
|
id: Id,
|
||||||
|
block_root: Hash256,
|
||||||
|
_custody_columns: DataColumnSidecarList<T::EthSpec>,
|
||||||
|
_duration: Duration,
|
||||||
|
) -> Result<(), SendErrorProcessor> {
|
||||||
|
let _beacon_processor = self
|
||||||
|
.beacon_processor_if_enabled()
|
||||||
|
.ok_or(SendErrorProcessor::ProcessorNotAvailable)?;
|
||||||
|
|
||||||
|
debug!(self.log, "Sending custody columns for processing"; "block" => ?block_root, "id" => id);
|
||||||
|
|
||||||
|
// Lookup sync event safety: If `beacon_processor.send_rpc_custody_columns` returns Ok() sync
|
||||||
|
// must receive a single `SyncMessage::BlockComponentProcessed` event with this process type
|
||||||
|
//
|
||||||
|
// TODO(das): After merging processor import PR, actually send columns to beacon processor.
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn register_metrics(&self) {
|
pub(crate) fn register_metrics(&self) {
|
||||||
metrics::set_gauge_vec(
|
metrics::set_gauge_vec(
|
||||||
&metrics::SYNC_ACTIVE_NETWORK_REQUESTS,
|
&metrics::SYNC_ACTIVE_NETWORK_REQUESTS,
|
||||||
|
|||||||
Reference in New Issue
Block a user