mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 02:42:38 +00:00
Remove delayed lookups (#4992)
* initial rip out * fix unused imports * delete tests and fix lint * fix peers scoring for blobs
This commit is contained in:
@@ -3,8 +3,7 @@ use crate::sync::block_lookups::single_block_lookup::{
|
||||
LookupRequestError, LookupVerifyError, SingleBlockLookup, SingleLookupRequestState, State,
|
||||
};
|
||||
use crate::sync::block_lookups::{
|
||||
BlobRequestState, BlockLookups, BlockRequestState, PeerShouldHave,
|
||||
SINGLE_BLOCK_LOOKUP_MAX_ATTEMPTS,
|
||||
BlobRequestState, BlockLookups, BlockRequestState, PeerId, SINGLE_BLOCK_LOOKUP_MAX_ATTEMPTS,
|
||||
};
|
||||
use crate::sync::manager::{BlockProcessType, Id, SingleLookupReqId};
|
||||
use crate::sync::network_context::SyncNetworkContext;
|
||||
@@ -13,7 +12,6 @@ use beacon_chain::data_availability_checker::{AvailabilityView, ChildComponents}
|
||||
use beacon_chain::{get_block_root, BeaconChainTypes};
|
||||
use lighthouse_network::rpc::methods::BlobsByRootRequest;
|
||||
use lighthouse_network::rpc::BlocksByRootRequest;
|
||||
use lighthouse_network::PeerId;
|
||||
use rand::prelude::IteratorRandom;
|
||||
use ssz_types::VariableList;
|
||||
use std::ops::IndexMut;
|
||||
@@ -89,7 +87,7 @@ pub trait RequestState<L: Lookup, T: BeaconChainTypes> {
|
||||
/* Request building methods */
|
||||
|
||||
/// Construct a new request.
|
||||
fn build_request(&mut self) -> Result<(PeerShouldHave, Self::RequestType), LookupRequestError> {
|
||||
fn build_request(&mut self) -> Result<(PeerId, Self::RequestType), LookupRequestError> {
|
||||
// Verify and construct request.
|
||||
self.too_many_attempts()?;
|
||||
let peer = self.get_peer()?;
|
||||
@@ -121,7 +119,7 @@ pub trait RequestState<L: Lookup, T: BeaconChainTypes> {
|
||||
id,
|
||||
req_counter: self.get_state().req_counter,
|
||||
};
|
||||
Self::make_request(id, peer_id.to_peer_id(), request, cx)
|
||||
Self::make_request(id, peer_id, request, cx)
|
||||
}
|
||||
|
||||
/// Verify the current request has not exceeded the maximum number of attempts.
|
||||
@@ -140,26 +138,15 @@ pub trait RequestState<L: Lookup, T: BeaconChainTypes> {
|
||||
|
||||
/// Get the next peer to request. Draws from the set of peers we think should have both the
|
||||
/// block and blob first. If that fails, we draw from the set of peers that may have either.
|
||||
fn get_peer(&mut self) -> Result<PeerShouldHave, LookupRequestError> {
|
||||
fn get_peer(&mut self) -> Result<PeerId, LookupRequestError> {
|
||||
let request_state = self.get_state_mut();
|
||||
let available_peer_opt = request_state
|
||||
let peer_id = request_state
|
||||
.available_peers
|
||||
.iter()
|
||||
.choose(&mut rand::thread_rng())
|
||||
.copied()
|
||||
.map(PeerShouldHave::BlockAndBlobs);
|
||||
|
||||
let Some(peer_id) = available_peer_opt.or_else(|| {
|
||||
request_state
|
||||
.potential_peers
|
||||
.iter()
|
||||
.choose(&mut rand::thread_rng())
|
||||
.copied()
|
||||
.map(PeerShouldHave::Neither)
|
||||
}) else {
|
||||
return Err(LookupRequestError::NoPeers);
|
||||
};
|
||||
request_state.used_peers.insert(peer_id.to_peer_id());
|
||||
.ok_or(LookupRequestError::NoPeers)?;
|
||||
request_state.used_peers.insert(peer_id);
|
||||
Ok(peer_id)
|
||||
}
|
||||
|
||||
@@ -211,7 +198,7 @@ pub trait RequestState<L: Lookup, T: BeaconChainTypes> {
|
||||
&mut self,
|
||||
expected_block_root: Hash256,
|
||||
response: Option<Self::ResponseType>,
|
||||
peer_id: PeerShouldHave,
|
||||
peer_id: PeerId,
|
||||
) -> Result<Option<Self::VerifiedResponseType>, LookupVerifyError>;
|
||||
|
||||
/// A getter for the parent root of the response. Returns an `Option` because we won't know
|
||||
@@ -241,11 +228,6 @@ pub trait RequestState<L: Lookup, T: BeaconChainTypes> {
|
||||
cx: &SyncNetworkContext<T>,
|
||||
) -> Result<(), LookupRequestError>;
|
||||
|
||||
/// Remove the peer from the lookup if it is useless.
|
||||
fn remove_if_useless(&mut self, peer: &PeerId) {
|
||||
self.get_state_mut().remove_peer_if_useless(peer)
|
||||
}
|
||||
|
||||
/// Register a failure to process the block or blob.
|
||||
fn register_failure_downloading(&mut self) {
|
||||
self.get_state_mut().register_failure_downloading()
|
||||
@@ -290,7 +272,7 @@ impl<L: Lookup, T: BeaconChainTypes> RequestState<L, T> for BlockRequestState<L>
|
||||
&mut self,
|
||||
expected_block_root: Hash256,
|
||||
response: Option<Self::ResponseType>,
|
||||
peer_id: PeerShouldHave,
|
||||
peer_id: PeerId,
|
||||
) -> Result<Option<Arc<SignedBeaconBlock<T::EthSpec>>>, LookupVerifyError> {
|
||||
match response {
|
||||
Some(block) => {
|
||||
@@ -310,13 +292,8 @@ impl<L: Lookup, T: BeaconChainTypes> RequestState<L, T> for BlockRequestState<L>
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if peer_id.should_have_block() {
|
||||
self.state.register_failure_downloading();
|
||||
Err(LookupVerifyError::NoBlockReturned)
|
||||
} else {
|
||||
self.state.state = State::AwaitingDownload;
|
||||
Err(LookupVerifyError::BenignFailure)
|
||||
}
|
||||
self.state.register_failure_downloading();
|
||||
Err(LookupVerifyError::NoBlockReturned)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,7 +373,7 @@ impl<L: Lookup, T: BeaconChainTypes> RequestState<L, T> for BlobRequestState<L,
|
||||
&mut self,
|
||||
_expected_block_root: Hash256,
|
||||
blob: Option<Self::ResponseType>,
|
||||
peer_id: PeerShouldHave,
|
||||
peer_id: PeerId,
|
||||
) -> Result<Option<FixedBlobSidecarList<T::EthSpec>>, LookupVerifyError> {
|
||||
match blob {
|
||||
Some(blob) => {
|
||||
|
||||
@@ -7,9 +7,7 @@ use crate::metrics;
|
||||
use crate::network_beacon_processor::ChainSegmentProcessId;
|
||||
use crate::sync::block_lookups::common::LookupType;
|
||||
use crate::sync::block_lookups::parent_lookup::{ParentLookup, RequestError};
|
||||
use crate::sync::block_lookups::single_block_lookup::{
|
||||
CachedChild, LookupRequestError, LookupVerifyError,
|
||||
};
|
||||
use crate::sync::block_lookups::single_block_lookup::{CachedChild, LookupRequestError};
|
||||
use crate::sync::manager::{Id, SingleLookupReqId};
|
||||
use beacon_chain::block_verification_types::{AsBlock, RpcBlock};
|
||||
pub use beacon_chain::data_availability_checker::ChildComponents;
|
||||
@@ -30,11 +28,9 @@ pub use single_block_lookup::{BlobRequestState, BlockRequestState};
|
||||
use slog::{debug, error, trace, warn, Logger};
|
||||
use smallvec::SmallVec;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use store::Hash256;
|
||||
use strum::Display;
|
||||
use types::blob_sidecar::FixedBlobSidecarList;
|
||||
use types::Slot;
|
||||
|
||||
@@ -49,43 +45,6 @@ pub type DownloadedBlock<T> = (Hash256, RpcBlock<T>);
|
||||
const FAILED_CHAINS_CACHE_EXPIRY_SECONDS: u64 = 60;
|
||||
pub const SINGLE_BLOCK_LOOKUP_MAX_ATTEMPTS: u8 = 3;
|
||||
|
||||
/// This enum is used to track what a peer *should* be able to respond with based on
|
||||
/// other messages we've seen from this peer on the network. This is useful for peer scoring.
|
||||
/// We expect a peer tracked by the `BlockAndBlobs` variant to be able to respond to all
|
||||
/// components of a block. This peer has either sent an attestation for the requested block
|
||||
/// or has forwarded a block or blob that is a descendant of the requested block. An honest node
|
||||
/// should not attest unless it has all components of a block, and it should not forward
|
||||
/// messages if it does not have all components of the parent block. A peer tracked by the
|
||||
/// `Neither` variant has likely just sent us a block or blob over gossip, in which case we
|
||||
/// can't know whether the peer has all components of the block, and could be acting honestly
|
||||
/// by forwarding a message without any other block components.
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Display)]
|
||||
pub enum PeerShouldHave {
|
||||
BlockAndBlobs(PeerId),
|
||||
Neither(PeerId),
|
||||
}
|
||||
|
||||
impl PeerShouldHave {
|
||||
fn as_peer_id(&self) -> &PeerId {
|
||||
match self {
|
||||
PeerShouldHave::BlockAndBlobs(id) => id,
|
||||
PeerShouldHave::Neither(id) => id,
|
||||
}
|
||||
}
|
||||
fn to_peer_id(self) -> PeerId {
|
||||
match self {
|
||||
PeerShouldHave::BlockAndBlobs(id) => id,
|
||||
PeerShouldHave::Neither(id) => id,
|
||||
}
|
||||
}
|
||||
fn should_have_block(&self) -> bool {
|
||||
match self {
|
||||
PeerShouldHave::BlockAndBlobs(_) => true,
|
||||
PeerShouldHave::Neither(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BlockLookups<T: BeaconChainTypes> {
|
||||
/// Parent chain lookups being downloaded.
|
||||
parent_lookups: SmallVec<[ParentLookup<T>; 3]>,
|
||||
@@ -123,7 +82,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
pub fn search_block(
|
||||
&mut self,
|
||||
block_root: Hash256,
|
||||
peer_source: &[PeerShouldHave],
|
||||
peer_source: &[PeerId],
|
||||
cx: &mut SyncNetworkContext<T>,
|
||||
) {
|
||||
self.new_current_lookup(block_root, None, peer_source, cx)
|
||||
@@ -139,7 +98,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
&mut self,
|
||||
block_root: Hash256,
|
||||
child_components: ChildComponents<T::EthSpec>,
|
||||
peer_source: &[PeerShouldHave],
|
||||
peer_source: &[PeerId],
|
||||
cx: &mut SyncNetworkContext<T>,
|
||||
) {
|
||||
self.new_current_lookup(block_root, Some(child_components), peer_source, cx)
|
||||
@@ -180,7 +139,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
&mut self,
|
||||
block_root: Hash256,
|
||||
child_components: Option<ChildComponents<T::EthSpec>>,
|
||||
peers: &[PeerShouldHave],
|
||||
peers: &[PeerId],
|
||||
cx: &mut SyncNetworkContext<T>,
|
||||
) {
|
||||
// Do not re-request a block that is already being requested
|
||||
@@ -248,9 +207,6 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
peer_id: PeerId,
|
||||
cx: &mut SyncNetworkContext<T>,
|
||||
) {
|
||||
// Gossip blocks or blobs shouldn't be propagated if parents are unavailable.
|
||||
let peer_source = PeerShouldHave::BlockAndBlobs(peer_id);
|
||||
|
||||
// If this block or it's parent is part of a known failed chain, ignore it.
|
||||
if self.failed_chains.contains(&parent_root) || self.failed_chains.contains(&block_root) {
|
||||
debug!(self.log, "Block is from a past failed chain. Dropping";
|
||||
@@ -263,7 +219,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
if let Some(parent_lookup) = self.parent_lookups.iter_mut().find(|parent_req| {
|
||||
parent_req.contains_block(&block_root) || parent_req.is_for_block(block_root)
|
||||
}) {
|
||||
parent_lookup.add_peer(peer_source);
|
||||
parent_lookup.add_peer(peer_id);
|
||||
// we are already searching for this block, ignore it
|
||||
return;
|
||||
}
|
||||
@@ -279,7 +235,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
let parent_lookup = ParentLookup::new(
|
||||
block_root,
|
||||
parent_root,
|
||||
peer_source,
|
||||
peer_id,
|
||||
self.da_checker.clone(),
|
||||
cx,
|
||||
);
|
||||
@@ -398,14 +354,8 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
"response_type" => ?response_type,
|
||||
"error" => ?e
|
||||
);
|
||||
if matches!(e, LookupVerifyError::BenignFailure) {
|
||||
request_state
|
||||
.get_state_mut()
|
||||
.remove_peer_if_useless(&peer_id);
|
||||
} else {
|
||||
let msg = e.into();
|
||||
cx.report_peer(peer_id, PeerAction::LowToleranceError, msg);
|
||||
};
|
||||
let msg = e.into();
|
||||
cx.report_peer(peer_id, PeerAction::LowToleranceError, msg);
|
||||
|
||||
request_state.register_failure_downloading();
|
||||
lookup.request_block_and_blobs(cx)?;
|
||||
@@ -456,7 +406,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
// we should penalize the blobs peer because they did not provide all blobs on the
|
||||
// initial request.
|
||||
if lookup.both_components_downloaded() {
|
||||
lookup.penalize_blob_peer(false, cx);
|
||||
lookup.penalize_blob_peer(cx);
|
||||
lookup
|
||||
.blob_request_state
|
||||
.state
|
||||
@@ -619,15 +569,6 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
"bbroot_failed_chains",
|
||||
);
|
||||
}
|
||||
ParentVerifyError::BenignFailure => {
|
||||
trace!(
|
||||
self.log,
|
||||
"Requested peer could not respond to block request, requesting a new peer";
|
||||
);
|
||||
let request_state = R::request_state_mut(&mut parent_lookup.current_parent_request);
|
||||
request_state.remove_if_useless(&peer_id);
|
||||
parent_lookup.request_parent(cx)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -846,7 +787,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
|
||||
request_state.get_state_mut().component_processed = true;
|
||||
if lookup.both_components_processed() {
|
||||
lookup.penalize_blob_peer(false, cx);
|
||||
lookup.penalize_blob_peer(cx);
|
||||
|
||||
// Try it again if possible.
|
||||
lookup
|
||||
@@ -864,7 +805,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
&mut self,
|
||||
cx: &mut SyncNetworkContext<T>,
|
||||
mut lookup: SingleBlockLookup<Current, T>,
|
||||
peer_id: PeerShouldHave,
|
||||
peer_id: PeerId,
|
||||
e: BlockError<T::EthSpec>,
|
||||
) -> Result<Option<SingleBlockLookup<Current, T>>, LookupRequestError> {
|
||||
let root = lookup.block_root();
|
||||
@@ -884,7 +825,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
let parent_root = block.parent_root();
|
||||
lookup.add_child_components(block.into());
|
||||
lookup.request_block_and_blobs(cx)?;
|
||||
self.search_parent(slot, root, parent_root, peer_id.to_peer_id(), cx);
|
||||
self.search_parent(slot, root, parent_root, peer_id, cx);
|
||||
}
|
||||
ref e @ BlockError::ExecutionPayloadError(ref epe) if !epe.penalize_peer() => {
|
||||
// These errors indicate that the execution layer is offline
|
||||
@@ -920,7 +861,7 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
warn!(self.log, "Peer sent invalid block in single block lookup"; "root" => %root, "error" => ?other, "peer_id" => %peer_id);
|
||||
if let Ok(block_peer) = lookup.block_request_state.state.processing_peer() {
|
||||
cx.report_peer(
|
||||
block_peer.to_peer_id(),
|
||||
block_peer,
|
||||
PeerAction::MidToleranceError,
|
||||
"single_block_failure",
|
||||
);
|
||||
@@ -1141,13 +1082,9 @@ impl<T: BeaconChainTypes> BlockLookups<T> {
|
||||
let Ok(block_peer_id) = parent_lookup.block_processing_peer() else {
|
||||
return;
|
||||
};
|
||||
let block_peer_id = block_peer_id.to_peer_id();
|
||||
|
||||
// We may not have a blob peer, if there were no blobs required for this block.
|
||||
let blob_peer_id = parent_lookup
|
||||
.blob_processing_peer()
|
||||
.ok()
|
||||
.map(PeerShouldHave::to_peer_id);
|
||||
let blob_peer_id = parent_lookup.blob_processing_peer().ok();
|
||||
|
||||
// all else we consider the chain a failure and downvote the peer that sent
|
||||
// us the last block
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::single_block_lookup::{LookupRequestError, LookupVerifyError, SingleBlockLookup};
|
||||
use super::{DownloadedBlock, PeerShouldHave};
|
||||
use super::{DownloadedBlock, PeerId};
|
||||
use crate::sync::block_lookups::common::Parent;
|
||||
use crate::sync::block_lookups::common::RequestState;
|
||||
use crate::sync::{manager::SLOT_IMPORT_TOLERANCE, network_context::SyncNetworkContext};
|
||||
@@ -8,7 +8,6 @@ use beacon_chain::block_verification_types::RpcBlock;
|
||||
use beacon_chain::data_availability_checker::{ChildComponents, DataAvailabilityChecker};
|
||||
use beacon_chain::BeaconChainTypes;
|
||||
use itertools::Itertools;
|
||||
use lighthouse_network::PeerId;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::Arc;
|
||||
use store::Hash256;
|
||||
@@ -41,7 +40,6 @@ pub enum ParentVerifyError {
|
||||
ExtraBlobsReturned,
|
||||
InvalidIndex(u64),
|
||||
PreviousFailure { parent_root: Hash256 },
|
||||
BenignFailure,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
@@ -61,7 +59,7 @@ impl<T: BeaconChainTypes> ParentLookup<T> {
|
||||
pub fn new(
|
||||
block_root: Hash256,
|
||||
parent_root: Hash256,
|
||||
peer_id: PeerShouldHave,
|
||||
peer_id: PeerId,
|
||||
da_checker: Arc<DataAvailabilityChecker<T>>,
|
||||
cx: &mut SyncNetworkContext<T>,
|
||||
) -> Self {
|
||||
@@ -126,14 +124,14 @@ impl<T: BeaconChainTypes> ParentLookup<T> {
|
||||
.update_requested_parent_block(next_parent)
|
||||
}
|
||||
|
||||
pub fn block_processing_peer(&self) -> Result<PeerShouldHave, ()> {
|
||||
pub fn block_processing_peer(&self) -> Result<PeerId, ()> {
|
||||
self.current_parent_request
|
||||
.block_request_state
|
||||
.state
|
||||
.processing_peer()
|
||||
}
|
||||
|
||||
pub fn blob_processing_peer(&self) -> Result<PeerShouldHave, ()> {
|
||||
pub fn blob_processing_peer(&self) -> Result<PeerId, ()> {
|
||||
self.current_parent_request
|
||||
.blob_request_state
|
||||
.state
|
||||
@@ -211,12 +209,12 @@ impl<T: BeaconChainTypes> ParentLookup<T> {
|
||||
Ok(root_and_verified)
|
||||
}
|
||||
|
||||
pub fn add_peer(&mut self, peer: PeerShouldHave) {
|
||||
pub fn add_peer(&mut self, peer: PeerId) {
|
||||
self.current_parent_request.add_peer(peer)
|
||||
}
|
||||
|
||||
/// Adds a list of peers to the parent request.
|
||||
pub fn add_peers(&mut self, peers: &[PeerShouldHave]) {
|
||||
pub fn add_peers(&mut self, peers: &[PeerId]) {
|
||||
self.current_parent_request.add_peers(peers)
|
||||
}
|
||||
|
||||
@@ -248,7 +246,6 @@ impl From<LookupVerifyError> for ParentVerifyError {
|
||||
E::ExtraBlobsReturned => ParentVerifyError::ExtraBlobsReturned,
|
||||
E::InvalidIndex(index) => ParentVerifyError::InvalidIndex(index),
|
||||
E::NotEnoughBlobsReturned => ParentVerifyError::NotEnoughBlobsReturned,
|
||||
E::BenignFailure => ParentVerifyError::BenignFailure,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::PeerShouldHave;
|
||||
use super::PeerId;
|
||||
use crate::sync::block_lookups::common::{Lookup, RequestState};
|
||||
use crate::sync::block_lookups::Id;
|
||||
use crate::sync::network_context::SyncNetworkContext;
|
||||
@@ -8,7 +8,7 @@ use beacon_chain::data_availability_checker::{
|
||||
};
|
||||
use beacon_chain::data_availability_checker::{AvailabilityView, ChildComponents};
|
||||
use beacon_chain::BeaconChainTypes;
|
||||
use lighthouse_network::{PeerAction, PeerId};
|
||||
use lighthouse_network::PeerAction;
|
||||
use slog::{trace, Logger};
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Debug;
|
||||
@@ -22,8 +22,8 @@ use types::EthSpec;
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum State {
|
||||
AwaitingDownload,
|
||||
Downloading { peer_id: PeerShouldHave },
|
||||
Processing { peer_id: PeerShouldHave },
|
||||
Downloading { peer_id: PeerId },
|
||||
Processing { peer_id: PeerId },
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, IntoStaticStr)]
|
||||
@@ -35,10 +35,6 @@ pub enum LookupVerifyError {
|
||||
ExtraBlobsReturned,
|
||||
NotEnoughBlobsReturned,
|
||||
InvalidIndex(u64),
|
||||
/// We don't have enough information to know
|
||||
/// whether the peer is at fault or simply missed
|
||||
/// what was requested on gossip.
|
||||
BenignFailure,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, IntoStaticStr)]
|
||||
@@ -66,7 +62,7 @@ impl<L: Lookup, T: BeaconChainTypes> SingleBlockLookup<L, T> {
|
||||
pub fn new(
|
||||
requested_block_root: Hash256,
|
||||
child_components: Option<ChildComponents<T::EthSpec>>,
|
||||
peers: &[PeerShouldHave],
|
||||
peers: &[PeerId],
|
||||
da_checker: Arc<DataAvailabilityChecker<T>>,
|
||||
id: Id,
|
||||
) -> Self {
|
||||
@@ -191,21 +187,13 @@ impl<L: Lookup, T: BeaconChainTypes> SingleBlockLookup<L, T> {
|
||||
}
|
||||
|
||||
/// Add all given peers to both block and blob request states.
|
||||
pub fn add_peer(&mut self, peer: PeerShouldHave) {
|
||||
match peer {
|
||||
PeerShouldHave::BlockAndBlobs(peer_id) => {
|
||||
self.block_request_state.state.add_peer(&peer_id);
|
||||
self.blob_request_state.state.add_peer(&peer_id);
|
||||
}
|
||||
PeerShouldHave::Neither(peer_id) => {
|
||||
self.block_request_state.state.add_potential_peer(&peer_id);
|
||||
self.blob_request_state.state.add_potential_peer(&peer_id);
|
||||
}
|
||||
}
|
||||
pub fn add_peer(&mut self, peer_id: PeerId) {
|
||||
self.block_request_state.state.add_peer(&peer_id);
|
||||
self.blob_request_state.state.add_peer(&peer_id);
|
||||
}
|
||||
|
||||
/// Add all given peers to both block and blob request states.
|
||||
pub fn add_peers(&mut self, peers: &[PeerShouldHave]) {
|
||||
pub fn add_peers(&mut self, peers: &[PeerId]) {
|
||||
for peer in peers {
|
||||
self.add_peer(*peer);
|
||||
}
|
||||
@@ -293,38 +281,31 @@ impl<L: Lookup, T: BeaconChainTypes> SingleBlockLookup<L, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Penalizes a blob peer if it should have blobs but didn't return them to us. Does not penalize
|
||||
/// a peer who we request blobs from based on seeing a block or blobs over gossip. This may
|
||||
/// have been a benign failure.
|
||||
pub fn penalize_blob_peer(&mut self, penalize_always: bool, cx: &SyncNetworkContext<T>) {
|
||||
/// Penalizes a blob peer if it should have blobs but didn't return them to us.
|
||||
pub fn penalize_blob_peer(&mut self, cx: &SyncNetworkContext<T>) {
|
||||
if let Ok(blob_peer) = self.blob_request_state.state.processing_peer() {
|
||||
if penalize_always || matches!(blob_peer, PeerShouldHave::BlockAndBlobs(_)) {
|
||||
cx.report_peer(
|
||||
blob_peer.to_peer_id(),
|
||||
PeerAction::MidToleranceError,
|
||||
"single_blob_failure",
|
||||
);
|
||||
}
|
||||
self.blob_request_state
|
||||
.state
|
||||
.remove_peer_if_useless(blob_peer.as_peer_id());
|
||||
cx.report_peer(
|
||||
blob_peer,
|
||||
PeerAction::MidToleranceError,
|
||||
"single_blob_failure",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// This failure occurs on download, so register a failure downloading, penalize the peer if
|
||||
/// necessary and clear the blob cache.
|
||||
/// This failure occurs on download, so register a failure downloading, penalize the peer
|
||||
/// and clear the blob cache.
|
||||
pub fn handle_consistency_failure(&mut self, cx: &SyncNetworkContext<T>) {
|
||||
self.penalize_blob_peer(false, cx);
|
||||
self.penalize_blob_peer(cx);
|
||||
if let Some(cached_child) = self.child_components.as_mut() {
|
||||
cached_child.clear_blobs();
|
||||
}
|
||||
self.blob_request_state.state.register_failure_downloading()
|
||||
}
|
||||
|
||||
/// This failure occurs after processing, so register a failure processing, penalize the peer if
|
||||
/// necessary and clear the blob cache.
|
||||
/// This failure occurs after processing, so register a failure processing, penalize the peer
|
||||
/// and clear the blob cache.
|
||||
pub fn handle_availability_check_failure(&mut self, cx: &SyncNetworkContext<T>) {
|
||||
self.penalize_blob_peer(true, cx);
|
||||
self.penalize_blob_peer(cx);
|
||||
if let Some(cached_child) = self.child_components.as_mut() {
|
||||
cached_child.clear_blobs();
|
||||
}
|
||||
@@ -345,7 +326,7 @@ pub struct BlobRequestState<L: Lookup, T: EthSpec> {
|
||||
}
|
||||
|
||||
impl<L: Lookup, E: EthSpec> BlobRequestState<L, E> {
|
||||
pub fn new(block_root: Hash256, peer_source: &[PeerShouldHave], is_deneb: bool) -> Self {
|
||||
pub fn new(block_root: Hash256, peer_source: &[PeerId], is_deneb: bool) -> Self {
|
||||
let default_ids = MissingBlobs::new_without_block(block_root, is_deneb);
|
||||
Self {
|
||||
requested_ids: default_ids,
|
||||
@@ -364,7 +345,7 @@ pub struct BlockRequestState<L: Lookup> {
|
||||
}
|
||||
|
||||
impl<L: Lookup> BlockRequestState<L> {
|
||||
pub fn new(block_root: Hash256, peers: &[PeerShouldHave]) -> Self {
|
||||
pub fn new(block_root: Hash256, peers: &[PeerId]) -> Self {
|
||||
Self {
|
||||
requested_block_root: block_root,
|
||||
state: SingleLookupRequestState::new(peers),
|
||||
@@ -396,8 +377,6 @@ pub struct SingleLookupRequestState {
|
||||
pub state: State,
|
||||
/// Peers that should have this block or blob.
|
||||
pub available_peers: HashSet<PeerId>,
|
||||
/// Peers that mar or may not have this block or blob.
|
||||
pub potential_peers: HashSet<PeerId>,
|
||||
/// Peers from which we have requested this block.
|
||||
pub used_peers: HashSet<PeerId>,
|
||||
/// How many times have we attempted to process this block or blob.
|
||||
@@ -417,24 +396,15 @@ pub struct SingleLookupRequestState {
|
||||
}
|
||||
|
||||
impl SingleLookupRequestState {
|
||||
pub fn new(peers: &[PeerShouldHave]) -> Self {
|
||||
pub fn new(peers: &[PeerId]) -> Self {
|
||||
let mut available_peers = HashSet::default();
|
||||
let mut potential_peers = HashSet::default();
|
||||
for peer in peers {
|
||||
match peer {
|
||||
PeerShouldHave::BlockAndBlobs(peer_id) => {
|
||||
available_peers.insert(*peer_id);
|
||||
}
|
||||
PeerShouldHave::Neither(peer_id) => {
|
||||
potential_peers.insert(*peer_id);
|
||||
}
|
||||
}
|
||||
for peer in peers.iter().copied() {
|
||||
available_peers.insert(peer);
|
||||
}
|
||||
|
||||
Self {
|
||||
state: State::AwaitingDownload,
|
||||
available_peers,
|
||||
potential_peers,
|
||||
used_peers: HashSet::default(),
|
||||
failed_processing: 0,
|
||||
failed_downloading: 0,
|
||||
@@ -462,25 +432,16 @@ impl SingleLookupRequestState {
|
||||
self.failed_processing + self.failed_downloading
|
||||
}
|
||||
|
||||
/// This method should be used for peers wrapped in `PeerShouldHave::BlockAndBlobs`.
|
||||
/// This method should be used for peers wrapped in `PeerId::BlockAndBlobs`.
|
||||
pub fn add_peer(&mut self, peer_id: &PeerId) {
|
||||
self.potential_peers.remove(peer_id);
|
||||
self.available_peers.insert(*peer_id);
|
||||
}
|
||||
|
||||
/// This method should be used for peers wrapped in `PeerShouldHave::Neither`.
|
||||
pub fn add_potential_peer(&mut self, peer_id: &PeerId) {
|
||||
if !self.available_peers.contains(peer_id) {
|
||||
self.potential_peers.insert(*peer_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// If a peer disconnects, this request could be failed. If so, an error is returned
|
||||
pub fn check_peer_disconnected(&mut self, dc_peer_id: &PeerId) -> Result<(), ()> {
|
||||
self.available_peers.remove(dc_peer_id);
|
||||
self.potential_peers.remove(dc_peer_id);
|
||||
if let State::Downloading { peer_id } = &self.state {
|
||||
if peer_id.as_peer_id() == dc_peer_id {
|
||||
if peer_id == dc_peer_id {
|
||||
// Peer disconnected before providing a block
|
||||
self.register_failure_downloading();
|
||||
return Err(());
|
||||
@@ -491,21 +452,13 @@ impl SingleLookupRequestState {
|
||||
|
||||
/// Returns the id peer we downloaded from if we have downloaded a verified block, otherwise
|
||||
/// returns an error.
|
||||
pub fn processing_peer(&self) -> Result<PeerShouldHave, ()> {
|
||||
pub fn processing_peer(&self) -> Result<PeerId, ()> {
|
||||
if let State::Processing { peer_id } = &self.state {
|
||||
Ok(*peer_id)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the given peer from the set of potential peers, so long as there is at least one
|
||||
/// other potential peer or we have any available peers.
|
||||
pub fn remove_peer_if_useless(&mut self, peer_id: &PeerId) {
|
||||
if !self.available_peers.is_empty() || self.potential_peers.len() > 1 {
|
||||
self.potential_peers.remove(peer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: Lookup, T: BeaconChainTypes> slog::Value for SingleBlockLookup<L, T> {
|
||||
@@ -609,7 +562,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_happy_path() {
|
||||
let peer_id = PeerShouldHave::BlockAndBlobs(PeerId::random());
|
||||
let peer_id = PeerId::random();
|
||||
let block = rand_block();
|
||||
let spec = E::default_spec();
|
||||
let slot_clock = TestingSlotClock::new(
|
||||
@@ -649,7 +602,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_block_lookup_failures() {
|
||||
let peer_id = PeerShouldHave::BlockAndBlobs(PeerId::random());
|
||||
let peer_id = PeerId::random();
|
||||
let block = rand_block();
|
||||
let spec = E::default_spec();
|
||||
let slot_clock = TestingSlotClock::new(
|
||||
|
||||
@@ -233,11 +233,7 @@ fn test_single_block_lookup_happy_path() {
|
||||
let peer_id = PeerId::random();
|
||||
let block_root = block.canonical_root();
|
||||
// Trigger the request
|
||||
bl.search_block(
|
||||
block_root,
|
||||
&[PeerShouldHave::BlockAndBlobs(peer_id)],
|
||||
&mut cx,
|
||||
);
|
||||
bl.search_block(block_root, &[peer_id], &mut cx);
|
||||
let id = rig.expect_lookup_request(response_type);
|
||||
// If we're in deneb, a blob request should have been triggered as well,
|
||||
// we don't require a response because we're generateing 0-blob blocks in this test.
|
||||
@@ -285,11 +281,7 @@ fn test_single_block_lookup_empty_response() {
|
||||
let peer_id = PeerId::random();
|
||||
|
||||
// Trigger the request
|
||||
bl.search_block(
|
||||
block_hash,
|
||||
&[PeerShouldHave::BlockAndBlobs(peer_id)],
|
||||
&mut cx,
|
||||
);
|
||||
bl.search_block(block_hash, &[peer_id], &mut cx);
|
||||
let id = rig.expect_lookup_request(response_type);
|
||||
// If we're in deneb, a blob request should have been triggered as well,
|
||||
// we don't require a response because we're generateing 0-blob blocks in this test.
|
||||
@@ -317,11 +309,7 @@ fn test_single_block_lookup_wrong_response() {
|
||||
let peer_id = PeerId::random();
|
||||
|
||||
// Trigger the request
|
||||
bl.search_block(
|
||||
block_hash,
|
||||
&[PeerShouldHave::BlockAndBlobs(peer_id)],
|
||||
&mut cx,
|
||||
);
|
||||
bl.search_block(block_hash, &[peer_id], &mut cx);
|
||||
let id = rig.expect_lookup_request(response_type);
|
||||
// If we're in deneb, a blob request should have been triggered as well,
|
||||
// we don't require a response because we're generateing 0-blob blocks in this test.
|
||||
@@ -359,11 +347,7 @@ fn test_single_block_lookup_failure() {
|
||||
let peer_id = PeerId::random();
|
||||
|
||||
// Trigger the request
|
||||
bl.search_block(
|
||||
block_hash,
|
||||
&[PeerShouldHave::BlockAndBlobs(peer_id)],
|
||||
&mut cx,
|
||||
);
|
||||
bl.search_block(block_hash, &[peer_id], &mut cx);
|
||||
let id = rig.expect_lookup_request(response_type);
|
||||
// If we're in deneb, a blob request should have been triggered as well,
|
||||
// we don't require a response because we're generateing 0-blob blocks in this test.
|
||||
@@ -395,11 +379,7 @@ fn test_single_block_lookup_becomes_parent_request() {
|
||||
let peer_id = PeerId::random();
|
||||
|
||||
// Trigger the request
|
||||
bl.search_block(
|
||||
block.canonical_root(),
|
||||
&[PeerShouldHave::BlockAndBlobs(peer_id)],
|
||||
&mut cx,
|
||||
);
|
||||
bl.search_block(block.canonical_root(), &[peer_id], &mut cx);
|
||||
let id = rig.expect_lookup_request(response_type);
|
||||
// If we're in deneb, a blob request should have been triggered as well,
|
||||
// we don't require a response because we're generateing 0-blob blocks in this test.
|
||||
@@ -981,11 +961,7 @@ fn test_single_block_lookup_ignored_response() {
|
||||
let peer_id = PeerId::random();
|
||||
|
||||
// Trigger the request
|
||||
bl.search_block(
|
||||
block.canonical_root(),
|
||||
&[PeerShouldHave::BlockAndBlobs(peer_id)],
|
||||
&mut cx,
|
||||
);
|
||||
bl.search_block(block.canonical_root(), &[peer_id], &mut cx);
|
||||
let id = rig.expect_lookup_request(response_type);
|
||||
// If we're in deneb, a blob request should have been triggered as well,
|
||||
// we don't require a response because we're generateing 0-blob blocks in this test.
|
||||
@@ -1205,7 +1181,6 @@ mod deneb_only {
|
||||
AttestationUnknownBlock,
|
||||
GossipUnknownParentBlock,
|
||||
GossipUnknownParentBlob,
|
||||
GossipUnknownBlockOrBlob,
|
||||
}
|
||||
|
||||
impl DenebTester {
|
||||
@@ -1234,11 +1209,7 @@ mod deneb_only {
|
||||
let (block_req_id, blob_req_id, parent_block_req_id, parent_blob_req_id) =
|
||||
match request_trigger {
|
||||
RequestTrigger::AttestationUnknownBlock => {
|
||||
bl.search_block(
|
||||
block_root,
|
||||
&[PeerShouldHave::BlockAndBlobs(peer_id)],
|
||||
&mut cx,
|
||||
);
|
||||
bl.search_block(block_root, &[peer_id], &mut cx);
|
||||
let block_req_id = rig.expect_lookup_request(ResponseType::Block);
|
||||
let blob_req_id = rig.expect_lookup_request(ResponseType::Blob);
|
||||
(Some(block_req_id), Some(blob_req_id), None, None)
|
||||
@@ -1261,7 +1232,7 @@ mod deneb_only {
|
||||
bl.search_child_block(
|
||||
child_root,
|
||||
ChildComponents::new(child_root, Some(child_block), None),
|
||||
&[PeerShouldHave::Neither(peer_id)],
|
||||
&[peer_id],
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
@@ -1299,7 +1270,7 @@ mod deneb_only {
|
||||
bl.search_child_block(
|
||||
child_root,
|
||||
ChildComponents::new(child_root, None, Some(blobs)),
|
||||
&[PeerShouldHave::Neither(peer_id)],
|
||||
&[peer_id],
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
@@ -1316,12 +1287,6 @@ mod deneb_only {
|
||||
Some(parent_blob_req_id),
|
||||
)
|
||||
}
|
||||
RequestTrigger::GossipUnknownBlockOrBlob => {
|
||||
bl.search_block(block_root, &[PeerShouldHave::Neither(peer_id)], &mut cx);
|
||||
let block_req_id = rig.expect_lookup_request(ResponseType::Block);
|
||||
let blob_req_id = rig.expect_lookup_request(ResponseType::Blob);
|
||||
(Some(block_req_id), Some(blob_req_id), None, None)
|
||||
}
|
||||
};
|
||||
|
||||
Some(Self {
|
||||
@@ -1838,186 +1803,6 @@ mod deneb_only {
|
||||
.block_response_triggering_process();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_block_and_blob_lookup_block_returned_first_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.block_response_triggering_process()
|
||||
.blobs_response()
|
||||
.blobs_response_was_valid()
|
||||
.block_imported();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_block_and_blob_lookup_blobs_returned_first_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.blobs_response()
|
||||
.blobs_response_was_valid()
|
||||
.block_response_triggering_process()
|
||||
.block_imported();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_block_and_blob_lookup_empty_response_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.empty_block_response()
|
||||
.expect_block_request()
|
||||
.expect_no_penalty()
|
||||
.expect_no_blobs_request()
|
||||
.empty_blobs_response()
|
||||
.expect_no_penalty()
|
||||
.expect_no_block_request()
|
||||
.expect_no_blobs_request()
|
||||
.block_response_triggering_process()
|
||||
.missing_components_from_block_request();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_block_response_then_empty_blob_response_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.block_response_triggering_process()
|
||||
.missing_components_from_block_request()
|
||||
.empty_blobs_response()
|
||||
.missing_components_from_blob_request()
|
||||
.expect_blobs_request()
|
||||
.expect_no_penalty()
|
||||
.expect_no_block_request();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_blob_response_then_empty_block_response_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.blobs_response()
|
||||
.blobs_response_was_valid()
|
||||
.expect_no_penalty()
|
||||
.expect_no_block_request()
|
||||
.expect_no_blobs_request()
|
||||
.missing_components_from_blob_request()
|
||||
.empty_block_response()
|
||||
.expect_block_request()
|
||||
.expect_no_penalty()
|
||||
.expect_no_blobs_request();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_invalid_block_response_then_blob_response_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.block_response_triggering_process()
|
||||
.invalid_block_processed()
|
||||
.expect_penalty()
|
||||
.expect_block_request()
|
||||
.expect_no_blobs_request()
|
||||
.blobs_response()
|
||||
.missing_components_from_blob_request()
|
||||
.expect_no_penalty()
|
||||
.expect_no_block_request()
|
||||
.expect_no_block_request();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_block_response_then_invalid_blob_response_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.block_response_triggering_process()
|
||||
.missing_components_from_block_request()
|
||||
.blobs_response()
|
||||
.invalid_blob_processed()
|
||||
.expect_penalty()
|
||||
.expect_blobs_request()
|
||||
.expect_no_block_request();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_block_response_then_too_few_blobs_response_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.block_response_triggering_process()
|
||||
.missing_components_from_block_request()
|
||||
.invalidate_blobs_too_few()
|
||||
.blobs_response()
|
||||
.missing_components_from_blob_request()
|
||||
.expect_blobs_request()
|
||||
.expect_no_penalty()
|
||||
.expect_no_block_request();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_block_response_then_too_many_blobs_response_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.block_response_triggering_process()
|
||||
.invalidate_blobs_too_many()
|
||||
.blobs_response()
|
||||
.expect_penalty()
|
||||
.expect_blobs_request()
|
||||
.expect_no_block_request();
|
||||
}
|
||||
#[test]
|
||||
fn too_few_blobs_response_then_block_response_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.invalidate_blobs_too_few()
|
||||
.blobs_response()
|
||||
.blobs_response_was_valid()
|
||||
.missing_components_from_blob_request()
|
||||
.expect_no_penalty()
|
||||
.expect_no_blobs_request()
|
||||
.expect_no_block_request()
|
||||
.block_response_triggering_process()
|
||||
.missing_components_from_block_request()
|
||||
.expect_blobs_request();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn too_many_blobs_response_then_block_response_gossip() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownBlockOrBlob) else {
|
||||
return;
|
||||
};
|
||||
|
||||
tester
|
||||
.invalidate_blobs_too_many()
|
||||
.blobs_response()
|
||||
.expect_penalty()
|
||||
.expect_blobs_request()
|
||||
.expect_no_block_request()
|
||||
.block_response_triggering_process();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parent_block_unknown_parent() {
|
||||
let Some(tester) = DenebTester::new(RequestTrigger::GossipUnknownParentBlock) else {
|
||||
|
||||
Reference in New Issue
Block a user