git.delta.rocks / unique-network / refs/commits / a7c64b4371aa

difftreelog

source

node/cli/src/service.rs36.7 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// std18use std::{19	collections::BTreeMap,20	marker::PhantomData,21	pin::Pin,22	sync::{Arc, Mutex},23	time::Duration,24};2526use cumulus_client_cli::CollatorOptions;27use cumulus_client_collator::service::CollatorService;28#[cfg(not(feature = "lookahead"))]29use cumulus_client_consensus_aura::collators::basic::{30	run as run_aura, Params as BuildAuraConsensusParams,31};32#[cfg(feature = "lookahead")]33use cumulus_client_consensus_aura::collators::lookahead::{34	run as run_aura, Params as BuildAuraConsensusParams,35};36use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImport;37use cumulus_client_consensus_proposer::Proposer;38use cumulus_client_service::{39	build_relay_chain_interface, prepare_node_config, start_relay_chain_tasks, DARecoveryProfile,40	StartRelayChainTasksParams,41};42use cumulus_primitives_core::ParaId;43use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface};44use fc_mapping_sync::{kv::MappingSyncWorker, EthereumBlockNotificationSinks, SyncStrategy};45use fc_rpc::{46	frontier_backend_client::SystemAccountId32StorageOverride, EthBlockDataCacheTask, EthConfig,47	EthTask, OverrideHandle, RuntimeApiStorageOverride, SchemaV1Override, SchemaV2Override,48	SchemaV3Override, StorageOverride,49};50use fc_rpc_core::types::{FeeHistoryCache, FilterPool};51use fp_rpc::EthereumRuntimeRPCApi;52use fp_storage::EthereumStorageSchema;53use futures::{54	stream::select,55	task::{Context, Poll},56	Stream, StreamExt,57};58use jsonrpsee::RpcModule;59use polkadot_service::CollatorPair;60use sc_client_api::{AuxStore, Backend, BlockOf, BlockchainEvents, StorageProvider};61use sc_consensus::ImportQueue;62use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch};63use sc_network::NetworkBlock;64use sc_network_sync::SyncingService;65use sc_rpc::SubscriptionTaskExecutor;66use sc_service::{Configuration, PartialComponents, TaskManager};67use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};68use serde::{Deserialize, Serialize};69use sp_api::{ProvideRuntimeApi, StateBackend};70use sp_block_builder::BlockBuilder;71use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};72use sp_consensus_aura::sr25519::AuthorityPair as AuraAuthorityPair;73use sp_keystore::KeystorePtr;74use sp_runtime::traits::BlakeTwo256;75use substrate_prometheus_endpoint::Registry;76use tokio::time::Interval;77use up_common::types::{opaque::*, Nonce};7879use crate::{80	chain_spec::RuntimeIdentification,81	rpc::{create_eth, create_full, EthDeps, FullDeps},82};8384/// Unique native executor instance.85#[cfg(feature = "unique-runtime")]86pub struct UniqueRuntimeExecutor;8788#[cfg(feature = "quartz-runtime")]89/// Quartz native executor instance.90pub struct QuartzRuntimeExecutor;9192/// Opal native executor instance.93pub struct OpalRuntimeExecutor;9495#[cfg(feature = "unique-runtime")]96impl NativeExecutionDispatch for UniqueRuntimeExecutor {97	/// Only enable the benchmarking host functions when we actually want to benchmark.98	#[cfg(feature = "runtime-benchmarks")]99	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;100	/// Otherwise we only use the default Substrate host functions.101	#[cfg(not(feature = "runtime-benchmarks"))]102	type ExtendHostFunctions = ();103104	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {105		unique_runtime::api::dispatch(method, data)106	}107108	fn native_version() -> sc_executor::NativeVersion {109		unique_runtime::native_version()110	}111}112113#[cfg(feature = "quartz-runtime")]114impl NativeExecutionDispatch for QuartzRuntimeExecutor {115	/// Only enable the benchmarking host functions when we actually want to benchmark.116	#[cfg(feature = "runtime-benchmarks")]117	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;118	/// Otherwise we only use the default Substrate host functions.119	#[cfg(not(feature = "runtime-benchmarks"))]120	type ExtendHostFunctions = ();121122	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {123		quartz_runtime::api::dispatch(method, data)124	}125126	fn native_version() -> sc_executor::NativeVersion {127		quartz_runtime::native_version()128	}129}130131impl NativeExecutionDispatch for OpalRuntimeExecutor {132	/// Only enable the benchmarking host functions when we actually want to benchmark.133	#[cfg(feature = "runtime-benchmarks")]134	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;135	/// Otherwise we only use the default Substrate host functions.136	#[cfg(not(feature = "runtime-benchmarks"))]137	type ExtendHostFunctions = ();138139	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {140		opal_runtime::api::dispatch(method, data)141	}142143	fn native_version() -> sc_executor::NativeVersion {144		opal_runtime::native_version()145	}146}147148pub struct AutosealInterval {149	interval: Interval,150}151152impl AutosealInterval {153	pub fn new(config: &Configuration, interval: u64) -> Self {154		let _tokio_runtime = config.tokio_handle.enter();155		let interval = tokio::time::interval(Duration::from_millis(interval));156157		Self { interval }158	}159}160161impl Stream for AutosealInterval {162	type Item = tokio::time::Instant;163164	fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {165		self.interval.poll_tick(cx).map(Some)166	}167}168169pub fn open_frontier_backend<C: HeaderBackend<Block>>(170	client: Arc<C>,171	config: &Configuration,172) -> Result<Arc<fc_db::kv::Backend<Block>>, String> {173	let config_dir = config.base_path.config_dir(config.chain_spec.id());174	let database_dir = config_dir.join("frontier").join("db");175176	Ok(Arc::new(fc_db::kv::Backend::<Block>::new(177		client,178		&fc_db::kv::DatabaseSettings {179			source: fc_db::DatabaseSource::RocksDb {180				path: database_dir,181				cache_size: 0,182			},183		},184	)?))185}186187type FullClient<RuntimeApi, ExecutorDispatch> =188	sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;189type FullBackend = sc_service::TFullBackend<Block>;190type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;191type ParachainBlockImport<RuntimeApi, ExecutorDispatch> =192	TParachainBlockImport<Block, Arc<FullClient<RuntimeApi, ExecutorDispatch>>, FullBackend>;193194/// Generate a supertrait based on bounds, and blanket impl for it.195macro_rules! ez_bounds {196	($vis:vis trait $name:ident$(<$($gen:ident $(: $($(+)? $bound:path)*)?),* $(,)?>)? $(:)? $($(+)? $super:path)* {}) => {197		$vis trait $name $(<$($gen $(: $($bound+)*)?,)*>)?: $($super +)* {}198		impl<T, $($($gen $(: $($bound+)*)?,)*)?> $name$(<$($gen,)*>)? for T199		where T: $($super +)* {}200	}201}202ez_bounds!(203	pub trait RuntimeApiDep<Runtime: RuntimeInstance>:204		sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>205		+ sp_consensus_aura::AuraApi<Block, AuraId>206		+ fp_rpc::EthereumRuntimeRPCApi<Block>207		+ sp_session::SessionKeys<Block>208		+ sp_block_builder::BlockBuilder<Block>209		+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>210		+ sp_api::ApiExt<Block>211		+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>212		+ app_promotion_rpc::AppPromotionApi<Block, BlockNumber, Runtime::CrossAccountId, AccountId>213		+ up_pov_estimate_rpc::PovEstimateApi<Block>214		+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>215		+ sp_api::Metadata<Block>216		+ sp_offchain::OffchainWorkerApi<Block>217		+ cumulus_primitives_core::CollectCollationInfo<Block>218		// Deprecated, not used.219		+ fp_rpc::ConvertTransactionRuntimeApi<Block>220	{221	}222);223#[cfg(not(feature = "lookahead"))]224ez_bounds!(225	pub trait LookaheadApiDep {}226);227#[cfg(feature = "lookahead")]228ez_bounds!(229	pub trait LookaheadApiDep: cumulus_primitives_aura::AuraUnincludedSegmentApi<Block> {}230);231232/// Starts a `ServiceBuilder` for a full service.233///234/// Use this macro if you don't actually need the full service, but just the builder in order to235/// be able to perform chain operations.236#[allow(clippy::type_complexity)]237pub fn new_partial<Runtime, RuntimeApi, ExecutorDispatch, BIQ>(238	config: &Configuration,239	build_import_queue: BIQ,240) -> Result<241	PartialComponents<242		FullClient<RuntimeApi, ExecutorDispatch>,243		FullBackend,244		FullSelectChain,245		sc_consensus::DefaultImportQueue<Block>,246		sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,247		OtherPartial,248	>,249	sc_service::Error,250>251where252	sc_client_api::StateBackendFor<FullBackend, Block>: sp_api::StateBackend<BlakeTwo256>,253	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>254		+ Send255		+ Sync256		+ 'static,257	RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,258	Runtime: RuntimeInstance,259	ExecutorDispatch: NativeExecutionDispatch + 'static,260	BIQ: FnOnce(261		Arc<FullClient<RuntimeApi, ExecutorDispatch>>,262		Arc<FullBackend>,263		&Configuration,264		Option<TelemetryHandle>,265		&TaskManager,266	) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>,267{268	let telemetry = config269		.telemetry_endpoints270		.clone()271		.filter(|x| !x.is_empty())272		.map(|endpoints| -> Result<_, sc_telemetry::Error> {273			let worker = TelemetryWorker::new(16)?;274			let telemetry = worker.handle().new_telemetry(endpoints);275			Ok((worker, telemetry))276		})277		.transpose()?;278279	let executor = sc_service::new_native_or_wasm_executor(config);280281	let (client, backend, keystore_container, task_manager) =282		sc_service::new_full_parts::<Block, RuntimeApi, _>(283			config,284			telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),285			executor,286		)?;287	let client = Arc::new(client);288289	let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());290291	let telemetry = telemetry.map(|(worker, telemetry)| {292		task_manager293			.spawn_handle()294			.spawn("telemetry", None, worker.run());295		telemetry296	});297298	let select_chain = sc_consensus::LongestChain::new(backend.clone());299300	let transaction_pool = sc_transaction_pool::BasicPool::new_full(301		config.transaction_pool.clone(),302		config.role.is_authority().into(),303		config.prometheus_registry(),304		task_manager.spawn_essential_handle(),305		client.clone(),306	);307308	let eth_filter_pool: Option<FilterPool> = Some(Arc::new(Mutex::new(BTreeMap::new())));309310	let eth_backend = open_frontier_backend(client.clone(), config)?;311312	let import_queue = build_import_queue(313		client.clone(),314		backend.clone(),315		config,316		telemetry.as_ref().map(|telemetry| telemetry.handle()),317		&task_manager,318	)?;319320	let params = PartialComponents {321		backend,322		client,323		import_queue,324		keystore_container,325		task_manager,326		transaction_pool,327		select_chain,328		other: OtherPartial {329			telemetry,330			eth_filter_pool,331			eth_backend,332			telemetry_worker_handle,333		},334	};335336	Ok(params)337}338339macro_rules! clone {340    ($($i:ident),* $(,)?) => {341		$(342			let $i = $i.clone();343		)*344    };345}346347/// Start a node with the given parachain `Configuration` and relay chain `Configuration`.348///349/// This is the actual implementation that is abstract over the executor and the runtime api.350#[sc_tracing::logging::prefix_logs_with("Parachain")]351pub async fn start_node<Runtime, RuntimeApi, ExecutorDispatch>(352	parachain_config: Configuration,353	polkadot_config: Configuration,354	collator_options: CollatorOptions,355	para_id: ParaId,356	hwbench: Option<sc_sysinfo::HwBench>,357) -> sc_service::error::Result<(TaskManager, Arc<FullClient<RuntimeApi, ExecutorDispatch>>)>358where359	sc_client_api::StateBackendFor<FullBackend, Block>: sp_api::StateBackend<BlakeTwo256>,360	Runtime: RuntimeInstance + Send + Sync + 'static,361	<Runtime as RuntimeInstance>::CrossAccountId: Serialize,362	for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,363	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>364		+ Send365		+ Sync366		+ 'static,367	RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,368	RuntimeApi::RuntimeApi: LookaheadApiDep,369	Runtime: RuntimeInstance,370	ExecutorDispatch: NativeExecutionDispatch + 'static,371{372	let parachain_config = prepare_node_config(parachain_config);373374	let params = new_partial::<Runtime, RuntimeApi, ExecutorDispatch, _>(375		&parachain_config,376		parachain_build_import_queue,377	)?;378	let OtherPartial {379		mut telemetry,380		telemetry_worker_handle,381		eth_filter_pool,382		eth_backend,383	} = params.other;384	let net_config = sc_network::config::FullNetworkConfiguration::new(&parachain_config.network);385386	let client = params.client.clone();387	let backend = params.backend.clone();388	let mut task_manager = params.task_manager;389390	let (relay_chain_interface, collator_key) = build_relay_chain_interface(391		polkadot_config,392		&parachain_config,393		telemetry_worker_handle,394		&mut task_manager,395		collator_options.clone(),396		hwbench.clone(),397	)398	.await399	.map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?;400401	// Aura is sybil-resistant, collator-selection is generally too.402	let block_announce_validator =403		cumulus_client_network::AssumeSybilResistance::allow_seconded_messages();404405	let validator = parachain_config.role.is_authority();406	let prometheus_registry = parachain_config.prometheus_registry().cloned();407	let transaction_pool = params.transaction_pool.clone();408	let import_queue_service = params.import_queue.service();409410	let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) =411		sc_service::build_network(sc_service::BuildNetworkParams {412			config: &parachain_config,413			net_config,414			client: client.clone(),415			transaction_pool: transaction_pool.clone(),416			spawn_handle: task_manager.spawn_handle(),417			import_queue: params.import_queue,418			block_announce_validator_builder: Some(Box::new(|_| {419				Box::new(block_announce_validator)420			})),421			warp_sync_params: None,422			block_relay: None,423		})?;424425	let select_chain = params.select_chain.clone();426427	let runtime_id = parachain_config.chain_spec.runtime_id();428429	// Frontier430	let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));431	let fee_history_limit = 2048;432433	let eth_pubsub_notification_sinks: Arc<434		EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,435	> = Default::default();436437	let overrides = overrides_handle(client.clone());438	let eth_block_data_cache = spawn_frontier_tasks(439		FrontierTaskParams {440			client: client.clone(),441			substrate_backend: backend.clone(),442			eth_filter_pool: eth_filter_pool.clone(),443			eth_backend: eth_backend.clone(),444			fee_history_limit,445			fee_history_cache: fee_history_cache.clone(),446			task_manager: &task_manager,447			prometheus_registry: prometheus_registry.clone(),448			overrides: overrides.clone(),449			sync_strategy: SyncStrategy::Parachain,450		},451		sync_service.clone(),452		eth_pubsub_notification_sinks.clone(),453	);454455	// Rpc456	let rpc_builder = Box::new({457		clone!(458			client,459			backend,460			eth_backend,461			eth_pubsub_notification_sinks,462			fee_history_cache,463			eth_block_data_cache,464			overrides,465			transaction_pool,466			network,467			sync_service,468		);469		move |deny_unsafe, subscription_task_executor: SubscriptionTaskExecutor| {470			clone!(471				backend,472				eth_block_data_cache,473				client,474				eth_backend,475				eth_filter_pool,476				eth_pubsub_notification_sinks,477				fee_history_cache,478				eth_block_data_cache,479				network,480				runtime_id,481				transaction_pool,482				select_chain,483				overrides,484			);485486			#[cfg(not(feature = "pov-estimate"))]487			let _ = backend;488489			let mut rpc_handle = RpcModule::new(());490491			let full_deps = FullDeps {492				client: client.clone(),493				runtime_id,494495				#[cfg(feature = "pov-estimate")]496				exec_params: uc_rpc::pov_estimate::ExecutorParams {497					wasm_method: parachain_config.wasm_method,498					default_heap_pages: parachain_config.default_heap_pages,499					max_runtime_instances: parachain_config.max_runtime_instances,500					runtime_cache_size: parachain_config.runtime_cache_size,501				},502503				#[cfg(feature = "pov-estimate")]504				backend,505506				deny_unsafe,507				pool: transaction_pool.clone(),508				select_chain,509			};510511			create_full::<_, _, _, Runtime, _>(&mut rpc_handle, full_deps)?;512513			let eth_deps = EthDeps {514				client,515				graph: transaction_pool.pool().clone(),516				pool: transaction_pool,517				is_authority: validator,518				network,519				eth_backend,520				// TODO: Unhardcode521				max_past_logs: 10000,522				fee_history_limit,523				fee_history_cache,524				eth_block_data_cache,525				// TODO: Unhardcode526				enable_dev_signer: false,527				eth_filter_pool,528				eth_pubsub_notification_sinks,529				overrides,530				sync: sync_service.clone(),531				pending_create_inherent_data_providers: |_, ()| async move { Ok(()) },532			};533534			create_eth::<535				_,536				_,537				_,538				_,539				_,540				_,541				DefaultEthConfig<FullClient<RuntimeApi, ExecutorDispatch>>,542			>(543				&mut rpc_handle,544				eth_deps,545				subscription_task_executor.clone(),546			)?;547548			Ok(rpc_handle)549		}550	});551552	sc_service::spawn_tasks(sc_service::SpawnTasksParams {553		rpc_builder,554		client: client.clone(),555		transaction_pool: transaction_pool.clone(),556		task_manager: &mut task_manager,557		config: parachain_config,558		keystore: params.keystore_container.keystore(),559		backend: backend.clone(),560		network,561		sync_service: sync_service.clone(),562		system_rpc_tx,563		telemetry: telemetry.as_mut(),564		tx_handler_controller,565	})?;566567	if let Some(hwbench) = hwbench {568		sc_sysinfo::print_hwbench(&hwbench);569570		if let Some(ref mut telemetry) = telemetry {571			let telemetry_handle = telemetry.handle();572			task_manager.spawn_handle().spawn(573				"telemetry_hwbench",574				None,575				sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench),576			);577		}578	}579580	let announce_block = {581		let sync_service = sync_service.clone();582		Arc::new(Box::new(move |hash, data| {583			sync_service.announce_block(hash, data)584		}))585	};586587	let relay_chain_slot_duration = Duration::from_secs(6);588589	let overseer_handle = relay_chain_interface590		.overseer_handle()591		.map_err(|e| sc_service::Error::Application(Box::new(e)))?;592593	start_relay_chain_tasks(StartRelayChainTasksParams {594		client: client.clone(),595		announce_block: announce_block.clone(),596		para_id,597		relay_chain_interface: relay_chain_interface.clone(),598		task_manager: &mut task_manager,599		da_recovery_profile: if validator {600			DARecoveryProfile::Collator601		} else {602			DARecoveryProfile::FullNode603		},604		import_queue: import_queue_service,605		relay_chain_slot_duration,606		recovery_handle: Box::new(overseer_handle.clone()),607		sync_service: sync_service.clone(),608	})?;609610	if validator {611		start_consensus(612			client.clone(),613			transaction_pool,614			StartConsensusParameters {615				backend: backend.clone(),616				prometheus_registry: prometheus_registry.as_ref(),617				telemetry: telemetry.as_ref().map(|t| t.handle()),618				task_manager: &task_manager,619				relay_chain_interface: relay_chain_interface.clone(),620				sync_oracle: sync_service,621				keystore: params.keystore_container.keystore(),622				overseer_handle,623				relay_chain_slot_duration,624				para_id,625				collator_key: collator_key.expect("cli args do not allow this"),626				announce_block,627			},628		)?;629	}630631	start_network.start_network();632633	Ok((task_manager, client))634}635636/// Build the import queue for the the parachain runtime.637pub fn parachain_build_import_queue<Runtime, RuntimeApi, ExecutorDispatch>(638	client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,639	backend: Arc<FullBackend>,640	config: &Configuration,641	telemetry: Option<TelemetryHandle>,642	task_manager: &TaskManager,643) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>644where645	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>646		+ Send647		+ Sync648		+ 'static,649	RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,650	Runtime: RuntimeInstance,651	ExecutorDispatch: NativeExecutionDispatch + 'static,652{653	let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;654655	let block_import = ParachainBlockImport::new(client.clone(), backend);656657	cumulus_client_consensus_aura::import_queue::<658		sp_consensus_aura::sr25519::AuthorityPair,659		_,660		_,661		_,662		_,663		_,664	>(cumulus_client_consensus_aura::ImportQueueParams {665		block_import,666		client,667		create_inherent_data_providers: move |_, _| async move {668			let time = sp_timestamp::InherentDataProvider::from_system_time();669670			let slot =671				sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(672					*time,673					slot_duration,674				);675676			Ok((slot, time))677		},678		registry: config.prometheus_registry(),679		spawner: &task_manager.spawn_essential_handle(),680		telemetry,681	})682	.map_err(Into::into)683}684685pub struct StartConsensusParameters<'a> {686	backend: Arc<FullBackend>,687	prometheus_registry: Option<&'a Registry>,688	telemetry: Option<TelemetryHandle>,689	task_manager: &'a TaskManager,690	relay_chain_interface: Arc<dyn RelayChainInterface>,691	sync_oracle: Arc<SyncingService<Block>>,692	keystore: KeystorePtr,693	overseer_handle: OverseerHandle,694	relay_chain_slot_duration: Duration,695	para_id: ParaId,696	collator_key: CollatorPair,697	announce_block: Arc<dyn Fn(Hash, Option<Vec<u8>>) + Send + Sync>,698}699700// Clones ignored for optional lookahead collator701#[allow(clippy::redundant_clone)]702pub fn start_consensus<ExecutorDispatch, RuntimeApi, Runtime>(703	client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,704	transaction_pool: Arc<705		sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,706	>,707	parameters: StartConsensusParameters<'_>,708) -> Result<(), sc_service::Error>709where710	ExecutorDispatch: NativeExecutionDispatch + 'static,711	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>712		+ Send713		+ Sync714		+ 'static,715	RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,716	RuntimeApi::RuntimeApi: LookaheadApiDep,717	Runtime: RuntimeInstance,718{719	let StartConsensusParameters {720		backend,721		prometheus_registry,722		telemetry,723		task_manager,724		relay_chain_interface,725		sync_oracle,726		keystore,727		overseer_handle,728		relay_chain_slot_duration,729		para_id,730		collator_key,731		announce_block,732	} = parameters;733	let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;734735	let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(736		task_manager.spawn_handle(),737		client.clone(),738		transaction_pool,739		prometheus_registry,740		telemetry,741	);742	let proposer = Proposer::new(proposer_factory);743744	let collator_service = CollatorService::new(745		client.clone(),746		Arc::new(task_manager.spawn_handle()),747		announce_block,748		client.clone(),749	);750751	let block_import = ParachainBlockImport::new(client.clone(), backend.clone());752753	let params = BuildAuraConsensusParams {754		create_inherent_data_providers: move |_, ()| async move { Ok(()) },755		block_import,756		para_client: client.clone(),757		#[cfg(feature = "lookahead")]758		para_backend: backend,759		para_id,760		relay_client: relay_chain_interface,761		sync_oracle,762		keystore,763		slot_duration,764		proposer,765		collator_service,766		// With async-baking, we allowed to be both slower (longer authoring) and faster (multiple para blocks per relay block)767		#[cfg(not(feature = "lookahead"))]768		authoring_duration: Duration::from_millis(500),769		#[cfg(feature = "lookahead")]770		authoring_duration: Duration::from_millis(1500),771		overseer_handle,772		#[cfg(feature = "lookahead")]773		code_hash_provider: move |block_hash| {774			client775				.code_at(block_hash)776				.ok()777				.map(cumulus_primitives_core::relay_chain::ValidationCode)778				.map(|c| c.hash())779		},780		collator_key,781		relay_chain_slot_duration,782	};783784	task_manager.spawn_essential_handle().spawn(785		"aura",786		None,787		#[cfg(not(feature = "lookahead"))]788		run_aura::<_, AuraAuthorityPair, _, _, _, _, _, _, _>(params),789		#[cfg(feature = "lookahead")]790		run_aura::<_, AuraAuthorityPair, _, _, _, _, _, _, _, _, _>(params),791	);792	Ok(())793}794795fn dev_build_import_queue<RuntimeApi, ExecutorDispatch>(796	client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,797	_: Arc<FullBackend>,798	config: &Configuration,799	_: Option<TelemetryHandle>,800	task_manager: &TaskManager,801) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>802where803	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>804		+ Send805		+ Sync806		+ 'static,807	RuntimeApi::RuntimeApi:808		sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> + sp_api::ApiExt<Block>,809	ExecutorDispatch: NativeExecutionDispatch + 'static,810{811	Ok(sc_consensus_manual_seal::import_queue(812		Box::new(client),813		&task_manager.spawn_essential_handle(),814		config.prometheus_registry(),815	))816}817818pub struct OtherPartial {819	pub telemetry: Option<Telemetry>,820	pub telemetry_worker_handle: Option<TelemetryWorkerHandle>,821	pub eth_filter_pool: Option<FilterPool>,822	pub eth_backend: Arc<fc_db::kv::Backend<Block>>,823}824825struct DefaultEthConfig<C>(PhantomData<C>);826impl<C> EthConfig<Block, C> for DefaultEthConfig<C>827where828	C: StorageProvider<Block, FullBackend> + Sync + Send + 'static,829{830	type EstimateGasAdapter = ();831	type RuntimeStorageOverride = SystemAccountId32StorageOverride<Block, C, FullBackend>;832}833834/// Builds a new development service. This service uses instant seal, and mocks835/// the parachain inherent836pub fn start_dev_node<Runtime, RuntimeApi, ExecutorDispatch>(837	config: Configuration,838	autoseal_interval: u64,839	autoseal_finalize_delay: Option<u64>,840	disable_autoseal_on_tx: bool,841) -> sc_service::error::Result<TaskManager>842where843	Runtime: RuntimeInstance + Send + Sync + 'static,844	<Runtime as RuntimeInstance>::CrossAccountId: Serialize,845	for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,846	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>847		+ Send848		+ Sync849		+ 'static,850	RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,851	ExecutorDispatch: NativeExecutionDispatch + 'static,852{853	use fc_consensus::FrontierBlockImport;854	use sc_consensus_manual_seal::{855		run_delayed_finalize, run_manual_seal, DelayedFinalizeParams, EngineCommand,856		ManualSealParams,857	};858859	let sc_service::PartialComponents {860		client,861		backend,862		mut task_manager,863		import_queue,864		keystore_container,865		select_chain: maybe_select_chain,866		transaction_pool,867		other:868			OtherPartial {869				telemetry,870				eth_filter_pool,871				eth_backend,872				telemetry_worker_handle: _,873			},874	} = new_partial::<Runtime, RuntimeApi, ExecutorDispatch, _>(875		&config,876		dev_build_import_queue::<RuntimeApi, ExecutorDispatch>,877	)?;878	let net_config = sc_network::config::FullNetworkConfiguration::new(&config.network);879	let prometheus_registry = config.prometheus_registry().cloned();880881	let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) =882		sc_service::build_network(sc_service::BuildNetworkParams {883			config: &config,884			net_config,885			client: client.clone(),886			transaction_pool: transaction_pool.clone(),887			spawn_handle: task_manager.spawn_handle(),888			import_queue,889			block_announce_validator_builder: None,890			warp_sync_params: None,891			block_relay: None,892		})?;893894	let collator = config.role.is_authority();895896	let select_chain = maybe_select_chain;897898	if collator {899		let block_import = FrontierBlockImport::new(client.clone(), client.clone());900901		let env = sc_basic_authorship::ProposerFactory::new(902			task_manager.spawn_handle(),903			client.clone(),904			transaction_pool.clone(),905			prometheus_registry.as_ref(),906			telemetry.as_ref().map(|x| x.handle()),907		);908909		let transactions_commands_stream: Box<910			dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,911		> = Box::new(912			transaction_pool913				.pool()914				.validated_pool()915				.import_notification_stream()916				.filter(move |_| futures::future::ready(!disable_autoseal_on_tx))917				.map(|_| EngineCommand::SealNewBlock {918					create_empty: true,919					finalize: false,920					parent_hash: None,921					sender: None,922				}),923		);924925		let autoseal_interval = Box::pin(AutosealInterval::new(&config, autoseal_interval));926927		let idle_commands_stream: Box<928			dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,929		> = Box::new(autoseal_interval.map(|_| EngineCommand::SealNewBlock {930			create_empty: true,931			finalize: false,932			parent_hash: None,933			sender: None,934		}));935936		let commands_stream = select(transactions_commands_stream, idle_commands_stream);937938		let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;939		let client_set_aside_for_cidp = client.clone();940941		if let Some(delay_sec) = autoseal_finalize_delay {942			let spawn_handle = task_manager.spawn_handle();943944			task_manager.spawn_essential_handle().spawn_blocking(945				"finalization_task",946				Some("block-authoring"),947				run_delayed_finalize(DelayedFinalizeParams {948					client: client.clone(),949					delay_sec,950					spawn_handle,951				}),952			);953		}954955		task_manager.spawn_essential_handle().spawn_blocking(956			"authorship_task",957			Some("block-authoring"),958			run_manual_seal(ManualSealParams {959				block_import,960				env,961				client: client.clone(),962				pool: transaction_pool.clone(),963				commands_stream,964				select_chain: select_chain.clone(),965				consensus_data_provider: None,966				create_inherent_data_providers: move |block: Hash, ()| {967					let current_para_block = client_set_aside_for_cidp968						.number(block)969						.expect("Header lookup should succeed")970						.expect("Header passed in as parent should be present in backend.");971972					let client_for_xcm = client_set_aside_for_cidp.clone();973					async move {974						let time = sp_timestamp::InherentDataProvider::from_system_time();975976						let mocked_parachain = cumulus_primitives_parachain_inherent::MockValidationDataInherentDataProvider {977							current_para_block,978							relay_offset: 1000,979							relay_blocks_per_para_block: 2,980							para_blocks_per_relay_epoch: 0,981							xcm_config: cumulus_primitives_parachain_inherent::MockXcmConfig::new(982								&*client_for_xcm,983								block,984								Default::default(),985								Default::default(),986							),987							relay_randomness_config: (),988							raw_downward_messages: vec![],989							raw_horizontal_messages: vec![],990						};991992						let slot =993						sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(994							*time,995							slot_duration,996						);997998						Ok((time, slot, mocked_parachain))999					}1000				},1001			}),1002		);1003	}10041005	#[cfg(feature = "pov-estimate")]1006	let rpc_backend = backend.clone();10071008	let runtime_id = config.chain_spec.runtime_id();10091010	// Frontier1011	let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));1012	let fee_history_limit = 2048;10131014	let eth_pubsub_notification_sinks: Arc<1015		EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,1016	> = Default::default();10171018	let overrides = overrides_handle(client.clone());1019	let eth_block_data_cache = spawn_frontier_tasks(1020		FrontierTaskParams {1021			client: client.clone(),1022			substrate_backend: backend.clone(),1023			eth_filter_pool: eth_filter_pool.clone(),1024			eth_backend: eth_backend.clone(),1025			fee_history_limit,1026			fee_history_cache: fee_history_cache.clone(),1027			task_manager: &task_manager,1028			prometheus_registry,1029			overrides: overrides.clone(),1030			sync_strategy: SyncStrategy::Normal,1031		},1032		sync_service.clone(),1033		eth_pubsub_notification_sinks.clone(),1034	);10351036	// Rpc1037	let rpc_builder = Box::new({1038		clone!(1039			client,1040			backend,1041			eth_backend,1042			eth_pubsub_notification_sinks,1043			fee_history_cache,1044			eth_block_data_cache,1045			overrides,1046			transaction_pool,1047			network,1048			sync_service,1049		);1050		move |deny_unsafe, subscription_task_executor: SubscriptionTaskExecutor| {1051			clone!(1052				backend,1053				eth_block_data_cache,1054				client,1055				eth_backend,1056				eth_filter_pool,1057				eth_pubsub_notification_sinks,1058				fee_history_cache,1059				eth_block_data_cache,1060				network,1061				runtime_id,1062				transaction_pool,1063				select_chain,1064				overrides,1065			);10661067			#[cfg(not(feature = "pov-estimate"))]1068			let _ = backend;10691070			let mut rpc_module = RpcModule::new(());10711072			let full_deps = FullDeps {1073				runtime_id,10741075				#[cfg(feature = "pov-estimate")]1076				exec_params: uc_rpc::pov_estimate::ExecutorParams {1077					wasm_method: config.wasm_method,1078					default_heap_pages: config.default_heap_pages,1079					max_runtime_instances: config.max_runtime_instances,1080					runtime_cache_size: config.runtime_cache_size,1081				},10821083				#[cfg(feature = "pov-estimate")]1084				backend,1085				// eth_backend,1086				deny_unsafe,1087				client: client.clone(),1088				pool: transaction_pool.clone(),1089				select_chain,1090			};10911092			create_full::<_, _, _, Runtime, _>(&mut rpc_module, full_deps)?;10931094			let eth_deps = EthDeps {1095				client,1096				graph: transaction_pool.pool().clone(),1097				pool: transaction_pool,1098				is_authority: true,1099				network,1100				eth_backend,1101				// TODO: Unhardcode1102				max_past_logs: 10000,1103				fee_history_limit,1104				fee_history_cache,1105				eth_block_data_cache,1106				// TODO: Unhardcode1107				enable_dev_signer: false,1108				eth_filter_pool,1109				eth_pubsub_notification_sinks,1110				overrides,1111				sync: sync_service.clone(),1112				// We don't have any inherents except parachain built-ins, which we can't even extract from inside `run_aura`.1113				pending_create_inherent_data_providers: |_, ()| async move { Ok(()) },1114			};11151116			create_eth::<1117				_,1118				_,1119				_,1120				_,1121				_,1122				_,1123				DefaultEthConfig<FullClient<RuntimeApi, ExecutorDispatch>>,1124			>(1125				&mut rpc_module,1126				eth_deps,1127				subscription_task_executor.clone(),1128			)?;11291130			Ok(rpc_module)1131		}1132	});11331134	sc_service::spawn_tasks(sc_service::SpawnTasksParams {1135		network,1136		sync_service,1137		client,1138		keystore: keystore_container.keystore(),1139		task_manager: &mut task_manager,1140		transaction_pool,1141		rpc_builder,1142		backend,1143		system_rpc_tx,1144		config,1145		telemetry: None,1146		tx_handler_controller,1147	})?;11481149	network_starter.start_network();1150	Ok(task_manager)1151}11521153fn overrides_handle<C, BE>(client: Arc<C>) -> Arc<OverrideHandle<Block>>1154where1155	C: ProvideRuntimeApi<Block> + StorageProvider<Block, BE> + AuxStore,1156	C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError>,1157	C: Send + Sync + 'static,1158	C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,1159	BE: Backend<Block> + 'static,1160	BE::State: StateBackend<BlakeTwo256>,1161{1162	let mut overrides_map = BTreeMap::new();1163	overrides_map.insert(1164		EthereumStorageSchema::V1,1165		Box::new(SchemaV1Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1166	);1167	overrides_map.insert(1168		EthereumStorageSchema::V2,1169		Box::new(SchemaV2Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1170	);1171	overrides_map.insert(1172		EthereumStorageSchema::V3,1173		Box::new(SchemaV3Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1174	);11751176	Arc::new(OverrideHandle {1177		schemas: overrides_map,1178		fallback: Box::new(RuntimeApiStorageOverride::new(client)),1179	})1180}11811182pub struct FrontierTaskParams<'a, C, B> {1183	pub task_manager: &'a TaskManager,1184	pub client: Arc<C>,1185	pub substrate_backend: Arc<B>,1186	pub eth_backend: Arc<fc_db::kv::Backend<Block>>,1187	pub eth_filter_pool: Option<FilterPool>,1188	pub overrides: Arc<OverrideHandle<Block>>,1189	pub fee_history_limit: u64,1190	pub fee_history_cache: FeeHistoryCache,1191	pub sync_strategy: SyncStrategy,1192	pub prometheus_registry: Option<Registry>,1193}11941195pub fn spawn_frontier_tasks<C, B>(1196	params: FrontierTaskParams<C, B>,1197	sync: Arc<SyncingService<Block>>,1198	pubsub_notification_sinks: Arc<1199		EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,1200	>,1201) -> Arc<EthBlockDataCacheTask<Block>>1202where1203	C: ProvideRuntimeApi<Block> + BlockOf,1204	C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError> + 'static,1205	C: BlockchainEvents<Block> + StorageProvider<Block, B>,1206	C: Send + Sync + 'static,1207	C::Api: EthereumRuntimeRPCApi<Block>,1208	C::Api: BlockBuilder<Block>,1209	B: Backend<Block> + 'static,1210	B::State: StateBackend<BlakeTwo256>,1211{1212	let FrontierTaskParams {1213		task_manager,1214		client,1215		substrate_backend,1216		eth_backend,1217		eth_filter_pool,1218		overrides,1219		fee_history_limit,1220		fee_history_cache,1221		sync_strategy,1222		prometheus_registry,1223	} = params;1224	// Frontier offchain DB task. Essential.1225	// Maps emulated ethereum data to substrate native data.1226	params.task_manager.spawn_essential_handle().spawn(1227		"frontier-mapping-sync-worker",1228		Some("frontier"),1229		MappingSyncWorker::new(1230			client.import_notification_stream(),1231			Duration::new(6, 0),1232			client.clone(),1233			substrate_backend,1234			overrides.clone(),1235			eth_backend,1236			3,1237			0,1238			sync_strategy,1239			sync,1240			pubsub_notification_sinks,1241		)1242		.for_each(|()| futures::future::ready(())),1243	);12441245	// Frontier `EthFilterApi` maintenance.1246	// Manages the pool of user-created Filters.1247	if let Some(eth_filter_pool) = eth_filter_pool {1248		// Each filter is allowed to stay in the pool for 100 blocks.1249		const FILTER_RETAIN_THRESHOLD: u64 = 100;1250		params.task_manager.spawn_essential_handle().spawn(1251			"frontier-filter-pool",1252			Some("frontier"),1253			EthTask::filter_pool_task(client.clone(), eth_filter_pool, FILTER_RETAIN_THRESHOLD),1254		);1255	}12561257	// Spawn Frontier FeeHistory cache maintenance task.1258	params.task_manager.spawn_essential_handle().spawn(1259		"frontier-fee-history",1260		Some("frontier"),1261		EthTask::fee_history_task(1262			client,1263			overrides.clone(),1264			fee_history_cache,1265			fee_history_limit,1266		),1267	);12681269	Arc::new(EthBlockDataCacheTask::new(1270		task_manager.spawn_handle(),1271		overrides,1272		50,1273		50,1274		prometheus_registry,1275	))1276}