git.delta.rocks / unique-network / refs/commits / 547ee7a8f073

difftreelog

source

node/cli/src/service.rs30.1 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.1819// std20use 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};3637// Cumulus Imports38use 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;4950// Substrate Imports51use 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;6364// Frontier Imports65use 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};7778// RMRK79use up_data_structs::{80	RmrkCollectionInfo,81	RmrkInstanceInfo,82	RmrkResourceInfo,83	RmrkPropertyInfo,84	RmrkBaseInfo,85	RmrkPartType,86	RmrkTheme,87};8889/// Unique native executor instance.90#[cfg(feature = "unique-runtime")]91pub struct UniqueRuntimeExecutor;9293#[cfg(feature = "quartz-runtime")]94/// Quartz native executor instance.9596pub struct QuartzRuntimeExecutor;9798/// Opal native executor instance.99pub struct OpalRuntimeExecutor;100101#[cfg(feature = "unique-runtime")]102impl NativeExecutionDispatch for UniqueRuntimeExecutor {103	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;104105	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {106		unique_runtime::api::dispatch(method, data)107	}108109	fn native_version() -> sc_executor::NativeVersion {110		unique_runtime::native_version()111	}112}113114#[cfg(feature = "quartz-runtime")]115impl NativeExecutionDispatch for QuartzRuntimeExecutor {116	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;117118	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {119		quartz_runtime::api::dispatch(method, data)120	}121122	fn native_version() -> sc_executor::NativeVersion {123		quartz_runtime::native_version()124	}125}126127impl NativeExecutionDispatch for OpalRuntimeExecutor {128	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;129130	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {131		opal_runtime::api::dispatch(method, data)132	}133134	fn native_version() -> sc_executor::NativeVersion {135		opal_runtime::native_version()136	}137}138139pub struct AutosealInterval {140	interval: Interval,141}142143impl AutosealInterval {144	pub fn new(config: &Configuration, interval: Duration) -> Self {145		let _tokio_runtime = config.tokio_handle.enter();146		let interval = tokio::time::interval(interval);147148		Self { interval }149	}150}151152impl Stream for AutosealInterval {153	type Item = tokio::time::Instant;154155	fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {156		self.interval.poll_tick(cx).map(Some)157	}158}159160pub fn open_frontier_backend(config: &Configuration) -> Result<Arc<fc_db::Backend<Block>>, String> {161	let config_dir = config162		.base_path163		.as_ref()164		.map(|base_path| base_path.config_dir(config.chain_spec.id()))165		.unwrap_or_else(|| {166			BasePath::from_project("", "", "unique").config_dir(config.chain_spec.id())167		});168	let database_dir = config_dir.join("frontier").join("db");169170	Ok(Arc::new(fc_db::Backend::<Block>::new(171		&fc_db::DatabaseSettings {172			source: fc_db::DatabaseSettingsSrc::RocksDb {173				path: database_dir,174				cache_size: 0,175			},176		},177	)?))178}179180type FullClient<RuntimeApi, ExecutorDispatch> =181	sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;182type FullBackend = sc_service::TFullBackend<Block>;183type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;184185/// Starts a `ServiceBuilder` for a full service.186///187/// Use this macro if you don't actually need the full service, but just the builder in order to188/// be able to perform chain operations.189#[allow(clippy::type_complexity)]190pub fn new_partial<RuntimeApi, ExecutorDispatch, BIQ>(191	config: &Configuration,192	build_import_queue: BIQ,193) -> Result<194	PartialComponents<195		FullClient<RuntimeApi, ExecutorDispatch>,196		FullBackend,197		FullSelectChain,198		sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,199		sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,200		(201			Option<Telemetry>,202			Option<FilterPool>,203			Arc<fc_db::Backend<Block>>,204			Option<TelemetryWorkerHandle>,205			FeeHistoryCache,206		),207	>,208	sc_service::Error,209>210where211	sc_client_api::StateBackendFor<FullBackend, Block>: sp_api::StateBackend<BlakeTwo256>,212	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>213		+ Send214		+ Sync215		+ 'static,216	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>,217	ExecutorDispatch: NativeExecutionDispatch + 'static,218	BIQ: FnOnce(219		Arc<FullClient<RuntimeApi, ExecutorDispatch>>,220		&Configuration,221		Option<TelemetryHandle>,222		&TaskManager,223	) -> Result<224		sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,225		sc_service::Error,226	>,227{228	let _telemetry = config229		.telemetry_endpoints230		.clone()231		.filter(|x| !x.is_empty())232		.map(|endpoints| -> Result<_, sc_telemetry::Error> {233			let worker = TelemetryWorker::new(16)?;234			let telemetry = worker.handle().new_telemetry(endpoints);235			Ok((worker, telemetry))236		})237		.transpose()?;238239	let telemetry = config240		.telemetry_endpoints241		.clone()242		.filter(|x| !x.is_empty())243		.map(|endpoints| -> Result<_, sc_telemetry::Error> {244			let worker = TelemetryWorker::new(16)?;245			let telemetry = worker.handle().new_telemetry(endpoints);246			Ok((worker, telemetry))247		})248		.transpose()?;249250	let executor = NativeElseWasmExecutor::<ExecutorDispatch>::new(251		config.wasm_method,252		config.default_heap_pages,253		config.max_runtime_instances,254		config.runtime_cache_size,255	);256257	let (client, backend, keystore_container, task_manager) =258		sc_service::new_full_parts::<Block, RuntimeApi, _>(259			config,260			telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),261			executor,262		)?;263	let client = Arc::new(client);264265	let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());266267	let telemetry = telemetry.map(|(worker, telemetry)| {268		task_manager269			.spawn_handle()270			.spawn("telemetry", None, worker.run());271		telemetry272	});273274	let select_chain = sc_consensus::LongestChain::new(backend.clone());275276	let transaction_pool = sc_transaction_pool::BasicPool::new_full(277		config.transaction_pool.clone(),278		config.role.is_authority().into(),279		config.prometheus_registry(),280		task_manager.spawn_essential_handle(),281		client.clone(),282	);283284	let filter_pool: Option<FilterPool> = Some(Arc::new(Mutex::new(BTreeMap::new())));285286	let frontier_backend = open_frontier_backend(config)?;287288	let import_queue = build_import_queue(289		client.clone(),290		config,291		telemetry.as_ref().map(|telemetry| telemetry.handle()),292		&task_manager,293	)?;294	let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));295296	let params = PartialComponents {297		backend,298		client,299		import_queue,300		keystore_container,301		task_manager,302		transaction_pool,303		select_chain,304		other: (305			telemetry,306			filter_pool,307			frontier_backend,308			telemetry_worker_handle,309			fee_history_cache,310		),311	};312313	Ok(params)314}315316async fn build_relay_chain_interface(317	polkadot_config: Configuration,318	parachain_config: &Configuration,319	telemetry_worker_handle: Option<TelemetryWorkerHandle>,320	task_manager: &mut TaskManager,321	collator_options: CollatorOptions,322) -> RelayChainResult<(323	Arc<(dyn RelayChainInterface + 'static)>,324	Option<CollatorPair>,325)> {326	match collator_options.relay_chain_rpc_url {327		Some(relay_chain_url) => Ok((328			Arc::new(RelayChainRPCInterface::new(relay_chain_url).await?) as Arc<_>,329			None,330		)),331		None => build_inprocess_relay_chain(332			polkadot_config,333			parachain_config,334			telemetry_worker_handle,335			task_manager,336		),337	}338}339340/// Start a node with the given parachain `Configuration` and relay chain `Configuration`.341///342/// This is the actual implementation that is abstract over the executor and the runtime api.343#[sc_tracing::logging::prefix_logs_with("Parachain")]344async fn start_node_impl<Runtime, RuntimeApi, ExecutorDispatch, BIQ, BIC>(345	parachain_config: Configuration,346	polkadot_config: Configuration,347	collator_options: CollatorOptions,348	id: ParaId,349	build_import_queue: BIQ,350	build_consensus: BIC,351) -> sc_service::error::Result<(TaskManager, Arc<FullClient<RuntimeApi, ExecutorDispatch>>)>352where353	sc_client_api::StateBackendFor<FullBackend, Block>: sp_api::StateBackend<BlakeTwo256>,354	Runtime: RuntimeInstance + Send + Sync + 'static,355	<Runtime as RuntimeInstance>::CrossAccountId: Serialize,356	for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,357	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>358		+ Send359		+ Sync360		+ 'static,361	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>362		+ fp_rpc::EthereumRuntimeRPCApi<Block>363		+ fp_rpc::ConvertTransactionRuntimeApi<Block>364		+ sp_session::SessionKeys<Block>365		+ sp_block_builder::BlockBuilder<Block>366		+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>367		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>368		+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>369		+ rmrk_rpc::RmrkApi<370			Block,371			AccountId,372			RmrkCollectionInfo<AccountId>,373			RmrkInstanceInfo<AccountId>,374			RmrkResourceInfo,375			RmrkPropertyInfo,376			RmrkBaseInfo<AccountId>,377			RmrkPartType,378			RmrkTheme,379		> + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>380		+ sp_api::Metadata<Block>381		+ sp_offchain::OffchainWorkerApi<Block>382		+ cumulus_primitives_core::CollectCollationInfo<Block>,383	ExecutorDispatch: NativeExecutionDispatch + 'static,384	BIQ: FnOnce(385		Arc<FullClient<RuntimeApi, ExecutorDispatch>>,386		&Configuration,387		Option<TelemetryHandle>,388		&TaskManager,389	) -> Result<390		sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,391		sc_service::Error,392	>,393	BIC: FnOnce(394		Arc<FullClient<RuntimeApi, ExecutorDispatch>>,395		Option<&Registry>,396		Option<TelemetryHandle>,397		&TaskManager,398		Arc<dyn RelayChainInterface>,399		Arc<sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>>,400		Arc<NetworkService<Block, Hash>>,401		SyncCryptoStorePtr,402		bool,403	) -> Result<Box<dyn ParachainConsensus<Block>>, sc_service::Error>,404{405	if matches!(parachain_config.role, Role::Light) {406		return Err("Light client not supported!".into());407	}408409	let parachain_config = prepare_node_config(parachain_config);410411	let params =412		new_partial::<RuntimeApi, ExecutorDispatch, BIQ>(&parachain_config, build_import_queue)?;413	let (mut telemetry, filter_pool, frontier_backend, telemetry_worker_handle, fee_history_cache) =414		params.other;415416	let client = params.client.clone();417	let backend = params.backend.clone();418	let mut task_manager = params.task_manager;419420	let (relay_chain_interface, collator_key) = build_relay_chain_interface(421		polkadot_config,422		&parachain_config,423		telemetry_worker_handle,424		&mut task_manager,425		collator_options.clone(),426	)427	.await428	.map_err(|e| match e {429		RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x,430		s => s.to_string().into(),431	})?;432433	let block_announce_validator = BlockAnnounceValidator::new(relay_chain_interface.clone(), id);434435	let force_authoring = parachain_config.force_authoring;436	let validator = parachain_config.role.is_authority();437	let prometheus_registry = parachain_config.prometheus_registry().cloned();438	let transaction_pool = params.transaction_pool.clone();439	let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue);440441	let (network, system_rpc_tx, start_network) =442		sc_service::build_network(sc_service::BuildNetworkParams {443			config: &parachain_config,444			client: client.clone(),445			transaction_pool: transaction_pool.clone(),446			spawn_handle: task_manager.spawn_handle(),447			import_queue: import_queue.clone(),448			block_announce_validator_builder: Some(Box::new(|_| {449				Box::new(block_announce_validator)450			})),451			warp_sync: None,452		})?;453454	let subscription_executor = sc_rpc::SubscriptionTaskExecutor::new(task_manager.spawn_handle());455	let rpc_client = client.clone();456	let rpc_pool = transaction_pool.clone();457	let select_chain = params.select_chain.clone();458	let rpc_network = network.clone();459460	let rpc_frontier_backend = frontier_backend.clone();461462	let block_data_cache = Arc::new(fc_rpc::EthBlockDataCache::new(463		task_manager.spawn_handle(),464		overrides_handle::<_, _, Runtime>(client.clone()),465		50,466		50,467	));468469	let rpc_extensions_builder = Box::new(move |deny_unsafe, _| {470		let full_deps = unique_rpc::FullDeps {471			backend: rpc_frontier_backend.clone(),472			deny_unsafe,473			client: rpc_client.clone(),474			pool: rpc_pool.clone(),475			graph: rpc_pool.pool().clone(),476			// TODO: Unhardcode477			enable_dev_signer: false,478			filter_pool: filter_pool.clone(),479			network: rpc_network.clone(),480			select_chain: select_chain.clone(),481			is_authority: validator,482			// TODO: Unhardcode483			max_past_logs: 10000,484			block_data_cache: block_data_cache.clone(),485			fee_history_cache: fee_history_cache.clone(),486			// TODO: Unhardcode487			fee_history_limit: 2048,488		};489490		Ok(491			unique_rpc::create_full::<_, _, _, _, Runtime, RuntimeApi, _>(492				full_deps,493				subscription_executor.clone(),494			),495		)496	});497498	task_manager.spawn_essential_handle().spawn(499		"frontier-mapping-sync-worker",500		None,501		MappingSyncWorker::new(502			client.import_notification_stream(),503			Duration::new(6, 0),504			client.clone(),505			backend.clone(),506			frontier_backend.clone(),507			3,508			0,509			SyncStrategy::Normal,510		)511		.for_each(|()| futures::future::ready(())),512	);513514	sc_service::spawn_tasks(sc_service::SpawnTasksParams {515		rpc_extensions_builder,516		client: client.clone(),517		transaction_pool: transaction_pool.clone(),518		task_manager: &mut task_manager,519		config: parachain_config,520		keystore: params.keystore_container.sync_keystore(),521		backend: backend.clone(),522		network: network.clone(),523		system_rpc_tx,524		telemetry: telemetry.as_mut(),525	})?;526527	let announce_block = {528		let network = network.clone();529		Arc::new(move |hash, data| network.announce_block(hash, data))530	};531532	let relay_chain_slot_duration = Duration::from_secs(6);533534	if validator {535		let parachain_consensus = build_consensus(536			client.clone(),537			prometheus_registry.as_ref(),538			telemetry.as_ref().map(|t| t.handle()),539			&task_manager,540			relay_chain_interface.clone(),541			transaction_pool,542			network,543			params.keystore_container.sync_keystore(),544			force_authoring,545		)?;546547		let spawner = task_manager.spawn_handle();548549		let params = StartCollatorParams {550			para_id: id,551			block_status: client.clone(),552			announce_block,553			client: client.clone(),554			task_manager: &mut task_manager,555			spawner,556			parachain_consensus,557			import_queue,558			collator_key: collator_key.expect("Command line arguments do not allow this. qed"),559			relay_chain_interface,560			relay_chain_slot_duration,561		};562563		start_collator(params).await?;564	} else {565		let params = StartFullNodeParams {566			client: client.clone(),567			announce_block,568			task_manager: &mut task_manager,569			para_id: id,570			import_queue,571			relay_chain_interface,572			relay_chain_slot_duration,573			collator_options,574		};575576		start_full_node(params)?;577	}578579	start_network.start_network();580581	Ok((task_manager, client))582}583584/// Build the import queue for the the parachain runtime.585pub fn parachain_build_import_queue<RuntimeApi, ExecutorDispatch>(586	client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,587	config: &Configuration,588	telemetry: Option<TelemetryHandle>,589	task_manager: &TaskManager,590) -> Result<591	sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,592	sc_service::Error,593>594where595	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>596		+ Send597		+ Sync598		+ 'static,599	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>600		+ sp_block_builder::BlockBuilder<Block>601		+ sp_consensus_aura::AuraApi<Block, AuraId>602		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,603	ExecutorDispatch: NativeExecutionDispatch + 'static,604{605	let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;606607	cumulus_client_consensus_aura::import_queue::<608		sp_consensus_aura::sr25519::AuthorityPair,609		_,610		_,611		_,612		_,613		_,614		_,615	>(cumulus_client_consensus_aura::ImportQueueParams {616		block_import: client.clone(),617		client: client.clone(),618		create_inherent_data_providers: move |_, _| async move {619			let time = sp_timestamp::InherentDataProvider::from_system_time();620621			let slot =622				sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(623					*time,624					slot_duration,625				);626627			Ok((time, slot))628		},629		registry: config.prometheus_registry(),630		can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),631		spawner: &task_manager.spawn_essential_handle(),632		telemetry,633	})634	.map_err(Into::into)635}636637/// Start a normal parachain node.638pub async fn start_node<Runtime, RuntimeApi, ExecutorDispatch>(639	parachain_config: Configuration,640	polkadot_config: Configuration,641	collator_options: CollatorOptions,642	id: ParaId,643) -> sc_service::error::Result<(TaskManager, Arc<FullClient<RuntimeApi, ExecutorDispatch>>)>644where645	Runtime: RuntimeInstance + Send + Sync + 'static,646	<Runtime as RuntimeInstance>::CrossAccountId: Serialize,647	for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,648	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>649		+ Send650		+ Sync651		+ 'static,652	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>653		+ fp_rpc::EthereumRuntimeRPCApi<Block>654		+ fp_rpc::ConvertTransactionRuntimeApi<Block>655		+ sp_session::SessionKeys<Block>656		+ sp_block_builder::BlockBuilder<Block>657		+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>658		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>659		+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>660		+ rmrk_rpc::RmrkApi<661			Block,662			AccountId,663			RmrkCollectionInfo<AccountId>,664			RmrkInstanceInfo<AccountId>,665			RmrkResourceInfo,666			RmrkPropertyInfo,667			RmrkBaseInfo<AccountId>,668			RmrkPartType,669			RmrkTheme,670		> + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>671		+ sp_api::Metadata<Block>672		+ sp_offchain::OffchainWorkerApi<Block>673		+ cumulus_primitives_core::CollectCollationInfo<Block>674		+ sp_consensus_aura::AuraApi<Block, AuraId>,675	ExecutorDispatch: NativeExecutionDispatch + 'static,676{677	start_node_impl::<Runtime, RuntimeApi, ExecutorDispatch, _, _>(678		parachain_config,679		polkadot_config,680		collator_options,681		id,682		parachain_build_import_queue,683		|client,684		 prometheus_registry,685		 telemetry,686		 task_manager,687		 relay_chain_interface,688		 transaction_pool,689		 sync_oracle,690		 keystore,691		 force_authoring| {692			let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;693694			let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(695				task_manager.spawn_handle(),696				client.clone(),697				transaction_pool,698				prometheus_registry,699				telemetry.clone(),700			);701702			Ok(AuraConsensus::build::<703				sp_consensus_aura::sr25519::AuthorityPair,704				_,705				_,706				_,707				_,708				_,709				_,710			>(BuildAuraConsensusParams {711				proposer_factory,712				create_inherent_data_providers: move |_, (relay_parent, validation_data)| {713					let relay_chain_interface = relay_chain_interface.clone();714					async move {715						let parachain_inherent =716						cumulus_primitives_parachain_inherent::ParachainInherentData::create_at(717							relay_parent,718							&relay_chain_interface,719							&validation_data,720							id,721						).await;722723						let time = sp_timestamp::InherentDataProvider::from_system_time();724725						let slot =726						sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(727							*time,728							slot_duration,729						);730731						let parachain_inherent = parachain_inherent.ok_or_else(|| {732							Box::<dyn std::error::Error + Send + Sync>::from(733								"Failed to create parachain inherent",734							)735						})?;736						Ok((time, slot, parachain_inherent))737					}738				},739				block_import: client.clone(),740				para_client: client,741				backoff_authoring_blocks: Option::<()>::None,742				sync_oracle,743				keystore,744				force_authoring,745				slot_duration,746				// We got around 500ms for proposing747				block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),748				telemetry,749				max_block_proposal_slot_portion: None,750			}))751		},752	)753	.await754}755756fn dev_build_import_queue<RuntimeApi, ExecutorDispatch>(757	client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,758	config: &Configuration,759	_: Option<TelemetryHandle>,760	task_manager: &TaskManager,761) -> Result<762	sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,763	sc_service::Error,764>765where766	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>767		+ Send768		+ Sync769		+ 'static,770	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>771		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,772	ExecutorDispatch: NativeExecutionDispatch + 'static,773{774	Ok(sc_consensus_manual_seal::import_queue(775		Box::new(client.clone()),776		&task_manager.spawn_essential_handle(),777		config.prometheus_registry(),778	))779}780781/// Builds a new development service. This service uses instant seal, and mocks782/// the parachain inherent783pub fn start_dev_node<Runtime, RuntimeApi, ExecutorDispatch>(784	config: Configuration,785	autoseal_interval: Duration,786) -> sc_service::error::Result<TaskManager>787where788	Runtime: RuntimeInstance + Send + Sync + 'static,789	<Runtime as RuntimeInstance>::CrossAccountId: Serialize,790	for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,791	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>792		+ Send793		+ Sync794		+ 'static,795	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>796		+ fp_rpc::EthereumRuntimeRPCApi<Block>797		+ fp_rpc::ConvertTransactionRuntimeApi<Block>798		+ sp_session::SessionKeys<Block>799		+ sp_block_builder::BlockBuilder<Block>800		+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>801		+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>802		+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>803		+ rmrk_rpc::RmrkApi<804			Block,805			AccountId,806			RmrkCollectionInfo<AccountId>,807			RmrkInstanceInfo<AccountId>,808			RmrkResourceInfo,809			RmrkPropertyInfo,810			RmrkBaseInfo<AccountId>,811			RmrkPartType,812			RmrkTheme,813		> + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>814		+ sp_api::Metadata<Block>815		+ sp_offchain::OffchainWorkerApi<Block>816		+ cumulus_primitives_core::CollectCollationInfo<Block>817		+ sp_consensus_aura::AuraApi<Block, AuraId>,818	ExecutorDispatch: NativeExecutionDispatch + 'static,819{820	use sc_consensus_manual_seal::{run_manual_seal, EngineCommand, ManualSealParams};821	use fc_consensus::FrontierBlockImport;822	use sc_client_api::HeaderBackend;823824	let sc_service::PartialComponents {825		client,826		backend,827		mut task_manager,828		import_queue,829		keystore_container,830		select_chain: maybe_select_chain,831		transaction_pool,832		other:833			(telemetry, filter_pool, frontier_backend, _telemetry_worker_handle, fee_history_cache),834	} = new_partial::<RuntimeApi, ExecutorDispatch, _>(835		&config,836		dev_build_import_queue::<RuntimeApi, ExecutorDispatch>,837	)?;838839	let block_data_cache = Arc::new(fc_rpc::EthBlockDataCache::new(840		task_manager.spawn_handle(),841		overrides_handle::<_, _, Runtime>(client.clone()),842		50,843		50,844	));845846	let (network, system_rpc_tx, network_starter) =847		sc_service::build_network(sc_service::BuildNetworkParams {848			config: &config,849			client: client.clone(),850			transaction_pool: transaction_pool.clone(),851			spawn_handle: task_manager.spawn_handle(),852			import_queue,853			block_announce_validator_builder: None,854			warp_sync: None,855		})?;856857	if config.offchain_worker.enabled {858		sc_service::build_offchain_workers(859			&config,860			task_manager.spawn_handle(),861			client.clone(),862			network.clone(),863		);864	}865866	let prometheus_registry = config.prometheus_registry().cloned();867	let collator = config.role.is_authority();868869	let select_chain = maybe_select_chain.clone();870871	if collator {872		let block_import =873			FrontierBlockImport::new(client.clone(), client.clone(), frontier_backend.clone());874875		let env = sc_basic_authorship::ProposerFactory::new(876			task_manager.spawn_handle(),877			client.clone(),878			transaction_pool.clone(),879			prometheus_registry.as_ref(),880			telemetry.as_ref().map(|x| x.handle()),881		);882883		let transactions_commands_stream: Box<884			dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,885		> = Box::new(886			transaction_pool887				.pool()888				.validated_pool()889				.import_notification_stream()890				.map(|_| EngineCommand::SealNewBlock {891					create_empty: true,892					finalize: false,893					parent_hash: None,894					sender: None,895				}),896		);897898		let autoseal_interval = Box::pin(AutosealInterval::new(&config, autoseal_interval));899		let idle_commands_stream: Box<900			dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,901		> = Box::new(autoseal_interval.map(|_| EngineCommand::SealNewBlock {902			create_empty: true,903			finalize: false,904			parent_hash: None,905			sender: None,906		}));907908		let commands_stream = select(transactions_commands_stream, idle_commands_stream);909910		let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;911		let client_set_aside_for_cidp = client.clone();912913		task_manager.spawn_essential_handle().spawn_blocking(914			"authorship_task",915			Some("block-authoring"),916			run_manual_seal(ManualSealParams {917				block_import,918				env,919				client: client.clone(),920				pool: transaction_pool.clone(),921				commands_stream,922				select_chain: select_chain.clone(),923				consensus_data_provider: None,924				create_inherent_data_providers: move |block: Hash, ()| {925					let current_para_block = client_set_aside_for_cidp926						.number(block)927						.expect("Header lookup should succeed")928						.expect("Header passed in as parent should be present in backend.");929930					let client_for_xcm = client_set_aside_for_cidp.clone();931					async move {932						let time = sp_timestamp::InherentDataProvider::from_system_time();933934						let mocked_parachain = cumulus_primitives_parachain_inherent::MockValidationDataInherentDataProvider {935							current_para_block,936							relay_offset: 1000,937							relay_blocks_per_para_block: 2,938							xcm_config: cumulus_primitives_parachain_inherent::MockXcmConfig::new(939								&*client_for_xcm,940								block,941								Default::default(),942								Default::default(),943							),944							raw_downward_messages: vec![],945							raw_horizontal_messages: vec![],946						};947948						let slot =949						sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(950							*time,951							slot_duration,952						);953954						Ok((time, slot, mocked_parachain))955					}956				},957			}),958		);959	}960961	task_manager.spawn_essential_handle().spawn(962		"frontier-mapping-sync-worker",963		Some("block-authoring"),964		MappingSyncWorker::new(965			client.import_notification_stream(),966			Duration::new(6, 0),967			client.clone(),968			backend.clone(),969			frontier_backend.clone(),970			3,971			0,972			SyncStrategy::Normal,973		)974		.for_each(|()| futures::future::ready(())),975	);976977	let subscription_executor = sc_rpc::SubscriptionTaskExecutor::new(task_manager.spawn_handle());978	let rpc_client = client.clone();979	let rpc_pool = transaction_pool.clone();980	let rpc_network = network.clone();981	let rpc_frontier_backend = frontier_backend.clone();982	let rpc_extensions_builder = Box::new(move |deny_unsafe, _| {983		let full_deps = unique_rpc::FullDeps {984			backend: rpc_frontier_backend.clone(),985			deny_unsafe,986			client: rpc_client.clone(),987			pool: rpc_pool.clone(),988			graph: rpc_pool.pool().clone(),989			// TODO: Unhardcode990			enable_dev_signer: false,991			filter_pool: filter_pool.clone(),992			network: rpc_network.clone(),993			select_chain: select_chain.clone(),994			is_authority: collator,995			// TODO: Unhardcode996			max_past_logs: 10000,997			block_data_cache: block_data_cache.clone(),998			fee_history_cache: fee_history_cache.clone(),999			// TODO: Unhardcode1000			fee_history_limit: 2048,1001		};10021003		Ok(1004			unique_rpc::create_full::<_, _, _, _, Runtime, RuntimeApi, _>(1005				full_deps,1006				subscription_executor.clone(),1007			),1008		)1009	});10101011	sc_service::spawn_tasks(sc_service::SpawnTasksParams {1012		network,1013		client,1014		keystore: keystore_container.sync_keystore(),1015		task_manager: &mut task_manager,1016		transaction_pool,1017		rpc_extensions_builder,1018		backend,1019		system_rpc_tx,1020		config,1021		telemetry: None,1022	})?;10231024	network_starter.start_network();1025	Ok(task_manager)1026}