From 8948567c23ebbbd06d9d3dad612ee346dac23016 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan <arkady.paronyan@gmail.com> Date: Sun, 6 Jan 2019 19:45:41 +0300 Subject: [PATCH] Fixed ancestry search/block queue interaction (#1337) * Fixed ancestry search - block queue interaction * Style --- substrate/core/network/src/sync.rs | 34 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/substrate/core/network/src/sync.rs b/substrate/core/network/src/sync.rs index 315156588ed..54da778266f 100644 --- a/substrate/core/network/src/sync.rs +++ b/substrate/core/network/src/sync.rs @@ -23,7 +23,7 @@ use consensus::BlockOrigin; use consensus::import_queue::{ImportQueue, IncomingBlock}; use client::error::Error as ClientError; use blocks::BlockCollection; -use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor}; +use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor, Zero}; use runtime_primitives::generic::BlockId; use message::{self, generic::Message as GenericMessage}; use config::Roles; @@ -32,9 +32,10 @@ use config::Roles; const MAX_BLOCKS_TO_REQUEST: usize = 128; // Maximum blocks to store in the import queue. const MAX_IMPORTING_BLOCKS: usize = 2048; +// Number of blocks in the queue that prevents ancestry search. +const MAJOR_SYNC_BLOCKS: usize = 5; struct PeerSync<B: BlockT> { - pub common_hash: B::Hash, pub common_number: NumberFor<B>, pub best_hash: B::Hash, pub best_number: NumberFor<B>, @@ -141,16 +142,25 @@ impl<B: BlockT> ChainSync<B> { (Ok(BlockStatus::KnownBad), _) => { protocol.report_peer(who, Severity::Bad(&format!("New peer with known bad best block {} ({}).", info.best_hash, info.best_number))); }, - (Ok(BlockStatus::Unknown), b) if b == As::sa(0) => { + (Ok(BlockStatus::Unknown), b) if b.is_zero() => { protocol.report_peer(who, Severity::Bad(&format!("New peer with unknown genesis hash {} ({}).", info.best_hash, info.best_number))); }, + (Ok(BlockStatus::Unknown), _) if self.import_queue.status().importing_count > MAJOR_SYNC_BLOCKS => { + // when actively syncing the common point moves too fast. + debug!(target:"sync", "New peer with unknown best hash {} ({}), assuming common block.", self.best_queued_hash, self.best_queued_number); + self.peers.insert(who, PeerSync { + common_number: self.best_queued_number, + best_hash: info.best_hash, + best_number: info.best_number, + state: PeerSyncState::Available, + }); + } (Ok(BlockStatus::Unknown), _) => { let our_best = self.best_queued_number; if our_best > As::sa(0) { let common_best = ::std::cmp::min(our_best, info.best_number); debug!(target:"sync", "New peer with unknown best hash {} ({}), searching for common ancestor.", info.best_hash, info.best_number); self.peers.insert(who, PeerSync { - common_hash: self.genesis_hash, common_number: As::sa(0), best_hash: info.best_hash, best_number: info.best_number, @@ -161,7 +171,6 @@ impl<B: BlockT> ChainSync<B> { // We are at genesis, just start downloading debug!(target:"sync", "New peer with best hash {} ({}).", info.best_hash, info.best_number); self.peers.insert(who, PeerSync { - common_hash: self.genesis_hash, common_number: As::sa(0), best_hash: info.best_hash, best_number: info.best_number, @@ -173,7 +182,6 @@ impl<B: BlockT> ChainSync<B> { (Ok(BlockStatus::Queued), _) | (Ok(BlockStatus::InChain), _) => { debug!(target:"sync", "New peer with known best hash {} ({}).", info.best_hash, info.best_number); self.peers.insert(who, PeerSync { - common_hash: info.best_hash, common_number: info.best_number, best_hash: info.best_hash, best_number: info.best_number, @@ -230,7 +238,6 @@ impl<B: BlockT> ChainSync<B> { match protocol.client().block_hash(n) { Ok(Some(block_hash)) if block_hash == block.hash => { if peer.common_number < n { - peer.common_hash = block.hash; peer.common_number = n; } peer.state = PeerSyncState::Available; @@ -300,15 +307,14 @@ impl<B: BlockT> ChainSync<B> { // Update common blocks for (n, peer) in self.peers.iter_mut() { if let PeerSyncState::AncestorSearch(_) = peer.state { - continue; + // Abort search. + peer.state = PeerSyncState::Available; } trace!(target: "sync", "Updating peer {} info, ours={}, common={}, their best={}", n, number, peer.common_number, peer.best_number); if peer.best_number >= number { peer.common_number = number; - peer.common_hash = *hash; } else { peer.common_number = peer.best_number; - peer.common_hash = peer.best_hash; } } } @@ -379,10 +385,6 @@ impl<B: BlockT> ChainSync<B> { pub(crate) fn restart(&mut self, protocol: &mut Context<B>) { self.import_queue.clear(); self.blocks.clear(); - let ids: Vec<NodeIndex> = self.peers.keys().map(|p| *p).collect(); - for id in ids { - self.new_peer(protocol, id); - } match protocol.client().info() { Ok(info) => { self.best_queued_hash = info.best_queued_hash.unwrap_or(info.chain.best_hash); @@ -395,6 +397,10 @@ impl<B: BlockT> ChainSync<B> { self.best_queued_number = As::sa(0); } } + let ids: Vec<NodeIndex> = self.peers.drain().map(|(id, _)| id).collect(); + for id in ids { + self.new_peer(protocol, id); + } } pub(crate) fn clear(&mut self) { -- GitLab