1use astar_primitives::*;
22use cumulus_client_bootnodes::{start_bootnode_tasks, StartBootnodeTasksParams};
23use cumulus_client_cli::CollatorOptions;
24use cumulus_client_consensus_aura::collators::slot_based::{
25 self as aura, Params as AuraParams, SlotBasedBlockImport, SlotBasedBlockImportHandle,
26};
27use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImport;
28use cumulus_client_consensus_relay_chain::Verifier as RelayChainVerifier;
29use cumulus_client_service::ParachainTracingExecuteBlock;
30use cumulus_client_service::{
31 prepare_node_config, start_relay_chain_tasks, BuildNetworkParams, DARecoveryProfile,
32 StartRelayChainTasksParams,
33};
34use cumulus_primitives_core::{
35 relay_chain::{CollatorPair, ValidationCode},
36 ParaId,
37};
38use cumulus_relay_chain_interface::RelayChainInterface;
39use fc_consensus::FrontierBlockImport as TFrontierBlockImport;
40use fc_rpc_core::types::{FeeHistoryCache, FilterPool};
41use fc_storage::StorageOverrideHandler;
42use futures::StreamExt;
43use sc_client_api::BlockchainEvents;
44use sc_client_db::PruningMode;
45use sc_consensus::{import_queue::BasicQueue, ImportQueue};
46use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY};
47use sc_network::{config::NetworkBackendType, NetworkBackend, NetworkBlock, PeerId};
48use sc_network_sync::SyncingService;
49use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager};
50use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};
51use sp_api::{ApiExt, ProvideRuntimeApi};
52use sp_consensus_aura::{
53 sr25519::AuthorityId as AuraId, sr25519::AuthorityPair as AuraPair, AuraApi,
54};
55use sp_keystore::KeystorePtr;
56use sp_runtime::{traits::Block as BlockT, Percent};
57use std::{collections::BTreeMap, sync::Arc, time::Duration};
58use substrate_prometheus_endpoint::Registry;
59
60use super::shell_upgrade::*;
61
62use crate::{
63 evm_tracing_types::{EthApi as EthApiCmd, FrontierConfig},
64 rpc::tracing,
65};
66
67#[cfg(feature = "runtime-benchmarks")]
69pub type HostFunctions = (
70 frame_benchmarking::benchmarking::HostFunctions,
71 cumulus_client_service::ParachainHostFunctions,
72 moonbeam_primitives_ext::moonbeam_ext::HostFunctions,
73);
74
75#[cfg(not(feature = "runtime-benchmarks"))]
77pub type HostFunctions = (
78 cumulus_client_service::ParachainHostFunctions,
79 moonbeam_primitives_ext::moonbeam_ext::HostFunctions,
80);
81
82pub type ParachainExecutor = WasmExecutor<HostFunctions>;
84
85type FullClient =
86 TFullClient<Block, crate::parachain::fake_runtime_api::RuntimeApi, ParachainExecutor>;
87
88type FrontierBlockImportType = TFrontierBlockImport<Block, Arc<FullClient>, FullClient>;
90
91type SlotBasedImport = SlotBasedBlockImport<Block, FrontierBlockImportType, FullClient>;
93
94type ParachainBlockImport = TParachainBlockImport<Block, SlotBasedImport, TFullBackend<Block>>;
96
97pub fn new_partial(
102 config: &Configuration,
103 evm_tracing_config: &FrontierConfig,
104) -> Result<
105 PartialComponents<
106 FullClient,
107 TFullBackend<Block>,
108 (),
109 sc_consensus::DefaultImportQueue<Block>,
110 sc_transaction_pool::TransactionPoolHandle<Block, FullClient>,
111 (
112 ParachainBlockImport,
113 SlotBasedBlockImportHandle<Block>,
114 Option<Telemetry>,
115 Option<TelemetryWorkerHandle>,
116 Arc<fc_db::Backend<Block, FullClient>>,
117 ),
118 >,
119 sc_service::Error,
120> {
121 let telemetry = config
122 .telemetry_endpoints
123 .clone()
124 .filter(|x| !x.is_empty())
125 .map(|endpoints| -> Result<_, sc_telemetry::Error> {
126 let worker = TelemetryWorker::new(16)?;
127 let telemetry = worker.handle().new_telemetry(endpoints);
128 Ok((worker, telemetry))
129 })
130 .transpose()?;
131
132 let heap_pages = config
133 .executor
134 .default_heap_pages
135 .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static {
136 extra_pages: h as _,
137 });
138
139 let executor = ParachainExecutor::builder()
140 .with_execution_method(config.executor.wasm_method)
141 .with_onchain_heap_alloc_strategy(heap_pages)
142 .with_offchain_heap_alloc_strategy(heap_pages)
143 .with_max_runtime_instances(config.executor.max_runtime_instances)
144 .with_runtime_cache_size(config.executor.runtime_cache_size)
145 .build();
146
147 let (client, backend, keystore_container, task_manager) =
148 sc_service::new_full_parts_record_import::<Block, _, _>(
149 config,
150 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
151 executor,
152 true,
153 Default::default(),
154 )?;
155 let client = Arc::new(client);
156
157 let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());
158
159 let telemetry = telemetry.map(|(worker, telemetry)| {
160 task_manager
161 .spawn_handle()
162 .spawn("telemetry", None, worker.run());
163 telemetry
164 });
165
166 let transaction_pool = sc_transaction_pool::Builder::new(
167 task_manager.spawn_essential_handle(),
168 client.clone(),
169 config.role.is_authority().into(),
170 )
171 .with_options(config.transaction_pool.clone())
172 .with_prometheus(config.prometheus_registry())
173 .build();
174
175 let frontier_backend = Arc::new(crate::rpc::open_frontier_backend(
176 client.clone(),
177 config,
178 evm_tracing_config,
179 )?);
180
181 let frontier_block_import = TFrontierBlockImport::new(client.clone(), client.clone());
182 let (slot_based_block_import, slot_based_import_handle) =
183 SlotBasedBlockImport::new(frontier_block_import, client.clone());
184 let parachain_block_import: ParachainBlockImport =
185 ParachainBlockImport::new(slot_based_block_import, backend.clone());
186
187 let import_queue = build_import_queue(
188 client.clone(),
189 parachain_block_import.clone(),
190 config,
191 telemetry.as_ref().map(|telemetry| telemetry.handle()),
192 &task_manager,
193 );
194
195 let params = PartialComponents {
196 backend,
197 client,
198 import_queue,
199 keystore_container,
200 task_manager,
201 transaction_pool: transaction_pool.into(),
202 select_chain: (),
203 other: (
204 parachain_block_import,
205 slot_based_import_handle,
206 telemetry,
207 telemetry_worker_handle,
208 frontier_backend,
209 ),
210 };
211
212 Ok(params)
213}
214
215#[derive(Clone)]
216pub struct AdditionalConfig {
218 pub evm_tracing_config: FrontierConfig,
220
221 pub enable_evm_rpc: bool,
223
224 pub proposer_block_size_limit: usize,
226
227 pub proposer_soft_deadline_percent: u8,
229
230 pub hwbench: Option<sc_sysinfo::HwBench>,
232}
233
234#[sc_tracing::logging::prefix_logs_with("Parachain")]
238async fn start_node_impl<N>(
239 parachain_config: Configuration,
240 polkadot_config: Configuration,
241 collator_options: CollatorOptions,
242 para_id: ParaId,
243 additional_config: AdditionalConfig,
244) -> sc_service::error::Result<(TaskManager, Arc<FullClient>)>
245where
246 N: NetworkBackend<Block, <Block as BlockT>::Hash>,
247{
248 let parachain_config = prepare_node_config(parachain_config);
249
250 let PartialComponents {
251 client,
252 backend,
253 mut task_manager,
254 keystore_container,
255 select_chain: _,
256 import_queue,
257 transaction_pool,
258 other:
259 (
260 parachain_block_import,
261 block_import_handle,
262 mut telemetry,
263 telemetry_worker_handle,
264 frontier_backend,
265 ),
266 } = new_partial(¶chain_config, &additional_config.evm_tracing_config)?;
267
268 let prometheus_registry = parachain_config.prometheus_registry().cloned();
269 let net_config = sc_network::config::FullNetworkConfiguration::<_, _, N>::new(
270 ¶chain_config.network,
271 prometheus_registry.clone(),
272 );
273
274 let metrics = N::register_notification_metrics(
275 parachain_config
276 .prometheus_config
277 .as_ref()
278 .map(|cfg| &cfg.registry),
279 );
280
281 let relay_chain_fork_id = polkadot_config
283 .chain_spec
284 .fork_id()
285 .map(ToString::to_string);
286
287 let (relay_chain_interface, collator_key, relay_chain_network, paranode_rx) =
288 cumulus_client_service::build_relay_chain_interface(
289 polkadot_config,
290 ¶chain_config,
291 telemetry_worker_handle,
292 &mut task_manager,
293 collator_options.clone(),
294 additional_config.hwbench.clone(),
295 )
296 .await
297 .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;
298
299 let is_authority = parachain_config.role.is_authority();
300 let import_queue_service = import_queue.service();
301 let (network, system_rpc_tx, tx_handler_controller, sync_service) =
302 cumulus_client_service::build_network(BuildNetworkParams {
303 parachain_config: ¶chain_config,
304 net_config,
305 para_id,
306 client: client.clone(),
307 transaction_pool: transaction_pool.clone(),
308 spawn_handle: task_manager.spawn_handle(),
309 spawn_essential_handle: task_manager.spawn_essential_handle(),
310 import_queue,
311 relay_chain_interface: relay_chain_interface.clone(),
312 sybil_resistance_level: cumulus_client_service::CollatorSybilResistance::Resistant,
313 metrics,
314 })
315 .await?;
316
317 let filter_pool: FilterPool = Arc::new(std::sync::Mutex::new(BTreeMap::new()));
318 let fee_history_cache: FeeHistoryCache = Arc::new(std::sync::Mutex::new(BTreeMap::new()));
319 let storage_override = Arc::new(StorageOverrideHandler::new(client.clone()));
320
321 let pubsub_notification_sinks: fc_mapping_sync::EthereumBlockNotificationSinks<
326 fc_mapping_sync::EthereumBlockNotification<Block>,
327 > = Default::default();
328 let pubsub_notification_sinks = Arc::new(pubsub_notification_sinks);
329
330 let ethapi_cmd = additional_config.evm_tracing_config.ethapi.clone();
331 let tracing_requesters =
332 if ethapi_cmd.contains(&EthApiCmd::Debug) || ethapi_cmd.contains(&EthApiCmd::Trace) {
333 tracing::spawn_tracing_tasks(
334 &additional_config.evm_tracing_config,
335 prometheus_registry.clone(),
336 tracing::SpawnTasksParams {
337 task_manager: &task_manager,
338 client: client.clone(),
339 substrate_backend: backend.clone(),
340 frontier_backend: frontier_backend.clone(),
341 storage_override: storage_override.clone(),
342 },
343 )
344 } else {
345 tracing::RpcRequesters {
346 debug: None,
347 trace: None,
348 }
349 };
350
351 match frontier_backend.as_ref() {
354 fc_db::Backend::KeyValue(ref b) => {
355 task_manager.spawn_essential_handle().spawn(
356 "frontier-mapping-sync-worker",
357 Some("frontier"),
358 fc_mapping_sync::kv::MappingSyncWorker::new(
359 client.import_notification_stream(),
360 Duration::new(6, 0),
361 client.clone(),
362 backend.clone(),
363 storage_override.clone(),
364 b.clone(),
365 3,
366 0,
367 parachain_config.state_pruning.clone().and_then(|mode| {
368 if let PruningMode::Constrained(c) = mode {
369 c.max_blocks.map(u64::from)
370 } else {
371 None
372 }
373 }),
374 fc_mapping_sync::SyncStrategy::Parachain,
375 sync_service.clone(),
376 pubsub_notification_sinks.clone(),
377 )
378 .for_each(|()| futures::future::ready(())),
379 );
380 }
381 fc_db::Backend::Sql(ref b) => {
382 task_manager.spawn_essential_handle().spawn_blocking(
383 "frontier-mapping-sync-worker",
384 Some("frontier"),
385 fc_mapping_sync::sql::SyncWorker::run(
386 client.clone(),
387 backend.clone(),
388 b.clone(),
389 client.import_notification_stream(),
390 fc_mapping_sync::sql::SyncWorkerConfig {
391 read_notification_timeout: Duration::from_secs(10),
392 check_indexed_blocks_interval: Duration::from_secs(60),
393 },
394 fc_mapping_sync::SyncStrategy::Parachain,
395 sync_service.clone(),
396 pubsub_notification_sinks.clone(),
397 ),
398 );
399 }
400 }
401
402 const FILTER_RETAIN_THRESHOLD: u64 = 100;
405 task_manager.spawn_essential_handle().spawn(
406 "frontier-filter-pool",
407 Some("frontier"),
408 fc_rpc::EthTask::filter_pool_task(
409 client.clone(),
410 filter_pool.clone(),
411 FILTER_RETAIN_THRESHOLD,
412 ),
413 );
414
415 const FEE_HISTORY_LIMIT: u64 = 2048;
416 task_manager.spawn_essential_handle().spawn(
417 "frontier-fee-history",
418 Some("frontier"),
419 fc_rpc::EthTask::fee_history_task(
420 client.clone(),
421 storage_override.clone(),
422 fee_history_cache.clone(),
423 FEE_HISTORY_LIMIT,
424 ),
425 );
426
427 let block_data_cache = Arc::new(fc_rpc::EthBlockDataCacheTask::new(
428 task_manager.spawn_handle(),
429 storage_override.clone(),
430 50,
431 50,
432 prometheus_registry.clone(),
433 ));
434
435 let rpc_extensions_builder = {
436 let client = client.clone();
437 let network = network.clone();
438 let transaction_pool = transaction_pool.clone();
439 let rpc_config = crate::rpc::EvmTracingConfig {
440 tracing_requesters,
441 trace_filter_max_count: additional_config.evm_tracing_config.ethapi_trace_max_count,
442 trace_filter_max_block_range: additional_config
443 .evm_tracing_config
444 .trace_filter_max_block_range,
445 enable_txpool: ethapi_cmd.contains(&EthApiCmd::TxPool),
446 };
447 let sync = sync_service.clone();
448 let pubsub_notification_sinks = pubsub_notification_sinks.clone();
449
450 Box::new(move |subscription| {
451 let deps = crate::rpc::FullDeps {
452 client: client.clone(),
453 pool: transaction_pool.clone(),
454 graph: transaction_pool.clone(),
455 network: network.clone(),
456 sync: sync.clone(),
457 is_authority,
458 frontier_backend: match *frontier_backend {
459 fc_db::Backend::KeyValue(ref b) => b.clone(),
460 fc_db::Backend::Sql(ref b) => b.clone(),
461 },
462 filter_pool: filter_pool.clone(),
463 fee_history_limit: FEE_HISTORY_LIMIT,
464 fee_history_cache: fee_history_cache.clone(),
465 block_data_cache: block_data_cache.clone(),
466 storage_override: storage_override.clone(),
467 enable_evm_rpc: additional_config.enable_evm_rpc,
468 command_sink: None,
469 };
470
471 crate::rpc::create_full(
472 deps,
473 subscription,
474 pubsub_notification_sinks.clone(),
475 rpc_config.clone(),
476 )
477 .map_err(Into::into)
478 })
479 };
480
481 let parachain_advertise_non_global_ips = parachain_config.network.allow_non_globals_in_dht;
483 let parachain_fork_id = parachain_config
484 .chain_spec
485 .fork_id()
486 .map(ToString::to_string);
487 let parachain_public_addresses = parachain_config.network.public_addresses.clone();
488
489 sc_service::spawn_tasks(sc_service::SpawnTasksParams {
491 rpc_builder: rpc_extensions_builder,
492 client: client.clone(),
493 transaction_pool: transaction_pool.clone(),
494 task_manager: &mut task_manager,
495 config: parachain_config,
496 keystore: keystore_container.keystore(),
497 backend: backend.clone(),
498 network: network.clone(),
499 system_rpc_tx,
500 sync_service: sync_service.clone(),
501 tx_handler_controller,
502 telemetry: telemetry.as_mut(),
503 tracing_execute_block: Some(Arc::new(ParachainTracingExecuteBlock::new(client.clone()))),
504 })?;
505
506 if let Some(hwbench) = additional_config.hwbench.clone() {
507 sc_sysinfo::print_hwbench(&hwbench);
508 if is_authority {
509 warn_if_slow_hardware(&hwbench);
510 }
511
512 if let Some(ref mut telemetry) = telemetry {
513 let telemetry_handle = telemetry.handle();
514 task_manager.spawn_handle().spawn(
515 "telemetry_hwbench",
516 None,
517 sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench),
518 );
519 }
520 }
521
522 let announce_block = {
523 let sync_service = sync_service.clone();
524 Arc::new(move |hash, data| sync_service.announce_block(hash, data))
525 };
526
527 let overseer_handle = relay_chain_interface
528 .overseer_handle()
529 .map_err(|e| sc_service::Error::Application(Box::new(e)))?;
530
531 start_relay_chain_tasks(StartRelayChainTasksParams {
532 client: client.clone(),
533 announce_block: announce_block.clone(),
534 task_manager: &mut task_manager,
535 para_id,
536 relay_chain_interface: relay_chain_interface.clone(),
537 relay_chain_slot_duration: Duration::from_secs(6),
538 import_queue: import_queue_service,
539 recovery_handle: Box::new(overseer_handle.clone()),
540 sync_service: sync_service.clone(),
541 da_recovery_profile: if is_authority {
542 DARecoveryProfile::Collator
543 } else {
544 DARecoveryProfile::FullNode
545 },
546 prometheus_registry: prometheus_registry.as_ref(),
547 })?;
548
549 start_bootnode_tasks(StartBootnodeTasksParams {
550 embedded_dht_bootnode: collator_options.embedded_dht_bootnode,
551 dht_bootnode_discovery: collator_options.dht_bootnode_discovery,
552 para_id,
553 task_manager: &mut task_manager,
554 relay_chain_interface: relay_chain_interface.clone(),
555 relay_chain_fork_id,
556 relay_chain_network,
557 request_receiver: paranode_rx,
558 parachain_network: network.clone(),
559 advertise_non_global_ips: parachain_advertise_non_global_ips,
560 parachain_genesis_hash: client.chain_info().genesis_hash.as_ref().to_vec(),
561 parachain_fork_id,
562 parachain_public_addresses,
563 });
564
565 if is_authority {
566 start_aura_consensus(
567 client.clone(),
568 backend,
569 parachain_block_import,
570 block_import_handle,
571 prometheus_registry.as_ref(),
572 telemetry.map(|t| t.handle()),
573 &mut task_manager,
574 relay_chain_interface,
575 transaction_pool,
576 sync_service,
577 keystore_container.keystore(),
578 para_id,
579 collator_key.expect("Command line arguments do not allow this. qed"),
580 network.local_peer_id(),
581 additional_config,
582 )?;
583 }
584
585 Ok((task_manager, client))
586}
587
588pub fn build_import_queue(
591 client: Arc<FullClient>,
592 block_import: ParachainBlockImport,
593 config: &Configuration,
594 telemetry_handle: Option<TelemetryHandle>,
595 task_manager: &TaskManager,
596) -> sc_consensus::DefaultImportQueue<Block> {
597 let verifier_client = client.clone();
598 let create_aura_inherent_data_providers = move |parent_hash, _| {
600 let cidp_client = verifier_client.clone();
601 async move {
602 let slot_duration =
603 cumulus_client_consensus_aura::slot_duration_at(&*cidp_client, parent_hash)?;
604 let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
605
606 let slot =
607 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
608 *timestamp,
609 slot_duration,
610 );
611
612 Ok((slot, timestamp))
613 }
614 };
615
616 let create_relay_inherent_data_providers = move |_parent_hash: Hash, _| async move {
619 let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
620 Ok(timestamp)
621 };
622
623 let aura_verifier = Box::new(cumulus_client_consensus_aura::build_verifier::<
624 AuraPair,
625 _,
626 _,
627 _,
628 >(cumulus_client_consensus_aura::BuildVerifierParams {
629 client: client.clone(),
630 create_inherent_data_providers: create_aura_inherent_data_providers,
631 telemetry: telemetry_handle,
632 }));
633
634 let relay_chain_verifier = Box::new(RelayChainVerifier::new(
635 client.clone(),
636 create_relay_inherent_data_providers,
637 )) as Box<_>;
638
639 let verifier = Verifier {
640 client,
641 relay_chain_verifier,
642 aura_verifier,
643 };
644
645 let registry = config.prometheus_registry();
646 let spawner = task_manager.spawn_essential_handle();
647
648 BasicQueue::new(verifier, Box::new(block_import), None, &spawner, registry)
649}
650
651fn start_aura_consensus(
653 client: Arc<FullClient>,
654 backend: Arc<TFullBackend<Block>>,
655 block_import: ParachainBlockImport,
656 block_import_handle: SlotBasedBlockImportHandle<Block>,
657 prometheus_registry: Option<&Registry>,
658 telemetry: Option<TelemetryHandle>,
659 task_manager: &TaskManager,
660 relay_chain_interface: Arc<dyn RelayChainInterface>,
661 transaction_pool: Arc<sc_transaction_pool::TransactionPoolHandle<Block, FullClient>>,
662 sync_oracle: Arc<SyncingService<Block>>,
663 keystore: KeystorePtr,
664 para_id: ParaId,
665 collator_key: CollatorPair,
666 collator_peer_id: PeerId,
667 additional_config: AdditionalConfig,
668) -> Result<(), sc_service::Error> {
669 let mut proposer_factory = sc_basic_authorship::ProposerFactory::new(
670 task_manager.spawn_handle(),
671 client.clone(),
672 transaction_pool,
673 prometheus_registry,
674 telemetry,
675 );
676
677 proposer_factory.set_default_block_size_limit(additional_config.proposer_block_size_limit);
678 proposer_factory.set_soft_deadline(Percent::from_percent(
679 additional_config.proposer_soft_deadline_percent,
680 ));
681
682 let announce_block = {
683 let sync_service = sync_oracle.clone();
684 Arc::new(move |hash, data| sync_service.announce_block(hash, data))
685 };
686
687 let collator_service = cumulus_client_collator::service::CollatorService::new(
688 client.clone(),
689 Arc::new(task_manager.spawn_handle()),
690 announce_block,
691 client.clone(),
692 );
693
694 let params = AuraParams {
695 create_inherent_data_providers: move |_, ()| async move { Ok(()) },
696 block_import,
697 para_client: client.clone(),
698 para_backend: backend,
699 relay_client: relay_chain_interface.clone(),
700 code_hash_provider: {
701 let client = client.clone();
702 move |block_hash| {
703 client
704 .code_at(block_hash)
705 .ok()
706 .map(|c| ValidationCode::from(c).hash())
707 }
708 },
709 keystore,
710 collator_key,
711 collator_peer_id,
712 para_id,
713 slot_offset: Duration::from_secs(1),
714 relay_chain_slot_duration: Duration::from_secs(6),
715 proposer: proposer_factory,
716 collator_service,
717 authoring_duration: Duration::from_millis(2000),
718 reinitialize: false,
719 block_import_handle,
720 spawner: task_manager.spawn_essential_handle(),
721 max_pov_percentage: None, export_pov: None,
725 };
726
727 let fut = async move {
728 wait_for_aura(client).await;
729 aura::run::<Block, AuraPair, _, _, _, _, _, _, _, _, _>(params);
730 };
731
732 task_manager.spawn_handle().spawn("aura", None, fut);
733 Ok(())
734}
735
736async fn wait_for_aura(client: Arc<FullClient>) {
740 let finalized_hash = client.chain_info().finalized_hash;
741 if client
742 .runtime_api()
743 .has_api::<dyn AuraApi<Block, AuraId>>(finalized_hash)
744 .unwrap_or_default()
745 {
746 return;
747 };
748
749 let mut stream = client.finality_notification_stream();
750 while let Some(notification) = stream.next().await {
751 if client
752 .runtime_api()
753 .has_api::<dyn AuraApi<Block, AuraId>>(notification.hash)
754 .unwrap_or_default()
755 {
756 return;
757 }
758 }
759}
760
761fn warn_if_slow_hardware(hwbench: &sc_sysinfo::HwBench) {
763 if let Err(err) =
766 frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE.check_hardware(hwbench, false)
767 {
768 log::warn!(
769 "⚠️ The hardware does not meet the minimal requirements {} for role 'Authority' find out more at:\n\
770 https://wiki.polkadot.network/docs/maintain-guides-how-to-validate-polkadot#reference-hardware",
771 err
772 );
773 }
774}
775
776pub async fn start_node(
778 parachain_config: Configuration,
779 polkadot_config: Configuration,
780 collator_options: CollatorOptions,
781 para_id: ParaId,
782 additional_config: AdditionalConfig,
783) -> sc_service::error::Result<(TaskManager, Arc<FullClient>)> {
784 match parachain_config.network.network_backend {
785 NetworkBackendType::Libp2p => {
786 start_node_impl::<sc_network::NetworkWorker<_, _>>(
787 parachain_config,
788 polkadot_config,
789 collator_options,
790 para_id,
791 additional_config,
792 )
793 .await
794 }
795 NetworkBackendType::Litep2p => {
796 start_node_impl::<sc_network::Litep2pNetworkBackend>(
797 parachain_config,
798 polkadot_config,
799 collator_options,
800 para_id,
801 additional_config,
802 )
803 .await
804 }
805 }
806}