Prepare syncing for parallel sync strategies (#3224)

This PR should supersede
https://github.com/paritytech/polkadot-sdk/pull/2814 and accomplish the
same with less changes. It's needed to run sync strategies in parallel,
like running `ChainSync` and `GapSync` as independent strategies, and
running `ChainSync` and Sync 2.0 alongside each other.

The difference with https://github.com/paritytech/polkadot-sdk/pull/2814
is that we allow simultaneous requests to remote peers initiated by
different strategies, as this is not tracked on the remote node in any
way. Therefore, `PeerPool` is not needed.

CC @skunert

---------

Co-authored-by: Sebastian Kunert <skunert49@gmail.com>
This commit is contained in:
Dmitry Markin
2024-02-13 21:59:44 +02:00
committed by GitHub
parent e0c902e3df
commit 96ebb305ed
8 changed files with 538 additions and 379 deletions
@@ -30,7 +30,7 @@
use crate::{
blocks::BlockCollection,
extra_requests::ExtraRequests,
justification_requests::ExtraRequests,
schema::v1::StateResponse,
strategy::{
state_sync::{ImportResult, StateSync, StateSyncProvider},
@@ -212,10 +212,10 @@ struct GapSync<B: BlockT> {
pub enum ChainSyncAction<B: BlockT> {
/// Send block request to peer. Always implies dropping a stale block request to the same peer.
SendBlockRequest { peer_id: PeerId, request: BlockRequest<B> },
/// Drop stale block request.
CancelBlockRequest { peer_id: PeerId },
/// Send state request to peer.
SendStateRequest { peer_id: PeerId, request: OpaqueStateRequest },
/// Drop stale request.
CancelRequest { peer_id: PeerId },
/// Peer misbehaved. Disconnect, report it and cancel the block request to it.
DropPeer(BadPeer),
/// Import blocks.
@@ -373,6 +373,7 @@ where
max_parallel_downloads: u32,
max_blocks_per_request: u32,
metrics_registry: Option<Registry>,
initial_peers: impl Iterator<Item = (PeerId, B::Hash, NumberFor<B>)>,
) -> Result<Self, ClientError> {
let mut sync = Self {
client,
@@ -405,6 +406,10 @@ where
};
sync.reset_sync_start_point()?;
initial_peers.for_each(|(peer_id, best_hash, best_number)| {
sync.add_peer(peer_id, best_hash, best_number);
});
Ok(sync)
}
@@ -1312,34 +1317,35 @@ where
);
let old_peers = std::mem::take(&mut self.peers);
old_peers.into_iter().for_each(|(peer_id, mut p)| {
// peers that were downloading justifications
// should be kept in that state.
if let PeerSyncState::DownloadingJustification(_) = p.state {
// We make sure our commmon number is at least something we have.
trace!(
target: LOG_TARGET,
"Keeping peer {} after restart, updating common number from={} => to={} (our best).",
peer_id,
p.common_number,
self.best_queued_number,
);
p.common_number = self.best_queued_number;
self.peers.insert(peer_id, p);
return
old_peers.into_iter().for_each(|(peer_id, mut peer_sync)| {
match peer_sync.state {
PeerSyncState::Available => {
self.add_peer(peer_id, peer_sync.best_hash, peer_sync.best_number);
},
PeerSyncState::AncestorSearch { .. } |
PeerSyncState::DownloadingNew(_) |
PeerSyncState::DownloadingStale(_) |
PeerSyncState::DownloadingGap(_) |
PeerSyncState::DownloadingState => {
// Cancel a request first, as `add_peer` may generate a new request.
self.actions.push(ChainSyncAction::CancelRequest { peer_id });
self.add_peer(peer_id, peer_sync.best_hash, peer_sync.best_number);
},
PeerSyncState::DownloadingJustification(_) => {
// Peers that were downloading justifications
// should be kept in that state.
// We make sure our commmon number is at least something we have.
trace!(
target: LOG_TARGET,
"Keeping peer {} after restart, updating common number from={} => to={} (our best).",
peer_id,
peer_sync.common_number,
self.best_queued_number,
);
peer_sync.common_number = self.best_queued_number;
self.peers.insert(peer_id, peer_sync);
},
}
// handle peers that were in other states.
let action = match self.add_peer_inner(peer_id, p.best_hash, p.best_number) {
// since the request is not a justification, remove it from pending responses
Ok(None) => ChainSyncAction::CancelBlockRequest { peer_id },
// update the request if the new one is available
Ok(Some(request)) => ChainSyncAction::SendBlockRequest { peer_id, request },
// this implies that we need to drop pending response from the peer
Err(bad_peer) => ChainSyncAction::DropPeer(bad_peer),
};
self.actions.push(action);
});
}