Skip to content

Commit 62d6f29

Browse files
altonendmitry-markinlexnv
authored
Rework the event system of sc-network (paritytech#1370)
This commit introduces a new concept called `NotificationService` which allows Polkadot protocols to communicate with the underlying notification protocol implementation directly, without routing events through `NetworkWorker`. This implies that each protocol has its own service which it uses to communicate with remote peers and that each `NotificationService` is unique with respect to the underlying notification protocol, meaning `NotificationService` for the transaction protocol can only be used to send and receive transaction-related notifications. The `NotificationService` concept introduces two additional benefits: * allow protocols to start using custom handshakes * allow protocols to accept/reject inbound peers Previously the validation of inbound connections was solely the responsibility of `ProtocolController`. This caused issues with light peers and `SyncingEngine` as `ProtocolController` would accept more peers than `SyncingEngine` could accept which caused peers to have differing views of their own states. `SyncingEngine` would reject excess peers but these rejections were not properly communicated to those peers causing them to assume that they were accepted. With `NotificationService`, the local handshake is not sent to remote peer if peer is rejected which allows it to detect that it was rejected. This commit also deprecates the use of `NetworkEventStream` for all notification-related events and going forward only DHT events are provided through `NetworkEventStream`. If protocols wish to follow each other's events, they must introduce additional abtractions, as is done for GRANDPA and transactions protocols by following the syncing protocol through `SyncEventStream`. Fixes paritytech#512 Fixes paritytech#514 Fixes paritytech#515 Fixes paritytech#554 Fixes paritytech#556 --- These changes are transferred from paritytech/substrate#14197 but there are no functional changes compared to that PR --------- Co-authored-by: Dmitry Markin <[email protected]> Co-authored-by: Alexandru Vasile <[email protected]>
1 parent cd9ee20 commit 62d6f29

File tree

86 files changed

+4545
-1842
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+4545
-1842
lines changed

substrate/bin/node-template/node/src/service.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,9 @@ pub fn new_full(config: Configuration) -> Result<TaskManager, ServiceError> {
163163
&client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"),
164164
&config.chain_spec,
165165
);
166-
net_config.add_notification_protocol(sc_consensus_grandpa::grandpa_peers_set_config(
167-
grandpa_protocol_name.clone(),
168-
));
166+
let (grandpa_protocol_config, grandpa_notification_service) =
167+
sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone());
168+
net_config.add_notification_protocol(grandpa_protocol_config);
169169

