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

@@ -40,7 +40,7 @@
//! and further batches are requested as current blocks are being processed.
use super::chain::ProcessingResult;
use super::chain_collection::{ChainCollection, SyncState};
use super::chain_collection::{ChainCollection, RangeSyncState};
use super::BatchId;
use crate::router::processor::PeerSyncInfo;
use crate::sync::block_processor::BatchProcessResult;
@@ -48,10 +48,10 @@ use crate::sync::manager::SyncMessage;
use crate::sync::network_context::SyncNetworkContext;
use beacon_chain::{BeaconChain, BeaconChainTypes};
use eth2_libp2p::rpc::RequestId;
use eth2_libp2p::PeerId;
use slog::{debug, error, trace, warn};
use eth2_libp2p::{NetworkGlobals, PeerId};
use slog::{debug, error, trace};
use std::collections::HashSet;
use std::sync::Weak;
use std::sync::Arc;
use tokio::sync::mpsc;
use types::{EthSpec, SignedBeaconBlock};
@@ -60,7 +60,7 @@ use types::{EthSpec, SignedBeaconBlock};
/// holds the current state of the long range sync.
pub struct RangeSync<T: BeaconChainTypes> {
/// The beacon chain for processing.
beacon_chain: Weak<BeaconChain<T>>,
beacon_chain: Arc<BeaconChain<T>>,
/// A collection of chains that need to be downloaded. This stores any head or finalized chains
/// that need to be downloaded.
chains: ChainCollection<T>,
@@ -77,13 +77,14 @@ pub struct RangeSync<T: BeaconChainTypes> {
impl<T: BeaconChainTypes> RangeSync<T> {
pub fn new(
beacon_chain: Weak<BeaconChain<T>>,
beacon_chain: Arc<BeaconChain<T>>,
network_globals: Arc<NetworkGlobals<T::EthSpec>>,
sync_send: mpsc::UnboundedSender<SyncMessage<T::EthSpec>>,
log: slog::Logger,
) -> Self {
RangeSync {
beacon_chain: beacon_chain.clone(),
chains: ChainCollection::new(beacon_chain),
chains: ChainCollection::new(beacon_chain, network_globals, log.clone()),
awaiting_head_peers: HashSet::new(),
sync_send,
log,
@@ -118,21 +119,14 @@ impl<T: BeaconChainTypes> RangeSync<T> {
// determine if we need to run a sync to the nearest finalized state or simply sync to
// its current head
let (chain, local_info) = match self.beacon_chain.upgrade() {
Some(chain) => match PeerSyncInfo::from_chain(&chain) {
Some(local) => (chain, local),
None => {
return error!(
self.log,
"Failed to get peer sync info";
"msg" => "likely due to head lock contention"
)
}
},
let local_info = match PeerSyncInfo::from_chain(&self.beacon_chain) {
Some(local) => local,
None => {
return warn!(self.log,
"Beacon chain dropped. Peer not considered for sync";
"peer_id" => format!("{:?}", peer_id));
return error!(
self.log,
"Failed to get peer sync info";
"msg" => "likely due to head lock contention"
)
}
};
@@ -148,10 +142,13 @@ impl<T: BeaconChainTypes> RangeSync<T> {
self.remove_peer(network, &peer_id);
// remove any out-of-date chains
self.chains.purge_outdated_chains(network, &self.log);
self.chains.purge_outdated_chains(network);
if remote_finalized_slot > local_info.head_slot
&& !chain.fork_choice.contains_block(&remote.finalized_root)
&& !self
.beacon_chain
.fork_choice
.contains_block(&remote.finalized_root)
{
debug!(self.log, "Finalization sync peer joined"; "peer_id" => format!("{:?}", peer_id));
// Finalized chain search
@@ -171,7 +168,7 @@ impl<T: BeaconChainTypes> RangeSync<T> {
chain.add_peer(network, peer_id);
// check if the new peer's addition will favour a new syncing chain.
self.chains.update_finalized(network, &self.log);
self.chains.update_finalized(network);
} else {
// there is no finalized chain that matches this peer's last finalized target
// create a new finalized chain
@@ -183,9 +180,8 @@ impl<T: BeaconChainTypes> RangeSync<T> {
remote_finalized_slot,
peer_id,
self.sync_send.clone(),
&self.log,
);
self.chains.update_finalized(network, &self.log);
self.chains.update_finalized(network);
}
} else {
if self.chains.is_finalizing_sync() {
@@ -216,10 +212,9 @@ impl<T: BeaconChainTypes> RangeSync<T> {
remote.head_slot,
peer_id,
self.sync_send.clone(),
&self.log,
);
}
self.chains.update_finalized(network, &self.log);
self.chains.update_finalized(network);
}
}
@@ -274,7 +269,7 @@ impl<T: BeaconChainTypes> RangeSync<T> {
chain.status_peers(network);
// update the state of the collection
self.chains.update_finalized(network, &self.log);
self.chains.update_finalized(network);
// set the state to a head sync, to inform the manager that we are awaiting a
// head chain.
@@ -282,13 +277,13 @@ impl<T: BeaconChainTypes> RangeSync<T> {
// if there are no more finalized chains, re-status all known peers awaiting a head
// sync
match self.chains.sync_state() {
SyncState::Idle | SyncState::Head => {
match self.chains.state() {
RangeSyncState::Idle | RangeSyncState::Head { .. } => {
for peer_id in self.awaiting_head_peers.drain() {
network.status_peer(self.beacon_chain.clone(), peer_id);
}
}
SyncState::Finalized => {} // Have more finalized chains to complete
RangeSyncState::Finalized { .. } => {} // Have more finalized chains to complete
}
}
Some((_, ProcessingResult::KeepChain)) => {}
@@ -308,7 +303,7 @@ impl<T: BeaconChainTypes> RangeSync<T> {
chain.status_peers(network);
// update the state of the collection
self.chains.update_finalized(network, &self.log);
self.chains.update_finalized(network);
}
Some((_, ProcessingResult::KeepChain)) => {}
None => {
@@ -321,15 +316,6 @@ impl<T: BeaconChainTypes> RangeSync<T> {
}
}
/// Public method to indicate the current state of the long range sync.
pub fn is_syncing(&self) -> bool {
match self.chains.sync_state() {
SyncState::Finalized => true,
SyncState::Head => true,
SyncState::Idle => false,
}
}
/// A peer has disconnected. This removes the peer from any ongoing chains and mappings. A
/// disconnected peer could remove a chain
pub fn peer_disconnect(
@@ -344,7 +330,7 @@ impl<T: BeaconChainTypes> RangeSync<T> {
self.remove_peer(network, peer_id);
// update the state of the collection
self.chains.update_finalized(network, &self.log);
self.chains.update_finalized(network);
}
/// When a peer gets removed, both the head and finalized chains need to be searched to check which pool the peer is in. The chain may also have a batch or batches awaiting
@@ -370,7 +356,7 @@ impl<T: BeaconChainTypes> RangeSync<T> {
{
// the chain needed to be removed
debug!(self.log, "Chain being removed due to failed batch");
self.chains.remove_chain(network, index, &self.log);
self.chains.remove_chain(network, index);
}
}
@@ -392,7 +378,7 @@ impl<T: BeaconChainTypes> RangeSync<T> {
Some((_, ProcessingResult::KeepChain)) => {} // error handled chain persists
Some((index, ProcessingResult::RemoveChain)) => {
debug!(self.log, "Chain being removed due to RPC error");
self.chains.remove_chain(network, index, &self.log)
self.chains.remove_chain(network, index)
}
None => {} // request wasn't in the finalized chains, check the head chains
}