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 )?;
154 let client = Arc::new(client);
155
156 let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());
157
158 let telemetry = telemetry.map(|(worker, telemetry)| {
159 task_manager
160 .spawn_handle()
161 .spawn("telemetry", None, worker.run());
162 telemetry
163 });
164
165 let transaction_pool = sc_transaction_pool::Builder::new(
166 task_manager.spawn_essential_handle(),
167 client.clone(),
168 config.role.is_authority().into(),
169 )
170 .with_options(config.transaction_pool.clone())
171 .with_prometheus(config.prometheus_registry())
172 .build();
173
174 let frontier_backend = Arc::new(crate::rpc::open_frontier_backend(
175 client.clone(),
176 config,
177 evm_tracing_config,
178 )?);
179
180 let frontier_block_import = TFrontierBlockImport::new(client.clone(), client.clone());
181 let (slot_based_block_import, slot_based_import_handle) =
182 SlotBasedBlockImport::new(frontier_block_import, client.clone());
183 let parachain_block_import: ParachainBlockImport =
184 ParachainBlockImport::new(slot_based_block_import, backend.clone());
185
186 let import_queue = build_import_queue(
187 client.clone(),
188 parachain_block_import.clone(),
189 config,
190 telemetry.as_ref().map(|telemetry| telemetry.handle()),
191 &task_manager,
192 );
193
194 let params = PartialComponents {
195 backend,
196 client,
197 import_queue,
198 keystore_container,
199 task_manager,
200 transaction_pool: transaction_pool.into(),
201 select_chain: (),
202 other: (
203 parachain_block_import,
204 slot_based_import_handle,
205 telemetry,
206 telemetry_worker_handle,
207 frontier_backend,
208 ),
209 };
210
211 Ok(params)
212}
213
214#[derive(Clone)]
215pub struct AdditionalConfig {
217 pub evm_tracing_config: FrontierConfig,
219
220 pub enable_evm_rpc: bool,
222
223 pub proposer_block_size_limit: usize,
225
226 pub proposer_soft_deadline_percent: u8,
228
229 pub hwbench: Option<sc_sysinfo::HwBench>,
231}
232
233#[sc_tracing::logging::prefix_logs_with("Parachain")]
237async fn start_node_impl<N>(
238 parachain_config: Configuration,
239 polkadot_config: Configuration,
240 collator_options: CollatorOptions,
241 para_id: ParaId,
242 additional_config: AdditionalConfig,
243) -> sc_service::error::Result<(TaskManager, Arc<FullClient>)>
244where
245 N: NetworkBackend<Block, <Block as BlockT>::Hash>,
246{
247 let parachain_config = prepare_node_config(parachain_config);
248
249 let PartialComponents {
250 client,
251 backend,
252 mut task_manager,
253 keystore_container,
254 select_chain: _,
255 import_queue,
256 transaction_pool,
257 other:
258 (
259 parachain_block_import,
260 block_import_handle,
261 mut telemetry,
262 telemetry_worker_handle,
263 frontier_backend,
264 ),
265 } = new_partial(¶chain_config, &additional_config.evm_tracing_config)?;
266
267 let prometheus_registry = parachain_config.prometheus_registry().cloned();
268 let net_config = sc_network::config::FullNetworkConfiguration::<_, _, N>::new(
269 ¶chain_config.network,
270 prometheus_registry.clone(),
271 );
272
273 let metrics = N::register_notification_metrics(
274 parachain_config
275 .prometheus_config
276 .as_ref()
277 .map(|cfg| &cfg.registry),
278 );
279
280 let relay_chain_fork_id = polkadot_config
282 .chain_spec
283 .fork_id()
284 .map(ToString::to_string);
285
286 let (relay_chain_interface, collator_key, relay_chain_network, paranode_rx) =
287 cumulus_client_service::build_relay_chain_interface(
288 polkadot_config,
289 ¶chain_config,
290 telemetry_worker_handle,
291 &mut task_manager,
292 collator_options.clone(),
293 additional_config.hwbench.clone(),
294 )
295 .await
296 .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;
297
298 let is_authority = parachain_config.role.is_authority();
299 let import_queue_service = import_queue.service();
300 let (network, system_rpc_tx, tx_handler_controller, sync_service) =
301 cumulus_client_service::build_network(BuildNetworkParams {
302 parachain_config: ¶chain_config,
303 net_config,
304 para_id,
305 client: client.clone(),
306 transaction_pool: transaction_pool.clone(),
307 spawn_handle: task_manager.spawn_handle(),
308 import_queue,
309 relay_chain_interface: relay_chain_interface.clone(),
310 sybil_resistance_level: cumulus_client_service::CollatorSybilResistance::Resistant,
311 metrics,
312 })
313 .await?;
314
315 let filter_pool: FilterPool = Arc::new(std::sync::Mutex::new(BTreeMap::new()));
316 let fee_history_cache: FeeHistoryCache = Arc::new(std::sync::Mutex::new(BTreeMap::new()));
317 let storage_override = Arc::new(StorageOverrideHandler::new(client.clone()));
318
319 let pubsub_notification_sinks: fc_mapping_sync::EthereumBlockNotificationSinks<
324 fc_mapping_sync::EthereumBlockNotification<Block>,
325 > = Default::default();
326 let pubsub_notification_sinks = Arc::new(pubsub_notification_sinks);
327
328 let ethapi_cmd = additional_config.evm_tracing_config.ethapi.clone();
329 let tracing_requesters =
330 if ethapi_cmd.contains(&EthApiCmd::Debug) || ethapi_cmd.contains(&EthApiCmd::Trace) {
331 tracing::spawn_tracing_tasks(
332 &additional_config.evm_tracing_config,
333 prometheus_registry.clone(),
334 tracing::SpawnTasksParams {
335 task_manager: &task_manager,
336 client: client.clone(),
337 substrate_backend: backend.clone(),
338 frontier_backend: frontier_backend.clone(),
339 storage_override: storage_override.clone(),
340 },
341 )
342 } else {
343 tracing::RpcRequesters {
344 debug: None,
345 trace: None,
346 }
347 };
348
349 match frontier_backend.as_ref() {
352 fc_db::Backend::KeyValue(ref b) => {
353 task_manager.spawn_essential_handle().spawn(
354 "frontier-mapping-sync-worker",
355 Some("frontier"),
356 fc_mapping_sync::kv::MappingSyncWorker::new(
357 client.import_notification_stream(),
358 Duration::new(6, 0),
359 client.clone(),
360 backend.clone(),
361 storage_override.clone(),
362 b.clone(),
363 3,
364 0,
365 parachain_config.state_pruning.clone().and_then(|mode| {
366 if let PruningMode::Constrained(c) = mode {
367 c.max_blocks.map(u64::from)
368 } else {
369 None
370 }
371 }),
372 fc_mapping_sync::SyncStrategy::Parachain,
373 sync_service.clone(),
374 pubsub_notification_sinks.clone(),
375 )
376 .for_each(|()| futures::future::ready(())),
377 );
378 }
379 fc_db::Backend::Sql(ref b) => {
380 task_manager.spawn_essential_handle().spawn_blocking(
381 "frontier-mapping-sync-worker",
382 Some("frontier"),
383 fc_mapping_sync::sql::SyncWorker::run(
384 client.clone(),
385 backend.clone(),
386 b.clone(),
387 client.import_notification_stream(),
388 fc_mapping_sync::sql::SyncWorkerConfig {
389 read_notification_timeout: Duration::from_secs(10),
390 check_indexed_blocks_interval: Duration::from_secs(60),
391 },
392 fc_mapping_sync::SyncStrategy::Parachain,
393 sync_service.clone(),
394 pubsub_notification_sinks.clone(),
395 ),
396 );
397 }
398 }
399
400 const FILTER_RETAIN_THRESHOLD: u64 = 100;
403 task_manager.spawn_essential_handle().spawn(
404 "frontier-filter-pool",
405 Some("frontier"),
406 fc_rpc::EthTask::filter_pool_task(
407 client.clone(),
408 filter_pool.clone(),
409 FILTER_RETAIN_THRESHOLD,
410 ),
411 );
412
413 const FEE_HISTORY_LIMIT: u64 = 2048;
414 task_manager.spawn_essential_handle().spawn(
415 "frontier-fee-history",
416 Some("frontier"),
417 fc_rpc::EthTask::fee_history_task(
418 client.clone(),
419 storage_override.clone(),
420 fee_history_cache.clone(),
421 FEE_HISTORY_LIMIT,
422 ),
423 );
424
425 let block_data_cache = Arc::new(fc_rpc::EthBlockDataCacheTask::new(
426 task_manager.spawn_handle(),
427 storage_override.clone(),
428 50,
429 50,
430 prometheus_registry.clone(),
431 ));
432
433 let rpc_extensions_builder = {
434 let client = client.clone();
435 let network = network.clone();
436 let transaction_pool = transaction_pool.clone();
437 let rpc_config = crate::rpc::EvmTracingConfig {
438 tracing_requesters,
439 trace_filter_max_count: additional_config.evm_tracing_config.ethapi_trace_max_count,
440 trace_filter_max_block_range: additional_config
441 .evm_tracing_config
442 .trace_filter_max_block_range,
443 enable_txpool: ethapi_cmd.contains(&EthApiCmd::TxPool),
444 };
445 let sync = sync_service.clone();
446 let pubsub_notification_sinks = pubsub_notification_sinks.clone();
447
448 Box::new(move |subscription| {
449 let deps = crate::rpc::FullDeps {
450 client: client.clone(),
451 pool: transaction_pool.clone(),
452 graph: transaction_pool.clone(),
453 network: network.clone(),
454 sync: sync.clone(),
455 is_authority,
456 frontier_backend: match *frontier_backend {
457 fc_db::Backend::KeyValue(ref b) => b.clone(),
458 fc_db::Backend::Sql(ref b) => b.clone(),
459 },
460 filter_pool: filter_pool.clone(),
461 fee_history_limit: FEE_HISTORY_LIMIT,
462 fee_history_cache: fee_history_cache.clone(),
463 block_data_cache: block_data_cache.clone(),
464 storage_override: storage_override.clone(),
465 enable_evm_rpc: additional_config.enable_evm_rpc,
466 command_sink: None,
467 };
468
469 crate::rpc::create_full(
470 deps,
471 subscription,
472 pubsub_notification_sinks.clone(),
473 rpc_config.clone(),
474 )
475 .map_err(Into::into)
476 })
477 };
478
479 let parachain_advertise_non_global_ips = parachain_config.network.allow_non_globals_in_dht;
481 let parachain_fork_id = parachain_config
482 .chain_spec
483 .fork_id()
484 .map(ToString::to_string);
485 let parachain_public_addresses = parachain_config.network.public_addresses.clone();
486
487 sc_service::spawn_tasks(sc_service::SpawnTasksParams {
489 rpc_builder: rpc_extensions_builder,
490 client: client.clone(),
491 transaction_pool: transaction_pool.clone(),
492 task_manager: &mut task_manager,
493 config: parachain_config,
494 keystore: keystore_container.keystore(),
495 backend: backend.clone(),
496 network: network.clone(),
497 system_rpc_tx,
498 sync_service: sync_service.clone(),
499 tx_handler_controller,
500 telemetry: telemetry.as_mut(),
501 tracing_execute_block: Some(Arc::new(ParachainTracingExecuteBlock::new(client.clone()))),
502 })?;
503
504 if let Some(hwbench) = additional_config.hwbench.clone() {
505 sc_sysinfo::print_hwbench(&hwbench);
506 if is_authority {
507 warn_if_slow_hardware(&hwbench);
508 }
509
510 if let Some(ref mut telemetry) = telemetry {
511 let telemetry_handle = telemetry.handle();
512 task_manager.spawn_handle().spawn(
513 "telemetry_hwbench",
514 None,
515 sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench),
516 );
517 }
518 }
519
520 let announce_block = {
521 let sync_service = sync_service.clone();
522 Arc::new(move |hash, data| sync_service.announce_block(hash, data))
523 };
524
525 let overseer_handle = relay_chain_interface
526 .overseer_handle()
527 .map_err(|e| sc_service::Error::Application(Box::new(e)))?;
528
529 start_relay_chain_tasks(StartRelayChainTasksParams {
530 client: client.clone(),
531 announce_block: announce_block.clone(),
532 task_manager: &mut task_manager,
533 para_id,
534 relay_chain_interface: relay_chain_interface.clone(),
535 relay_chain_slot_duration: Duration::from_secs(6),
536 import_queue: import_queue_service,
537 recovery_handle: Box::new(overseer_handle.clone()),
538 sync_service: sync_service.clone(),
539 da_recovery_profile: if is_authority {
540 DARecoveryProfile::Collator
541 } else {
542 DARecoveryProfile::FullNode
543 },
544 prometheus_registry: prometheus_registry.as_ref(),
545 })?;
546
547 start_bootnode_tasks(StartBootnodeTasksParams {
548 embedded_dht_bootnode: collator_options.embedded_dht_bootnode,
549 dht_bootnode_discovery: collator_options.dht_bootnode_discovery,
550 para_id,
551 task_manager: &mut task_manager,
552 relay_chain_interface: relay_chain_interface.clone(),
553 relay_chain_fork_id,
554 relay_chain_network,
555 request_receiver: paranode_rx,
556 parachain_network: network.clone(),
557 advertise_non_global_ips: parachain_advertise_non_global_ips,
558 parachain_genesis_hash: client.chain_info().genesis_hash.as_ref().to_vec(),
559 parachain_fork_id,
560 parachain_public_addresses,
561 });
562
563 if is_authority {
564 start_aura_consensus(
565 client.clone(),
566 backend,
567 parachain_block_import,
568 block_import_handle,
569 prometheus_registry.as_ref(),
570 telemetry.map(|t| t.handle()),
571 &mut task_manager,
572 relay_chain_interface,
573 transaction_pool,
574 sync_service,
575 keystore_container.keystore(),
576 para_id,
577 collator_key.expect("Command line arguments do not allow this. qed"),
578 network.local_peer_id(),
579 additional_config,
580 )?;
581 }
582
583 Ok((task_manager, client))
584}
585
586pub fn build_import_queue(
589 client: Arc<FullClient>,
590 block_import: ParachainBlockImport,
591 config: &Configuration,
592 telemetry_handle: Option<TelemetryHandle>,
593 task_manager: &TaskManager,
594) -> sc_consensus::DefaultImportQueue<Block> {
595 let verifier_client = client.clone();
596 let create_aura_inherent_data_providers = move |parent_hash, _| {
598 let cidp_client = verifier_client.clone();
599 async move {
600 let slot_duration =
601 cumulus_client_consensus_aura::slot_duration_at(&*cidp_client, parent_hash)?;
602 let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
603
604 let slot =
605 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
606 *timestamp,
607 slot_duration,
608 );
609
610 Ok((slot, timestamp))
611 }
612 };
613
614 let create_relay_inherent_data_providers = move |_parent_hash: Hash, _| async move {
617 let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
618 Ok(timestamp)
619 };
620
621 let aura_verifier = Box::new(cumulus_client_consensus_aura::build_verifier::<
622 AuraPair,
623 _,
624 _,
625 _,
626 >(cumulus_client_consensus_aura::BuildVerifierParams {
627 client: client.clone(),
628 create_inherent_data_providers: create_aura_inherent_data_providers,
629 telemetry: telemetry_handle,
630 }));
631
632 let relay_chain_verifier = Box::new(RelayChainVerifier::new(
633 client.clone(),
634 create_relay_inherent_data_providers,
635 )) as Box<_>;
636
637 let verifier = Verifier {
638 client,
639 relay_chain_verifier,
640 aura_verifier,
641 };
642
643 let registry = config.prometheus_registry();
644 let spawner = task_manager.spawn_essential_handle();
645
646 BasicQueue::new(verifier, Box::new(block_import), None, &spawner, registry)
647}
648
649fn start_aura_consensus(
651 client: Arc<FullClient>,
652 backend: Arc<TFullBackend<Block>>,
653 block_import: ParachainBlockImport,
654 block_import_handle: SlotBasedBlockImportHandle<Block>,
655 prometheus_registry: Option<&Registry>,
656 telemetry: Option<TelemetryHandle>,
657 task_manager: &TaskManager,
658 relay_chain_interface: Arc<dyn RelayChainInterface>,
659 transaction_pool: Arc<sc_transaction_pool::TransactionPoolHandle<Block, FullClient>>,
660 sync_oracle: Arc<SyncingService<Block>>,
661 keystore: KeystorePtr,
662 para_id: ParaId,
663 collator_key: CollatorPair,
664 collator_peer_id: PeerId,
665 additional_config: AdditionalConfig,
666) -> Result<(), sc_service::Error> {
667 let mut proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
668 task_manager.spawn_handle(),
669 client.clone(),
670 transaction_pool,
671 prometheus_registry,
672 telemetry,
673 );
674
675 proposer_factory.set_default_block_size_limit(additional_config.proposer_block_size_limit);
676 proposer_factory.set_soft_deadline(Percent::from_percent(
677 additional_config.proposer_soft_deadline_percent,
678 ));
679
680 let announce_block = {
681 let sync_service = sync_oracle.clone();
682 Arc::new(move |hash, data| sync_service.announce_block(hash, data))
683 };
684
685 let collator_service = cumulus_client_collator::service::CollatorService::new(
686 client.clone(),
687 Arc::new(task_manager.spawn_handle()),
688 announce_block,
689 client.clone(),
690 );
691
692 let params = AuraParams {
693 create_inherent_data_providers: move |_, ()| async move { Ok(()) },
694 block_import,
695 para_client: client.clone(),
696 para_backend: backend,
697 relay_client: relay_chain_interface.clone(),
698 code_hash_provider: {
699 let client = client.clone();
700 move |block_hash| {
701 client
702 .code_at(block_hash)
703 .ok()
704 .map(|c| ValidationCode::from(c).hash())
705 }
706 },
707 keystore,
708 collator_key,
709 collator_peer_id,
710 para_id,
711 slot_offset: Duration::from_secs(1),
712 relay_chain_slot_duration: Duration::from_secs(6),
713 proposer: proposer_factory,
714 collator_service,
715 authoring_duration: Duration::from_millis(2000),
716 reinitialize: false,
717 block_import_handle,
718 spawner: task_manager.spawn_essential_handle(),
719 max_pov_percentage: None, export_pov: None,
723 };
724
725 let fut = async move {
726 wait_for_aura(client).await;
727 aura::run::<Block, AuraPair, _, _, _, _, _, _, _, _, _>(params);
728 };
729
730 task_manager.spawn_handle().spawn("aura", None, fut);
731 Ok(())
732}
733
734async fn wait_for_aura(client: Arc<FullClient>) {
738 let finalized_hash = client.chain_info().finalized_hash;
739 if client
740 .runtime_api()
741 .has_api::<dyn AuraApi<Block, AuraId>>(finalized_hash)
742 .unwrap_or_default()
743 {
744 return;
745 };
746
747 let mut stream = client.finality_notification_stream();
748 while let Some(notification) = stream.next().await {
749 if client
750 .runtime_api()
751 .has_api::<dyn AuraApi<Block, AuraId>>(notification.hash)
752 .unwrap_or_default()
753 {
754 return;
755 }
756 }
757}
758
759fn warn_if_slow_hardware(hwbench: &sc_sysinfo::HwBench) {
761 if let Err(err) =
764 frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE.check_hardware(hwbench, false)
765 {
766 log::warn!(
767 "⚠️ The hardware does not meet the minimal requirements {} for role 'Authority' find out more at:\n\
768 https://wiki.polkadot.network/docs/maintain-guides-how-to-validate-polkadot#reference-hardware",
769 err
770 );
771 }
772}
773
774pub async fn start_node(
776 parachain_config: Configuration,
777 polkadot_config: Configuration,
778 collator_options: CollatorOptions,
779 para_id: ParaId,
780 additional_config: AdditionalConfig,
781) -> sc_service::error::Result<(TaskManager, Arc<FullClient>)> {
782 match parachain_config.network.network_backend {
783 NetworkBackendType::Libp2p => {
784 start_node_impl::<sc_network::NetworkWorker<_, _>>(
785 parachain_config,
786 polkadot_config,
787 collator_options,
788 para_id,
789 additional_config,
790 )
791 .await
792 }
793 NetworkBackendType::Litep2p => {
794 start_node_impl::<sc_network::Litep2pNetworkBackend>(
795 parachain_config,
796 polkadot_config,
797 collator_options,
798 para_id,
799 additional_config,
800 )
801 .await
802 }
803 }
804}