git.delta.rocks / unique-network / refs/commits / 5bf7ef40777d

difftreelog

source

node/cli/src/service.rs36.8 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		#[cfg(not(feature = "lookahead"))]783		collation_request_receiver: None,784	};785786	task_manager.spawn_essential_handle().spawn(787		"aura",788		None,789		#[cfg(not(feature = "lookahead"))]790		run_aura::<_, AuraAuthorityPair, _, _, _, _, _, _, _>(params),791		#[cfg(feature = "lookahead")]792		run_aura::<_, AuraAuthorityPair, _, _, _, _, _, _, _, _, _>(params),793	);794	Ok(())795}796797fn dev_build_import_queue<RuntimeApi, ExecutorDispatch>(798	client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,799	_: Arc<FullBackend>,800	config: &Configuration,801	_: Option<TelemetryHandle>,802	task_manager: &TaskManager,803) -> Result<sc_consensus::DefaultImportQueue<Block>, sc_service::Error>804where805	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>806		+ Send807		+ Sync808		+ 'static,809	RuntimeApi::RuntimeApi:810		sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> + sp_api::ApiExt<Block>,811	ExecutorDispatch: NativeExecutionDispatch + 'static,812{813	Ok(sc_consensus_manual_seal::import_queue(814		Box::new(client),815		&task_manager.spawn_essential_handle(),816		config.prometheus_registry(),817	))818}819820pub struct OtherPartial {821	pub telemetry: Option<Telemetry>,822	pub telemetry_worker_handle: Option<TelemetryWorkerHandle>,823	pub eth_filter_pool: Option<FilterPool>,824	pub eth_backend: Arc<fc_db::kv::Backend<Block>>,825}826827struct DefaultEthConfig<C>(PhantomData<C>);828impl<C> EthConfig<Block, C> for DefaultEthConfig<C>829where830	C: StorageProvider<Block, FullBackend> + Sync + Send + 'static,831{832	type EstimateGasAdapter = ();833	type RuntimeStorageOverride = SystemAccountId32StorageOverride<Block, C, FullBackend>;834}835836/// Builds a new development service. This service uses instant seal, and mocks837/// the parachain inherent838pub fn start_dev_node<Runtime, RuntimeApi, ExecutorDispatch>(839	config: Configuration,840	autoseal_interval: u64,841	autoseal_finalize_delay: Option<u64>,842	disable_autoseal_on_tx: bool,843) -> sc_service::error::Result<TaskManager>844where845	Runtime: RuntimeInstance + Send + Sync + 'static,846	<Runtime as RuntimeInstance>::CrossAccountId: Serialize,847	for<'de> <Runtime as RuntimeInstance>::CrossAccountId: Deserialize<'de>,848	RuntimeApi: sp_api::ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>849		+ Send850		+ Sync851		+ 'static,852	RuntimeApi::RuntimeApi: RuntimeApiDep<Runtime> + 'static,853	ExecutorDispatch: NativeExecutionDispatch + 'static,854{855	use fc_consensus::FrontierBlockImport;856	use sc_consensus_manual_seal::{857		run_delayed_finalize, run_manual_seal, DelayedFinalizeParams, EngineCommand,858		ManualSealParams,859	};860861	let sc_service::PartialComponents {862		client,863		backend,864		mut task_manager,865		import_queue,866		keystore_container,867		select_chain: maybe_select_chain,868		transaction_pool,869		other:870			OtherPartial {871				telemetry,872				eth_filter_pool,873				eth_backend,874				telemetry_worker_handle: _,875			},876	} = new_partial::<Runtime, RuntimeApi, ExecutorDispatch, _>(877		&config,878		dev_build_import_queue::<RuntimeApi, ExecutorDispatch>,879	)?;880	let net_config = sc_network::config::FullNetworkConfiguration::new(&config.network);881	let prometheus_registry = config.prometheus_registry().cloned();882883	let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) =884		sc_service::build_network(sc_service::BuildNetworkParams {885			config: &config,886			net_config,887			client: client.clone(),888			transaction_pool: transaction_pool.clone(),889			spawn_handle: task_manager.spawn_handle(),890			import_queue,891			block_announce_validator_builder: None,892			warp_sync_params: None,893			block_relay: None,894		})?;895896	let collator = config.role.is_authority();897898	let select_chain = maybe_select_chain;899900	if collator {901		let block_import = FrontierBlockImport::new(client.clone(), client.clone());902903		let env = sc_basic_authorship::ProposerFactory::new(904			task_manager.spawn_handle(),905			client.clone(),906			transaction_pool.clone(),907			prometheus_registry.as_ref(),908			telemetry.as_ref().map(|x| x.handle()),909		);910911		let transactions_commands_stream: Box<912			dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,913		> = Box::new(914			transaction_pool915				.pool()916				.validated_pool()917				.import_notification_stream()918				.filter(move |_| futures::future::ready(!disable_autoseal_on_tx))919				.map(|_| EngineCommand::SealNewBlock {920					create_empty: true,921					finalize: false,922					parent_hash: None,923					sender: None,924				}),925		);926927		let autoseal_interval = Box::pin(AutosealInterval::new(&config, autoseal_interval));928929		let idle_commands_stream: Box<930			dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin,931		> = Box::new(autoseal_interval.map(|_| EngineCommand::SealNewBlock {932			create_empty: true,933			finalize: false,934			parent_hash: None,935			sender: None,936		}));937938		let commands_stream = select(transactions_commands_stream, idle_commands_stream);939940		let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;941		let client_set_aside_for_cidp = client.clone();942943		if let Some(delay_sec) = autoseal_finalize_delay {944			let spawn_handle = task_manager.spawn_handle();945946			task_manager.spawn_essential_handle().spawn_blocking(947				"finalization_task",948				Some("block-authoring"),949				run_delayed_finalize(DelayedFinalizeParams {950					client: client.clone(),951					delay_sec,952					spawn_handle,953				}),954			);955		}956957		task_manager.spawn_essential_handle().spawn_blocking(958			"authorship_task",959			Some("block-authoring"),960			run_manual_seal(ManualSealParams {961				block_import,962				env,963				client: client.clone(),964				pool: transaction_pool.clone(),965				commands_stream,966				select_chain: select_chain.clone(),967				consensus_data_provider: None,968				create_inherent_data_providers: move |block: Hash, ()| {969					let current_para_block = client_set_aside_for_cidp970						.number(block)971						.expect("Header lookup should succeed")972						.expect("Header passed in as parent should be present in backend.");973974					let client_for_xcm = client_set_aside_for_cidp.clone();975					async move {976						let time = sp_timestamp::InherentDataProvider::from_system_time();977978						let mocked_parachain = cumulus_primitives_parachain_inherent::MockValidationDataInherentDataProvider {979							current_para_block,980							relay_offset: 1000,981							relay_blocks_per_para_block: 2,982							para_blocks_per_relay_epoch: 0,983							xcm_config: cumulus_primitives_parachain_inherent::MockXcmConfig::new(984								&*client_for_xcm,985								block,986								Default::default(),987								Default::default(),988							),989							relay_randomness_config: (),990							raw_downward_messages: vec![],991							raw_horizontal_messages: vec![],992						};993994						let slot =995						sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(996							*time,997							slot_duration,998						);9991000						Ok((time, slot, mocked_parachain))1001					}1002				},1003			}),1004		);1005	}10061007	#[cfg(feature = "pov-estimate")]1008	let rpc_backend = backend.clone();10091010	let runtime_id = config.chain_spec.runtime_id();10111012	// Frontier1013	let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new()));1014	let fee_history_limit = 2048;10151016	let eth_pubsub_notification_sinks: Arc<1017		EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,1018	> = Default::default();10191020	let overrides = overrides_handle(client.clone());1021	let eth_block_data_cache = spawn_frontier_tasks(1022		FrontierTaskParams {1023			client: client.clone(),1024			substrate_backend: backend.clone(),1025			eth_filter_pool: eth_filter_pool.clone(),1026			eth_backend: eth_backend.clone(),1027			fee_history_limit,1028			fee_history_cache: fee_history_cache.clone(),1029			task_manager: &task_manager,1030			prometheus_registry,1031			overrides: overrides.clone(),1032			sync_strategy: SyncStrategy::Normal,1033		},1034		sync_service.clone(),1035		eth_pubsub_notification_sinks.clone(),1036	);10371038	// Rpc1039	let rpc_builder = Box::new({1040		clone!(1041			client,1042			backend,1043			eth_backend,1044			eth_pubsub_notification_sinks,1045			fee_history_cache,1046			eth_block_data_cache,1047			overrides,1048			transaction_pool,1049			network,1050			sync_service,1051		);1052		move |deny_unsafe, subscription_task_executor: SubscriptionTaskExecutor| {1053			clone!(1054				backend,1055				eth_block_data_cache,1056				client,1057				eth_backend,1058				eth_filter_pool,1059				eth_pubsub_notification_sinks,1060				fee_history_cache,1061				eth_block_data_cache,1062				network,1063				runtime_id,1064				transaction_pool,1065				select_chain,1066				overrides,1067			);10681069			#[cfg(not(feature = "pov-estimate"))]1070			let _ = backend;10711072			let mut rpc_module = RpcModule::new(());10731074			let full_deps = FullDeps {1075				runtime_id,10761077				#[cfg(feature = "pov-estimate")]1078				exec_params: uc_rpc::pov_estimate::ExecutorParams {1079					wasm_method: config.wasm_method,1080					default_heap_pages: config.default_heap_pages,1081					max_runtime_instances: config.max_runtime_instances,1082					runtime_cache_size: config.runtime_cache_size,1083				},10841085				#[cfg(feature = "pov-estimate")]1086				backend,1087				// eth_backend,1088				deny_unsafe,1089				client: client.clone(),1090				pool: transaction_pool.clone(),1091				select_chain,1092			};10931094			create_full::<_, _, _, Runtime, _>(&mut rpc_module, full_deps)?;10951096			let eth_deps = EthDeps {1097				client,1098				graph: transaction_pool.pool().clone(),1099				pool: transaction_pool,1100				is_authority: true,1101				network,1102				eth_backend,1103				// TODO: Unhardcode1104				max_past_logs: 10000,1105				fee_history_limit,1106				fee_history_cache,1107				eth_block_data_cache,1108				// TODO: Unhardcode1109				enable_dev_signer: false,1110				eth_filter_pool,1111				eth_pubsub_notification_sinks,1112				overrides,1113				sync: sync_service.clone(),1114				// We don't have any inherents except parachain built-ins, which we can't even extract from inside `run_aura`.1115				pending_create_inherent_data_providers: |_, ()| async move { Ok(()) },1116			};11171118			create_eth::<1119				_,1120				_,1121				_,1122				_,1123				_,1124				_,1125				DefaultEthConfig<FullClient<RuntimeApi, ExecutorDispatch>>,1126			>(1127				&mut rpc_module,1128				eth_deps,1129				subscription_task_executor.clone(),1130			)?;11311132			Ok(rpc_module)1133		}1134	});11351136	sc_service::spawn_tasks(sc_service::SpawnTasksParams {1137		network,1138		sync_service,1139		client,1140		keystore: keystore_container.keystore(),1141		task_manager: &mut task_manager,1142		transaction_pool,1143		rpc_builder,1144		backend,1145		system_rpc_tx,1146		config,1147		telemetry: None,1148		tx_handler_controller,1149	})?;11501151	network_starter.start_network();1152	Ok(task_manager)1153}11541155fn overrides_handle<C, BE>(client: Arc<C>) -> Arc<OverrideHandle<Block>>1156where1157	C: ProvideRuntimeApi<Block> + StorageProvider<Block, BE> + AuxStore,1158	C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError>,1159	C: Send + Sync + 'static,1160	C::Api: fp_rpc::EthereumRuntimeRPCApi<Block>,1161	BE: Backend<Block> + 'static,1162	BE::State: StateBackend<BlakeTwo256>,1163{1164	let mut overrides_map = BTreeMap::new();1165	overrides_map.insert(1166		EthereumStorageSchema::V1,1167		Box::new(SchemaV1Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1168	);1169	overrides_map.insert(1170		EthereumStorageSchema::V2,1171		Box::new(SchemaV2Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1172	);1173	overrides_map.insert(1174		EthereumStorageSchema::V3,1175		Box::new(SchemaV3Override::new(client.clone())) as Box<dyn StorageOverride<_> + 'static>,1176	);11771178	Arc::new(OverrideHandle {1179		schemas: overrides_map,1180		fallback: Box::new(RuntimeApiStorageOverride::new(client)),1181	})1182}11831184pub struct FrontierTaskParams<'a, C, B> {1185	pub task_manager: &'a TaskManager,1186	pub client: Arc<C>,1187	pub substrate_backend: Arc<B>,1188	pub eth_backend: Arc<fc_db::kv::Backend<Block>>,1189	pub eth_filter_pool: Option<FilterPool>,1190	pub overrides: Arc<OverrideHandle<Block>>,1191	pub fee_history_limit: u64,1192	pub fee_history_cache: FeeHistoryCache,1193	pub sync_strategy: SyncStrategy,1194	pub prometheus_registry: Option<Registry>,1195}11961197pub fn spawn_frontier_tasks<C, B>(1198	params: FrontierTaskParams<C, B>,1199	sync: Arc<SyncingService<Block>>,1200	pubsub_notification_sinks: Arc<1201		EthereumBlockNotificationSinks<fc_mapping_sync::EthereumBlockNotification<Block>>,1202	>,1203) -> Arc<EthBlockDataCacheTask<Block>>1204where1205	C: ProvideRuntimeApi<Block> + BlockOf,1206	C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError> + 'static,1207	C: BlockchainEvents<Block> + StorageProvider<Block, B>,1208	C: Send + Sync + 'static,1209	C::Api: EthereumRuntimeRPCApi<Block>,1210	C::Api: BlockBuilder<Block>,1211	B: Backend<Block> + 'static,1212	B::State: StateBackend<BlakeTwo256>,1213{1214	let FrontierTaskParams {1215		task_manager,1216		client,1217		substrate_backend,1218		eth_backend,1219		eth_filter_pool,1220		overrides,1221		fee_history_limit,1222		fee_history_cache,1223		sync_strategy,1224		prometheus_registry,1225	} = params;1226	// Frontier offchain DB task. Essential.1227	// Maps emulated ethereum data to substrate native data.1228	params.task_manager.spawn_essential_handle().spawn(1229		"frontier-mapping-sync-worker",1230		Some("frontier"),1231		MappingSyncWorker::new(1232			client.import_notification_stream(),1233			Duration::new(6, 0),1234			client.clone(),1235			substrate_backend,1236			overrides.clone(),1237			eth_backend,1238			3,1239			0,1240			sync_strategy,1241			sync,1242			pubsub_notification_sinks,1243		)1244		.for_each(|()| futures::future::ready(())),1245	);12461247	// Frontier `EthFilterApi` maintenance.1248	// Manages the pool of user-created Filters.1249	if let Some(eth_filter_pool) = eth_filter_pool {1250		// Each filter is allowed to stay in the pool for 100 blocks.1251		const FILTER_RETAIN_THRESHOLD: u64 = 100;1252		params.task_manager.spawn_essential_handle().spawn(1253			"frontier-filter-pool",1254			Some("frontier"),1255			EthTask::filter_pool_task(client.clone(), eth_filter_pool, FILTER_RETAIN_THRESHOLD),1256		);1257	}12581259	// Spawn Frontier FeeHistory cache maintenance task.1260	params.task_manager.spawn_essential_handle().spawn(1261		"frontier-fee-history",1262		Some("frontier"),1263		EthTask::fee_history_task(1264			client,1265			overrides.clone(),1266			fee_history_cache,1267			fee_history_limit,1268		),1269	);12701271	Arc::new(EthBlockDataCacheTask::new(1272		task_manager.spawn_handle(),1273		overrides,1274		50,1275		50,1276		prometheus_registry,1277	))1278}