1use super::{Error, IsParachainNode, Registry};
18use polkadot_collator_protocol::ReputationConfig;
19use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient};
20use polkadot_overseer::{DummySubsystem, InitializedOverseerBuilder, SubsystemError};
21use sp_core::traits::SpawnNamed;
22
23use polkadot_availability_distribution::IncomingRequestReceivers;
24use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig;
25use polkadot_node_core_av_store::Config as AvailabilityConfig;
26use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig;
27use polkadot_node_core_chain_selection::Config as ChainSelectionConfig;
28use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig;
29use polkadot_node_network_protocol::{
30 peer_set::{PeerSet, PeerSetProtocolNames},
31 request_response::{
32 v1 as request_v1, v2 as request_v2, v3 as request_v3, IncomingRequestReceiver,
33 ReqProtocolNames,
34 },
35};
36#[cfg(any(feature = "malus", test))]
37pub use polkadot_overseer::{dummy::dummy_overseer_builder, HeadSupportsParachains};
38use polkadot_overseer::{
39 metrics::Metrics as OverseerMetrics, MetricsTrait, Overseer, OverseerConnector, OverseerHandle,
40 SpawnGlue,
41};
42
43use parking_lot::Mutex;
44use sc_authority_discovery::Service as AuthorityDiscoveryService;
45use sc_client_api::AuxStore;
46use sc_keystore::LocalKeystore;
47use sc_network::{NetworkStateInfo, NotificationService};
48use std::{
49 collections::{HashMap, HashSet},
50 sync::Arc,
51 time::Duration,
52};
53
54pub use polkadot_approval_distribution::ApprovalDistribution as ApprovalDistributionSubsystem;
55pub use polkadot_availability_bitfield_distribution::BitfieldDistribution as BitfieldDistributionSubsystem;
56pub use polkadot_availability_distribution::AvailabilityDistributionSubsystem;
57pub use polkadot_availability_recovery::AvailabilityRecoverySubsystem;
58pub use polkadot_collator_protocol::{CollatorProtocolSubsystem, ProtocolSide};
59pub use polkadot_dispute_distribution::DisputeDistributionSubsystem;
60pub use polkadot_gossip_support::GossipSupport as GossipSupportSubsystem;
61pub use polkadot_network_bridge::{
62 Metrics as NetworkBridgeMetrics, NetworkBridgeRx as NetworkBridgeRxSubsystem,
63 NetworkBridgeTx as NetworkBridgeTxSubsystem,
64};
65pub use polkadot_node_collation_generation::CollationGenerationSubsystem;
66pub use polkadot_node_core_approval_voting::ApprovalVotingSubsystem;
67pub use polkadot_node_core_approval_voting_parallel::{
68 ApprovalVotingParallelSubsystem, Metrics as ApprovalVotingParallelMetrics,
69};
70pub use polkadot_node_core_av_store::AvailabilityStoreSubsystem;
71pub use polkadot_node_core_backing::CandidateBackingSubsystem;
72pub use polkadot_node_core_bitfield_signing::BitfieldSigningSubsystem;
73pub use polkadot_node_core_candidate_validation::CandidateValidationSubsystem;
74pub use polkadot_node_core_chain_api::ChainApiSubsystem;
75pub use polkadot_node_core_chain_selection::ChainSelectionSubsystem;
76pub use polkadot_node_core_dispute_coordinator::DisputeCoordinatorSubsystem;
77pub use polkadot_node_core_prospective_parachains::ProspectiveParachainsSubsystem;
78pub use polkadot_node_core_provisioner::ProvisionerSubsystem;
79pub use polkadot_node_core_pvf_checker::PvfCheckerSubsystem;
80pub use polkadot_node_core_runtime_api::RuntimeApiSubsystem;
81pub use polkadot_statement_distribution::StatementDistributionSubsystem;
82
83pub struct OverseerGenArgs<'a, Spawner, RuntimeClient>
85where
86 Spawner: 'static + SpawnNamed + Clone + Unpin,
87{
88 pub runtime_client: Arc<RuntimeClient>,
90 pub network_service: Arc<dyn sc_network::service::traits::NetworkService>,
92 pub sync_service: Arc<dyn sp_consensus::SyncOracle + Send + Sync>,
94 pub authority_discovery_service: AuthorityDiscoveryService,
96 pub collation_req_v2_receiver: IncomingRequestReceiver<request_v2::CollationFetchingRequest>,
98 pub collation_req_v3_receiver: IncomingRequestReceiver<request_v3::CollationFetchingRequest>,
100 pub available_data_req_receiver:
102 IncomingRequestReceiver<request_v1::AvailableDataFetchingRequest>,
103 pub registry: Option<&'a Registry>,
105 pub spawner: Spawner,
107 pub is_parachain_node: IsParachainNode,
109 pub overseer_message_channel_capacity_override: Option<usize>,
111 pub req_protocol_names: ReqProtocolNames,
113 pub peerset_protocol_names: PeerSetProtocolNames,
115 pub notification_services: HashMap<PeerSet, Box<dyn NotificationService>>,
117}
118
119pub struct ExtendedOverseerGenArgs {
120 pub keystore: Arc<LocalKeystore>,
122 pub parachains_db: Arc<dyn polkadot_node_subsystem_util::database::Database>,
124 pub candidate_validation_config: Option<CandidateValidationConfig>,
126 pub availability_config: AvailabilityConfig,
128 pub pov_req_receiver: IncomingRequestReceiver<request_v1::PoVFetchingRequest>,
130 pub chunk_req_v1_receiver: IncomingRequestReceiver<request_v1::ChunkFetchingRequest>,
132 pub chunk_req_v2_receiver: IncomingRequestReceiver<request_v2::ChunkFetchingRequest>,
134 pub candidate_req_v2_receiver: IncomingRequestReceiver<request_v2::AttestedCandidateRequest>,
136 pub approval_voting_config: ApprovalVotingConfig,
138 pub dispute_req_receiver: IncomingRequestReceiver<request_v1::DisputeRequest>,
140 pub dispute_coordinator_config: DisputeCoordinatorConfig,
142 pub chain_selection_config: ChainSelectionConfig,
144 pub fetch_chunks_threshold: Option<usize>,
148 pub invulnerable_ah_collators: HashSet<polkadot_node_network_protocol::PeerId>,
150 pub collator_protocol_hold_off: Option<Duration>,
152 pub experimental_collator_protocol: bool,
154 pub reputation_config: ReputationConfig,
156}
157
158pub fn validator_overseer_builder<Spawner, RuntimeClient>(
160 OverseerGenArgs {
161 runtime_client,
162 network_service,
163 sync_service,
164 authority_discovery_service,
165 collation_req_v2_receiver: _,
166 collation_req_v3_receiver: _,
167 available_data_req_receiver,
168 registry,
169 spawner,
170 is_parachain_node,
171 overseer_message_channel_capacity_override,
172 req_protocol_names,
173 peerset_protocol_names,
174 notification_services,
175 }: OverseerGenArgs<Spawner, RuntimeClient>,
176 ExtendedOverseerGenArgs {
177 keystore,
178 parachains_db,
179 candidate_validation_config,
180 availability_config,
181 pov_req_receiver,
182 chunk_req_v1_receiver,
183 chunk_req_v2_receiver,
184 candidate_req_v2_receiver,
185 approval_voting_config,
186 dispute_req_receiver,
187 dispute_coordinator_config,
188 chain_selection_config,
189 fetch_chunks_threshold,
190 invulnerable_ah_collators,
191 collator_protocol_hold_off,
192 experimental_collator_protocol,
193 reputation_config,
194 }: ExtendedOverseerGenArgs,
195) -> Result<
196 InitializedOverseerBuilder<
197 SpawnGlue<Spawner>,
198 Arc<RuntimeClient>,
199 CandidateValidationSubsystem,
200 PvfCheckerSubsystem,
201 CandidateBackingSubsystem,
202 StatementDistributionSubsystem,
203 AvailabilityDistributionSubsystem,
204 AvailabilityRecoverySubsystem,
205 BitfieldSigningSubsystem,
206 BitfieldDistributionSubsystem,
207 ProvisionerSubsystem,
208 RuntimeApiSubsystem<RuntimeClient>,
209 AvailabilityStoreSubsystem,
210 NetworkBridgeRxSubsystem<
211 Arc<dyn sc_network::service::traits::NetworkService>,
212 AuthorityDiscoveryService,
213 >,
214 NetworkBridgeTxSubsystem<
215 Arc<dyn sc_network::service::traits::NetworkService>,
216 AuthorityDiscoveryService,
217 >,
218 ChainApiSubsystem<RuntimeClient>,
219 DummySubsystem,
220 CollatorProtocolSubsystem,
221 DummySubsystem,
222 DummySubsystem,
223 ApprovalVotingParallelSubsystem,
224 GossipSupportSubsystem<AuthorityDiscoveryService>,
225 DisputeCoordinatorSubsystem,
226 DisputeDistributionSubsystem<AuthorityDiscoveryService>,
227 ChainSelectionSubsystem,
228 ProspectiveParachainsSubsystem,
229 >,
230 Error,
231>
232where
233 RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
234 Spawner: 'static + SpawnNamed + Clone + Unpin,
235{
236 use polkadot_node_subsystem_util::metrics::Metrics;
237
238 let metrics = <OverseerMetrics as MetricsTrait>::register(registry)?;
239 let notification_sinks = Arc::new(Mutex::new(HashMap::new()));
240
241 let spawner = SpawnGlue(spawner);
242
243 let network_bridge_metrics: NetworkBridgeMetrics = Metrics::register(registry)?;
244 let approval_voting_parallel_metrics: ApprovalVotingParallelMetrics =
245 Metrics::register(registry)?;
246 let builder = Overseer::builder()
247 .network_bridge_tx(NetworkBridgeTxSubsystem::new(
248 network_service.clone(),
249 authority_discovery_service.clone(),
250 network_bridge_metrics.clone(),
251 req_protocol_names.clone(),
252 peerset_protocol_names.clone(),
253 notification_sinks.clone(),
254 ))
255 .network_bridge_rx(NetworkBridgeRxSubsystem::new(
256 network_service.clone(),
257 authority_discovery_service.clone(),
258 Box::new(sync_service.clone()),
259 network_bridge_metrics,
260 peerset_protocol_names,
261 notification_services,
262 notification_sinks,
263 ))
264 .availability_distribution(AvailabilityDistributionSubsystem::new(
265 keystore.clone(),
266 IncomingRequestReceivers {
267 pov_req_receiver,
268 chunk_req_v1_receiver,
269 chunk_req_v2_receiver,
270 },
271 req_protocol_names.clone(),
272 Metrics::register(registry)?,
273 ))
274 .availability_recovery(AvailabilityRecoverySubsystem::for_validator(
275 fetch_chunks_threshold,
276 available_data_req_receiver,
277 &req_protocol_names,
278 Metrics::register(registry)?,
279 ))
280 .availability_store(AvailabilityStoreSubsystem::new(
281 parachains_db.clone(),
282 availability_config,
283 Box::new(sync_service.clone()),
284 Metrics::register(registry)?,
285 ))
286 .bitfield_distribution(BitfieldDistributionSubsystem::new(Metrics::register(registry)?))
287 .bitfield_signing(BitfieldSigningSubsystem::new(
288 keystore.clone(),
289 Metrics::register(registry)?,
290 ))
291 .candidate_backing(CandidateBackingSubsystem::new(
292 keystore.clone(),
293 Metrics::register(registry)?,
294 ))
295 .candidate_validation(CandidateValidationSubsystem::with_config(
296 candidate_validation_config,
297 keystore.clone(),
298 Metrics::register(registry)?, Metrics::register(registry)?, ))
301 .pvf_checker(PvfCheckerSubsystem::new(keystore.clone(), Metrics::register(registry)?))
302 .chain_api(ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?))
303 .collation_generation(DummySubsystem)
304 .collator_protocol({
305 let side = match is_parachain_node {
306 IsParachainNode::Collator(_) | IsParachainNode::FullNode => {
307 return Err(Error::Overseer(SubsystemError::Context(
308 "build validator overseer for parachain node".to_owned(),
309 )))
310 },
311 IsParachainNode::No => {
312 if experimental_collator_protocol {
313 ProtocolSide::ValidatorExperimental {
314 keystore: keystore.clone(),
315 metrics: Metrics::register(registry)?,
316 db: parachains_db.clone(),
317 reputation_config,
318 clock: polkadot_node_clock::system_clock(),
319 }
320 } else {
321 ProtocolSide::Validator {
322 keystore: keystore.clone(),
323 eviction_policy: Default::default(),
324 metrics: Metrics::register(registry)?,
325 invulnerables: invulnerable_ah_collators,
326 collator_protocol_hold_off,
327 clock: polkadot_node_clock::system_clock(),
328 }
329 }
330 },
331 };
332 CollatorProtocolSubsystem::new(side)
333 })
334 .provisioner(ProvisionerSubsystem::new(Metrics::register(registry)?))
335 .runtime_api(RuntimeApiSubsystem::new(
336 runtime_client.clone(),
337 Metrics::register(registry)?,
338 spawner.clone(),
339 ))
340 .statement_distribution(StatementDistributionSubsystem::new(
341 keystore.clone(),
342 candidate_req_v2_receiver,
343 Metrics::register(registry)?,
344 ))
345 .approval_distribution(DummySubsystem)
346 .approval_voting(DummySubsystem)
347 .approval_voting_parallel(ApprovalVotingParallelSubsystem::with_config(
348 approval_voting_config,
349 parachains_db.clone(),
350 keystore.clone(),
351 Box::new(sync_service.clone()),
352 approval_voting_parallel_metrics,
353 spawner.clone(),
354 overseer_message_channel_capacity_override,
355 ))
356 .gossip_support(GossipSupportSubsystem::new(
357 keystore.clone(),
358 authority_discovery_service.clone(),
359 Metrics::register(registry)?,
360 ))
361 .dispute_coordinator(DisputeCoordinatorSubsystem::new(
362 parachains_db.clone(),
363 dispute_coordinator_config,
364 keystore.clone(),
365 Metrics::register(registry)?,
366 ))
367 .dispute_distribution(DisputeDistributionSubsystem::new(
368 keystore.clone(),
369 dispute_req_receiver,
370 authority_discovery_service.clone(),
371 Metrics::register(registry)?,
372 ))
373 .chain_selection(ChainSelectionSubsystem::new(chain_selection_config, parachains_db))
374 .prospective_parachains(ProspectiveParachainsSubsystem::new(Metrics::register(registry)?))
375 .activation_external_listeners(Default::default())
376 .active_leaves(Default::default())
377 .supports_parachains(runtime_client)
378 .metrics(metrics)
379 .spawner(spawner);
380
381 let builder = if let Some(capacity) = overseer_message_channel_capacity_override {
382 builder.message_channel_capacity(capacity)
383 } else {
384 builder
385 };
386 Ok(builder)
387}
388
389pub fn collator_overseer_builder<Spawner, RuntimeClient>(
391 OverseerGenArgs {
392 runtime_client,
393 network_service,
394 sync_service,
395 authority_discovery_service,
396 collation_req_v2_receiver,
397 collation_req_v3_receiver,
398 available_data_req_receiver,
399 registry,
400 spawner,
401 is_parachain_node,
402 overseer_message_channel_capacity_override,
403 req_protocol_names,
404 peerset_protocol_names,
405 notification_services,
406 }: OverseerGenArgs<Spawner, RuntimeClient>,
407) -> Result<
408 InitializedOverseerBuilder<
409 SpawnGlue<Spawner>,
410 Arc<RuntimeClient>,
411 DummySubsystem,
412 DummySubsystem,
413 DummySubsystem,
414 DummySubsystem,
415 DummySubsystem,
416 AvailabilityRecoverySubsystem,
417 DummySubsystem,
418 DummySubsystem,
419 DummySubsystem,
420 RuntimeApiSubsystem<RuntimeClient>,
421 DummySubsystem,
422 NetworkBridgeRxSubsystem<
423 Arc<dyn sc_network::service::traits::NetworkService>,
424 AuthorityDiscoveryService,
425 >,
426 NetworkBridgeTxSubsystem<
427 Arc<dyn sc_network::service::traits::NetworkService>,
428 AuthorityDiscoveryService,
429 >,
430 ChainApiSubsystem<RuntimeClient>,
431 CollationGenerationSubsystem,
432 CollatorProtocolSubsystem,
433 DummySubsystem,
434 DummySubsystem,
435 DummySubsystem,
436 DummySubsystem,
437 DummySubsystem,
438 DummySubsystem,
439 DummySubsystem,
440 DummySubsystem,
441 >,
442 Error,
443>
444where
445 Spawner: 'static + SpawnNamed + Clone + Unpin,
446 RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
447{
448 use polkadot_node_subsystem_util::metrics::Metrics;
449
450 let notification_sinks = Arc::new(Mutex::new(HashMap::new()));
451
452 let spawner = SpawnGlue(spawner);
453
454 let network_bridge_metrics: NetworkBridgeMetrics = Metrics::register(registry)?;
455
456 let builder = Overseer::builder()
457 .network_bridge_tx(NetworkBridgeTxSubsystem::new(
458 network_service.clone(),
459 authority_discovery_service.clone(),
460 network_bridge_metrics.clone(),
461 req_protocol_names.clone(),
462 peerset_protocol_names.clone(),
463 notification_sinks.clone(),
464 ))
465 .network_bridge_rx(NetworkBridgeRxSubsystem::new(
466 network_service.clone(),
467 authority_discovery_service.clone(),
468 Box::new(sync_service.clone()),
469 network_bridge_metrics,
470 peerset_protocol_names,
471 notification_services,
472 notification_sinks,
473 ))
474 .availability_distribution(DummySubsystem)
475 .availability_recovery(AvailabilityRecoverySubsystem::for_collator(
476 None,
477 available_data_req_receiver,
478 &req_protocol_names,
479 Metrics::register(registry)?,
480 ))
481 .availability_store(DummySubsystem)
482 .bitfield_distribution(DummySubsystem)
483 .bitfield_signing(DummySubsystem)
484 .candidate_backing(DummySubsystem)
485 .candidate_validation(DummySubsystem)
486 .pvf_checker(DummySubsystem)
487 .chain_api(ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?))
488 .collation_generation(CollationGenerationSubsystem::new(Metrics::register(registry)?))
489 .collator_protocol({
490 let side = match is_parachain_node {
491 IsParachainNode::No => {
492 return Err(Error::Overseer(SubsystemError::Context(
493 "build parachain node overseer for validator".to_owned(),
494 )))
495 },
496 IsParachainNode::Collator(collator_pair) => ProtocolSide::Collator {
497 peer_id: network_service.local_peer_id(),
498 collator_pair,
499 request_receiver_v2: collation_req_v2_receiver,
500 request_receiver_v3: collation_req_v3_receiver,
501 metrics: Metrics::register(registry)?,
502 clock: polkadot_node_clock::system_clock(),
503 },
504 IsParachainNode::FullNode => ProtocolSide::None,
505 };
506 CollatorProtocolSubsystem::new(side)
507 })
508 .provisioner(DummySubsystem)
509 .runtime_api(RuntimeApiSubsystem::new(
510 runtime_client.clone(),
511 Metrics::register(registry)?,
512 spawner.clone(),
513 ))
514 .statement_distribution(DummySubsystem)
515 .approval_distribution(DummySubsystem)
516 .approval_voting(DummySubsystem)
517 .approval_voting_parallel(DummySubsystem)
518 .gossip_support(DummySubsystem)
519 .dispute_coordinator(DummySubsystem)
520 .dispute_distribution(DummySubsystem)
521 .chain_selection(DummySubsystem)
522 .prospective_parachains(DummySubsystem)
523 .activation_external_listeners(Default::default())
524 .active_leaves(Default::default())
525 .supports_parachains(runtime_client)
526 .metrics(Metrics::register(registry)?)
527 .spawner(spawner);
528
529 let builder = if let Some(capacity) = overseer_message_channel_capacity_override {
530 builder.message_channel_capacity(capacity)
531 } else {
532 builder
533 };
534 Ok(builder)
535}
536
537pub trait OverseerGen {
539 fn generate<Spawner, RuntimeClient>(
541 &self,
542 connector: OverseerConnector,
543 args: OverseerGenArgs<Spawner, RuntimeClient>,
544 ext_args: Option<ExtendedOverseerGenArgs>,
545 ) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
546 where
547 RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
548 Spawner: 'static + SpawnNamed + Clone + Unpin;
549
550 }
554
555pub struct ValidatorOverseerGen;
557
558impl OverseerGen for ValidatorOverseerGen {
559 fn generate<Spawner, RuntimeClient>(
560 &self,
561 connector: OverseerConnector,
562 args: OverseerGenArgs<Spawner, RuntimeClient>,
563 ext_args: Option<ExtendedOverseerGenArgs>,
564 ) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
565 where
566 RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
567 Spawner: 'static + SpawnNamed + Clone + Unpin,
568 {
569 let ext_args = ext_args.ok_or(Error::Overseer(SubsystemError::Context(
570 "create validator overseer as mandatory extended arguments were not provided"
571 .to_owned(),
572 )))?;
573 validator_overseer_builder(args, ext_args)?
574 .build_with_connector(connector)
575 .map_err(|e| e.into())
576 }
577}
578
579pub struct CollatorOverseerGen;
581
582impl OverseerGen for CollatorOverseerGen {
583 fn generate<Spawner, RuntimeClient>(
584 &self,
585 connector: OverseerConnector,
586 args: OverseerGenArgs<Spawner, RuntimeClient>,
587 _ext_args: Option<ExtendedOverseerGenArgs>,
588 ) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
589 where
590 RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
591 Spawner: 'static + SpawnNamed + Clone + Unpin,
592 {
593 collator_overseer_builder(args)?
594 .build_with_connector(connector)
595 .map_err(|e| e.into())
596 }
597}