Improve peer status handling
This commit is contained in:
parent
708d9b5674
commit
ebb9ced0a4
@ -4,7 +4,7 @@ use crate::service::{NetworkMessage, OutgoingMessage};
|
|||||||
use crate::sync::SimpleSync;
|
use crate::sync::SimpleSync;
|
||||||
use crossbeam_channel::{unbounded as channel, Sender};
|
use crossbeam_channel::{unbounded as channel, Sender};
|
||||||
use eth2_libp2p::{
|
use eth2_libp2p::{
|
||||||
rpc::{IncomingGossip, RPCRequest, RPCResponse},
|
rpc::{methods::GoodbyeReason, IncomingGossip, RPCRequest, RPCResponse},
|
||||||
PeerId, RPCEvent,
|
PeerId, RPCEvent,
|
||||||
};
|
};
|
||||||
use futures::future;
|
use futures::future;
|
||||||
@ -199,7 +199,8 @@ impl MessageHandler {
|
|||||||
.on_block_gossip(peer_id, message, &mut self.network_context)
|
.on_block_gossip(peer_id, message, &mut self.network_context)
|
||||||
}
|
}
|
||||||
IncomingGossip::Attestation(message) => {
|
IncomingGossip::Attestation(message) => {
|
||||||
//
|
self.sync
|
||||||
|
.on_attestation_gossip(peer_id, message, &mut self.network_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +227,8 @@ impl NetworkContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disconnect(&self, _peer_id: PeerId) {
|
pub fn disconnect(&mut self, peer_id: PeerId, reason: GoodbyeReason) {
|
||||||
|
self.send_rpc_request(peer_id, RPCRequest::Goodbye(reason))
|
||||||
// TODO: disconnect peers.
|
// TODO: disconnect peers.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@ pub struct PeerSyncInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PeerSyncInfo {
|
impl PeerSyncInfo {
|
||||||
/// Returns `true` if the peer is on the same chain as `other`.
|
/// Returns `true` if the has a different network ID to `other`.
|
||||||
fn is_on_same_chain(&self, other: Self) -> bool {
|
fn has_different_network_id_to(&self, other: Self) -> bool {
|
||||||
self.network_id == other.network_id
|
self.network_id != other.network_id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the peer has a higher finalized epoch than `other`.
|
/// Returns `true` if the peer has a higher finalized epoch than `other`.
|
||||||
@ -41,19 +41,6 @@ impl PeerSyncInfo {
|
|||||||
fn has_higher_best_slot_than(&self, other: Self) -> bool {
|
fn has_higher_best_slot_than(&self, other: Self) -> bool {
|
||||||
self.best_slot > other.best_slot
|
self.best_slot > other.best_slot
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `PeerStatus` of `self` in relation to `other`.
|
|
||||||
pub fn status_compared_to(&self, other: Self) -> PeerStatus {
|
|
||||||
if self.has_higher_finalized_epoch_than(other) {
|
|
||||||
PeerStatus::HigherFinalizedEpoch
|
|
||||||
} else if !self.is_on_same_chain(other) {
|
|
||||||
PeerStatus::OnDifferentChain
|
|
||||||
} else if self.has_higher_best_slot_than(other) {
|
|
||||||
PeerStatus::HigherBestSlot
|
|
||||||
} else {
|
|
||||||
PeerStatus::NotInteresting
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The status of a peers view on the chain, relative to some other view of the chain (presumably
|
/// The status of a peers view on the chain, relative to some other view of the chain (presumably
|
||||||
@ -61,7 +48,9 @@ impl PeerSyncInfo {
|
|||||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||||
pub enum PeerStatus {
|
pub enum PeerStatus {
|
||||||
/// The peer is on a completely different chain.
|
/// The peer is on a completely different chain.
|
||||||
OnDifferentChain,
|
DifferentNetworkId,
|
||||||
|
/// The peer lists a finalized epoch for which we have a different root.
|
||||||
|
FinalizedEpochNotInChain,
|
||||||
/// The peer has a higher finalized epoch.
|
/// The peer has a higher finalized epoch.
|
||||||
HigherFinalizedEpoch,
|
HigherFinalizedEpoch,
|
||||||
/// The peer has a higher best slot.
|
/// The peer has a higher best slot.
|
||||||
@ -70,6 +59,18 @@ pub enum PeerStatus {
|
|||||||
NotInteresting,
|
NotInteresting,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PeerStatus {
|
||||||
|
pub fn should_handshake(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
PeerStatus::DifferentNetworkId => false,
|
||||||
|
PeerStatus::FinalizedEpochNotInChain => false,
|
||||||
|
PeerStatus::HigherFinalizedEpoch => true,
|
||||||
|
PeerStatus::HigherBestSlot => true,
|
||||||
|
PeerStatus::NotInteresting => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<HelloMessage> for PeerSyncInfo {
|
impl From<HelloMessage> for PeerSyncInfo {
|
||||||
fn from(hello: HelloMessage) -> PeerSyncInfo {
|
fn from(hello: HelloMessage) -> PeerSyncInfo {
|
||||||
PeerSyncInfo {
|
PeerSyncInfo {
|
||||||
@ -183,6 +184,51 @@ impl SimpleSync {
|
|||||||
self.process_hello(peer_id, hello, network);
|
self.process_hello(peer_id, hello, network);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a `PeerStatus` for some peer.
|
||||||
|
fn peer_status(&self, peer: PeerSyncInfo) -> PeerStatus {
|
||||||
|
let local = PeerSyncInfo::from(&self.chain);
|
||||||
|
|
||||||
|
if peer.has_different_network_id_to(local) {
|
||||||
|
return PeerStatus::DifferentNetworkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if local.has_higher_finalized_epoch_than(peer) {
|
||||||
|
let peer_finalized_slot = peer
|
||||||
|
.latest_finalized_epoch
|
||||||
|
.start_slot(self.chain.get_spec().slots_per_epoch);
|
||||||
|
|
||||||
|
let local_roots = self.chain.get_block_roots(peer_finalized_slot, 1, 0);
|
||||||
|
|
||||||
|
if let Ok(local_roots) = local_roots {
|
||||||
|
if let Some(local_root) = local_roots.get(0) {
|
||||||
|
if *local_root != peer.latest_finalized_root {
|
||||||
|
return PeerStatus::FinalizedEpochNotInChain;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
self.log,
|
||||||
|
"Cannot get root for peer finalized slot.";
|
||||||
|
"error" => "empty roots"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
self.log,
|
||||||
|
"Cannot get root for peer finalized slot.";
|
||||||
|
"error" => format!("{:?}", local_roots)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if peer.has_higher_finalized_epoch_than(local) {
|
||||||
|
PeerStatus::HigherFinalizedEpoch
|
||||||
|
} else if peer.has_higher_best_slot_than(local) {
|
||||||
|
PeerStatus::HigherBestSlot
|
||||||
|
} else {
|
||||||
|
PeerStatus::NotInteresting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Process a `Hello` message, requesting new blocks if appropriate.
|
/// Process a `Hello` message, requesting new blocks if appropriate.
|
||||||
///
|
///
|
||||||
/// Disconnects the peer if required.
|
/// Disconnects the peer if required.
|
||||||
@ -196,26 +242,22 @@ impl SimpleSync {
|
|||||||
|
|
||||||
let remote = PeerSyncInfo::from(hello);
|
let remote = PeerSyncInfo::from(hello);
|
||||||
let local = PeerSyncInfo::from(&self.chain);
|
let local = PeerSyncInfo::from(&self.chain);
|
||||||
let remote_status = remote.status_compared_to(local);
|
let remote_status = self.peer_status(remote);
|
||||||
|
|
||||||
// network id must match
|
if remote_status.should_handshake() {
|
||||||
if remote_status != PeerStatus::OnDifferentChain {
|
|
||||||
info!(self.log, "HandshakeSuccess"; "peer" => format!("{:?}", peer_id));
|
info!(self.log, "HandshakeSuccess"; "peer" => format!("{:?}", peer_id));
|
||||||
self.known_peers.insert(peer_id.clone(), remote);
|
self.known_peers.insert(peer_id.clone(), remote);
|
||||||
|
} else {
|
||||||
|
info!(
|
||||||
|
self.log, "HandshakeFailure";
|
||||||
|
"peer" => format!("{:?}", peer_id),
|
||||||
|
"reason" => "network_id"
|
||||||
|
);
|
||||||
|
network.disconnect(peer_id.clone(), GoodbyeReason::IrreleventNetwork);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: boot peer if finalization is wrong.
|
// If required, send requests for blocks.
|
||||||
|
|
||||||
match remote_status {
|
match remote_status {
|
||||||
PeerStatus::OnDifferentChain => {
|
|
||||||
info!(
|
|
||||||
self.log, "Failure";
|
|
||||||
"peer" => format!("{:?}", peer_id),
|
|
||||||
"reason" => "network_id"
|
|
||||||
);
|
|
||||||
|
|
||||||
network.disconnect(peer_id);
|
|
||||||
}
|
|
||||||
PeerStatus::HigherFinalizedEpoch => {
|
PeerStatus::HigherFinalizedEpoch => {
|
||||||
let start_slot = remote
|
let start_slot = remote
|
||||||
.latest_finalized_epoch
|
.latest_finalized_epoch
|
||||||
@ -243,6 +285,8 @@ impl SimpleSync {
|
|||||||
network,
|
network,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
PeerStatus::FinalizedEpochNotInChain => {}
|
||||||
|
PeerStatus::DifferentNetworkId => {}
|
||||||
PeerStatus::NotInteresting => {}
|
PeerStatus::NotInteresting => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -541,7 +585,7 @@ impl SimpleSync {
|
|||||||
"sender_peer_id" => format!("{:?}", sender),
|
"sender_peer_id" => format!("{:?}", sender),
|
||||||
"reason" => format!("{:?}", outcome),
|
"reason" => format!("{:?}", outcome),
|
||||||
);
|
);
|
||||||
network.disconnect(sender);
|
network.disconnect(sender, GoodbyeReason::Fault);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this results to true, the item will be removed from the queue.
|
// If this results to true, the item will be removed from the queue.
|
||||||
|
Loading…
Reference in New Issue
Block a user