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 Default::default(),
426 )?;
427 let client = Arc::new(client);
428 let telemetry = telemetry.map(|(worker, telemetry)| {
429 task_manager
430 .spawn_handle()
431 .spawn("telemetry", None, worker.run());
432 telemetry
433 });
434 let select_chain = sc_consensus::LongestChain::new(backend.clone());
435 let transaction_pool = sc_transaction_pool::Builder::new(
436 task_manager.spawn_essential_handle(),
437 client.clone(),
438 config.role.is_authority().into(),
439 )
440 .with_options(config.transaction_pool.clone())
441 .with_prometheus(config.prometheus_registry())
442 .build();
443 let frontier_backend = Arc::new(crate::rpc::open_frontier_backend(
444 client.clone(),
445 config,
446 evm_tracing_config,
447 )?);
448 let frontier_block_import = FrontierBlockImport::new(client.clone(), client.clone());
449
450 let import_queue = sc_consensus_manual_seal::import_queue(
451 Box::new(client.clone()),
452 &task_manager.spawn_essential_handle(),
453 config.prometheus_registry(),
454 );
455
456 Ok(sc_service::PartialComponents {
457 client,
458 backend,
459 task_manager,
460 import_queue,
461 keystore_container,
462 select_chain,
463 transaction_pool: transaction_pool.into(),
464 other: (frontier_block_import, telemetry, frontier_backend),
465 })
466}
467
468pub fn start_node<N>(
470 mut config: Configuration,
471 evm_tracing_config: FrontierConfig,
472) -> Result<TaskManager, ServiceError>
473where
474 N: NetworkBackend<Block, <Block as BlockT>::Hash>,
475{
476 let sc_service::PartialComponents {
477 client,
478 backend,
479 mut task_manager,
480 import_queue,
481 keystore_container,
482 select_chain,
483 transaction_pool,
484 other: (block_import, mut telemetry, frontier_backend),
485 } = new_partial(&config, &evm_tracing_config)?;
486
487 config.network.default_peers_set.in_peers = 0;
489 config.network.default_peers_set.out_peers = 0;
490
491 let net_config = sc_network::config::FullNetworkConfiguration::<_, _, N>::new(
492 &config.network,
493 config.prometheus_registry().cloned(),
494 );
495
496 let metrics = N::register_notification_metrics(
497 config.prometheus_config.as_ref().map(|cfg| &cfg.registry),
498 );
499 let (network, system_rpc_tx, tx_handler_controller, sync_service) =
500 sc_service::build_network(sc_service::BuildNetworkParams {
501 config: &config,
502 net_config,
503 client: client.clone(),
504 transaction_pool: transaction_pool.clone(),
505 spawn_handle: task_manager.spawn_handle(),
506 spawn_essential_handle: task_manager.spawn_essential_handle(),
507 import_queue,
508 block_announce_validator_builder: None,
509 warp_sync_config: None,
510 block_relay: None,
511 metrics,
512 })?;
513
514 if config.offchain_worker.enabled {
515 task_manager.spawn_handle().spawn(
516 "offchain-workers-runner",
517 "offchain-work",
518 sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions {
519 runtime_api_provider: client.clone(),
520 keystore: Some(keystore_container.keystore()),
521 offchain_db: backend.offchain_storage(),
522 transaction_pool: Some(OffchainTransactionPoolFactory::new(
523 transaction_pool.clone(),
524 )),
525 network_provider: Arc::new(network.clone()),
526 is_validator: config.role.is_authority(),
527 enable_http_requests: true,
528 custom_extensions: move |_| vec![],
529 })?
530 .run(client.clone(), task_manager.spawn_handle())
531 .boxed(),
532 );
533 }
534
535 let filter_pool: FilterPool = Arc::new(std::sync::Mutex::new(BTreeMap::new()));
536 let fee_history_cache: FeeHistoryCache = Arc::new(std::sync::Mutex::new(BTreeMap::new()));
537 let storage_override = Arc::new(StorageOverrideHandler::new(client.clone()));
538
539 let pubsub_notification_sinks: fc_mapping_sync::EthereumBlockNotificationSinks<
544 fc_mapping_sync::EthereumBlockNotification<Block>,
545 > = Default::default();
546 let pubsub_notification_sinks = Arc::new(pubsub_notification_sinks);
547
548 let ethapi_cmd = evm_tracing_config.ethapi.clone();
549
550 let tracing_requesters =
551 if ethapi_cmd.contains(&EthApiCmd::Debug) || ethapi_cmd.contains(&EthApiCmd::Trace) {
552 tracing::spawn_tracing_tasks(
553 &evm_tracing_config,
554 config.prometheus_registry().cloned(),
555 tracing::SpawnTasksParams {
556 task_manager: &task_manager,
557 client: client.clone(),
558 substrate_backend: backend.clone(),
559 frontier_backend: frontier_backend.clone(),
560 storage_override: storage_override.clone(),
561 },
562 )
563 } else {
564 tracing::RpcRequesters {
565 debug: None,
566 trace: None,
567 }
568 };
569
570 match frontier_backend.as_ref() {
573 fc_db::Backend::KeyValue(ref b) => {
574 task_manager.spawn_essential_handle().spawn(
575 "frontier-mapping-sync-worker",
576 Some("frontier"),
577 fc_mapping_sync::kv::MappingSyncWorker::new(
578 client.import_notification_stream(),
579 Duration::new(6, 0),
580 client.clone(),
581 backend.clone(),
582 storage_override.clone(),
583 b.clone(),
584 3,
585 0,
586 None,
587 fc_mapping_sync::SyncStrategy::Parachain,
588 sync_service.clone(),
589 pubsub_notification_sinks.clone(),
590 )
591 .for_each(|()| futures::future::ready(())),
592 );
593 }
594 fc_db::Backend::Sql(ref b) => {
595 task_manager.spawn_essential_handle().spawn_blocking(
596 "frontier-mapping-sync-worker",
597 Some("frontier"),
598 fc_mapping_sync::sql::SyncWorker::run(
599 client.clone(),
600 backend.clone(),
601 b.clone(),
602 client.import_notification_stream(),
603 fc_mapping_sync::sql::SyncWorkerConfig {
604 read_notification_timeout: Duration::from_secs(10),
605 check_indexed_blocks_interval: Duration::from_secs(60),
606 },
607 fc_mapping_sync::SyncStrategy::Parachain,
608 sync_service.clone(),
609 pubsub_notification_sinks.clone(),
610 ),
611 );
612 }
613 }
614
615 const FILTER_RETAIN_THRESHOLD: u64 = 100;
618 task_manager.spawn_essential_handle().spawn(
619 "frontier-filter-pool",
620 Some("frontier"),
621 fc_rpc::EthTask::filter_pool_task(
622 client.clone(),
623 filter_pool.clone(),
624 FILTER_RETAIN_THRESHOLD,
625 ),
626 );
627
628 const FEE_HISTORY_LIMIT: u64 = 2048;
629 task_manager.spawn_essential_handle().spawn(
630 "frontier-fee-history",
631 Some("frontier"),
632 fc_rpc::EthTask::fee_history_task(
633 client.clone(),
634 storage_override.clone(),
635 fee_history_cache.clone(),
636 FEE_HISTORY_LIMIT,
637 ),
638 );
639
640 let role = config.role.clone();
641 let prometheus_registry = config.prometheus_registry().cloned();
642 let is_authority = config.role.is_authority();
643
644 let block_data_cache = Arc::new(fc_rpc::EthBlockDataCacheTask::new(
645 task_manager.spawn_handle(),
646 storage_override.clone(),
647 50,
648 50,
649 prometheus_registry.clone(),
650 ));
651
652 let (command_sink, commands_stream) = futures::channel::mpsc::channel(1024);
654 let local_para_id = ParaId::from(
655 crate::parachain::chain_spec::Extensions::try_get(&*config.chain_spec)
656 .map(|e| e.para_id)
657 .unwrap_or(2000),
658 );
659
660 let rpc_extensions_builder = {
661 let client = client.clone();
662 let network = network.clone();
663 let transaction_pool = transaction_pool.clone();
664 let sync = sync_service.clone();
665 let pubsub_notification_sinks = pubsub_notification_sinks.clone();
666
667 Box::new(move |subscription| {
668 let deps = crate::rpc::FullDeps {
669 client: client.clone(),
670 pool: transaction_pool.clone(),
671 graph: transaction_pool.clone(),
672 network: network.clone(),
673 sync: sync.clone(),
674 is_authority,
675 frontier_backend: match *frontier_backend {
676 fc_db::Backend::KeyValue(ref b) => b.clone(),
677 fc_db::Backend::Sql(ref b) => b.clone(),
678 },
679 filter_pool: filter_pool.clone(),
680 fee_history_limit: FEE_HISTORY_LIMIT,
681 fee_history_cache: fee_history_cache.clone(),
682 block_data_cache: block_data_cache.clone(),
683 storage_override: storage_override.clone(),
684 enable_evm_rpc: true, command_sink: Some(command_sink.clone()),
686 };
687
688 crate::rpc::create_full_local_dev(
689 deps,
690 subscription,
691 pubsub_notification_sinks.clone(),
692 local_para_id,
693 crate::rpc::EvmTracingConfig {
694 tracing_requesters: tracing_requesters.clone(),
695 trace_filter_max_count: evm_tracing_config.ethapi_trace_max_count,
696 trace_filter_max_block_range: evm_tracing_config.trace_filter_max_block_range,
697 enable_txpool: ethapi_cmd.contains(&EthApiCmd::TxPool),
698 },
699 )
700 .map_err::<ServiceError, _>(Into::into)
701 })
702 };
703
704 let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
705 network: network.clone(),
706 client: client.clone(),
707 keystore: keystore_container.keystore(),
708 task_manager: &mut task_manager,
709 transaction_pool: transaction_pool.clone(),
710 rpc_builder: rpc_extensions_builder,
711 backend,
712 system_rpc_tx,
713 tx_handler_controller,
714 sync_service: sync_service.clone(),
715 config,
716 telemetry: telemetry.as_mut(),
717 tracing_execute_block: None,
718 })?;
719
720 if role.is_authority() {
721 let proposer_factory = sc_basic_authorship::ProposerFactory::new(
722 task_manager.spawn_handle(),
723 client.clone(),
724 transaction_pool.clone(),
725 prometheus_registry.as_ref(),
726 telemetry.as_ref().map(|x| x.handle()),
727 );
728
729 let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
730
731 let para_id = local_para_id;
732 let initial_relay_slot = std::time::SystemTime::now()
733 .duration_since(std::time::UNIX_EPOCH)
734 .expect("Current time is always after UNIX_EPOCH; qed")
735 .sub(Duration::from_secs(2 * 60 * 60))
736 .as_millis() as u64
737 / RELAY_CHAIN_SLOT_DURATION_MILLIS;
738
739 let aura =
740 sc_consensus_manual_seal::run_manual_seal(sc_consensus_manual_seal::ManualSealParams {
741 block_import,
742 env: proposer_factory,
743 client: client.clone(),
744 pool: transaction_pool.clone(),
745 commands_stream,
746 select_chain,
747 consensus_data_provider: Some(Box::new(
748 sc_consensus_manual_seal::consensus::aura::AuraConsensusDataProvider::new(
749 client.clone(),
750 ),
751 )),
752 create_inherent_data_providers: move |parent_hash, ()| {
753 let client = client.clone();
754 async move {
755 let current_para_head = client
756 .header(parent_hash)
757 .expect("Header lookup should succeed")
758 .expect("Header passed in as parent should be present in backend.");
759
760 let should_send_go_ahead = client
761 .runtime_api()
762 .collect_collation_info(parent_hash, ¤t_para_head)
763 .map(|info| info.new_validation_code.is_some())
764 .unwrap_or_default();
765
766 let current_para_block = UniqueSaturatedInto::<u32>::unique_saturated_into(
767 *current_para_head.number(),
768 ) + 1;
769
770 let relay_blocks_per_para_block =
771 (slot_duration.as_millis() / RELAY_CHAIN_SLOT_DURATION_MILLIS).max(1)
772 as u32;
773 let current_para_block_u64 = u64::from(current_para_block);
774 let relay_blocks_per_para_block_u64 =
775 u64::from(relay_blocks_per_para_block);
776 let target_relay_slot = initial_relay_slot.saturating_add(
777 current_para_block_u64.saturating_mul(relay_blocks_per_para_block_u64),
778 );
779
780 let current_para_block_head = Some(current_para_head.encode().into());
781 let relay_parent_offset =
782 client.runtime_api().relay_parent_offset(parent_hash)?;
783
784 let (timestamp_provider, mocked_parachain) = build_local_mock_inherent_data(
785 para_id,
786 current_para_block,
787 current_para_block_head,
788 relay_blocks_per_para_block,
789 target_relay_slot,
790 relay_parent_offset,
791 should_send_go_ahead.then_some(UpgradeGoAhead::GoAhead),
792 );
793
794 Ok((timestamp_provider, mocked_parachain))
795 }
796 },
797 });
798
799 task_manager
800 .spawn_essential_handle()
801 .spawn_blocking("aura", Some("block-authoring"), aura);
802 }
803
804 Ok(task_manager)
805}