Extract syncing protocol from sc-network (#12828)

* Move import queue out of `sc-network`

Add supplementary asynchronous API for the import queue which means
it can be run as an independent task and communicated with through
the `ImportQueueService`.

This commit removes removes block and justification imports from
`sc-network` and provides `ChainSync` with a handle to import queue so
it can import blocks and justifications. Polling of the import queue is
moved complete out of `sc-network` and `sc_consensus::Link` is
implemented for `ChainSyncInterfaceHandled` so the import queue
can still influence the syncing process.

* Move stuff to SyncingEngine

* Move `ChainSync` instanation to `SyncingEngine`

Some of the tests have to be rewritten

* Move peer hashmap to `SyncingEngine`

* Let `SyncingEngine` to implement `ChainSyncInterface`

* Introduce `SyncStatusProvider`

* Move `sync_peer_(connected|disconnected)` to `SyncingEngine`

* Implement `SyncEventStream`

Remove `SyncConnected`/`SyncDisconnected` events from
`NetworkEvenStream` and provide those events through
`ChainSyncInterface` instead.

Modify BEEFY/GRANDPA/transactions protocol and `NetworkGossip` to take
`SyncEventStream` object which they listen to for incoming sync peer
events.

* Introduce `ChainSyncInterface`

This interface provides a set of miscellaneous functions that other
subsystems can use to query, for example, the syncing status.

* Move event stream polling to `SyncingEngine`

Subscribe to `NetworkStreamEvent` and poll the incoming notifications
and substream events from `SyncingEngine`.

The code needs refactoring.

* Make `SyncingEngine` into an asynchronous runner

This commits removes the last hard dependency of syncing from
`sc-network` meaning the protocol now lives completely outside of
`sc-network`, ignoring the hardcoded peerset entry which will be
addressed in the future.

Code needs a lot of refactoring.

* Fix warnings

* Code refactoring

* Use `SyncingService` for BEEFY

* Use `SyncingService` for GRANDPA

* Remove call delegation from `NetworkService`

* Remove `ChainSyncService`

* Remove `ChainSync` service tests

They were written for the sole purpose of verifying that `NetworWorker`
continues to function while the calls are being dispatched to
`ChainSync`.

* Refactor code

* Refactor code

* Update client/finality-grandpa/src/communication/tests.rs

Co-authored-by: Anton <anton.kalyaev@gmail.com>

* Fix warnings

* Apply review comments

* Fix docs

* Fix test

* cargo-fmt

* Update client/network/sync/src/engine.rs

Co-authored-by: Anton <anton.kalyaev@gmail.com>

* Update client/network/sync/src/engine.rs

Co-authored-by: Anton <anton.kalyaev@gmail.com>

* Add missing docs

* Refactor code

---------

Co-authored-by: Anton <anton.kalyaev@gmail.com>
This commit is contained in:
Aaro Altonen
2023-03-06 18:33:38 +02:00
committed by GitHub
parent 8adde84330
commit 1a7f5be07f
57 changed files with 2904 additions and 2877 deletions
+20 -10
View File
@@ -40,7 +40,7 @@ use sc_client_api::{Backend, BlockBackend, BlockchainEvents, FinalityNotificatio
use sc_consensus::BlockImport;
use sc_network::ProtocolName;
use sc_network_common::service::NetworkRequest;
use sc_network_gossip::{GossipEngine, Network as GossipNetwork};
use sc_network_gossip::{GossipEngine, Network as GossipNetwork, Syncing as GossipSyncing};
use sp_api::{HeaderT, NumberFor, ProvideRuntimeApi};
use sp_blockchain::{
Backend as BlockchainBackend, Error as ClientError, HeaderBackend, Result as ClientResult,
@@ -172,9 +172,11 @@ where
}
/// BEEFY gadget network parameters.
pub struct BeefyNetworkParams<B: Block, N> {
pub struct BeefyNetworkParams<B: Block, N, S> {
/// Network implementing gossip, requests and sync-oracle.
pub network: Arc<N>,
/// Syncing service implementing a sync oracle and an event stream for peers.
pub sync: Arc<S>,
/// Chain specific BEEFY gossip protocol name. See
/// [`communication::beefy_protocol_name::gossip_protocol_name`].
pub gossip_protocol_name: ProtocolName,
@@ -186,7 +188,7 @@ pub struct BeefyNetworkParams<B: Block, N> {
}
/// BEEFY gadget initialization parameters.
pub struct BeefyParams<B: Block, BE, C, N, P, R> {
pub struct BeefyParams<B: Block, BE, C, N, P, R, S> {
/// BEEFY client
pub client: Arc<C>,
/// Client Backend
@@ -198,7 +200,7 @@ pub struct BeefyParams<B: Block, BE, C, N, P, R> {
/// Local key store
pub key_store: Option<SyncCryptoStorePtr>,
/// BEEFY voter network params
pub network_params: BeefyNetworkParams<B, N>,
pub network_params: BeefyNetworkParams<B, N, S>,
/// Minimal delta between blocks, BEEFY should vote for
pub min_block_delta: u32,
/// Prometheus metric registry
@@ -212,15 +214,17 @@ pub struct BeefyParams<B: Block, BE, C, N, P, R> {
/// Start the BEEFY gadget.
///
/// This is a thin shim around running and awaiting a BEEFY worker.
pub async fn start_beefy_gadget<B, BE, C, N, P, R>(beefy_params: BeefyParams<B, BE, C, N, P, R>)
where
pub async fn start_beefy_gadget<B, BE, C, N, P, R, S>(
beefy_params: BeefyParams<B, BE, C, N, P, R, S>,
) where
B: Block,
BE: Backend<B>,
C: Client<B, BE> + BlockBackend<B>,
P: PayloadProvider<B>,
R: ProvideRuntimeApi<B>,
R::Api: BeefyApi<B> + MmrApi<B, MmrRootHash, NumberFor<B>>,
N: GossipNetwork<B> + NetworkRequest + SyncOracle + Send + Sync + 'static,
N: GossipNetwork<B> + NetworkRequest + Send + Sync + 'static,
S: GossipSyncing<B> + SyncOracle + 'static,
{
let BeefyParams {
client,
@@ -235,14 +239,20 @@ where
on_demand_justifications_handler,
} = beefy_params;
let BeefyNetworkParams { network, gossip_protocol_name, justifications_protocol_name, .. } =
network_params;
let BeefyNetworkParams {
network,
sync,
gossip_protocol_name,
justifications_protocol_name,
..
} = network_params;
let known_peers = Arc::new(Mutex::new(KnownPeers::new()));
let gossip_validator =
Arc::new(communication::gossip::GossipValidator::new(known_peers.clone()));
let mut gossip_engine = sc_network_gossip::GossipEngine::new(
network.clone(),
sync.clone(),
gossip_protocol_name,
gossip_validator.clone(),
None,
@@ -280,7 +290,7 @@ where
backend,
payload_provider,
runtime,
network,
sync,
key_store: key_store.into(),
gossip_engine,
gossip_validator,
@@ -223,6 +223,10 @@ impl TestNetFactory for BeefyTestNet {
&self.peers
}
fn peers_mut(&mut self) -> &mut Vec<BeefyPeer> {
&mut self.peers
}
fn mut_peers<F: FnOnce(&mut Vec<BeefyPeer>)>(&mut self, closure: F) {
closure(&mut self.peers);
}
@@ -353,6 +357,7 @@ async fn voter_init_setup(
Arc::new(crate::communication::gossip::GossipValidator::new(known_peers));
let mut gossip_engine = sc_network_gossip::GossipEngine::new(
net.peer(0).network_service().clone(),
net.peer(0).sync_service().clone(),
"/beefy/whatever",
gossip_validator,
None,
@@ -389,6 +394,7 @@ where
let network_params = crate::BeefyNetworkParams {
network: peer.network_service().clone(),
sync: peer.sync_service().clone(),
gossip_protocol_name: beefy_gossip_proto_name(),
justifications_protocol_name: on_demand_justif_handler.protocol_name(),
_phantom: PhantomData,
@@ -407,7 +413,7 @@ where
prometheus_registry: None,
on_demand_justifications_handler: on_demand_justif_handler,
};
let task = crate::start_beefy_gadget::<_, _, _, _, _, _>(beefy_params);
let task = crate::start_beefy_gadget::<_, _, _, _, _, _, _>(beefy_params);
fn assert_send<T: Send>(_: &T) {}
assert_send(&task);
+22 -17
View File
@@ -33,7 +33,6 @@ use codec::{Codec, Decode, Encode};
use futures::{stream::Fuse, FutureExt, StreamExt};
use log::{debug, error, info, log_enabled, trace, warn};
use sc_client_api::{Backend, FinalityNotification, FinalityNotifications, HeaderBackend};
use sc_network_common::service::{NetworkEventStream, NetworkRequest};
use sc_network_gossip::GossipEngine;
use sc_utils::notification::NotificationReceiver;
use sp_api::{BlockId, ProvideRuntimeApi};
@@ -244,11 +243,11 @@ impl<B: Block> VoterOracle<B> {
}
}
pub(crate) struct WorkerParams<B: Block, BE, P, R, N> {
pub(crate) struct WorkerParams<B: Block, BE, P, R, S> {
pub backend: Arc<BE>,
pub payload_provider: P,
pub runtime: Arc<R>,
pub network: N,
pub sync: Arc<S>,
pub key_store: BeefyKeystore,
pub gossip_engine: GossipEngine<B>,
pub gossip_validator: Arc<GossipValidator<B>>,
@@ -296,12 +295,12 @@ impl<B: Block> PersistedState<B> {
}
/// A BEEFY worker plays the BEEFY protocol
pub(crate) struct BeefyWorker<B: Block, BE, P, RuntimeApi, N> {
pub(crate) struct BeefyWorker<B: Block, BE, P, RuntimeApi, S> {
// utilities
backend: Arc<BE>,
payload_provider: P,
runtime: Arc<RuntimeApi>,
network: N,
sync: Arc<S>,
key_store: BeefyKeystore,
// communication
@@ -330,14 +329,14 @@ pub(crate) struct BeefyWorker<B: Block, BE, P, RuntimeApi, N> {
persisted_state: PersistedState<B>,
}
impl<B, BE, P, R, N> BeefyWorker<B, BE, P, R, N>
impl<B, BE, P, R, S> BeefyWorker<B, BE, P, R, S>
where
B: Block + Codec,
BE: Backend<B>,
P: PayloadProvider<B>,
S: SyncOracle,
R: ProvideRuntimeApi<B>,
R::Api: BeefyApi<B>,
N: NetworkEventStream + NetworkRequest + SyncOracle + Send + Sync + Clone + 'static,
{
/// Return a new BEEFY worker instance.
///
@@ -345,13 +344,13 @@ where
/// BEEFY pallet has been deployed on-chain.
///
/// The BEEFY pallet is needed in order to keep track of the BEEFY authority set.
pub(crate) fn new(worker_params: WorkerParams<B, BE, P, R, N>) -> Self {
pub(crate) fn new(worker_params: WorkerParams<B, BE, P, R, S>) -> Self {
let WorkerParams {
backend,
payload_provider,
runtime,
key_store,
network,
sync,
gossip_engine,
gossip_validator,
on_demand_justifications,
@@ -364,7 +363,7 @@ where
backend,
payload_provider,
runtime,
network,
sync,
key_store,
gossip_engine,
gossip_validator,
@@ -836,7 +835,7 @@ where
}
// Don't bother voting or requesting justifications during major sync.
if !self.network.is_major_syncing() {
if !self.sync.is_major_syncing() {
// There were external events, 'state' is changed, author a vote if needed/possible.
if let Err(err) = self.try_to_vote() {
debug!(target: LOG_TARGET, "🥩 {}", err);
@@ -1065,7 +1064,7 @@ pub(crate) mod tests {
use futures::{future::poll_fn, task::Poll};
use parking_lot::Mutex;
use sc_client_api::{Backend as BackendT, HeaderBackend};
use sc_network::NetworkService;
use sc_network_sync::SyncingService;
use sc_network_test::TestNetFactory;
use sp_api::HeaderT;
use sp_blockchain::Backend as BlockchainBackendT;
@@ -1075,7 +1074,7 @@ pub(crate) mod tests {
};
use sp_runtime::traits::One;
use substrate_test_runtime_client::{
runtime::{Block, Digest, DigestItem, Header, H256},
runtime::{Block, Digest, DigestItem, Header},
Backend,
};
@@ -1113,7 +1112,7 @@ pub(crate) mod tests {
Backend,
MmrRootProvider<Block, TestApi>,
TestApi,
Arc<NetworkService<Block, H256>>,
Arc<SyncingService<Block>>,
> {
let keystore = create_beefy_keystore(*key);
@@ -1137,10 +1136,16 @@ pub(crate) mod tests {
let backend = peer.client().as_backend();
let api = Arc::new(TestApi::with_validator_set(&genesis_validator_set));
let network = peer.network_service().clone();
let sync = peer.sync_service().clone();
let known_peers = Arc::new(Mutex::new(KnownPeers::new()));
let gossip_validator = Arc::new(GossipValidator::new(known_peers.clone()));
let gossip_engine =
GossipEngine::new(network.clone(), "/beefy/1", gossip_validator.clone(), None);
let gossip_engine = GossipEngine::new(
network.clone(),
sync.clone(),
"/beefy/1",
gossip_validator.clone(),
None,
);
let metrics = None;
let on_demand_justifications = OnDemandJustificationsEngine::new(
network.clone(),
@@ -1169,7 +1174,7 @@ pub(crate) mod tests {
gossip_engine,
gossip_validator,
metrics,
network,
sync: Arc::new(sync),
on_demand_justifications,
persisted_state,
};