Global Sync access (#994)

* Connect sync logic to network globals

* Add further sync info to sync status

* Build new syncing HTTP API methods

* Fix bug in updating sync state

* Highest slot is current slot

* Update book for syncing API
This commit is contained in:
Age Manning
2020-04-14 18:17:35 +10:00
committed by GitHub
parent db7847c34a
commit e5874f4565
22 changed files with 818 additions and 399 deletions

View File

@@ -15,7 +15,7 @@ use types::EthSpec;
mod peer_info;
mod peerdb;
pub use peer_info::PeerInfo;
pub use peer_info::{PeerInfo, PeerSyncStatus};
/// The minimum reputation before a peer is disconnected.
// Most likely this needs tweaking
const MINIMUM_REPUTATION_BEFORE_BAN: Rep = 20;
@@ -196,14 +196,14 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
pub fn connect_ingoing(&mut self, peer_id: &PeerId) -> bool {
self.update_reputations();
let mut peerdb = self.network_globals.peers.write();
peerdb.new_peer(peer_id);
if !peerdb.connection_status(peer_id).is_banned() {
peerdb.connect_ingoing(peer_id);
// start a ping and status timer for the peer
self.ping_peers.insert(peer_id.clone());
self.status_peers.insert(peer_id.clone());
return true;
}
// start a ping and status timer for the peer
self.ping_peers.insert(peer_id.clone());
self.status_peers.insert(peer_id.clone());
false
}
@@ -213,14 +213,14 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
pub fn connect_outgoing(&mut self, peer_id: &PeerId) -> bool {
self.update_reputations();
let mut peerdb = self.network_globals.peers.write();
peerdb.new_peer(peer_id);
if !peerdb.connection_status(peer_id).is_banned() {
peerdb.connect_outgoing(peer_id);
// start a ping and status timer for the peer
self.ping_peers.insert(peer_id.clone());
self.status_peers.insert(peer_id.clone());
return true;
}
// start a ping and status timer for the peer
self.ping_peers.insert(peer_id.clone());
self.status_peers.insert(peer_id.clone());
false
}

View File

@@ -1,7 +1,7 @@
use super::peerdb::{Rep, DEFAULT_REPUTATION};
use crate::rpc::MetaData;
use std::time::Instant;
use types::{EthSpec, SubnetId};
use types::{EthSpec, Slot, SubnetId};
use PeerConnectionStatus::*;
/// Information about a given connected peer.
@@ -17,7 +17,7 @@ pub struct PeerInfo<T: EthSpec> {
pub connection_status: PeerConnectionStatus,
/// The current syncing state of the peer. The state may be determined after it's initial
/// connection.
pub syncing_status: PeerSyncingStatus,
pub sync_status: PeerSyncStatus,
/// The ENR subnet bitfield of the peer. This may be determined after it's initial
/// connection.
pub meta_data: Option<MetaData<T>>,
@@ -33,7 +33,7 @@ impl<TSpec: EthSpec> Default for PeerInfo<TSpec> {
_version: vec![0],
},
connection_status: Default::default(),
syncing_status: PeerSyncingStatus::Unknown,
sync_status: PeerSyncStatus::Unknown,
meta_data: None,
}
}
@@ -98,14 +98,18 @@ pub enum PeerConnectionStatus {
},
}
#[derive(Debug, Clone)]
pub enum PeerSyncingStatus {
/// At the current state as our node.
Synced,
/// The peer is further ahead than our node and useful for block downloads.
Ahead,
#[derive(Debug, Clone, PartialEq)]
pub enum PeerSyncStatus {
/// At the current state as our node or ahead of us.
Synced {
/// The last known head slot from the peer's handshake.
status_head_slot: Slot,
},
/// Is behind our current head and not useful for block downloads.
Behind,
Behind {
/// The last known head slot from the peer's handshake.
status_head_slot: Slot,
},
/// Not currently known as a STATUS handshake has not occurred.
Unknown,
}

View File

@@ -1,7 +1,7 @@
use super::peer_info::{PeerConnectionStatus, PeerInfo};
use super::peer_info::{PeerConnectionStatus, PeerInfo, PeerSyncStatus};
use crate::rpc::methods::MetaData;
use crate::PeerId;
use slog::warn;
use slog::{crit, warn};
use std::collections::HashMap;
use types::{EthSpec, SubnetId};
@@ -31,6 +31,9 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
peers: HashMap::new(),
}
}
/* Getters */
/// Gives the reputation of a peer, or DEFAULT_REPUTATION if it is unknown.
pub fn reputation(&self, peer_id: &PeerId) -> Rep {
self.peers
@@ -53,6 +56,15 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
self.peers.get_mut(peer_id)
}
/// Returns true if the peer is synced at least to our current head.
pub fn peer_synced(&self, peer_id: &PeerId) -> bool {
match self.peers.get(peer_id).map(|info| &info.sync_status) {
Some(PeerSyncStatus::Synced { .. }) => true,
Some(_) => false,
None => false,
}
}
/// Gives the ids of all known connected peers.
pub fn connected_peers(&self) -> impl Iterator<Item = &PeerId> {
self.peers
@@ -61,6 +73,19 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
.map(|(peer_id, _)| peer_id)
}
/// Gives the `peer_id` of all known connected and synced peers.
pub fn synced_peers(&self) -> impl Iterator<Item = &PeerId> {
self.peers
.iter()
.filter(|(_, info)| {
if let PeerSyncStatus::Synced { .. } = info.sync_status {
return info.connection_status.is_connected();
}
false
})
.map(|(peer_id, _)| peer_id)
}
/// Gives an iterator of all peers on a given subnet.
pub fn peers_on_subnet(&self, subnet_id: &SubnetId) -> impl Iterator<Item = &PeerId> {
let subnet_id_filter = subnet_id.clone();
@@ -115,6 +140,16 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
.map(|(id, _)| id)
}
/// Gets the connection status of the peer.
pub fn connection_status(&self, peer_id: &PeerId) -> PeerConnectionStatus {
self.peer_info(peer_id)
.map_or(PeerConnectionStatus::default(), |info| {
info.connection_status.clone()
})
}
/* Setters */
/// Sets a peer as connected with an ingoing connection
pub fn connect_ingoing(&mut self, peer_id: &PeerId) {
let info = self
@@ -128,15 +163,6 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
info.connection_status.connect_ingoing();
}
/// Add the meta data of a peer.
pub fn add_metadata(&mut self, peer_id: &PeerId, meta_data: MetaData<TSpec>) {
if let Some(peer_info) = self.peers.get_mut(peer_id) {
peer_info.meta_data = Some(meta_data);
} else {
warn!(self.log, "Tried to add meta data for a non-existant peer"; "peer_id" => format!("{}", peer_id));
}
}
/// Sets a peer as connected with an outgoing connection
pub fn connect_outgoing(&mut self, peer_id: &PeerId) {
let info = self
@@ -197,31 +223,35 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
info.connection_status.ban();
}
/// Inserts a new peer with the default PeerInfo if it is not already present
/// Returns if the peer was new to the PeerDB
pub fn new_peer(&mut self, peer_id: &PeerId) -> bool {
if !self.peers.contains_key(peer_id) {
self.peers.insert(peer_id.clone(), Default::default());
return true;
/// Add the meta data of a peer.
pub fn add_metadata(&mut self, peer_id: &PeerId, meta_data: MetaData<TSpec>) {
if let Some(peer_info) = self.peers.get_mut(peer_id) {
peer_info.meta_data = Some(meta_data);
} else {
warn!(self.log, "Tried to add meta data for a non-existant peer"; "peer_id" => format!("{}", peer_id));
}
false
}
/// Sets the reputation of peer
/// Sets the reputation of peer.
pub fn set_reputation(&mut self, peer_id: &PeerId, rep: Rep) {
let log_ref = &self.log;
self.peers
.entry(peer_id.clone())
.or_insert_with(|| {
warn!(log_ref, "Setting the reputation of an unknown peer";
"peer_id" => format!("{:?}",peer_id));
PeerInfo::default()
})
.reputation = rep;
if let Some(peer_info) = self.peers.get_mut(peer_id) {
peer_info.reputation = rep;
} else {
crit!(self.log, "Tried to modify reputation for an unknown peer"; "peer_id" => format!("{}",peer_id));
}
}
/// Sets the syncing status of a peer.
pub fn set_sync_status(&mut self, peer_id: &PeerId, sync_status: PeerSyncStatus) {
if let Some(peer_info) = self.peers.get_mut(peer_id) {
peer_info.sync_status = sync_status;
} else {
crit!(self.log, "Tried to the sync status for an unknown peer"; "peer_id" => format!("{}",peer_id));
}
}
/// Adds to a peer's reputation by `change`. If the reputation exceeds Rep's
/// upper (lower) bounds, it stays at the maximum (minimum) value
/// upper (lower) bounds, it stays at the maximum (minimum) value.
pub fn add_reputation(&mut self, peer_id: &PeerId, change: Rep) {
let log_ref = &self.log;
let info = self.peers.entry(peer_id.clone()).or_insert_with(|| {
@@ -231,13 +261,6 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
});
info.reputation = info.reputation.saturating_add(change);
}
pub fn connection_status(&self, peer_id: &PeerId) -> PeerConnectionStatus {
self.peer_info(peer_id)
.map_or(PeerConnectionStatus::default(), |info| {
info.connection_status.clone()
})
}
}
#[cfg(test)]
@@ -355,9 +378,6 @@ mod tests {
let p0 = PeerId::random();
let p1 = PeerId::random();
let p2 = PeerId::random();
pdb.new_peer(&p0);
pdb.new_peer(&p1);
pdb.new_peer(&p2);
pdb.connect_ingoing(&p0);
pdb.connect_ingoing(&p1);
pdb.connect_ingoing(&p2);
@@ -378,9 +398,6 @@ mod tests {
let p0 = PeerId::random();
let p1 = PeerId::random();
let p2 = PeerId::random();
pdb.new_peer(&p0);
pdb.new_peer(&p1);
pdb.new_peer(&p2);
pdb.connect_ingoing(&p0);
pdb.connect_ingoing(&p1);
pdb.connect_ingoing(&p2);
@@ -401,7 +418,7 @@ mod tests {
let random_peer = PeerId::random();
pdb.new_peer(&random_peer);
pdb.connect_ingoing(&random_peer);
assert_eq!(pdb.n_dc, pdb.disconnected_peers().count());
pdb.connect_ingoing(&random_peer);