diff --git a/substrate/client/network/src/protocol.rs b/substrate/client/network/src/protocol.rs
index 7662a476e9a6fc9a45e48c0643cc4fcfaa7f5be8..4153129a0ac4d3a85ad7b74cf05544987c91908f 100644
--- a/substrate/client/network/src/protocol.rs
+++ b/substrate/client/network/src/protocol.rs
@@ -111,7 +111,7 @@ mod rep {
 	/// reputation change should be refunded with `ANY_EXTRINSIC_REFUND`
 	pub const ANY_EXTRINSIC: Rep = Rep::new(-(1 << 4), "Any extrinsic");
 	/// Reputation change when a peer sends us any extrinsic that is not invalid.
- 	pub const ANY_EXTRINSIC_REFUND: Rep = Rep::new(1 << 4, "Any extrinsic (refund)");
+	pub const ANY_EXTRINSIC_REFUND: Rep = Rep::new(1 << 4, "Any extrinsic (refund)");
 	/// Reputation change when a peer sends us an extrinsic that we didn't know about.
 	pub const GOOD_EXTRINSIC: Rep = Rep::new(1 << 7, "Good extrinsic");
 	/// Reputation change when a peer sends us a bad extrinsic.
@@ -535,6 +535,12 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
 		self.sync.num_sync_requests()
 	}
 
+	/// Sync local state with the blockchain state.
+	pub fn update_chain(&mut self) {
+		let info = self.context_data.chain.info();
+		self.sync.update_chain_info(&info.best_hash, info.best_number);
+	}
+
 	/// Accepts a response from the legacy substream and determines what the corresponding
 	/// request was.
 	fn handle_response(
@@ -1419,17 +1425,6 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
 		}
 	}
 
