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

difftreelog

source

node/src/service.rs13.4 KiBsourcehistory
1//! Service and ServiceFactory implementation. Specialized wrapper over substrate service.23//4// This file is subject to the terms and conditions defined in5// file 'LICENSE', which is part of this source code package.6//78// std9use std::sync::Arc;1011// Local Runtime Types12use nft_runtime::RuntimeApi;1314// Cumulus Imports15use cumulus_client_consensus_aura::{16	build_aura_consensus, BuildAuraConsensusParams, SlotProportion,17};18use cumulus_client_consensus_common::ParachainConsensus;19use cumulus_client_network::build_block_announce_validator;20use cumulus_client_service::{21	prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams,22};23use cumulus_primitives_core::ParaId;2425// Polkadot Imports26use polkadot_primitives::v1::CollatorPair;2728// Substrate Imports29use sc_client_api::ExecutorProvider;30pub use sc_executor::NativeExecutor;31use sc_executor::native_executor_instance;32use sc_network::NetworkService;33use sc_service::{Configuration, PartialComponents, Role, TFullBackend, TFullClient, TaskManager};34use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle};35use sp_api::ConstructRuntimeApi;36use sp_consensus::SlotData;37use sp_keystore::SyncCryptoStorePtr;38use sp_runtime::traits::BlakeTwo256;39use substrate_prometheus_endpoint::Registry;4041// Runtime type overrides42type BlockNumber = u32;43type Header = sp_runtime::generic::Header<BlockNumber, sp_runtime::traits::BlakeTwo256>;44pub type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;45type Hash = sp_core::H256;4647// Native executor instance.48native_executor_instance!(49	pub ParachainRuntimeExecutor,50	nft_runtime::api::dispatch,51	nft_runtime::native_version,52	frame_benchmarking::benchmarking::HostFunctions,53);5455/// Starts a `ServiceBuilder` for a full service.56///57/// Use this macro if you don't actually need the full service, but just the builder in order to58/// be able to perform chain operations.59pub fn new_partial<RuntimeApi, Executor, BIQ>(60	config: &Configuration,61	build_import_queue: BIQ,62) -> Result<63	PartialComponents<64		TFullClient<Block, RuntimeApi, Executor>,65		TFullBackend<Block>,66		(),67		sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,68		sc_transaction_pool::FullPool<Block, TFullClient<Block, RuntimeApi, Executor>>,69		(Option<Telemetry>, Option<TelemetryWorkerHandle>),70	>,71	sc_service::Error,72>73where74	RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, Executor>>75		+ Send76		+ Sync77		+ 'static,78	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>79		+ sp_api::Metadata<Block>80		+ sp_session::SessionKeys<Block>81		+ sp_api::ApiExt<82			Block,83			StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,84		> + sp_offchain::OffchainWorkerApi<Block>85		+ sp_block_builder::BlockBuilder<Block>,86	sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,87	Executor: sc_executor::NativeExecutionDispatch + 'static,88	BIQ: FnOnce(89		Arc<TFullClient<Block, RuntimeApi, Executor>>,90		&Configuration,91		Option<TelemetryHandle>,92		&TaskManager,93	) -> Result<94		sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,95		sc_service::Error,96	>,97{98	let telemetry = config99		.telemetry_endpoints100		.clone()101		.filter(|x| !x.is_empty())102		.map(|endpoints| -> Result<_, sc_telemetry::Error> {103			let worker = TelemetryWorker::new(16)?;104			let telemetry = worker.handle().new_telemetry(endpoints);105			Ok((worker, telemetry))106		})107		.transpose()?;108109	let (client, backend, keystore_container, task_manager) =110		sc_service::new_full_parts::<Block, RuntimeApi, Executor>(111			&config,112			telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),113		)?;114	let client = Arc::new(client);115116	let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());117118	let telemetry = telemetry.map(|(worker, telemetry)| {119		task_manager.spawn_handle().spawn("telemetry", worker.run());120		telemetry121	});122123	let transaction_pool = sc_transaction_pool::BasicPool::new_full(124		config.transaction_pool.clone(),125		config.role.is_authority().into(),126		config.prometheus_registry(),127		task_manager.spawn_handle(),128		client.clone(),129	);130131	let import_queue = build_import_queue(132		client.clone(),133		config,134		telemetry.as_ref().map(|telemetry| telemetry.handle()),135		&task_manager,136	)?;137138	let params = PartialComponents {139		backend,140		client,141		import_queue,142		keystore_container,143		task_manager,144		transaction_pool,145		select_chain: (),146		other: (telemetry, telemetry_worker_handle),147	};148149	Ok(params)150}151152/// Start a node with the given parachain `Configuration` and relay chain `Configuration`.153///154/// This is the actual implementation that is abstract over the executor and the runtime api.155#[sc_tracing::logging::prefix_logs_with("Parachain")]156async fn start_node_impl<RuntimeApi, Executor, RB, BIQ, BIC>(157	parachain_config: Configuration,158	collator_key: CollatorPair,159	polkadot_config: Configuration,160	id: ParaId,161	rpc_ext_builder: RB,162	build_import_queue: BIQ,163	build_consensus: BIC,164) -> sc_service::error::Result<(TaskManager, Arc<TFullClient<Block, RuntimeApi, Executor>>)>165where166	RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, Executor>>167		+ Send168		+ Sync169		+ 'static,170	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>171		+ sp_api::Metadata<Block>172		+ sp_session::SessionKeys<Block>173		+ sp_api::ApiExt<174			Block,175			StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,176		> + sp_offchain::OffchainWorkerApi<Block>177		+ sp_block_builder::BlockBuilder<Block>178		+ cumulus_primitives_core::CollectCollationInfo<Block>,179	sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,180	Executor: sc_executor::NativeExecutionDispatch + 'static,181	RB: Fn(182			Arc<TFullClient<Block, RuntimeApi, Executor>>,183		) -> jsonrpc_core::IoHandler<sc_rpc::Metadata>184		+ Send185		+ 'static,186	BIQ: FnOnce(187		Arc<TFullClient<Block, RuntimeApi, Executor>>,188		&Configuration,189		Option<TelemetryHandle>,190		&TaskManager,191	) -> Result<192		sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,193		sc_service::Error,194	>,195	BIC: FnOnce(196		Arc<TFullClient<Block, RuntimeApi, Executor>>,197		Option<&Registry>,198		Option<TelemetryHandle>,199		&TaskManager,200		&polkadot_service::NewFull<polkadot_service::Client>,201		Arc<sc_transaction_pool::FullPool<Block, TFullClient<Block, RuntimeApi, Executor>>>,202		Arc<NetworkService<Block, Hash>>,203		SyncCryptoStorePtr,204		bool,205	) -> Result<Box<dyn ParachainConsensus<Block>>, sc_service::Error>,206{207	if matches!(parachain_config.role, Role::Light) {208		return Err("Light client not supported!".into());209	}210211	let parachain_config = prepare_node_config(parachain_config);212213	let params = new_partial::<RuntimeApi, Executor, BIQ>(&parachain_config, build_import_queue)?;214	let (mut telemetry, telemetry_worker_handle) = params.other;215216	let relay_chain_full_node = cumulus_client_service::build_polkadot_full_node(217		polkadot_config,218		collator_key.clone(),219		telemetry_worker_handle,220	)221	.map_err(|e| match e {222		polkadot_service::Error::Sub(x) => x,223		s => format!("{}", s).into(),224	})?;225226	let client = params.client.clone();227	let backend = params.backend.clone();228	let block_announce_validator = build_block_announce_validator(229		relay_chain_full_node.client.clone(),230		id,231		Box::new(relay_chain_full_node.network.clone()),232		relay_chain_full_node.backend.clone(),233	);234235	let force_authoring = parachain_config.force_authoring;236	let validator = parachain_config.role.is_authority();237	let prometheus_registry = parachain_config.prometheus_registry().cloned();238	let transaction_pool = params.transaction_pool.clone();239	let mut task_manager = params.task_manager;240	let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue);241	let (network, network_status_sinks, system_rpc_tx, start_network) =242		sc_service::build_network(sc_service::BuildNetworkParams {243			config: &parachain_config,244			client: client.clone(),245			transaction_pool: transaction_pool.clone(),246			spawn_handle: task_manager.spawn_handle(),247			import_queue: import_queue.clone(),248			on_demand: None,249			block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)),250		})?;251252	let rpc_client = client.clone();253	let rpc_extensions_builder = Box::new(move |_, _| rpc_ext_builder(rpc_client.clone()));254255	sc_service::spawn_tasks(sc_service::SpawnTasksParams {256		on_demand: None,257		remote_blockchain: None,258		rpc_extensions_builder,259		client: client.clone(),260		transaction_pool: transaction_pool.clone(),261		task_manager: &mut task_manager,262		config: parachain_config,263		keystore: params.keystore_container.sync_keystore(),264		backend: backend.clone(),265		network: network.clone(),266		network_status_sinks,267		system_rpc_tx,268		telemetry: telemetry.as_mut(),269	})?;270271	let announce_block = {272		let network = network.clone();273		Arc::new(move |hash, data| network.announce_block(hash, data))274	};275276	if validator {277		let parachain_consensus = build_consensus(278			client.clone(),279			prometheus_registry.as_ref(),280			telemetry.as_ref().map(|t| t.handle()),281			&task_manager,282			&relay_chain_full_node,283			transaction_pool,284			network,285			params.keystore_container.sync_keystore(),286			force_authoring,287		)?;288289		let spawner = task_manager.spawn_handle();290291		let params = StartCollatorParams {292			para_id: id,293			block_status: client.clone(),294			announce_block,295			client: client.clone(),296			task_manager: &mut task_manager,297			collator_key,298			relay_chain_full_node,299			spawner,300			parachain_consensus,301			import_queue,302		};303304		start_collator(params).await?;305	} else {306		let params = StartFullNodeParams {307			client: client.clone(),308			announce_block,309			task_manager: &mut task_manager,310			para_id: id,311			relay_chain_full_node,312		};313314		start_full_node(params)?;315	}316317	start_network.start_network();318319	Ok((task_manager, client))320}321322/// Build the import queue for the the parachain runtime.323pub fn parachain_build_import_queue(324	client: Arc<TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>>,325	config: &Configuration,326	telemetry: Option<TelemetryHandle>,327	task_manager: &TaskManager,328) -> Result<329	sp_consensus::DefaultImportQueue<330		Block,331		TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>,332	>,333	sc_service::Error,334> {335	let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;336337338	cumulus_client_consensus_aura::import_queue::<339		sp_consensus_aura::sr25519::AuthorityPair,340		_,341		_,342		_,343		_,344		_,345		_,346	>(cumulus_client_consensus_aura::ImportQueueParams {347		block_import:  client.clone(),348		client: client.clone(),349		create_inherent_data_providers: move |_, _| async move {350			let time = sp_timestamp::InherentDataProvider::from_system_time();351352			let slot =353				sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(354					*time,355					slot_duration.slot_duration(),356				);357358			Ok((time, slot))359		},360		registry: config.prometheus_registry().clone(),361		can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),362		spawner: &task_manager.spawn_essential_handle(),363		telemetry,364	})365	.map_err(Into::into)366}367368/// Start a normal parachain node.369pub async fn start_node(370	parachain_config: Configuration,371	collator_key: CollatorPair,372	polkadot_config: Configuration,373	id: ParaId,374) -> sc_service::error::Result<(TaskManager, Arc<TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>>)> {375	start_node_impl::<RuntimeApi, ParachainRuntimeExecutor, _, _, _>(376		parachain_config,377		collator_key,378		polkadot_config,379		id,380		|_| Default::default(),381		parachain_build_import_queue,382		|client,383		 prometheus_registry,384		 telemetry,385		 task_manager,386		 relay_chain_node,387		 transaction_pool,388		 sync_oracle,389		 keystore,390		 force_authoring| {391			let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;392393			let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(394				task_manager.spawn_handle(),395				client.clone(),396				transaction_pool,397				prometheus_registry.clone(),398				telemetry.clone(),399			);400401			let relay_chain_backend = relay_chain_node.backend.clone();402			let relay_chain_client = relay_chain_node.client.clone();403			Ok(build_aura_consensus::<404				sp_consensus_aura::sr25519::AuthorityPair,405				_,406				_,407				_,408				_,409				_,410				_,411				_,412				_,413				_,414			>(BuildAuraConsensusParams {415				proposer_factory,416				create_inherent_data_providers: move |_, (relay_parent, validation_data)| {417					let parachain_inherent =418					cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client(419						relay_parent,420						&relay_chain_client,421						&*relay_chain_backend,422						&validation_data,423						id,424					);425					async move {426						let time = sp_timestamp::InherentDataProvider::from_system_time();427428						let slot =429						sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(430							*time,431							slot_duration.slot_duration(),432						);433434						let parachain_inherent = parachain_inherent.ok_or_else(|| {435							Box::<dyn std::error::Error + Send + Sync>::from(436								"Failed to create parachain inherent",437							)438						})?;439						Ok((time, slot, parachain_inherent))440					}441				},442				block_import: client.clone(),443				relay_chain_client: relay_chain_node.client.clone(),444				relay_chain_backend: relay_chain_node.backend.clone(),445				para_client: client.clone(),446				backoff_authoring_blocks: Option::<()>::None,447				sync_oracle,448				keystore,449				force_authoring,450				slot_duration,451				// We got around 500ms for proposing452				block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),453				telemetry,454			}))455		},456	)457	.await458}