diff --git a/substrate/client/network/sync/src/engine.rs b/substrate/client/network/sync/src/engine.rs index 73bf071c1a63..93d3d2e752d0 100644 --- a/substrate/client/network/sync/src/engine.rs +++ b/substrate/client/network/sync/src/engine.rs @@ -858,6 +858,13 @@ where }, ToServiceCommand::OnBlockFinalized(hash, header) => self.strategy.on_block_finalized(&hash, *header.number()), + ToServiceCommand::Restart(sync_restart_args, tx) => { + if let Some(number) = sync_restart_args.new_best_block { + self.strategy.update_common_number_for_peers(number); + } + self.strategy.on_restart(sync_restart_args.sync_mode.into()); + let _ = tx.send(()); + }, } } diff --git a/substrate/client/network/sync/src/service/syncing_service.rs b/substrate/client/network/sync/src/service/syncing_service.rs index f4bc58afd4fd..469af148e915 100644 --- a/substrate/client/network/sync/src/service/syncing_service.rs +++ b/substrate/client/network/sync/src/service/syncing_service.rs @@ -26,6 +26,7 @@ use sc_network::{NetworkBlock, NetworkSyncForkRequest}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; use sp_runtime::traits::{Block as BlockT, NumberFor}; +use sc_network_common::sync::SyncMode; use std::{ pin::Pin, sync::{ @@ -34,8 +35,17 @@ use std::{ }, }; +/// Arguments for chain-sync restart. +pub struct SyncRestartArgs { + /// Updates the common blocks for connected peers when set. + pub new_best_block: Option>, + /// New sync mode for sync strategy restart. + pub sync_mode: SyncMode, +} + /// Commands send to `SyncingEngine` pub enum ToServiceCommand { + Restart(SyncRestartArgs, oneshot::Sender<()>), SetSyncForkRequest(Vec, B::Hash, NumberFor), RequestJustification(B::Hash, NumberFor), ClearJustificationRequests, @@ -91,6 +101,14 @@ impl SyncingService { rx.await } + /// Restart the synchronization with new arguments. + pub async fn restart(&self, sync_restart_args: SyncRestartArgs) { + let (tx, rx) = oneshot::channel(); + let _ = self.tx.unbounded_send(ToServiceCommand::Restart(sync_restart_args, tx)); + + let _ = rx.await; + } + /// Get best seen block. pub async fn best_seen_block(&self) -> Result>, oneshot::Canceled> { let (tx, rx) = oneshot::channel(); diff --git a/substrate/client/network/sync/src/strategy.rs b/substrate/client/network/sync/src/strategy.rs index 3269e6cf9047..d6b17c0063ec 100644 --- a/substrate/client/network/sync/src/strategy.rs +++ b/substrate/client/network/sync/src/strategy.rs @@ -291,6 +291,11 @@ where new_best } + /// Restart the chain-sync strategy with the new arguments. + pub fn on_restart(&mut self, sync_mode: SyncMode) { + self.chain_sync.as_mut().map(|s| s.on_restart(chain_sync_mode(sync_mode))); + } + /// Configure an explicit fork sync request in case external code has detected that there is a /// stale fork missing. pub fn set_sync_fork_request( @@ -305,6 +310,10 @@ where } } + pub fn update_common_number_for_peers(&mut self, number: NumberFor) { + self.chain_sync.as_mut().map(|s| s.update_common_number_for_peers(number)); + } + /// Request extra justification. pub fn request_justification(&mut self, hash: &B::Hash, number: NumberFor) { // Justifications can only be requested via `ChainSync`. diff --git a/substrate/client/network/sync/src/strategy/chain_sync.rs b/substrate/client/network/sync/src/strategy/chain_sync.rs index a6277d071111..d92a9fe58ad7 100644 --- a/substrate/client/network/sync/src/strategy/chain_sync.rs +++ b/substrate/client/network/sync/src/strategy/chain_sync.rs @@ -473,6 +473,12 @@ where .count() } + /// Restart the chain-sync with the new sync mode. + pub fn on_restart(&mut self, chain_sync_mode: ChainSyncMode) { + self.mode = chain_sync_mode; + self.restart(); + } + /// Get the total number of downloaded blocks. pub fn num_downloaded_blocks(&self) -> usize { self.downloaded_blocks @@ -1292,6 +1298,16 @@ where } } + pub fn update_common_number_for_peers(&mut self, new_common: NumberFor) { + for peer in self.peers.values_mut() { + if peer.best_number >= new_common { + peer.update_common_number(new_common); + } else { + peer.update_common_number(peer.best_number); + } + } + } + /// Called when a block has been queued for import. /// /// Updates our internal state for best queued block and then goes