170170
let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new(
171171
backend.clone(),
@@ -316,6 +316,7 @@ pub fn new_full(config: Configuration) -> Result<TaskManager, ServiceError> {
316316
link: grandpa_link,
317317
network,
318318
sync: Arc::new(sync_service),
319+
notification_service: grandpa_notification_service,
319320
voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(),
320321
prometheus_registry,
321322
shared_voter_state: SharedVoterState::empty(),

substrate/bin/node/cli/src/service.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -370,28 +370,28 @@ pub fn new_full_base(
370370
let shared_voter_state = rpc_setup;
371371
let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht;
372372
let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network);
373-
374373
let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed");
375374

376375
let grandpa_protocol_name = grandpa::protocol_standard_name(&genesis_hash, &config.chain_spec);
377-
net_config.add_notification_protocol(grandpa::grandpa_peers_set_config(
378-
grandpa_protocol_name.clone(),
379-
));
376+
let (grandpa_protocol_config, grandpa_notification_service) =
377+
grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone());
378+
net_config.add_notification_protocol(grandpa_protocol_config);
380379

381-
let statement_handler_proto = sc_network_statement::StatementHandlerPrototype::new(
382-
genesis_hash,
383-
config.chain_spec.fork_id(),
384-
);
385-
net_config.add_notification_protocol(statement_handler_proto.set_config());
380+
let (statement_handler_proto, statement_config) =
381+
sc_network_statement::StatementHandlerPrototype::new(
382+
genesis_hash,
383+
config.chain_spec.fork_id(),
384+
);
385+
net_config.add_notification_protocol(statement_config);
386386

387387
let mixnet_protocol_name =
388388
sc_mixnet::protocol_name(genesis_hash.as_ref(), config.chain_spec.fork_id());
389-
if let Some(mixnet_config) = &mixnet_config {
390-
net_config.add_notification_protocol(sc_mixnet::peers_set_config(
391-
mixnet_protocol_name.clone(),
392-
mixnet_config,
393-
));
394-
}
389+
let mixnet_notification_service = mixnet_config.as_ref().map(|mixnet_config| {
390+
let (config, notification_service) =
391+
sc_mixnet::peers_set_config(mixnet_protocol_name.clone(), mixnet_config);
392+
net_config.add_notification_protocol(config);
393+
notification_service
394+
});
395395

396396
let warp_sync = Arc::new(grandpa::warp_proof::NetworkProvider::new(
397397
backend.clone(),
@@ -422,6 +422,8 @@ pub fn new_full_base(
422422
mixnet_protocol_name,
423423
transaction_pool.clone(),
424424
Some(keystore_container.keystore()),
425+
mixnet_notification_service
426+
.expect("`NotificationService` exists since mixnet was enabled; qed"),
425427
);
426428
task_manager.spawn_handle().spawn("mixnet", None, mixnet);
427429
}
@@ -590,6 +592,7 @@ pub fn new_full_base(
590592
link: grandpa_link,
591593
network: network.clone(),
592594
sync: Arc::new(sync_service.clone()),
595+
notification_service: grandpa_notification_service,
593596
telemetry: telemetry.as_ref().map(|x| x.handle()),
594597
voting_rule: grandpa::VotingRulesBuilder::default().build(),
595598
prometheus_registry: prometheus_registry.clone(),

substrate/client/consensus/beefy/src/communication/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,16 @@ pub(crate) mod beefy_protocol_name {
6767
/// For standard protocol name see [`beefy_protocol_name::gossip_protocol_name`].
6868
pub fn beefy_peers_set_config(
6969
gossip_protocol_name: sc_network::ProtocolName,
70-
) -> sc_network::config::NonDefaultSetConfig {
71-
let mut cfg = sc_network::config::NonDefaultSetConfig::new(gossip_protocol_name, 1024 * 1024);
70+
) -> (sc_network::config::NonDefaultSetConfig, Box<dyn sc_network::NotificationService>) {
71+
let (mut cfg, notification_service) = sc_network::config::NonDefaultSetConfig::new(
72+
gossip_protocol_name,
73+
Vec::new(),
74+
1024 * 1024,
75+
None,
76+
Default::default(),
77+
);
7278
cfg.allow_non_reserved(25, 25);
73-
cfg
79+
(cfg, notification_service)
7480
}
7581

7682
// cost scalars for reporting peers.

substrate/client/consensus/beefy/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use parking_lot::Mutex;
3838
use prometheus::Registry;
3939
use sc_client_api::{Backend, BlockBackend, BlockchainEvents, FinalityNotifications, Finalizer};
4040
use sc_consensus::BlockImport;
41-
use sc_network::{NetworkRequest, ProtocolName};
41+
use sc_network::{NetworkRequest, NotificationService, ProtocolName};
4242
use sc_network_gossip::{GossipEngine, Network as GossipNetwork, Syncing as GossipSyncing};
4343
use sp_api::ProvideRuntimeApi;
4444
use sp_blockchain::{
@@ -178,6 +178,8 @@ pub struct BeefyNetworkParams<B: Block, N, S> {
178178
pub network: Arc<N>,
179179
/// Syncing service implementing a sync oracle and an event stream for peers.
180180
pub sync: Arc<S>,
181+
/// Handle for receiving notification events.
182+
pub notification_service: Box<dyn NotificationService>,
181183
/// Chain specific BEEFY gossip protocol name. See
182184
/// [`communication::beefy_protocol_name::gossip_protocol_name`].
183185
pub gossip_protocol_name: ProtocolName,
@@ -243,6 +245,7 @@ pub async fn start_beefy_gadget<B, BE, C, N, P, R, S>(
243245
let BeefyNetworkParams {
244246
network,
245247
sync,
248+
notification_service,
246249
gossip_protocol_name,
247250
justifications_protocol_name,
248251
..
@@ -264,6 +267,7 @@ pub async fn start_beefy_gadget<B, BE, C, N, P, R, S>(
264267
let gossip_engine = GossipEngine::new(
265268
network.clone(),
266269
sync.clone(),
270+
notification_service,
267271
gossip_protocol_name.clone(),
268272
gossip_validator.clone(),
269273
None,

substrate/client/consensus/beefy/src/tests.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ use substrate_test_runtime_client::{BlockBuilderExt, ClientExt};
7272
use tokio::time::Duration;
7373

7474
const GENESIS_HASH: H256 = H256::zero();
75-
fn beefy_gossip_proto_name() -> ProtocolName {
75+
pub(crate) fn beefy_gossip_proto_name() -> ProtocolName {
7676
gossip_protocol_name(GENESIS_HASH, None)
7777
}
7878

@@ -371,6 +371,7 @@ async fn voter_init_setup(
371371
let mut gossip_engine = sc_network_gossip::GossipEngine::new(
372372
net.peer(0).network_service().clone(),
373373
net.peer(0).sync_service().clone(),
374+
net.peer(0).take_notification_service(&beefy_gossip_proto_name()).unwrap(),
374375
"/beefy/whatever",
375376
gossip_validator,
376377
None,
@@ -392,6 +393,14 @@ where
392393
{
393394
let tasks = FuturesUnordered::new();
394395

396+
let mut notification_services = peers
397+
.iter()
398+
.map(|(peer_id, _, _)| {
399+
let peer = &mut net.peers[*peer_id];
400+
(*peer_id, peer.take_notification_service(&beefy_gossip_proto_name()).unwrap())
401+
})
402+
.collect::<std::collections::HashMap<_, _>>();
403+
395404
for (peer_id, key, api) in peers.into_iter() {
396405
let peer = &net.peers[peer_id];
397406

@@ -409,6 +418,7 @@ where
409418
let network_params = crate::BeefyNetworkParams {
410419
network: peer.network_service().clone(),
411420
sync: peer.sync_service().clone(),
421+
notification_service: notification_services.remove(&peer_id).unwrap(),
412422
gossip_protocol_name: beefy_gossip_proto_name(),
413423
justifications_protocol_name: on_demand_justif_handler.protocol_name(),
414424
_phantom: PhantomData,
@@ -1045,7 +1055,25 @@ async fn should_initialize_voter_at_custom_genesis() {
10451055
net.peer(0).client().as_client().finalize_block(hashes[8], None).unwrap();
10461056

10471057
// load persistent state - nothing in DB, should init at genesis
1048-
let persisted_state = voter_init_setup(&mut net, &mut finality, &api).await.unwrap();
1058+
//
1059+
// NOTE: code from `voter_init_setup()` is moved here because the new network event system
1060+
// doesn't allow creating a new `GossipEngine` as the notification handle is consumed by the
1061+
// first `GossipEngine`
1062+
let known_peers = Arc::new(Mutex::new(KnownPeers::new()));
1063+
let (gossip_validator, _) = GossipValidator::new(known_peers);
1064+
let gossip_validator = Arc::new(gossip_validator);
1065+
let mut gossip_engine = sc_network_gossip::GossipEngine::new(
1066+
net.peer(0).network_service().clone(),
1067+
net.peer(0).sync_service().clone(),
1068+
net.peer(0).take_notification_service(&beefy_gossip_proto_name()).unwrap(),
1069+
"/beefy/whatever",
1070+
gossip_validator,
1071+
None,
1072+
);
1073+
let (beefy_genesis, best_grandpa) =
1074+
wait_for_runtime_pallet(&api, &mut gossip_engine, &mut finality).await.unwrap();
1075+
let persisted_state =
1076+
load_or_init_voter_state(&*backend, &api, beefy_genesis, best_grandpa, 1).unwrap();
10491077

10501078
// Test initialization at session boundary.
10511079
// verify voter initialized with single session starting at block `custom_pallet_genesis` (7)
@@ -1075,7 +1103,11 @@ async fn should_initialize_voter_at_custom_genesis() {
10751103

10761104
net.peer(0).client().as_client().finalize_block(hashes[10], None).unwrap();
10771105
// load persistent state - state preset in DB, but with different pallet genesis
1078-
let new_persisted_state = voter_init_setup(&mut net, &mut finality, &api).await.unwrap();
1106+
// the network state persists and uses the old `GossipEngine` initialized for `peer(0)`
1107+
let (beefy_genesis, best_grandpa) =
1108+
wait_for_runtime_pallet(&api, &mut gossip_engine, &mut finality).await.unwrap();
1109+
let new_persisted_state =
1110+
load_or_init_voter_state(&*backend, &api, beefy_genesis, best_grandpa, 1).unwrap();
10791111

10801112
// verify voter initialized with single session starting at block `new_pallet_genesis` (10)
10811113
let sessions = new_persisted_state.voting_oracle().sessions();
@@ -1371,7 +1403,7 @@ async fn gossipped_finality_proofs() {
13711403
let api = Arc::new(TestApi::with_validator_set(&validator_set));
13721404
let beefy_peers = peers.iter().enumerate().map(|(id, key)| (id, key, api.clone())).collect();
13731405

1374-
let charlie = &net.peers[2];
1406+
let charlie = &mut net.peers[2];
13751407
let known_peers = Arc::new(Mutex::new(KnownPeers::<Block>::new()));
13761408
// Charlie will run just the gossip engine and not the full voter.
13771409
let (gossip_validator, _) = GossipValidator::new(known_peers);
@@ -1384,6 +1416,7 @@ async fn gossipped_finality_proofs() {
13841416
let mut charlie_gossip_engine = sc_network_gossip::GossipEngine::new(
13851417
charlie.network_service().clone(),
13861418
charlie.sync_service().clone(),
1419+
charlie.take_notification_service(&beefy_gossip_proto_name()).unwrap(),
13871420
beefy_gossip_proto_name(),
13881421
charlie_gossip_validator.clone(),
13891422
None,

substrate/client/consensus/beefy/src/worker.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,12 +1145,16 @@ pub(crate) mod tests {
11451145
let api = Arc::new(TestApi::with_validator_set(&genesis_validator_set));
11461146
let network = peer.network_service().clone();
11471147
let sync = peer.sync_service().clone();
1148+
let notification_service = peer
1149+
.take_notification_service(&crate::tests::beefy_gossip_proto_name())
1150+
.unwrap();
11481151
let known_peers = Arc::new(Mutex::new(KnownPeers::new()));
11491152
let (gossip_validator, gossip_report_stream) = GossipValidator::new(known_peers.clone());
11501153
let gossip_validator = Arc::new(gossip_validator);
11511154
let gossip_engine = GossipEngine::new(
11521155
network.clone(),
11531156
sync.clone(),
1157+
notification_service,
11541158
"/beefy/1",
11551159
gossip_validator.clone(),
11561160
None,

substrate/client/consensus/grandpa/src/communication/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use finality_grandpa::{
4646
Message::{Precommit, Prevote, PrimaryPropose},
4747
};
4848
use parity_scale_codec::{Decode, DecodeAll, Encode};
49-
use sc_network::{NetworkBlock, NetworkSyncForkRequest, ReputationChange};
49+
use sc_network::{NetworkBlock, NetworkSyncForkRequest, NotificationService, ReputationChange};
5050
use sc_network_gossip::{GossipEngine, Network as GossipNetwork};
5151
use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_DEBUG, CONSENSUS_INFO};
5252
use sp_keystore::KeystorePtr;
@@ -247,6 +247,7 @@ impl<B: BlockT, N: Network<B>, S: Syncing<B>> NetworkBridge<B, N, S> {
247247
pub(crate) fn new(
248248
service: N,
249249
sync: S,
250+
notification_service: Box<dyn NotificationService>,
250251
config: crate::Config,
251252
set_state: crate::environment::SharedVoterSetState<B>,
252253
prometheus_registry: Option<&Registry>,
@@ -260,6 +261,7 @@ impl<B: BlockT, N: Network<B>, S: Syncing<B>> NetworkBridge<B, N, S> {
260261
let gossip_engine = Arc::new(Mutex::new(GossipEngine::new(
261262
service.clone(),
262263
sync.clone(),
264+
notification_service,
263265
protocol,
264266
validator.clone(),
265267
prometheus_registry,

0 commit comments

Comments
 (0)