Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract warp sync strategy from ChainSync #2467

Merged
merged 60 commits into from
Jan 12, 2024
Merged

Conversation

dmitry-markin
Copy link
Contributor

@dmitry-markin dmitry-markin commented Nov 23, 2023

Extract WarpSync (and StateSync as part of warp sync) from ChainSync as independent syncing strategy called by SyncingEngine. Introduce SyncingStrategy enum as a proxy between SyncingEngine and specific syncing strategies.

Limitations

Gap sync is kept in ChainSync for now because it shares the same set of peers as block syncing implementation in ChainSync. Extraction of a common context responsible for peer management in syncing strategies able to run in parallel is planned for a follow-up PR.

Further improvements

A possibility of conversion of SyncingStartegy into a trait should be evaluated. The main stopper for this is that different strategies need to communicate different actions to SyncingEngine and respond to different events / provide different APIs (e.g., requesting justifications is only possible via ChainSync and not through WarpSync; SendWarpProofRequest action is only relevant to WarpSync, etc.)

@dmitry-markin dmitry-markin added the T0-node This PR/Issue is related to the topic “node”. label Nov 23, 2023
@dmitry-markin dmitry-markin marked this pull request as draft November 23, 2023 13:48
Copy link
Contributor

@altonen altonen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice work! I left a bunch of comments but apart from state sync still partly being in ChainSync and the inability to share BlocksCollection between strategies (which can be addressed in a follow-up), I think it's looking good

Comment on lines +390 to +393
let warp_sync_progress = self.gap_sync.as_ref().map(|gap_sync| WarpSyncProgress {
phase: WarpSyncPhase::DownloadingBlocks(gap_sync.best_queued_number),
total_bytes: 0,
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this belongs here but I understand that in practice it might be harder to refactor out. We need to find a way to share BlocksCollection/peer download states and share them between strategies. This would be needed to run Sync 1.0 and 2.0 in parallel.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No sharing of BlockCollection yet as it's not needed to run GapSync in parallel with ChainSync (it has its own instance of BlockCollection), but here is a draft PR with the initial implementation of sharing of peers between the strategies: #2814.

I don't think time should be invested now into reviewing it as a lot could change, but hopefully it shows the general idea of what a follow-up PR may look like.

substrate/client/network/sync/src/chain_sync.rs Outdated Show resolved Hide resolved
substrate/client/network/sync/src/engine.rs Outdated Show resolved Hide resolved
substrate/client/network/sync/src/engine.rs Outdated Show resolved Hide resolved
substrate/client/network/sync/src/warp.rs Outdated Show resolved Hide resolved
substrate/client/network/sync/src/warp.rs Outdated Show resolved Hide resolved
substrate/client/network/sync/src/warp.rs Outdated Show resolved Hide resolved
substrate/client/network/sync/src/warp.rs Outdated Show resolved Hide resolved
substrate/client/network/sync/src/warp.rs Outdated Show resolved Hide resolved
Co-authored-by: Aaro Altonen <48052676+altonen@users.noreply.github.com>
@dmitry-markin
Copy link
Contributor Author

Very nice work! I left a bunch of comments but apart from state sync still partly being in ChainSync and the inability to share BlocksCollection between strategies (which can be addressed in a follow-up), I think it's looking good

Another thing that should be shared between the strategies running in parallel similarly to BlocksCollection is the set of peers and their states. Unless we accept that it's OK to treat peers independently in different strategies and issue parallel requests to them.

@altonen
Copy link
Contributor

altonen commented Nov 30, 2023

Unless we accept that it's OK to treat peers independently in different strategies and issue parallel requests to them.

I don't think it's a good idea. All strategies should have the same view of connected peers. We can't have two simultaneous in-flight request to any peer so their states have to be synchronized across strategies.

If we introduce some kind of peer + blocks collection which is shared between strategies using Arc<Mutex<Context>> (and maybe some nice API on top of it), that would probably work.

substrate/client/network/sync/src/engine.rs Outdated Show resolved Hide resolved
substrate/client/network/sync/src/strategy.rs Show resolved Hide resolved
substrate/client/network/sync/src/strategy.rs Show resolved Hide resolved
substrate/client/network/test/src/sync.rs Show resolved Hide resolved
#[must_use]
pub fn actions(&mut self) -> Box<dyn Iterator<Item = SyncingAction<B>>> {
match self {
SyncingStrategy::WarpSyncStrategy(strategy) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Just for readability, maybe a good place for an Into implementation? But just a matter of taste.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'll do it in a follow-up PR #2814 to not complicate rebasing though)

@michalkucharczyk
Copy link
Contributor

lgtm, left some nits.

@dmitry-markin dmitry-markin added this pull request to the merge queue Jan 12, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to no response for status checks Jan 12, 2024
@dmitry-markin dmitry-markin added this pull request to the merge queue Jan 12, 2024
Merged via the queue into master with commit 5208bed Jan 12, 2024
120 checks passed
@dmitry-markin dmitry-markin deleted the dm-warp-sync-strategy branch January 12, 2024 16:47
use warp::{EncodedProof, WarpProofRequest, WarpSync, WarpSyncAction, WarpSyncConfig};

/// Corresponding `ChainSync` mode.
fn chain_sync_mode(sync_mode: SyncMode) -> ChainSyncMode {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function really necessary? It reverted paritytech/substrate#14465 and the fact that there are two types again makes it painful to backport paritytech/substrate#14482 (whose goal is to allow combining Substrate's sync with a custom sync mechanism we have in Subspace).

Can this be replaced with a method on SyncMode that returns true for both SyncMode::Full and SyncMode::Warp? Or match enum against two possible variants explicitly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What this and upcoming PRs aim to achieve is to clearly separate syncing strategies like Warp, State, ChainSync, etc. Introducing an atomic variable accessible by ChainSync that refers to warp sync would be going into the opposite direction.

On the other hand, once the refactoring is over, it should be possible to plug custom sync as a separate strategy and switch to ChainSync only when the initial sync is over, without the need to pause ChainSync. May be this will suite you?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that sounds like exactly what I need. Not sure if it will be flexible enough, but definitely sounds promising.

bgallois pushed a commit to duniter/duniter-polkadot-sdk that referenced this pull request Mar 25, 2024
Extract `WarpSync` (and `StateSync` as part of warp sync) from
`ChainSync` as independent syncing strategy called by `SyncingEngine`.
Introduce `SyncingStrategy` enum as a proxy between `SyncingEngine` and
specific syncing strategies.

## Limitations
Gap sync is kept in `ChainSync` for now because it shares the same set
of peers as block syncing implementation in `ChainSync`. Extraction of a
common context responsible for peer management in syncing strategies
able to run in parallel is planned for a follow-up PR.

## Further improvements
A possibility of conversion of `SyncingStartegy` into a trait should be
evaluated. The main stopper for this is that different strategies need
to communicate different actions to `SyncingEngine` and respond to
different events / provide different APIs (e.g., requesting
justifications is only possible via `ChainSync` and not through
`WarpSync`; `SendWarpProofRequest` action is only relevant to
`WarpSync`, etc.)

---------

Co-authored-by: Aaro Altonen <48052676+altonen@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T0-node This PR/Issue is related to the topic “node”.
Projects
Status: Blocked ⛔️
Status: Draft
Development

Successfully merging this pull request may close these issues.

6 participants