## Issue Addressed #1856 ## Proposed Changes - For clarity, the router's processor now only decides if a peer is compatible and it disconnects it or sends it to sync accordingly. No logic here regarding how useful is the peer. - Update peer_sync_info's rules - Add an `IrrelevantPeer` sync status to account for incompatible peers (maybe this should be "IncompatiblePeer" now that I think about it?) this state is update upon receiving an internal goodbye in the peer manager - Misc code cleanups - Reduce the need to create `StatusMessage`s (and thus, `Arc` accesses ) - Add missing calls to update the global sync state The overall effect should be: - More peers recognized as Behind, and less as Unknown - Peers identified as incompatible
88 lines
3.7 KiB
Rust
88 lines
3.7 KiB
Rust
use super::manager::SLOT_IMPORT_TOLERANCE;
|
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
|
use eth2_libp2p::{PeerSyncStatus, SyncInfo};
|
|
use std::cmp::Ordering;
|
|
|
|
/// The type of peer relative to our current state.
|
|
pub enum PeerSyncType {
|
|
/// The peer is on our chain and is fully synced with respect to our chain.
|
|
FullySynced,
|
|
/// The peer has a greater knowledge of the chain than us that warrants a full sync.
|
|
Advanced,
|
|
/// A peer is behind in the sync and not useful to us for downloading blocks.
|
|
Behind,
|
|
}
|
|
|
|
impl PeerSyncType {
|
|
pub fn as_sync_status(&self, info: &SyncInfo) -> PeerSyncStatus {
|
|
match self {
|
|
PeerSyncType::FullySynced => PeerSyncStatus::Synced { info: info.clone() },
|
|
PeerSyncType::Behind => PeerSyncStatus::Behind { info: info.clone() },
|
|
PeerSyncType::Advanced => PeerSyncStatus::Advanced { info: info.clone() },
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn remote_sync_type<T: BeaconChainTypes>(
|
|
local: &SyncInfo,
|
|
remote: &SyncInfo,
|
|
chain: &BeaconChain<T>,
|
|
) -> PeerSyncType {
|
|
// auxiliary variables for clarity: Inclusive boundaries of the range in which we consider a peer's
|
|
// head "near" ours.
|
|
let near_range_start = local.head_slot - SLOT_IMPORT_TOLERANCE as u64;
|
|
let near_range_end = local.head_slot + SLOT_IMPORT_TOLERANCE as u64;
|
|
|
|
match remote.finalized_epoch.cmp(&local.finalized_epoch) {
|
|
Ordering::Less => {
|
|
// The node has a lower finalized epoch, their chain is not useful to us. There are two
|
|
// cases where a node can have a lower finalized epoch:
|
|
//
|
|
// ## The node is on the same chain
|
|
//
|
|
// If a node is on the same chain but has a lower finalized epoch, their head must be
|
|
// lower than ours. Therefore, we have nothing to request from them.
|
|
//
|
|
// ## The node is on a fork
|
|
//
|
|
// If a node is on a fork that has a lower finalized epoch, switching to that fork would
|
|
// cause us to revert a finalized block. This is not permitted, therefore we have no
|
|
// interest in their blocks.
|
|
//
|
|
// We keep these peers to allow them to sync from us.
|
|
PeerSyncType::Behind
|
|
}
|
|
Ordering::Equal => {
|
|
// NOTE: if a peer has our same `finalized_epoch` with a different `finalized_root`
|
|
// they are not considered relevant and won't be propagated to sync.
|
|
// Check if the peer is the peer is inside the tolerance range to be considered synced.
|
|
if remote.head_slot < near_range_start {
|
|
PeerSyncType::Behind
|
|
} else if remote.head_slot > near_range_end
|
|
&& !chain.fork_choice.read().contains_block(&remote.head_root)
|
|
{
|
|
// This peer has a head ahead enough of ours and we have no knowledge of their best
|
|
// block.
|
|
PeerSyncType::Advanced
|
|
} else {
|
|
// This peer is either in the tolerance range, or ahead us with an already rejected
|
|
// block.
|
|
PeerSyncType::FullySynced
|
|
}
|
|
}
|
|
Ordering::Greater => {
|
|
if (local.finalized_epoch + 1 == remote.finalized_epoch
|
|
&& near_range_start <= remote.head_slot
|
|
&& remote.head_slot <= near_range_end)
|
|
|| chain.fork_choice.read().contains_block(&remote.head_root)
|
|
{
|
|
// This peer is near enough to us to be considered synced, or
|
|
// we have already synced up to this peer's head
|
|
PeerSyncType::FullySynced
|
|
} else {
|
|
PeerSyncType::Advanced
|
|
}
|
|
}
|
|
}
|
|
}
|