1234567891011121314151617181920use std::sync::Arc;21use std::sync::Mutex;22use std::collections::BTreeMap;23use std::time::Duration;24use std::pin::Pin;25use fc_rpc_core::types::FeeHistoryCache;26use futures::{27 Stream, StreamExt,28 stream::select,29 task::{Context, Poll},30};31use tokio::time::Interval;3233use unique_rpc::overrides_handle;3435use serde::{Serialize, Deserialize};363738use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion};39use cumulus_client_consensus_common::ParachainConsensus;40use cumulus_client_service::{41 prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams,42};43use cumulus_client_cli::CollatorOptions;44use cumulus_client_network::BlockAnnounceValidator;45use cumulus_primitives_core::ParaId;46use cumulus_relay_chain_inprocess_interface::build_inprocess_relay_chain;47use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult};48use cumulus_relay_chain_rpc_interface::RelayChainRPCInterface;495051use sc_client_api::ExecutorProvider;52use sc_executor::NativeElseWasmExecutor;53use sc_executor::NativeExecutionDispatch;54use sc_network::NetworkService;55use sc_service::{BasePath, Configuration, PartialComponents, Role, TaskManager};56use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};57use sp_keystore::SyncCryptoStorePtr;58use sp_runtime::traits::BlakeTwo256;59use substrate_prometheus_endpoint::Registry;60use sc_client_api::BlockchainEvents;6162use polkadot_service::CollatorPair;636465use fc_rpc_core::types::FilterPool;66use fc_mapping_sync::{MappingSyncWorker, SyncStrategy};6768use unique_runtime_common::types::{69 AuraId,70 RuntimeInstance,71 AccountId,72 Balance,73 Index,74 Hash,75 Block,76 77 RmrkCollectionInfo,78 RmrkInstanceInfo,79 RmrkResourceInfo,80 RmrkPropertyInfo,81 RmrkBaseInfo,82 RmrkPartType,83 RmrkTheme,84};858687#[cfg(feature = "unique-runtime")]88pub struct UniqueRuntimeExecutor;8990#[cfg(feature = "quartz-runtime")]919293pub struct QuartzRuntimeExecutor;949596pub struct OpalRuntimeExecutor;9798#[cfg(feature = "unique-runtime")]99impl NativeExecutionDispatch for UniqueRuntimeExecutor {100 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;101102 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {103 unique_runtime::api::dispatch(method, data)104 }105106 fn native_version() -> sc_executor::NativeVersion {107 unique_runtime::native_version()108 }109}110111#[cfg(feature = "quartz-runtime")]112impl NativeExecutionDispatch for QuartzRuntimeExecutor {113 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;114115 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {116 quartz_runtime::api::dispatch(method, data)117 }118119 fn native_version() -> sc_executor::NativeVersion {120 quartz_runtime::native_version()121 }122}123124impl NativeExecutionDispatch for OpalRuntimeExecutor {125 type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;126127 fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {128 opal_runtime::api::dispatch(method, data)129 }130131 fn native_version() -> sc_executor::NativeVersion {132 opal_runtime::native_version()133 }134}135136pub struct AutosealInterval {137 interval: Interval,138}139140impl AutosealInterval {141 pub fn new(config: &Configuration, interval: Duration) -> Self {142 let _tokio_runtime = config.tokio_handle.enter();143 let interval = tokio::time::interval(interval);144145 Self { interval }146 }147}148149impl Stream for AutosealInterval {150 type Item = tokio::time::Instant;151152 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {153 self.interval.poll_tick(cx).map(Some)154 }155}156157pub fn open_frontier_backend(config: &Configuration) -> Result<Arc<fc_db::Backend<Block>>, String> {158 let config_dir = config159 .base_path160 .as_ref()161 .map(|base_path| base_path.config_dir(config.chain_spec.id()))162 .unwrap_or_else(|| {163 BasePath::from_project("", "", "unique").config_dir(config.chain_spec.id())164 });165 let database_dir = config_dir.join("frontier").join("db");166167 Ok(Arc::new(fc_db::Backend::<Block>::new(168 &fc_db::DatabaseSettings {169 source: fc_db::DatabaseSettingsSrc::RocksDb {170 path: database_dir,171 cache_size: 0,172 },173 },174 )?))175}176177type FullClient<RuntimeApi, ExecutorDispatch> =178 sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;179type FullBackend = sc_service::TFullBackend<Block>;180type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;181182183184185186#[allow(clippy::type_complexity)]187pub fn new_partial<RuntimeApi, ExecutorDispatch, BIQ>(188 config: &Configuration,189 build_import_queue: BIQ,190) -> Result<191 PartialComponents<192 FullClient<RuntimeApi, ExecutorDispatch>,193 FullBackend,194 FullSelectChain,195 sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,196 sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,197 (198 Option<Telemetry>,199 Option<FilterPool>,200 Arc<fc_db::Backend<Block>>,201 Option<TelemetryWorkerHandle>,202 FeeHistoryCache,203 ),204 >,205 sc_service::Error,206>207where208 sc_client_api::StateBackendFor<FullBackend, Block>: sp_api::StateBackend<BlakeTwo256>,209 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>210 + Send211 + Sync212 + 'static,213 RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>,214 ExecutorDispatch: NativeExecutionDispatch + 'static,215 BIQ: FnOnce(216 Arc<FullClient<RuntimeApi, ExecutorDispatch>>,217 &Configuration,218 Option<TelemetryHandle>,219 &TaskManager,220 ) -> Result<221 sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,222 sc_service::Error,223 >,224{225 let _telemetry = config226 .telemetry_endpoints227 .clone()228 .filter(|x| !x.is_empty())229 .map(|endpoints| -> Result<_, sc_telemetry::Error> {230 let worker = TelemetryWorker::new(16)?;231 let telemetry = worker.handle().new_telemetry(endpoints);232 Ok((worker, telemetry))233 })234 .transpose()?;235236 let telemetry = config237 .telemetry_endpoints238 .clone()239 .filter(|x| !x.is_empty())240 .map(|endpoints| -> Result<_, sc_telemetry::Error> {241 let worker = TelemetryWorker::new(16)?;242 let telemetry = worker.handle().new_telemetry(endpoints);243 Ok((worker, telemetry))244 })245 .transpose()?;246247 let executor = NativeElseWasmExecutor::<ExecutorDispatch>::new(248 config.wasm_method,249 config.default_heap_pages,250 config.max_runtime_instances,251 config.runtime_cache_size,252 );253254 let (client, backend, keystore_container, task_manager) =255 sc_service::new_full_parts::<Block, RuntimeApi, _>(256 config,257 telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),258 executor,259 )?;260 let client = Arc::new(client);261262 let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());263264 let telemetry = telemetry.map(|(worker, telemetry)| {265 task_manager266 .spawn_handle()267 .spawn("telemetry", None, worker.run());268 telemetry269 });270271 let select_chain = sc_consensus::LongestChain::new(backend.clone());272273 let transaction_pool = sc_transaction_pool::BasicPool::new_full(274 config.transaction_pool.clone(),275 config.role.is_authority().into(),276 config.prometheus_registry(),277 task_manager.spawn_essential_handle(),278 client.clone(),279 );280281 let filter_pool: Option<FilterPool> = Some(Arc::new(Mutex::new(BTreeMap::new())));282283 let frontier_backend = open_frontier_backend(config)?;284285 let import_queue = build_import_queue(286 client.clone(),287 config,288 telemetry.as_ref().map(|telemetry| telemetry.handle()),289 &task_manager,290 )?;291 let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));292293 let params = PartialComponents {294 backend,295 client,296 import_queue,297 keystore_container,298 task_manager,299 transaction_pool,300 select_chain,301 other: (302 telemetry,303 filter_pool,304 frontier_backend,305 telemetry_worker_handle,306 fee_history_cache,307 ),308 };309310 Ok(params)311}312313async fn build_relay_chain_interface(314 polkadot_config: Configuration,315 parachain_config: &Configuration,316 telemetry_worker_handle: Option<TelemetryWorkerHandle>,317 task_manager: &mut TaskManager,318 collator_options: CollatorOptions,319) -> RelayChainResult<(320 Arc<(dyn RelayChainInterface + 'static)>,321 Option<CollatorPair>,322)> {323 match collator_options.relay_chain_rpc_url {324 Some(relay_chain_url) => Ok((325 Arc::new(RelayChainRPCInterface::new(relay_chain_url).await?) as Arc<_>,326 None,327 )),328 None => build_inprocess_relay_chain(329 polkadot_config,330 parachain_config,331 telemetry_worker_handle,332 task_manager,333 ),334 }335}336337338339340#[sc_tracing::logging::prefix_logs_with("Parachain")]341async fn start_node_impl<Runtime, RuntimeApi, ExecutorDispatch, BIQ, BIC>(342 parachain_config: Configuration,343 polkadot_config: Configuration,344 collator_options: CollatorOptions,345 id: ParaId,346 build_import_queue: BIQ,347 build_consensus: BIC,348) -> sc_service::error::Result<(TaskManager, Arc<FullClient<RuntimeApi, ExecutorDispatch>>)>349where350 sc_client_api::StateBackendFor<FullBackend, Block>: sp_api::StateBackend<BlakeTwo256>,351 Runtime: RuntimeInstance + Send + Sync + 'static,352 <Runtime as RuntimeInstance>::CrossAccountId: Serialize,353 for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,354 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>355 + Send356 + Sync357 + 'static,358 RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>359 + fp_rpc::EthereumRuntimeRPCApi<Block>360 + fp_rpc::ConvertTransactionRuntimeApi<Block>361 + sp_session::SessionKeys<Block>362 + sp_block_builder::BlockBuilder<Block>363 + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>364 + sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>365 + up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>366 + rmrk_rpc::RmrkApi<367 Block,368 AccountId,369 RmrkCollectionInfo,370 RmrkInstanceInfo,371 RmrkResourceInfo, 372 RmrkPropertyInfo,373 RmrkBaseInfo,374 RmrkPartType,375 RmrkTheme,376 > + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>377 + sp_api::Metadata<Block>378 + sp_offchain::OffchainWorkerApi<Block>379 + cumulus_primitives_core::CollectCollationInfo<Block>,380 ExecutorDispatch: NativeExecutionDispatch + 'static,381 BIQ: FnOnce(382 Arc<FullClient<RuntimeApi, ExecutorDispatch>>,383 &Configuration,384 Option<TelemetryHandle>,385 &TaskManager,386 ) -> Result<387 sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,388 sc_service::Error,389 >,390 BIC: FnOnce(391 Arc<FullClient<RuntimeApi, ExecutorDispatch>>,392 Option<&Registry>,393 Option<TelemetryHandle>,394 &TaskManager,395 Arc<dyn RelayChainInterface>,396 Arc<sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>>,397 Arc<NetworkService<Block, Hash>>,398 SyncCryptoStorePtr,399 bool,400 ) -> Result<Box<dyn ParachainConsensus<Block>>, sc_service::Error>,401{402 if matches!(parachain_config.role, Role::Light) {403 return Err("Light client not supported!".into());404 }405406 let parachain_config = prepare_node_config(parachain_config);407408 let params =409 new_partial::<RuntimeApi, ExecutorDispatch, BIQ>(¶chain_config, build_import_queue)?;410 let (mut telemetry, filter_pool, frontier_backend, telemetry_worker_handle, fee_history_cache) =411 params.other;412413 let client = params.client.clone();414 let backend = params.backend.clone();415 let mut task_manager = params.task_manager;416417 let (relay_chain_interface, collator_key) = build_relay_chain_interface(418 polkadot_config,419 ¶chain_config,420 telemetry_worker_handle,421 &mut task_manager,422 collator_options.clone(),423 )424 .await425 .map_err(|e| match e {426 RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x,427 s => s.to_string().into(),428 })?;429430 let block_announce_validator = BlockAnnounceValidator::new(relay_chain_interface.clone(), id);431432 let force_authoring = parachain_config.force_authoring;433 let validator = parachain_config.role.is_authority();434 let prometheus_registry = parachain_config.prometheus_registry().cloned();435 let transaction_pool = params.transaction_pool.clone();436 let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue);437438 let (network, system_rpc_tx, start_network) =439 sc_service::build_network(sc_service::BuildNetworkParams {440 config: ¶chain_config,441 client: client.clone(),442 transaction_pool: transaction_pool.clone(),443 spawn_handle: task_manager.spawn_handle(),444 import_queue: import_queue.clone(),445 block_announce_validator_builder: Some(Box::new(|_| {446 Box::new(block_announce_validator)447 })),448 warp_sync: None,449 })?;450451 let subscription_executor = sc_rpc::SubscriptionTaskExecutor::new(task_manager.spawn_handle());452 let rpc_client = client.clone();453 let rpc_pool = transaction_pool.clone();454 let select_chain = params.select_chain.clone();455 let rpc_network = network.clone();456457 let rpc_frontier_backend = frontier_backend.clone();458459 let block_data_cache = Arc::new(fc_rpc::EthBlockDataCache::new(460 task_manager.spawn_handle(),461 overrides_handle::<_, _, Runtime>(client.clone()),462 50,463 50,464 ));465466 let rpc_extensions_builder = Box::new(move |deny_unsafe, _| {467 let full_deps = unique_rpc::FullDeps {468 backend: rpc_frontier_backend.clone(),469 deny_unsafe,470 client: rpc_client.clone(),471 pool: rpc_pool.clone(),472 graph: rpc_pool.pool().clone(),473 474 enable_dev_signer: false,475 filter_pool: filter_pool.clone(),476 network: rpc_network.clone(),477 select_chain: select_chain.clone(),478 is_authority: validator,479 480 max_past_logs: 10000,481 block_data_cache: block_data_cache.clone(),482 fee_history_cache: fee_history_cache.clone(),483 484 fee_history_limit: 2048,485 };486487 Ok(488 unique_rpc::create_full::<_, _, _, _, Runtime, RuntimeApi, _>(489 full_deps,490 subscription_executor.clone(),491 ),492 )493 });494495 task_manager.spawn_essential_handle().spawn(496 "frontier-mapping-sync-worker",497 None,498 MappingSyncWorker::new(499 client.import_notification_stream(),500 Duration::new(6, 0),501 client.clone(),502 backend.clone(),503 frontier_backend.clone(),504 3,505 0,506 SyncStrategy::Normal,507 )508 .for_each(|()| futures::future::ready(())),509 );510511 sc_service::spawn_tasks(sc_service::SpawnTasksParams {512 rpc_extensions_builder,513 client: client.clone(),514 transaction_pool: transaction_pool.clone(),515 task_manager: &mut task_manager,516 config: parachain_config,517 keystore: params.keystore_container.sync_keystore(),518 backend: backend.clone(),519 network: network.clone(),520 system_rpc_tx,521 telemetry: telemetry.as_mut(),522 })?;523524 let announce_block = {525 let network = network.clone();526 Arc::new(move |hash, data| network.announce_block(hash, data))527 };528529 let relay_chain_slot_duration = Duration::from_secs(6);530531 if validator {532 let parachain_consensus = build_consensus(533 client.clone(),534 prometheus_registry.as_ref(),535 telemetry.as_ref().map(|t| t.handle()),536 &task_manager,537 relay_chain_interface.clone(),538 transaction_pool,539 network,540 params.keystore_container.sync_keystore(),541 force_authoring,542 )?;543544 let spawner = task_manager.spawn_handle();545546 let params = StartCollatorParams {547 para_id: id,548 block_status: client.clone(),549 announce_block,550 client: client.clone(),551 task_manager: &mut task_manager,552 spawner,553 parachain_consensus,554 import_queue,555 collator_key: collator_key.expect("Command line arguments do not allow this. qed"),556 relay_chain_interface,557 relay_chain_slot_duration,558 };559560 start_collator(params).await?;561 } else {562 let params = StartFullNodeParams {563 client: client.clone(),564 announce_block,565 task_manager: &mut task_manager,566 para_id: id,567 import_queue,568 relay_chain_interface,569 relay_chain_slot_duration,570 collator_options,571 };572573 start_full_node(params)?;574 }575576 start_network.start_network();577578 Ok((task_manager, client))579}580581582pub fn parachain_build_import_queue<RuntimeApi, ExecutorDispatch>(583 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,584 config: &Configuration,585 telemetry: Option<TelemetryHandle>,586 task_manager: &TaskManager,587) -> Result<588 sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,589 sc_service::Error,590>591where592 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>593 + Send594 + Sync595 + 'static,596 RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>597 + sp_block_builder::BlockBuilder<Block>598 + sp_consensus_aura::AuraApi<Block, AuraId>599 + sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,600 ExecutorDispatch: NativeExecutionDispatch + 'static,601{602 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;603604 cumulus_client_consensus_aura::import_queue::<605 sp_consensus_aura::sr25519::AuthorityPair,606 _,607 _,608 _,609 _,610 _,611 _,612 >(cumulus_client_consensus_aura::ImportQueueParams {613 block_import: client.clone(),614 client: client.clone(),615 create_inherent_data_providers: move |_, _| async move {616 let time = sp_timestamp::InherentDataProvider::from_system_time();617618 let slot =619 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(620 *time,621 slot_duration,622 );623624 Ok((time, slot))625 },626 registry: config.prometheus_registry(),627 can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),628 spawner: &task_manager.spawn_essential_handle(),629 telemetry,630 })631 .map_err(Into::into)632}633634635pub async fn start_node<Runtime, RuntimeApi, ExecutorDispatch>(636 parachain_config: Configuration,637 polkadot_config: Configuration,638 collator_options: CollatorOptions,639 id: ParaId,640) -> sc_service::error::Result<(TaskManager, Arc<FullClient<RuntimeApi, ExecutorDispatch>>)>641where642 Runtime: RuntimeInstance + Send + Sync + 'static,643 <Runtime as RuntimeInstance>::CrossAccountId: Serialize,644 for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,645 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>646 + Send647 + Sync648 + 'static,649 RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>650 + fp_rpc::EthereumRuntimeRPCApi<Block>651 + fp_rpc::ConvertTransactionRuntimeApi<Block>652 + sp_session::SessionKeys<Block>653 + sp_block_builder::BlockBuilder<Block>654 + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>655 + sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>656 + up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>657 + rmrk_rpc::RmrkApi<658 Block,659 AccountId,660 RmrkCollectionInfo,661 RmrkInstanceInfo,662 RmrkResourceInfo, 663 RmrkPropertyInfo,664 RmrkBaseInfo,665 RmrkPartType,666 RmrkTheme,667 > + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>668 + sp_api::Metadata<Block>669 + sp_offchain::OffchainWorkerApi<Block>670 + cumulus_primitives_core::CollectCollationInfo<Block>671 + sp_consensus_aura::AuraApi<Block, AuraId>,672 ExecutorDispatch: NativeExecutionDispatch + 'static,673{674 start_node_impl::<Runtime, RuntimeApi, ExecutorDispatch, _, _>(675 parachain_config,676 polkadot_config,677 collator_options,678 id,679 parachain_build_import_queue,680 |client,681 prometheus_registry,682 telemetry,683 task_manager,684 relay_chain_interface,685 transaction_pool,686 sync_oracle,687 keystore,688 force_authoring| {689 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;690691 let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(692 task_manager.spawn_handle(),693 client.clone(),694 transaction_pool,695 prometheus_registry,696 telemetry.clone(),697 );698699 Ok(AuraConsensus::build::<700 sp_consensus_aura::sr25519::AuthorityPair,701 _,702 _,703 _,704 _,705 _,706 _,707 >(BuildAuraConsensusParams {708 proposer_factory,709 create_inherent_data_providers: move |_, (relay_parent, validation_data)| {710 let relay_chain_interface = relay_chain_interface.clone();711 async move {712 let parachain_inherent =713 cumulus_primitives_parachain_inherent::ParachainInherentData::create_at(714 relay_parent,715 &relay_chain_interface,716 &validation_data,717 id,718 ).await;719720 let time = sp_timestamp::InherentDataProvider::from_system_time();721722 let slot =723 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(724 *time,725 slot_duration,726 );727728 let parachain_inherent = parachain_inherent.ok_or_else(|| {729 Box::<dyn std::error::Error + Send + Sync>::from(730 "Failed to create parachain inherent",731 )732 })?;733 Ok((time, slot, parachain_inherent))734 }735 },736 block_import: client.clone(),737 para_client: client,738 backoff_authoring_blocks: Option::<()>::None,739 sync_oracle,740 keystore,741 force_authoring,742 slot_duration,743 744 block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),745 telemetry,746 max_block_proposal_slot_portion: None,747 }))748 },749 )750 .await751}752753fn dev_build_import_queue<RuntimeApi, ExecutorDispatch>(754 client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,755 config: &Configuration,756 _: Option<TelemetryHandle>,757 task_manager: &TaskManager,758) -> Result<759 sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,760 sc_service::Error,761>762where763 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>764 + Send765 + Sync766 + 'static,767 RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>768 + sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,769 ExecutorDispatch: NativeExecutionDispatch + 'static,770{771 Ok(sc_consensus_manual_seal::import_queue(772 Box::new(client.clone()),773 &task_manager.spawn_essential_handle(),774 config.prometheus_registry(),775 ))776}777778779780pub fn start_dev_node<Runtime, RuntimeApi, ExecutorDispatch>(781 config: Configuration,782 autoseal_interval: Duration,783) -> sc_service::error::Result<TaskManager>784where785 Runtime: RuntimeInstance + Send + Sync + 'static,786 <Runtime as RuntimeInstance>::CrossAccountId: Serialize,787 for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,788 RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>789 + Send790 + Sync791 + 'static,792 RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>793 + fp_rpc::EthereumRuntimeRPCApi<Block>794 + fp_rpc::ConvertTransactionRuntimeApi<Block>795 + sp_session::SessionKeys<Block>796 + sp_block_builder::BlockBuilder<Block>797 + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>798 + sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>799 + up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>800 + rmrk_rpc::RmrkApi<801 Block,802 AccountId,803 RmrkCollectionInfo,804 RmrkInstanceInfo,805 RmrkResourceInfo, 806 RmrkPropertyInfo,807 RmrkBaseInfo,808 RmrkPartType,809 RmrkTheme,810 > + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>811 + sp_api::Metadata<Block>812 + sp_offchain::OffchainWorkerApi<Block>813 + cumulus_primitives_core::CollectCollationInfo<Block>814 + sp_consensus_aura::AuraApi<Block, AuraId>,815 ExecutorDispatch: NativeExecutionDispatch + 'static,816{817 use sc_consensus_manual_seal::{run_manual_seal, EngineCommand, ManualSealParams};818 use fc_consensus::FrontierBlockImport;819 use sc_client_api::HeaderBackend;820821 let sc_service::PartialComponents {822 client,823 backend,824 mut task_manager,825 import_queue,826 keystore_container,827 select_chain: maybe_select_chain,828 transaction_pool,829 other:830 (telemetry, filter_pool, frontier_backend, _telemetry_worker_handle, fee_history_cache),831 } = new_partial::<RuntimeApi, ExecutorDispatch, _>(832 &config,833 dev_build_import_queue::<RuntimeApi, ExecutorDispatch>,834 )?;835836 let block_data_cache = Arc::new(fc_rpc::EthBlockDataCache::new(837 task_manager.spawn_handle(),838 overrides_handle::<_, _, Runtime>(client.clone()),839 50,840 50,841 ));842843 let (network, system_rpc_tx, network_starter) =844 sc_service::build_network(sc_service::BuildNetworkParams {845 config: &config,846 client: client.clone(),847 transaction_pool: transaction_pool.clone(),848 spawn_handle: task_manager.spawn_handle(),849 import_queue,850 block_announce_validator_builder: None,851 warp_sync: None,852 })?;853854 if config.offchain_worker.enabled {855 sc_service::build_offchain_workers(856 &config,857 task_manager.spawn_handle(),858 client.clone(),859 network.clone(),860 );861 }862863 let prometheus_registry = config.prometheus_registry().cloned();864 let collator = config.role.is_authority();865866 let select_chain = maybe_select_chain.clone();867868 if collator {869 let block_import =870 FrontierBlockImport::new(client.clone(), client.clone(), frontier_backend.clone());871872 let env = sc_basic_authorship::ProposerFactory::new(873 task_manager.spawn_handle(),874 client.clone(),875 transaction_pool.clone(),876 prometheus_registry.as_ref(),877 telemetry.as_ref().map(|x| x.handle()),878 );879880 let transactions_commands_stream: Box<881 dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,882 > = Box::new(883 transaction_pool884 .pool()885 .validated_pool()886 .import_notification_stream()887 .map(|_| EngineCommand::SealNewBlock {888 create_empty: true,889 finalize: false,890 parent_hash: None,891 sender: None,892 }),893 );894895 let autoseal_interval = Box::pin(AutosealInterval::new(&config, autoseal_interval));896 let idle_commands_stream: Box<897 dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,898 > = Box::new(autoseal_interval.map(|_| EngineCommand::SealNewBlock {899 create_empty: true,900 finalize: false,901 parent_hash: None,902 sender: None,903 }));904905 let commands_stream = select(transactions_commands_stream, idle_commands_stream);906907 let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;908 let client_set_aside_for_cidp = client.clone();909910 task_manager.spawn_essential_handle().spawn_blocking(911 "authorship_task",912 Some("block-authoring"),913 run_manual_seal(ManualSealParams {914 block_import,915 env,916 client: client.clone(),917 pool: transaction_pool.clone(),918 commands_stream,919 select_chain: select_chain.clone(),920 consensus_data_provider: None,921 create_inherent_data_providers: move |block: Hash, ()| {922 let current_para_block = client_set_aside_for_cidp923 .number(block)924 .expect("Header lookup should succeed")925 .expect("Header passed in as parent should be present in backend.");926927 let client_for_xcm = client_set_aside_for_cidp.clone();928 async move {929 let time = sp_timestamp::InherentDataProvider::from_system_time();930931 let mocked_parachain = cumulus_primitives_parachain_inherent::MockValidationDataInherentDataProvider {932 current_para_block,933 relay_offset: 1000,934 relay_blocks_per_para_block: 2,935 xcm_config: cumulus_primitives_parachain_inherent::MockXcmConfig::new(936 &*client_for_xcm,937 block,938 Default::default(),939 Default::default(),940 ),941 raw_downward_messages: vec![],942 raw_horizontal_messages: vec![],943 };944945 let slot =946 sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(947 *time,948 slot_duration,949 );950951 Ok((time, slot, mocked_parachain))952 }953 },954 }),955 );956 }957958 task_manager.spawn_essential_handle().spawn(959 "frontier-mapping-sync-worker",960 Some("block-authoring"),961 MappingSyncWorker::new(962 client.import_notification_stream(),963 Duration::new(6, 0),964 client.clone(),965 backend.clone(),966 frontier_backend.clone(),967 3,968 0,969 SyncStrategy::Normal,970 )971 .for_each(|()| futures::future::ready(())),972 );973974 let subscription_executor = sc_rpc::SubscriptionTaskExecutor::new(task_manager.spawn_handle());975 let rpc_client = client.clone();976 let rpc_pool = transaction_pool.clone();977 let rpc_network = network.clone();978 let rpc_frontier_backend = frontier_backend.clone();979 let rpc_extensions_builder = Box::new(move |deny_unsafe, _| {980 let full_deps = unique_rpc::FullDeps {981 backend: rpc_frontier_backend.clone(),982 deny_unsafe,983 client: rpc_client.clone(),984 pool: rpc_pool.clone(),985 graph: rpc_pool.pool().clone(),986 987 enable_dev_signer: false,988 filter_pool: filter_pool.clone(),989 network: rpc_network.clone(),990 select_chain: select_chain.clone(),991 is_authority: collator,992 993 max_past_logs: 10000,994 block_data_cache: block_data_cache.clone(),995 fee_history_cache: fee_history_cache.clone(),996 997 fee_history_limit: 2048,998 };9991000 Ok(1001 unique_rpc::create_full::<_, _, _, _, Runtime, RuntimeApi, _>(1002 full_deps,1003 subscription_executor.clone(),1004 ),1005 )1006 });10071008 sc_service::spawn_tasks(sc_service::SpawnTasksParams {1009 network,1010 client,1011 keystore: keystore_container.sync_keystore(),1012 task_manager: &mut task_manager,1013 transaction_pool,1014 rpc_extensions_builder,1015 backend,1016 system_rpc_tx,1017 config,1018 telemetry: None,1019 })?;10201021 network_starter.start_network();1022 Ok(task_manager)1023}