1pub use crate::parachain::fake_runtime_api::RuntimeApi;
22use crate::{
23 evm_tracing_types::{EthApi as EthApiCmd, FrontierConfig},
24 rpc::tracing,
25};
26use cumulus_client_parachain_inherent::MockXcmConfig;
27use cumulus_primitives_aura::Slot;
28use cumulus_primitives_core::{
29 relay_chain,
30 relay_chain::{well_known_keys, AsyncBackingParams, HeadData, UpgradeGoAhead},
31 AbridgedHostConfiguration, CollectCollationInfo, InboundHrmpMessage, ParaId,
32 RelayParentOffsetApi,
33};
34use cumulus_primitives_parachain_inherent::{MessageQueueChain, ParachainInherentData};
35use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
36use fc_consensus::FrontierBlockImport;
37use fc_rpc_core::types::{FeeHistoryCache, FilterPool};
38use fc_storage::StorageOverrideHandler;
39use futures::{FutureExt, StreamExt};
40use parity_scale_codec::Encode;
41use polkadot_core_primitives::InboundDownwardMessage;
42use polkadot_primitives::PersistedValidationData;
43use sc_client_api::{Backend, BlockchainEvents};
44use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY};
45use sc_network::NetworkBackend;
46use sc_service::{error::Error as ServiceError, Configuration, TaskManager};
47use sc_telemetry::{Telemetry, TelemetryWorker};
48use sc_transaction_pool_api::OffchainTransactionPoolFactory;
49use sp_api::ProvideRuntimeApi;
50use sp_blockchain::HeaderBackend;
51use sp_inherents::{InherentData, InherentDataProvider};
52use sp_runtime::traits::{Block as BlockT, Header as HeaderT, UniqueSaturatedInto};
53use std::{collections::BTreeMap, marker::PhantomData, ops::Sub, sync::Arc, time::Duration};
54
55use astar_primitives::*;
56
57pub struct LocalPendingInherentDataProvider<B, C> {
59 client: Arc<C>,
60 para_id: ParaId,
61 phantom_data: PhantomData<B>,
62}
63
64const RELAY_CHAIN_SLOT_DURATION_MILLIS: u64 = 6000;
65
66#[derive(Default)]
69pub struct MockValidationDataInherentDataProvider<R = ()> {
70 pub current_para_block: u32,
72 pub para_id: ParaId,
74 pub current_para_block_head: Option<cumulus_primitives_core::relay_chain::HeadData>,
76 pub relay_offset: u32,
79 pub relay_parent_offset: u32,
81 pub relay_blocks_per_para_block: u32,
84 pub para_blocks_per_relay_epoch: u32,
87 pub relay_randomness_config: R,
89 pub xcm_config: MockXcmConfig,
91 pub raw_downward_messages: Vec<Vec<u8>>,
93 pub raw_horizontal_messages: Vec<(ParaId, Vec<u8>)>,
95 pub additional_key_values: Option<Vec<(Vec<u8>, Vec<u8>)>>,
97 pub upgrade_go_ahead: Option<UpgradeGoAhead>,
99}
100
101pub trait GenerateRandomness<I> {
103 fn generate_randomness(&self, input: I) -> relay_chain::Hash;
105}
106
107impl GenerateRandomness<u64> for () {
108 fn generate_randomness(&self, input: u64) -> relay_chain::Hash {
111 let mut mock_randomness: [u8; 32] = [0u8; 32];
112 mock_randomness[..8].copy_from_slice(&input.to_be_bytes());
113 mock_randomness.into()
114 }
115}
116
117#[async_trait::async_trait]
118impl<R: Send + Sync + GenerateRandomness<u64>> InherentDataProvider
119 for MockValidationDataInherentDataProvider<R>
120{
121 async fn provide_inherent_data(
122 &self,
123 inherent_data: &mut InherentData,
124 ) -> Result<(), sp_inherents::Error> {
125 let mut sproof_builder = RelayStateSproofBuilder {
127 para_id: self.para_id,
128 ..Default::default()
129 };
130
131 let relay_parent_number =
133 self.relay_offset + self.relay_blocks_per_para_block * self.current_para_block;
134 sproof_builder.current_slot = Slot::from(relay_parent_number as u64);
135
136 sproof_builder.upgrade_go_ahead = self.upgrade_go_ahead;
137 let mut downward_messages = Vec::new();
139 let mut dmq_mqc = MessageQueueChain::new(self.xcm_config.starting_dmq_mqc_head);
140 for msg in &self.raw_downward_messages {
141 let wrapped = InboundDownwardMessage {
142 sent_at: relay_parent_number,
143 msg: msg.clone(),
144 };
145
146 dmq_mqc.extend_downward(&wrapped);
147 downward_messages.push(wrapped);
148 }
149 sproof_builder.dmq_mqc_head = Some(dmq_mqc.head());
150
151 let mut horizontal_messages = BTreeMap::<ParaId, Vec<InboundHrmpMessage>>::new();
154 for (para_id, msg) in &self.raw_horizontal_messages {
155 let wrapped = InboundHrmpMessage {
156 sent_at: relay_parent_number,
157 data: msg.clone(),
158 };
159
160 horizontal_messages
161 .entry(*para_id)
162 .or_default()
163 .push(wrapped);
164 }
165
166 for (para_id, messages) in &horizontal_messages {
168 let mut channel_mqc = MessageQueueChain::new(
169 *self
170 .xcm_config
171 .starting_hrmp_mqc_heads
172 .get(para_id)
173 .unwrap_or(&relay_chain::Hash::default()),
174 );
175 for message in messages {
176 channel_mqc.extend_hrmp(message);
177 }
178 sproof_builder.upsert_inbound_channel(*para_id).mqc_head = Some(channel_mqc.head());
179 }
180
181 sproof_builder.current_epoch = if self.para_blocks_per_relay_epoch == 0 {
183 self.current_para_block.into()
185 } else {
186 (self.current_para_block / self.para_blocks_per_relay_epoch).into()
187 };
188 sproof_builder.randomness = self
190 .relay_randomness_config
191 .generate_randomness(self.current_para_block.into());
192
193 if let Some(key_values) = &self.additional_key_values {
194 sproof_builder.additional_key_values = key_values.clone()
195 }
196
197 sproof_builder.included_para_head = self.current_para_block_head.clone();
199
200 let (relay_parent_storage_root, proof, relay_parent_descendants) =
201 sproof_builder.into_state_root_proof_and_descendants(self.relay_parent_offset.into());
202 let parachain_inherent_data = ParachainInherentData {
203 validation_data: PersistedValidationData {
204 parent_head: Default::default(),
205 relay_parent_storage_root,
206 relay_parent_number,
207 max_pov_size: Default::default(),
208 },
209 downward_messages,
210 horizontal_messages,
211 relay_chain_state: proof,
212 relay_parent_descendants,
213 collator_peer_id: None,
214 };
215
216 parachain_inherent_data
217 .provide_inherent_data(inherent_data)
218 .await
219 }
220
221 async fn try_handle_error(
223 &self,
224 _: &sp_inherents::InherentIdentifier,
225 _: &[u8],
226 ) -> Option<Result<(), sp_inherents::Error>> {
227 None
228 }
229}
230
231fn build_local_mock_inherent_data(
232 para_id: ParaId,
233 current_para_block: u32,
234 current_para_block_head: Option<HeadData>,
235 relay_blocks_per_para_block: u32,
236 relay_slot: u64,
237 relay_parent_offset: u32,
238 upgrade_go_ahead: Option<UpgradeGoAhead>,
239) -> (
240 sp_timestamp::InherentDataProvider,
241 MockValidationDataInherentDataProvider<()>,
242) {
243 let relay_offset = relay_parent_offset.saturating_add(
244 (relay_slot as u32)
245 .saturating_sub(relay_blocks_per_para_block.saturating_mul(current_para_block)),
246 );
247
248 let local_host_config = AbridgedHostConfiguration {
249 max_code_size: 16 * 1024 * 1024, max_head_data_size: 1024 * 1024,
251 max_upward_queue_count: 8,
252 max_upward_queue_size: 1024,
253 max_upward_message_size: 256,
254 max_upward_message_num_per_candidate: 5,
255 hrmp_max_message_num_per_candidate: 5,
256 validation_upgrade_cooldown: 6,
257 validation_upgrade_delay: 6,
258 async_backing_params: AsyncBackingParams {
259 allowed_ancestry_len: 0,
260 max_candidate_depth: 0,
261 },
262 };
263
264 let mocked_parachain = MockValidationDataInherentDataProvider::<()> {
265 current_para_block,
266 para_id,
267 current_para_block_head,
268 relay_blocks_per_para_block,
269 relay_offset,
270 relay_parent_offset,
271 para_blocks_per_relay_epoch: 10,
272 upgrade_go_ahead,
273 additional_key_values: Some(vec![(
274 well_known_keys::ACTIVE_CONFIG.to_vec(),
275 local_host_config.encode(),
276 )]),
277 ..Default::default()
278 };
279
280 let timestamp = relay_slot
281 .saturating_add(u64::from(relay_parent_offset))
282 .saturating_mul(RELAY_CHAIN_SLOT_DURATION_MILLIS);
283 let timestamp_provider = sp_timestamp::InherentDataProvider::new(timestamp.into());
284
285 (timestamp_provider, mocked_parachain)
286}
287
288impl<B, C> LocalPendingInherentDataProvider<B, C> {
289 pub fn new(client: Arc<C>, para_id: ParaId) -> Self {
291 Self {
292 client,
293 para_id,
294 phantom_data: Default::default(),
295 }
296 }
297}
298
299#[async_trait::async_trait]
300impl<B, C> sp_inherents::CreateInherentDataProviders<B, ()>
301 for LocalPendingInherentDataProvider<B, C>
302where
303 B: BlockT,
304 C: ProvideRuntimeApi<B> + HeaderBackend<B> + Send + Sync,
305 C::Api: RelayParentOffsetApi<B>,
306{
307 type InherentDataProviders = (
308 sp_timestamp::InherentDataProvider,
309 MockValidationDataInherentDataProvider<()>,
310 );
311
312 async fn create_inherent_data_providers(
313 &self,
314 parent: B::Hash,
315 _extra_args: (),
316 ) -> Result<Self::InherentDataProviders, Box<dyn std::error::Error + Send + Sync>> {
317 let relay_slot = std::time::SystemTime::now()
318 .duration_since(std::time::UNIX_EPOCH)
319 .expect("Current time is always after UNIX_EPOCH; qed")
320 .as_millis() as u64
321 / RELAY_CHAIN_SLOT_DURATION_MILLIS;
322
323 let current_para_block = self
324 .client
325 .header(parent)?
326 .map(|header| {
327 UniqueSaturatedInto::<u32>::unique_saturated_into(*header.number())
328 .saturating_add(1)
329 })
330 .unwrap_or(1);
331
332 let current_para_block_head = self
333 .client
334 .header(parent)?
335 .map(|header| header.encode().into());
336
337 let relay_parent_offset = self.client.runtime_api().relay_parent_offset(parent)?;
338
339 let (timestamp_provider, mocked_parachain) = build_local_mock_inherent_data(
340 self.para_id,
341 current_para_block,
342 current_para_block_head,
343 1,
344 relay_slot,
345 relay_parent_offset,
346 None,
347 );
348
349 Ok((timestamp_provider, mocked_parachain))
350 }
351}
352
353#[cfg(feature = "runtime-benchmarks")]
355pub type HostFunctions = (
356 frame_benchmarking::benchmarking::HostFunctions,
357 cumulus_client_service::ParachainHostFunctions,
358 moonbeam_primitives_ext::moonbeam_ext::HostFunctions,
359);
360
361#[cfg(not(feature = "runtime-benchmarks"))]
363pub type HostFunctions = (
364 cumulus_client_service::ParachainHostFunctions,
365 moonbeam_primitives_ext::moonbeam_ext::HostFunctions,
366);
367
368type ParachainExecutor = WasmExecutor<HostFunctions>;
369
370type FullClient = sc_service::TFullClient<Block, RuntimeApi, ParachainExecutor>;
371type FullBackend = sc_service::TFullBackend<Block>;
372type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
373
374pub fn new_partial(
376 config: &Configuration,
377 evm_tracing_config: &FrontierConfig,
378) -> Result<
379 sc_service::PartialComponents<
380 FullClient,
381 FullBackend,
382 FullSelectChain,
383 sc_consensus::DefaultImportQueue<Block>,
384 sc_transaction_pool::TransactionPoolHandle<Block, FullClient>,
385 (
386 FrontierBlockImport<Block, Arc<FullClient>, FullClient>,
387 Option<Telemetry>,
388 Arc<fc_db::Backend<Block, FullClient>>,
389 ),
390 >,
391 ServiceError,
392> {
393 let telemetry = config
394 .telemetry_endpoints
395 .clone()
396 .filter(|x| !x.is_empty())
397 .map(|endpoints| -> Result<_, sc_telemetry::Error> {
398 let worker = TelemetryWorker::new(16)?;
399 let telemetry = worker.handle().new_telemetry(endpoints);
400 Ok((worker, telemetry))
401 })
402 .transpose()?;
403
404 let heap_pages = config
405 .executor
406 .default_heap_pages
407 .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static {
408 extra_pages: h as _,
409 });
410
411 let executor = ParachainExecutor::builder()
412 .with_execution_method(config.executor.wasm_method)
413 .with_onchain_heap_alloc_strategy(heap_pages)
414 .with_offchain_heap_alloc_strategy(heap_pages)
415 .with_max_runtime_instances(config.executor.max_runtime_instances)
416 .with_runtime_cache_size(config.executor.runtime_cache_size)
417 .build();
418
419 let (client, backend, keystore_container, task_manager) =
420 sc_service::new_full_parts_record_import::<Block, RuntimeApi, _>(
421 config,
422 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
423 executor,
424 true,
425 )?;
426 let client = Arc::new(client);
427 let telemetry = telemetry.map(|(worker, telemetry)| {
428 task_manager
429 .spawn_handle()
430 .spawn("telemetry", None, worker.run());
431 telemetry
432 });
433 let select_chain = sc_consensus::LongestChain::new(backend.clone());
434 let transaction_pool = sc_transaction_pool::Builder::new(
435 task_manager.spawn_essential_handle(),
436 client.clone(),
437 config.role.is_authority().into(),
438 )
439 .with_options(config.transaction_pool.clone())
440 .with_prometheus(config.prometheus_registry())
441 .build();
442 let frontier_backend = Arc::new(crate::rpc::open_frontier_backend(
443 client.clone(),
444 config,
445 evm_tracing_config,
446 )?);
447 let frontier_block_import = FrontierBlockImport::new(client.clone(), client.clone());
448
449 let import_queue = sc_consensus_manual_seal::import_queue(
450 Box::new(client.clone()),
451 &task_manager.spawn_essential_handle(),
452 config.prometheus_registry(),
453 );
454
455 Ok(sc_service::PartialComponents {
456 client,
457 backend,
458 task_manager,
459 import_queue,
460 keystore_container,
461 select_chain,
462 transaction_pool: transaction_pool.into(),
463 other: (frontier_block_import, telemetry, frontier_backend),
464 })
465}
466
467pub fn start_node<N>(
469 mut config: Configuration,
470 evm_tracing_config: FrontierConfig,
471) -> Result<TaskManager, ServiceError>
472where
473 N: NetworkBackend<Block, <Block as BlockT>::Hash>,
474{
475 let sc_service::PartialComponents {
476 client,
477 backend,
478 mut task_manager,
479 import_queue,
480 keystore_container,
481 select_chain,
482 transaction_pool,
483 other: (block_import, mut telemetry, frontier_backend),
484 } = new_partial(&config, &evm_tracing_config)?;
485
486 config.network.default_peers_set.in_peers = 0;
488 config.network.default_peers_set.out_peers = 0;
489
490 let net_config = sc_network::config::FullNetworkConfiguration::<_, _, N>::new(
491 &config.network,
492 config.prometheus_registry().cloned(),
493 );
494
495 let metrics = N::register_notification_metrics(
496 config.prometheus_config.as_ref().map(|cfg| &cfg.registry),
497 );
498 let (network, system_rpc_tx, tx_handler_controller, sync_service) =
499 sc_service::build_network(sc_service::BuildNetworkParams {
500 config: &config,
501 net_config,
502 client: client.clone(),
503 transaction_pool: transaction_pool.clone(),
504 spawn_handle: task_manager.spawn_handle(),
505 import_queue,
506 block_announce_validator_builder: None,
507 warp_sync_config: None,
508 block_relay: None,
509 metrics,
510 })?;
511
512 if config.offchain_worker.enabled {
513 task_manager.spawn_handle().spawn(
514 "offchain-workers-runner",
515 "offchain-work",
516 sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions {
517 runtime_api_provider: client.clone(),
518 keystore: Some(keystore_container.keystore()),
519 offchain_db: backend.offchain_storage(),
520 transaction_pool: Some(OffchainTransactionPoolFactory::new(
521 transaction_pool.clone(),
522 )),
523 network_provider: Arc::new(network.clone()),
524 is_validator: config.role.is_authority(),
525 enable_http_requests: true,
526 custom_extensions: move |_| vec![],
527 })?
528 .run(client.clone(), task_manager.spawn_handle())
529 .boxed(),
530 );
531 }
532
533 let filter_pool: FilterPool = Arc::new(std::sync::Mutex::new(BTreeMap::new()));
534 let fee_history_cache: FeeHistoryCache = Arc::new(std::sync::Mutex::new(BTreeMap::new()));
535 let storage_override = Arc::new(StorageOverrideHandler::new(client.clone()));
536
537 let pubsub_notification_sinks: fc_mapping_sync::EthereumBlockNotificationSinks<
542 fc_mapping_sync::EthereumBlockNotification<Block>,
543 > = Default::default();
544 let pubsub_notification_sinks = Arc::new(pubsub_notification_sinks);
545
546 let ethapi_cmd = evm_tracing_config.ethapi.clone();
547
548 let tracing_requesters =
549 if ethapi_cmd.contains(&EthApiCmd::Debug) || ethapi_cmd.contains(&EthApiCmd::Trace) {
550 tracing::spawn_tracing_tasks(
551 &evm_tracing_config,
552 config.prometheus_registry().cloned(),
553 tracing::SpawnTasksParams {
554 task_manager: &task_manager,
555 client: client.clone(),
556 substrate_backend: backend.clone(),
557 frontier_backend: frontier_backend.clone(),
558 storage_override: storage_override.clone(),
559 },
560 )
561 } else {
562 tracing::RpcRequesters {
563 debug: None,
564 trace: None,
565 }
566 };
567
568 match frontier_backend.as_ref() {
571 fc_db::Backend::KeyValue(ref b) => {
572 task_manager.spawn_essential_handle().spawn(
573 "frontier-mapping-sync-worker",
574 Some("frontier"),
575 fc_mapping_sync::kv::MappingSyncWorker::new(
576 client.import_notification_stream(),
577 Duration::new(6, 0),
578 client.clone(),
579 backend.clone(),
580 storage_override.clone(),
581 b.clone(),
582 3,
583 0,
584 None,
585 fc_mapping_sync::SyncStrategy::Parachain,
586 sync_service.clone(),
587 pubsub_notification_sinks.clone(),
588 )
589 .for_each(|()| futures::future::ready(())),
590 );
591 }
592 fc_db::Backend::Sql(ref b) => {
593 task_manager.spawn_essential_handle().spawn_blocking(
594 "frontier-mapping-sync-worker",
595 Some("frontier"),
596 fc_mapping_sync::sql::SyncWorker::run(
597 client.clone(),
598 backend.clone(),
599 b.clone(),
600 client.import_notification_stream(),
601 fc_mapping_sync::sql::SyncWorkerConfig {
602 read_notification_timeout: Duration::from_secs(10),
603 check_indexed_blocks_interval: Duration::from_secs(60),
604 },
605 fc_mapping_sync::SyncStrategy::Parachain,
606 sync_service.clone(),
607 pubsub_notification_sinks.clone(),
608 ),
609 );
610 }
611 }
612
613 const FILTER_RETAIN_THRESHOLD: u64 = 100;
616 task_manager.spawn_essential_handle().spawn(
617 "frontier-filter-pool",
618 Some("frontier"),
619 fc_rpc::EthTask::filter_pool_task(
620 client.clone(),
621 filter_pool.clone(),
622 FILTER_RETAIN_THRESHOLD,
623 ),
624 );
625
626 const FEE_HISTORY_LIMIT: u64 = 2048;
627 task_manager.spawn_essential_handle().spawn(
628 "frontier-fee-history",
629 Some("frontier"),
630 fc_rpc::EthTask::fee_history_task(
631 client.clone(),
632 storage_override.clone(),
633 fee_history_cache.clone(),
634 FEE_HISTORY_LIMIT,
635 ),
636 );
637
638 let role = config.role.clone();
639 let prometheus_registry = config.prometheus_registry().cloned();
640 let is_authority = config.role.is_authority();
641
642 let block_data_cache = Arc::new(fc_rpc::EthBlockDataCacheTask::new(
643 task_manager.spawn_handle(),
644 storage_override.clone(),
645 50,
646 50,
647 prometheus_registry.clone(),
648 ));
649
650 let (command_sink, commands_stream) = futures::channel::mpsc::channel(1024);
652 let local_para_id = ParaId::from(
653 crate::parachain::chain_spec::Extensions::try_get(&*config.chain_spec)
654 .map(|e| e.para_id)
655 .unwrap_or(2000),
656 );
657
658 let rpc_extensions_builder = {
659 let client = client.clone();
660 let network = network.clone();
661 let transaction_pool = transaction_pool.clone();
662 let sync = sync_service.clone();
663 let pubsub_notification_sinks = pubsub_notification_sinks.clone();
664
665 Box::new(move |subscription| {
666 let deps = crate::rpc::FullDeps {
667 client: client.clone(),
668 pool: transaction_pool.clone(),
669 graph: transaction_pool.clone(),
670 network: network.clone(),
671 sync: sync.clone(),
672 is_authority,
673 frontier_backend: match *frontier_backend {
674 fc_db::Backend::KeyValue(ref b) => b.clone(),
675 fc_db::Backend::Sql(ref b) => b.clone(),
676 },
677 filter_pool: filter_pool.clone(),
678 fee_history_limit: FEE_HISTORY_LIMIT,
679 fee_history_cache: fee_history_cache.clone(),
680 block_data_cache: block_data_cache.clone(),
681 storage_override: storage_override.clone(),
682 enable_evm_rpc: true, command_sink: Some(command_sink.clone()),
684 };
685
686 crate::rpc::create_full_local_dev(
687 deps,
688 subscription,
689 pubsub_notification_sinks.clone(),
690 local_para_id,
691 crate::rpc::EvmTracingConfig {
692 tracing_requesters: tracing_requesters.clone(),
693 trace_filter_max_count: evm_tracing_config.ethapi_trace_max_count,
694 trace_filter_max_block_range: evm_tracing_config.trace_filter_max_block_range,
695 enable_txpool: ethapi_cmd.contains(&EthApiCmd::TxPool),
696 },
697 )
698 .map_err::<ServiceError, _>(Into::into)
699 })
700 };
701
702 let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
703 network: network.clone(),
704 client: client.clone(),
705 keystore: keystore_container.keystore(),
706 task_manager: &mut task_manager,
707 transaction_pool: transaction_pool.clone(),
708 rpc_builder: rpc_extensions_builder,
709 backend,
710 system_rpc_tx,
711 tx_handler_controller,
712 sync_service: sync_service.clone(),
713 config,
714 telemetry: telemetry.as_mut(),
715 tracing_execute_block: None,
716 })?;
717
718 if role.is_authority() {
719 let proposer_factory = sc_basic_authorship::ProposerFactory::new(
720 task_manager.spawn_handle(),
721 client.clone(),
722 transaction_pool.clone(),
723 prometheus_registry.as_ref(),
724 telemetry.as_ref().map(|x| x.handle()),
725 );
726
727 let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
728
729 let para_id = local_para_id;
730 let initial_relay_slot = std::time::SystemTime::now()
731 .duration_since(std::time::UNIX_EPOCH)
732 .expect("Current time is always after UNIX_EPOCH; qed")
733 .sub(Duration::from_secs(2 * 60 * 60))
734 .as_millis() as u64
735 / RELAY_CHAIN_SLOT_DURATION_MILLIS;
736
737 let aura =
738 sc_consensus_manual_seal::run_manual_seal(sc_consensus_manual_seal::ManualSealParams {
739 block_import,
740 env: proposer_factory,
741 client: client.clone(),
742 pool: transaction_pool.clone(),
743 commands_stream,
744 select_chain,
745 consensus_data_provider: Some(Box::new(
746 sc_consensus_manual_seal::consensus::aura::AuraConsensusDataProvider::new(
747 client.clone(),
748 ),
749 )),
750 create_inherent_data_providers: move |parent_hash, ()| {
751 let client = client.clone();
752 async move {
753 let current_para_head = client
754 .header(parent_hash)
755 .expect("Header lookup should succeed")
756 .expect("Header passed in as parent should be present in backend.");
757
758 let should_send_go_ahead = client
759 .runtime_api()
760 .collect_collation_info(parent_hash, ¤t_para_head)
761 .map(|info| info.new_validation_code.is_some())
762 .unwrap_or_default();
763
764 let current_para_block = UniqueSaturatedInto::<u32>::unique_saturated_into(
765 *current_para_head.number(),
766 ) + 1;
767
768 let relay_blocks_per_para_block =
769 (slot_duration.as_millis() / RELAY_CHAIN_SLOT_DURATION_MILLIS).max(1)
770 as u32;
771 let current_para_block_u64 = u64::from(current_para_block);
772 let relay_blocks_per_para_block_u64 =
773 u64::from(relay_blocks_per_para_block);
774 let target_relay_slot = initial_relay_slot.saturating_add(
775 current_para_block_u64.saturating_mul(relay_blocks_per_para_block_u64),
776 );
777
778 let current_para_block_head = Some(current_para_head.encode().into());
779 let relay_parent_offset =
780 client.runtime_api().relay_parent_offset(parent_hash)?;
781
782 let (timestamp_provider, mocked_parachain) = build_local_mock_inherent_data(
783 para_id,
784 current_para_block,
785 current_para_block_head,
786 relay_blocks_per_para_block,
787 target_relay_slot,
788 relay_parent_offset,
789 should_send_go_ahead.then_some(UpgradeGoAhead::GoAhead),
790 );
791
792 Ok((timestamp_provider, mocked_parachain))
793 }
794 },
795 });
796
797 task_manager
798 .spawn_essential_handle()
799 .spawn_blocking("aura", Some("block-authoring"), aura);
800 }
801
802 Ok(task_manager)
803}