1#![cfg(feature = "full-node")]
20
21mod partial;
22use partial::PolkadotPartialComponents;
23pub(crate) use partial::{new_partial, new_partial_basics};
24
25use crate::{
26 grandpa_support, open_database,
27 overseer::{ExtendedOverseerGenArgs, OverseerGen, OverseerGenArgs},
28 parachains_db,
29 relay_chain_selection::SelectRelayChain,
30 workers, Chain, Error, FullBackend, FullClient, IdentifyVariant, IsParachainNode,
31 GRANDPA_JUSTIFICATION_PERIOD, KEEP_FINALIZED_FOR_LIVE_NETWORKS,
32};
33use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE;
34use gum::info;
35use mmr_gadget::MmrGadget;
36use polkadot_availability_recovery::FETCH_CHUNKS_THRESHOLD;
37use polkadot_collator_protocol::ReputationConfig;
38use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig;
39use polkadot_node_core_av_store::Config as AvailabilityConfig;
40use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig;
41use polkadot_node_core_chain_selection::{
42 self as chain_selection_subsystem, Config as ChainSelectionConfig,
43};
44use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig;
45use polkadot_node_network_protocol::{
46 peer_set::{PeerSet, PeerSetProtocolNames},
47 request_response::{IncomingRequest, ReqProtocolNames},
48};
49use polkadot_node_subsystem_types::DefaultSubsystemClient;
50use polkadot_overseer::{Handle, OverseerConnector};
51use polkadot_primitives::Block;
52use sc_client_api::Backend;
53use sc_network::config::FullNetworkConfiguration;
54use sc_network_sync::WarpSyncConfig;
55use sc_service::{Configuration, RpcHandlers, TaskManager};
56use sc_sysinfo::Metric;
57use sc_telemetry::TelemetryWorkerHandle;
58use sc_transaction_pool_api::OffchainTransactionPoolFactory;
59use sp_consensus_beefy::ecdsa_crypto;
60use sp_runtime::traits::Block as BlockT;
61use std::{
62 collections::{HashMap, HashSet},
63 sync::Arc,
64 time::Duration,
65};
66
67pub struct NewFullParams<OverseerGenerator: OverseerGen> {
69 pub is_parachain_node: IsParachainNode,
70 pub enable_beefy: bool,
71 pub force_authoring_backoff: bool,
74 pub telemetry_worker_handle: Option<TelemetryWorkerHandle>,
75 pub node_version: Option<String>,
78 pub secure_validator_mode: bool,
80 pub workers_path: Option<std::path::PathBuf>,
82 pub workers_names: Option<(String, String)>,
84 pub execute_workers_max_num: Option<usize>,
86 pub prepare_workers_soft_max_num: Option<usize>,
89 pub prepare_workers_hard_max_num: Option<usize>,
91 pub keep_finalized_for: Option<u32>,
93 pub overseer_gen: OverseerGenerator,
94 pub overseer_message_channel_capacity_override: Option<usize>,
95 #[allow(dead_code)]
96 pub malus_finality_delay: Option<u32>,
97 pub hwbench: Option<sc_sysinfo::HwBench>,
98 pub invulnerable_ah_collators: HashSet<polkadot_node_network_protocol::PeerId>,
100 pub collator_protocol_hold_off: Option<Duration>,
102 pub experimental_collator_protocol: bool,
104 pub collator_reputation_persist_interval: Option<Duration>,
106}
107
108pub struct NewFull {
110 pub task_manager: TaskManager,
111 pub client: Arc<FullClient>,
112 pub overseer_handle: Option<Handle>,
113 pub network: Arc<dyn sc_network::service::traits::NetworkService>,
114 pub sync_service: Arc<sc_network_sync::SyncingService<Block>>,
115 pub rpc_handlers: RpcHandlers,
116 pub backend: Arc<FullBackend>,
117}
118
119pub struct PolkadotServiceBuilder<OverseerGenerator, Network>
120where
121 OverseerGenerator: OverseerGen,
122 Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Hash>,
123{
124 config: Configuration,
125 params: NewFullParams<OverseerGenerator>,
126 overseer_connector: OverseerConnector,
127 partial_components: PolkadotPartialComponents<SelectRelayChain<FullBackend>>,
128 net_config: FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Network>,
129}
130
131impl<OverseerGenerator, Network> PolkadotServiceBuilder<OverseerGenerator, Network>
132where
133 OverseerGenerator: OverseerGen,
134 Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Hash>,
135{
136 pub fn new(
138 mut config: Configuration,
139 params: NewFullParams<OverseerGenerator>,
140 ) -> Result<PolkadotServiceBuilder<OverseerGenerator, Network>, Error> {
141 let basics = new_partial_basics(&mut config, params.telemetry_worker_handle.clone())?;
142
143 let prometheus_registry = config.prometheus_registry().cloned();
144 let overseer_connector = OverseerConnector::default();
145 let overseer_handle = Handle::new(overseer_connector.handle());
146 let auth_or_collator = config.role.is_authority() || params.is_parachain_node.is_collator();
147
148 let select_chain = if auth_or_collator {
149 let metrics = polkadot_node_subsystem_util::metrics::Metrics::register(
150 prometheus_registry.as_ref(),
151 )?;
152
153 SelectRelayChain::new_with_overseer(
154 basics.backend.clone(),
155 overseer_handle.clone(),
156 metrics,
157 Some(basics.task_manager.spawn_handle()),
158 )
159 } else {
160 SelectRelayChain::new_longest_chain(basics.backend.clone())
161 };
162
163 let partial_components =
164 new_partial::<SelectRelayChain<_>>(&mut config, basics, select_chain)?;
165
166 let net_config = sc_network::config::FullNetworkConfiguration::<_, _, Network>::new(
167 &config.network,
168 config.prometheus_config.as_ref().map(|cfg| cfg.registry.clone()),
169 );
170
171 Ok(PolkadotServiceBuilder {
172 config,
173 params,
174 overseer_connector,
175 partial_components,
176 net_config,
177 })
178 }
179
180 pub fn genesis_hash(&self) -> <Block as BlockT>::Hash {
182 self.partial_components.client.chain_info().genesis_hash
183 }
184
185 pub fn add_extra_request_response_protocol(
187 &mut self,
188 config: Network::RequestResponseProtocolConfig,
189 ) {
190 self.net_config.add_request_response_protocol(config);
191 }
192
193 pub fn build(self) -> Result<NewFull, Error> {
195 let Self {
196 config,
197 params:
198 NewFullParams {
199 is_parachain_node,
200 enable_beefy,
201 force_authoring_backoff,
202 telemetry_worker_handle: _,
203 node_version,
204 secure_validator_mode,
205 workers_path,
206 workers_names,
207 overseer_gen,
208 overseer_message_channel_capacity_override,
209 malus_finality_delay: _malus_finality_delay,
210 hwbench,
211 execute_workers_max_num,
212 prepare_workers_soft_max_num,
213 prepare_workers_hard_max_num,
214 keep_finalized_for,
215 invulnerable_ah_collators,
216 collator_protocol_hold_off,
217 experimental_collator_protocol,
218 collator_reputation_persist_interval,
219 },
220 overseer_connector,
221 partial_components:
222 sc_service::PartialComponents::<_, _, SelectRelayChain<_>, _, _, _> {
223 client,
224 backend,
225 mut task_manager,
226 keystore_container,
227 select_chain,
228 import_queue,
229 transaction_pool,
230 other:
231 (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, mut telemetry),
232 },
233 mut net_config,
234 } = self;
235
236 let role = config.role;
237 let auth_or_collator = config.role.is_authority() || is_parachain_node.is_collator();
238 let is_offchain_indexing_enabled = config.offchain_worker.indexing_enabled;
239 let force_authoring = config.force_authoring;
240 let disable_grandpa = config.disable_grandpa;
241 let name = config.network.node_name.clone();
242 let backoff_authoring_blocks = if !force_authoring_backoff &&
243 (config.chain_spec.is_polkadot() || config.chain_spec.is_kusama())
244 {
245 None
247 } else {
248 let mut backoff = sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging::default();
249
250 if config.chain_spec.is_rococo() ||
251 config.chain_spec.is_versi() ||
252 config.chain_spec.is_dev()
253 {
254 backoff.max_interval = 10;
258 }
259
260 Some(backoff)
261 };
262 let shared_voter_state = rpc_setup;
263 let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht;
264 let auth_disc_public_addresses = config.network.public_addresses.clone();
265
266 let genesis_hash = client.chain_info().genesis_hash;
267 let peer_store_handle = net_config.peer_store_handle();
268
269 let prometheus_registry = config.prometheus_registry().cloned();
270 let metrics = Network::register_notification_metrics(
271 config.prometheus_config.as_ref().map(|cfg| &cfg.registry),
272 );
273
274 let grandpa_protocol_name =
278 sc_consensus_grandpa::protocol_standard_name(&genesis_hash, &config.chain_spec);
279 let (grandpa_protocol_config, grandpa_notification_service) =
280 sc_consensus_grandpa::grandpa_peers_set_config::<_, Network>(
281 grandpa_protocol_name.clone(),
282 metrics.clone(),
283 Arc::clone(&peer_store_handle),
284 );
285 net_config.add_notification_protocol(grandpa_protocol_config);
286
287 let beefy_gossip_proto_name =
288 sc_consensus_beefy::gossip_protocol_name(&genesis_hash, config.chain_spec.fork_id());
289 let (beefy_on_demand_justifications_handler, beefy_req_resp_cfg) =
292 sc_consensus_beefy::communication::request_response::BeefyJustifsRequestHandler::new::<
293 _,
294 Network,
295 >(
296 &genesis_hash,
297 config.chain_spec.fork_id(),
298 client.clone(),
299 prometheus_registry.clone(),
300 );
301 let beefy_notification_service = match enable_beefy {
302 false => None,
303 true => {
304 let (beefy_notification_config, beefy_notification_service) =
305 sc_consensus_beefy::communication::beefy_peers_set_config::<_, Network>(
306 beefy_gossip_proto_name.clone(),
307 metrics.clone(),
308 Arc::clone(&peer_store_handle),
309 );
310
311 net_config.add_notification_protocol(beefy_notification_config);
312 net_config.add_request_response_protocol(beefy_req_resp_cfg);
313 Some(beefy_notification_service)
314 },
315 };
316
317 let peerset_protocol_names =
319 PeerSetProtocolNames::new(genesis_hash, config.chain_spec.fork_id());
320
321 let notification_services = if role.is_authority() ||
327 is_parachain_node.is_running_alongside_parachain_node()
328 {
329 use polkadot_network_bridge::{peer_sets_info, IsAuthority};
330 let is_authority = if role.is_authority() { IsAuthority::Yes } else { IsAuthority::No };
331
332 peer_sets_info::<_, Network>(
333 is_authority,
334 &peerset_protocol_names,
335 metrics.clone(),
336 Arc::clone(&peer_store_handle),
337 )
338 .into_iter()
339 .map(|(config, (peerset, service))| {
340 net_config.add_notification_protocol(config);
341 (peerset, service)
342 })
343 .collect::<HashMap<PeerSet, Box<dyn sc_network::NotificationService>>>()
344 } else {
345 std::collections::HashMap::new()
346 };
347
348 let req_protocol_names = ReqProtocolNames::new(&genesis_hash, config.chain_spec.fork_id());
349
350 let (collation_req_v1_receiver, cfg) =
351 IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names);
352 net_config.add_request_response_protocol(cfg);
353 let (collation_req_v2_receiver, cfg) =
354 IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names);
355 net_config.add_request_response_protocol(cfg);
356 let (available_data_req_receiver, cfg) =
357 IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names);
358 net_config.add_request_response_protocol(cfg);
359 let (pov_req_receiver, cfg) =
360 IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names);
361 net_config.add_request_response_protocol(cfg);
362 let (chunk_req_v1_receiver, cfg) =
363 IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names);
364 net_config.add_request_response_protocol(cfg);
365 let (chunk_req_v2_receiver, cfg) =
366 IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names);
367 net_config.add_request_response_protocol(cfg);
368
369 let grandpa_hard_forks = if config.chain_spec.is_kusama() {
370 grandpa_support::kusama_hard_forks()
371 } else {
372 Vec::new()
373 };
374
375 let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new(
376 backend.clone(),
377 import_setup.1.shared_authority_set().clone(),
378 grandpa_hard_forks,
379 ));
380
381 let ext_overseer_args = if is_parachain_node.is_running_alongside_parachain_node() {
382 None
383 } else {
384 let parachains_db = open_database(&config.database)?;
385 let candidate_validation_config = if role.is_authority() {
386 let (prep_worker_path, exec_worker_path) = workers::determine_workers_paths(
387 workers_path,
388 workers_names,
389 node_version.clone(),
390 )?;
391 log::info!("๐ Using prepare-worker binary at: {:?}", prep_worker_path);
392 log::info!("๐ Using execute-worker binary at: {:?}", exec_worker_path);
393
394 Some(CandidateValidationConfig {
395 artifacts_cache_path: config
396 .database
397 .path()
398 .ok_or(Error::DatabasePathRequired)?
399 .join("pvf-artifacts"),
400 node_version,
401 secure_validator_mode,
402 prep_worker_path,
403 exec_worker_path,
404 pvf_execute_workers_max_num: execute_workers_max_num.unwrap_or(4),
407 pvf_prepare_workers_soft_max_num: prepare_workers_soft_max_num.unwrap_or(1),
408 pvf_prepare_workers_hard_max_num: prepare_workers_hard_max_num.unwrap_or(2),
409 })
410 } else {
411 None
412 };
413 let (candidate_req_v2_receiver, cfg) =
414 IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names);
415 net_config.add_request_response_protocol(cfg);
416 let (dispute_req_receiver, cfg) =
417 IncomingRequest::get_config_receiver::<_, Network>(&req_protocol_names);
418 net_config.add_request_response_protocol(cfg);
419 let approval_voting_config = ApprovalVotingConfig {
420 col_approval_data: parachains_db::REAL_COLUMNS.col_approval_data,
421 slot_duration_millis: slot_duration.as_millis() as u64,
422 };
423 let dispute_coordinator_config = DisputeCoordinatorConfig {
424 col_dispute_data: parachains_db::REAL_COLUMNS.col_dispute_coordinator_data,
425 };
426 let chain_selection_config = ChainSelectionConfig {
427 col_data: parachains_db::REAL_COLUMNS.col_chain_selection_data,
428 stagnant_check_interval: Default::default(),
429 stagnant_check_mode: chain_selection_subsystem::StagnantCheckMode::PruneOnly,
430 };
431 let reputation_config = ReputationConfig {
432 col_reputation_data: parachains_db::REAL_COLUMNS.col_collator_reputation_data,
433 persist_interval: collator_reputation_persist_interval,
434 };
435
436 let fetch_chunks_threshold =
438 if config.chain_spec.is_polkadot() { None } else { Some(FETCH_CHUNKS_THRESHOLD) };
439
440 let availability_config = AvailabilityConfig {
441 col_data: parachains_db::REAL_COLUMNS.col_availability_data,
442 col_meta: parachains_db::REAL_COLUMNS.col_availability_meta,
443 keep_finalized_for: if matches!(config.chain_spec.identify_chain(), Chain::Rococo) {
444 keep_finalized_for.unwrap_or(1)
445 } else {
446 KEEP_FINALIZED_FOR_LIVE_NETWORKS
447 },
448 };
449
450 Some(ExtendedOverseerGenArgs {
451 keystore: keystore_container.local_keystore(),
452 parachains_db,
453 candidate_validation_config,
454 availability_config,
455 pov_req_receiver,
456 chunk_req_v1_receiver,
457 chunk_req_v2_receiver,
458 candidate_req_v2_receiver,
459 approval_voting_config,
460 dispute_req_receiver,
461 dispute_coordinator_config,
462 chain_selection_config,
463 fetch_chunks_threshold,
464 invulnerable_ah_collators,
465 collator_protocol_hold_off,
466 experimental_collator_protocol,
467 reputation_config,
468 })
469 };
470
471 let (network, system_rpc_tx, tx_handler_controller, sync_service) =
472 sc_service::build_network(sc_service::BuildNetworkParams {
473 config: &config,
474 net_config,
475 client: client.clone(),
476 transaction_pool: transaction_pool.clone(),
477 spawn_handle: task_manager.spawn_handle(),
478 spawn_essential_handle: task_manager.spawn_essential_handle(),
479 import_queue,
480 block_announce_validator_builder: None,
481 warp_sync_config: Some(WarpSyncConfig::WithProvider(warp_sync)),
482 block_relay: None,
483 metrics,
484 })?;
485
486 if config.offchain_worker.enabled {
487 use futures::FutureExt;
488
489 task_manager.spawn_handle().spawn(
490 "offchain-workers-runner",
491 "offchain-work",
492 sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions {
493 runtime_api_provider: client.clone(),
494 keystore: Some(keystore_container.keystore()),
495 offchain_db: backend.offchain_storage(),
496 transaction_pool: Some(OffchainTransactionPoolFactory::new(
497 transaction_pool.clone(),
498 )),
499 network_provider: Arc::new(network.clone()),
500 is_validator: role.is_authority(),
501 enable_http_requests: false,
502 custom_extensions: move |_| vec![],
503 })?
504 .run(client.clone(), task_manager.spawn_handle())
505 .boxed(),
506 );
507 }
508
509 let network_config = config.network.clone();
510 let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
511 config,
512 backend: backend.clone(),
513 client: client.clone(),
514 keystore: keystore_container.keystore(),
515 network: network.clone(),
516 sync_service: sync_service.clone(),
517 rpc_builder: Box::new(rpc_extensions_builder),
518 transaction_pool: transaction_pool.clone(),
519 task_manager: &mut task_manager,
520 system_rpc_tx,
521 tx_handler_controller,
522 telemetry: telemetry.as_mut(),
523 tracing_execute_block: None,
524 })?;
525
526 if let Some(hwbench) = hwbench {
527 sc_sysinfo::print_hwbench(&hwbench);
528 match SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench, role.is_authority()) {
529 Err(err) if role.is_authority() => {
530 if err
531 .0
532 .iter()
533 .any(|failure| matches!(failure.metric, Metric::Blake2256Parallel { .. }))
534 {
535 log::warn!(
536 "โ ๏ธ Starting January 2025 the hardware will fail the minimal physical CPU cores requirements {} for role 'Authority',\n\
537 find out more when this will become mandatory at:\n\
538 https://docs.polkadot.com/infrastructure/running-a-validator/requirements/#minimum-hardware-requirements",
539 err
540 );
541 }
542 if err
543 .0
544 .iter()
545 .any(|failure| !matches!(failure.metric, Metric::Blake2256Parallel { .. }))
546 {
547 log::warn!(
548 "โ ๏ธ The hardware does not meet the minimal requirements {} for role 'Authority' find out more at:\n\
549 https://docs.polkadot.com/infrastructure/running-a-validator/requirements/#minimum-hardware-requirements",
550 err
551 );
552 }
553 },
554 _ => {},
555 }
556
557 if let Some(ref mut telemetry) = telemetry {
558 let telemetry_handle = telemetry.handle();
559 task_manager.spawn_handle().spawn(
560 "telemetry_hwbench",
561 None,
562 sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench),
563 );
564 }
565 }
566
567 let (block_import, link_half, babe_link, beefy_links) = import_setup;
568
569 let overseer_client = client.clone();
570 let spawner = task_manager.spawn_handle();
571
572 let authority_discovery_service =
573 if role.is_authority() || is_parachain_node.is_running_alongside_parachain_node() {
577 use futures::StreamExt;
578 use sc_network::{Event, NetworkEventStream};
579
580 let authority_discovery_role = if role.is_authority() {
581 sc_authority_discovery::Role::PublishAndDiscover(keystore_container.keystore())
582 } else {
583 sc_authority_discovery::Role::Discover
585 };
586 let dht_event_stream =
587 network.event_stream("authority-discovery").filter_map(|e| async move {
588 match e {
589 Event::Dht(e) => Some(e),
590 _ => None,
591 }
592 });
593 let (worker, service) = sc_authority_discovery::new_worker_and_service_with_config(
594 sc_authority_discovery::WorkerConfig {
595 publish_non_global_ips: auth_disc_publish_non_global_ips,
596 public_addresses: auth_disc_public_addresses,
597 strict_record_validation: true,
599 persisted_cache_directory: network_config.net_config_path,
600 ..Default::default()
601 },
602 client.clone(),
603 Arc::new(network.clone()),
604 Box::pin(dht_event_stream),
605 authority_discovery_role,
606 prometheus_registry.clone(),
607 task_manager.spawn_handle(),
608 );
609
610 task_manager.spawn_handle().spawn(
611 "authority-discovery-worker",
612 Some("authority-discovery"),
613 Box::pin(worker.run()),
614 );
615 Some(service)
616 } else {
617 None
618 };
619
620 let runtime_client = Arc::new(DefaultSubsystemClient::new(
621 overseer_client.clone(),
622 OffchainTransactionPoolFactory::new(transaction_pool.clone()),
623 ));
624
625 let overseer_handle = if let Some(authority_discovery_service) = authority_discovery_service
626 {
627 let (overseer, overseer_handle) = overseer_gen
628 .generate::<sc_service::SpawnTaskHandle, DefaultSubsystemClient<FullClient>>(
629 overseer_connector,
630 OverseerGenArgs {
631 runtime_client,
632 network_service: network.clone(),
633 sync_service: sync_service.clone(),
634 authority_discovery_service,
635 collation_req_v1_receiver,
636 collation_req_v2_receiver,
637 available_data_req_receiver,
638 registry: prometheus_registry.as_ref(),
639 spawner,
640 is_parachain_node,
641 overseer_message_channel_capacity_override,
642 req_protocol_names,
643 peerset_protocol_names,
644 notification_services,
645 },
646 ext_overseer_args,
647 )
648 .map_err(|e| {
649 gum::error!("Failed to init overseer: {}", e);
650 e
651 })?;
652 let handle = Handle::new(overseer_handle.clone());
653
654 {
655 let handle = handle.clone();
656 task_manager.spawn_essential_handle().spawn_blocking(
657 "overseer",
658 None,
659 Box::pin(async move {
660 use futures::{pin_mut, select, FutureExt};
661
662 let forward = polkadot_overseer::forward_events(overseer_client, handle);
663
664 let forward = forward.fuse();
665 let overseer_fut = overseer.run().fuse();
666
667 pin_mut!(overseer_fut);
668 pin_mut!(forward);
669
670 select! {
671 () = forward => (),
672 () = overseer_fut => (),
673 complete => (),
674 }
675 }),
676 );
677 }
678 Some(handle)
679 } else {
680 assert!(
681 !auth_or_collator,
682 "Precondition congruence (false) is guaranteed by manual checking. qed"
683 );
684 None
685 };
686
687 if role.is_authority() {
688 let mut proposer = sc_basic_authorship::ProposerFactory::new(
689 task_manager.spawn_handle(),
690 client.clone(),
691 transaction_pool.clone(),
692 prometheus_registry.as_ref(),
693 telemetry.as_ref().map(|x| x.handle()),
694 );
695 proposer.set_default_block_size_limit(15 * 1024 * 1024);
698
699 let client_clone = client.clone();
700 let overseer_handle =
701 overseer_handle.as_ref().ok_or(Error::AuthoritiesRequireRealOverseer)?.clone();
702 let slot_duration = babe_link.config().slot_duration();
703 let babe_config = sc_consensus_babe::BabeParams {
704 keystore: keystore_container.keystore(),
705 client: client.clone(),
706 select_chain,
707 block_import,
708 env: proposer,
709 sync_oracle: sync_service.clone(),
710 justification_sync_link: sync_service.clone(),
711 create_inherent_data_providers: move |parent, ()| {
712 let client_clone = client_clone.clone();
713 let overseer_handle = overseer_handle.clone();
714
715 async move {
716 let parachain =
717 polkadot_node_core_parachains_inherent::ParachainsInherentDataProvider::new(
718 client_clone,
719 overseer_handle,
720 parent,
721 );
722
723 let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
724
725 let slot =
726 sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
727 *timestamp,
728 slot_duration,
729 );
730
731 Ok((slot, timestamp, parachain))
732 }
733 },
734 force_authoring,
735 backoff_authoring_blocks,
736 babe_link,
737 block_proposal_slot_portion: sc_consensus_babe::SlotProportion::new(2f32 / 3f32),
738 max_block_proposal_slot_portion: None,
739 telemetry: telemetry.as_ref().map(|x| x.handle()),
740 };
741
742 let babe = sc_consensus_babe::start_babe(babe_config)?;
743 task_manager.spawn_essential_handle().spawn_blocking("babe", None, babe);
744 }
745
746 let keystore_opt =
749 if role.is_authority() { Some(keystore_container.keystore()) } else { None };
750
751 if let Some(notification_service) = beefy_notification_service {
753 let justifications_protocol_name =
754 beefy_on_demand_justifications_handler.protocol_name();
755 let network_params = sc_consensus_beefy::BeefyNetworkParams {
756 network: Arc::new(network.clone()),
757 sync: sync_service.clone(),
758 gossip_protocol_name: beefy_gossip_proto_name,
759 justifications_protocol_name,
760 notification_service,
761 _phantom: core::marker::PhantomData::<Block>,
762 };
763 let payload_provider = sp_consensus_beefy::mmr::MmrRootProvider::new(client.clone());
764 let beefy_params = sc_consensus_beefy::BeefyParams {
765 client: client.clone(),
766 backend: backend.clone(),
767 payload_provider,
768 runtime: client.clone(),
769 key_store: keystore_opt.clone(),
770 network_params,
771 min_block_delta: 8,
772 prometheus_registry: prometheus_registry.clone(),
773 links: beefy_links,
774 on_demand_justifications_handler: beefy_on_demand_justifications_handler,
775 is_authority: role.is_authority(),
776 };
777
778 let gadget = sc_consensus_beefy::start_beefy_gadget::<
779 _,
780 _,
781 _,
782 _,
783 _,
784 _,
785 _,
786 ecdsa_crypto::AuthorityId,
787 >(beefy_params);
788
789 task_manager
792 .spawn_essential_handle()
793 .spawn_blocking("beefy-gadget", None, gadget);
794 }
795 if is_offchain_indexing_enabled {
797 task_manager.spawn_essential_handle().spawn_blocking(
798 "mmr-gadget",
799 None,
800 MmrGadget::start(
801 client.clone(),
802 backend.clone(),
803 sp_mmr_primitives::INDEXING_PREFIX.to_vec(),
804 ),
805 );
806 }
807
808 let config = sc_consensus_grandpa::Config {
809 gossip_duration: Duration::from_millis(1000),
813 justification_generation_period: GRANDPA_JUSTIFICATION_PERIOD,
814 name: Some(name),
815 observer_enabled: false,
816 keystore: keystore_opt,
817 local_role: role,
818 telemetry: telemetry.as_ref().map(|x| x.handle()),
819 protocol_name: grandpa_protocol_name,
820 };
821
822 let enable_grandpa = !disable_grandpa;
823 if enable_grandpa {
824 let mut voting_rules_builder = sc_consensus_grandpa::VotingRulesBuilder::default();
832
833 #[cfg(not(feature = "malus"))]
834 let _malus_finality_delay = None;
835
836 if let Some(delay) = _malus_finality_delay {
837 info!(?delay, "Enabling malus finality delay",);
838 voting_rules_builder =
839 voting_rules_builder.add(sc_consensus_grandpa::BeforeBestBlockBy(delay));
840 };
841
842 let grandpa_config = sc_consensus_grandpa::GrandpaParams {
843 config,
844 link: link_half,
845 network: network.clone(),
846 sync: sync_service.clone(),
847 voting_rule: voting_rules_builder.build(),
848 prometheus_registry: prometheus_registry.clone(),
849 shared_voter_state,
850 telemetry: telemetry.as_ref().map(|x| x.handle()),
851 notification_service: grandpa_notification_service,
852 offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(
853 transaction_pool.clone(),
854 ),
855 };
856
857 task_manager.spawn_essential_handle().spawn_blocking(
858 "grandpa-voter",
859 None,
860 sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?,
861 );
862 }
863
864 Ok(NewFull {
865 task_manager,
866 client,
867 overseer_handle,
868 network,
869 sync_service,
870 rpc_handlers,
871 backend,
872 })
873 }
874}
875
876pub fn new_full<
886 OverseerGenerator: OverseerGen,
887 Network: sc_network::NetworkBackend<Block, <Block as BlockT>::Hash>,
888>(
889 config: Configuration,
890 params: NewFullParams<OverseerGenerator>,
891) -> Result<NewFull, Error> {
892 PolkadotServiceBuilder::<OverseerGenerator, Network>::new(config, params)?.build()
893}