-	/// Call this when a block has been imported in the import queue
-	pub fn on_block_imported(&mut self, header: &B::Header, is_best: bool) {
-		if is_best {
-			self.sync.update_chain_info(header);
-			self.behaviour.set_notif_protocol_handshake(
-				&self.block_announces_protocol,
-				BlockAnnouncesHandshake::build(&self.config, &self.context_data.chain).encode()
-			);
-		}
-	}
-
 	/// Call this when a block has been finalized. The sync layer may have some additional
 	/// requesting to perform.
 	pub fn on_block_finalized(&mut self, hash: B::Hash, header: &B::Header) {
@@ -1494,12 +1489,23 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
 	/// A batch of blocks have been processed, with or without errors.
 	/// Call this when a batch of blocks have been processed by the importqueue, with or without
 	/// errors.
-	pub fn blocks_processed(
+	pub fn on_blocks_processed(
 		&mut self,
 		imported: usize,
 		count: usize,
 		results: Vec<(Result<BlockImportResult<NumberFor<B>>, BlockImportError>, B::Hash)>
 	) {
+		let new_best = results.iter().rev().find_map(|r| match r {
+			(Ok(BlockImportResult::ImportedUnknown(n, aux, _)), hash) if aux.is_new_best => Some((*n, hash.clone())),
+			_ => None,
+		});
+		if let Some((best_num, best_hash)) = new_best {
+			self.sync.update_chain_info(&best_hash, best_num);
+			self.behaviour.set_notif_protocol_handshake(
+				&self.block_announces_protocol,
+				BlockAnnouncesHandshake::build(&self.config, &self.context_data.chain).encode()
+			);
+		}
 		let results = self.sync.on_blocks_processed(
 			imported,
 			count,
diff --git a/substrate/client/network/src/protocol/sync.rs b/substrate/client/network/src/protocol/sync.rs
index f4c935de5d3af5d02a7e1c71a8b8b788caca6779..e08fcf4e9b580297d455dc6663758d10968c6831 100644
--- a/substrate/client/network/src/protocol/sync.rs
+++ b/substrate/client/network/src/protocol/sync.rs
@@ -513,10 +513,10 @@ impl<B: BlockT> ChainSync<B> {
 		}
 	}
 
-	/// Signal that `best_header` has been queued for import and update the
+	/// Signal that a new best block has been imported.
 	/// `ChainSync` state with that information.
-	pub fn update_chain_info(&mut self, best_header: &B::Header) {
-		self.on_block_queued(&best_header.hash(), *best_header.number())
+	pub fn update_chain_info(&mut self, best_hash: &B::Hash, best_number: NumberFor<B>) {
+		self.on_block_queued(best_hash, best_number);
 	}
 
 	/// Schedule a justification request for the given block.
diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs
index ba6c7a39b4b2125c5ac3c70c28e43804f605b9ca..544856893060143fa7e8e80f3be2accc02ef7ac8 100644
--- a/substrate/client/network/src/service.rs
+++ b/substrate/client/network/src/service.rs
@@ -400,16 +400,18 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
 		&self.service
 	}
 
-	/// You must call this when a new block is imported by the client.
-	pub fn on_block_imported(&mut self, header: B::Header, is_best: bool) {
-		self.network_service.user_protocol_mut().on_block_imported(&header, is_best);
-	}
-
 	/// You must call this when a new block is finalized by the client.
 	pub fn on_block_finalized(&mut self, hash: B::Hash, header: B::Header) {
 		self.network_service.user_protocol_mut().on_block_finalized(hash, &header);
 	}
 
+	/// This should be called when blocks are added to the
+	/// chain by something other than the import queue.
+	/// Currently this is only useful for tests.
+	pub fn update_chain(&mut self) {
+		self.network_service.user_protocol_mut().update_chain();
+	}
+
 	/// Returns the local `PeerId`.
 	pub fn local_peer_id(&self) -> &PeerId {
 		Swarm::<B, H>::local_peer_id(&self.network_service)
@@ -1349,7 +1351,7 @@ impl<'a, B: BlockT, H: ExHashT> Link<B> for NetworkLink<'a, B, H> {
 		count: usize,
 		results: Vec<(Result<BlockImportResult<NumberFor<B>>, BlockImportError>, B::Hash)>
 	) {
-		self.protocol.user_protocol_mut().blocks_processed(imported, count, results)
+		self.protocol.user_protocol_mut().on_blocks_processed(imported, count, results)
 	}
 	fn justification_imported(&mut self, who: PeerId, hash: &B::Hash, number: NumberFor<B>, success: bool) {
 		self.protocol.user_protocol_mut().justification_import_result(hash.clone(), number, success);
diff --git a/substrate/client/network/test/src/lib.rs b/substrate/client/network/test/src/lib.rs
index 76bc2afa6953cf09b39048aba733869077b80b61..25a7f3a606fa2a0b6890a17fae3591af1414071e 100644
--- a/substrate/client/network/test/src/lib.rs
+++ b/substrate/client/network/test/src/lib.rs
@@ -295,11 +295,11 @@ impl<D> Peer<D> {
 				Default::default()
 			};
 			self.block_import.import_block(import_block, cache).expect("block_import failed");
-			self.network.on_block_imported(header, true);
 			self.network.service().announce_block(hash, Vec::new());
 			at = hash;
 		}
 
+		self.network.update_chain();
 		self.network.service().announce_block(at.clone(), Vec::new());
 		at
 	}
@@ -813,10 +813,6 @@ pub trait TestNetFactory: Sized {
 
 				// We poll `imported_blocks_stream`.
 				while let Poll::Ready(Some(notification)) = peer.imported_blocks_stream.as_mut().poll_next(cx) {
-					peer.network.on_block_imported(
-						notification.header,
-						true,
-					);
 					peer.network.service().announce_block(notification.hash, Vec::new());
 				}
 
diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs
index ebd2b99ef1d31956d849eec21fc5eb977dda41c8..5604b98e82dbc8da6a16760524cce1e730ce04bd 100644
--- a/substrate/client/service/src/lib.rs
+++ b/substrate/client/service/src/lib.rs
@@ -369,8 +369,6 @@ fn build_network_future<
 
 		// We poll `imported_blocks_stream`.
 		while let Poll::Ready(Some(notification)) = Pin::new(&mut imported_blocks_stream).poll_next(cx) {
-			network.on_block_imported(notification.header, notification.is_new_best);
-
 			if announce_imported_blocks {
 				network.service().announce_block(notification.hash, Vec::new());
 			}