git.delta.rocks / unique-network / refs/commits / 4dbeda6769b2

difftreelog

source

node/src/service.rs13.7 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 telemetry = config.telemetry_endpoints.clone()110		.filter(|x| !x.is_empty())111		.map(|endpoints| -> Result<_, sc_telemetry::Error> {112			let worker = TelemetryWorker::new(16)?;113			let telemetry = worker.handle().new_telemetry(endpoints);114			Ok((worker, telemetry))115		})116		.transpose()?;117118	let (client, backend, keystore_container, task_manager) =119		sc_service::new_full_parts::<Block, RuntimeApi, Executor>(120			&config,121			telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),122		)?;123	let client = Arc::new(client);124125	let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle());126127	let telemetry = telemetry.map(|(worker, telemetry)| {128		task_manager.spawn_handle().spawn("telemetry", worker.run());129		telemetry130	});131132	let transaction_pool = sc_transaction_pool::BasicPool::new_full(133		config.transaction_pool.clone(),134		config.role.is_authority().into(),135		config.prometheus_registry(),136		task_manager.spawn_handle(),137		client.clone(),138	);139140	let import_queue = build_import_queue(141		client.clone(),142		config,143		telemetry.as_ref().map(|telemetry| telemetry.handle()),144		&task_manager,145	)?;146147	let params = PartialComponents {148		backend,149		client,150		import_queue,151		keystore_container,152		task_manager,153		transaction_pool,154		select_chain: (),155		other: (telemetry, telemetry_worker_handle),156	};157158	Ok(params)159}160161/// Start a node with the given parachain `Configuration` and relay chain `Configuration`.162///163/// This is the actual implementation that is abstract over the executor and the runtime api.164#[sc_tracing::logging::prefix_logs_with("Parachain")]165async fn start_node_impl<RuntimeApi, Executor, RB, BIQ, BIC>(166	parachain_config: Configuration,167	collator_key: CollatorPair,168	polkadot_config: Configuration,169	id: ParaId,170	rpc_ext_builder: RB,171	build_import_queue: BIQ,172	build_consensus: BIC,173) -> sc_service::error::Result<(TaskManager, Arc<TFullClient<Block, RuntimeApi, Executor>>)>174where175	RuntimeApi: ConstructRuntimeApi<Block, TFullClient<Block, RuntimeApi, Executor>>176		+ Send177		+ Sync178		+ 'static,179	RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>180		+ sp_api::Metadata<Block>181		+ sp_session::SessionKeys<Block>182		+ sp_api::ApiExt<183			Block,184			StateBackend = sc_client_api::StateBackendFor<TFullBackend<Block>, Block>,185		> + sp_offchain::OffchainWorkerApi<Block>186		+ sp_block_builder::BlockBuilder<Block>187		+ cumulus_primitives_core::CollectCollationInfo<Block>,188	sc_client_api::StateBackendFor<TFullBackend<Block>, Block>: sp_api::StateBackend<BlakeTwo256>,189	Executor: sc_executor::NativeExecutionDispatch + 'static,190	RB: Fn(191			Arc<TFullClient<Block, RuntimeApi, Executor>>,192		) -> jsonrpc_core::IoHandler<sc_rpc::Metadata>193		+ Send194		+ 'static,195	BIQ: FnOnce(196		Arc<TFullClient<Block, RuntimeApi, Executor>>,197		&Configuration,198		Option<TelemetryHandle>,199		&TaskManager,200	) -> Result<201		sp_consensus::DefaultImportQueue<Block, TFullClient<Block, RuntimeApi, Executor>>,202		sc_service::Error,203	>,204	BIC: FnOnce(205		Arc<TFullClient<Block, RuntimeApi, Executor>>,206		Option<&Registry>,207		Option<TelemetryHandle>,208		&TaskManager,209		&polkadot_service::NewFull<polkadot_service::Client>,210		Arc<sc_transaction_pool::FullPool<Block, TFullClient<Block, RuntimeApi, Executor>>>,211		Arc<NetworkService<Block, Hash>>,212		SyncCryptoStorePtr,213		bool,214	) -> Result<Box<dyn ParachainConsensus<Block>>, sc_service::Error>,215{216	if matches!(parachain_config.role, Role::Light) {217		return Err("Light client not supported!".into());218	}219220	let parachain_config = prepare_node_config(parachain_config);221222	let params = new_partial::<RuntimeApi, Executor, BIQ>(&parachain_config, build_import_queue)?;223	let (mut telemetry, telemetry_worker_handle) = params.other;224225	let relay_chain_full_node = cumulus_client_service::build_polkadot_full_node(226		polkadot_config,227		collator_key.clone(),228		telemetry_worker_handle,229	)230	.map_err(|e| match e {231		polkadot_service::Error::Sub(x) => x,232		s => format!("{}", s).into(),233	})?;234235	let client = params.client.clone();236	let backend = params.backend.clone();237	let block_announce_validator = build_block_announce_validator(238		relay_chain_full_node.client.clone(),239		id,240		Box::new(relay_chain_full_node.network.clone()),241		relay_chain_full_node.backend.clone(),242	);243244	let force_authoring = parachain_config.force_authoring;245	let validator = parachain_config.role.is_authority();246	let prometheus_registry = parachain_config.prometheus_registry().cloned();247	let transaction_pool = params.transaction_pool.clone();248	let mut task_manager = params.task_manager;249	let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue);250	let (network, network_status_sinks, system_rpc_tx, start_network) =251		sc_service::build_network(sc_service::BuildNetworkParams {252			config: &parachain_config,253			client: client.clone(),254			transaction_pool: transaction_pool.clone(),255			spawn_handle: task_manager.spawn_handle(),256			import_queue: import_queue.clone(),257			on_demand: None,258			block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)),259		})?;260261	let rpc_client = client.clone();262	let rpc_extensions_builder = Box::new(move |_, _| rpc_ext_builder(rpc_client.clone()));263264	sc_service::spawn_tasks(sc_service::SpawnTasksParams {265		on_demand: None,266		remote_blockchain: None,267		rpc_extensions_builder,268		client: client.clone(),269		transaction_pool: transaction_pool.clone(),270		task_manager: &mut task_manager,271		config: parachain_config,272		keystore: params.keystore_container.sync_keystore(),273		backend: backend.clone(),274		network: network.clone(),275		network_status_sinks,276		system_rpc_tx,277		telemetry: telemetry.as_mut(),278	})?;279280	let announce_block = {281		let network = network.clone();282		Arc::new(move |hash, data| network.announce_block(hash, data))283	};284285	if validator {286		let parachain_consensus = build_consensus(287			client.clone(),288			prometheus_registry.as_ref(),289			telemetry.as_ref().map(|t| t.handle()),290			&task_manager,291			&relay_chain_full_node,292			transaction_pool,293			network,294			params.keystore_container.sync_keystore(),295			force_authoring,296		)?;297298		let spawner = task_manager.spawn_handle();299300		let params = StartCollatorParams {301			para_id: id,302			block_status: client.clone(),303			announce_block,304			client: client.clone(),305			task_manager: &mut task_manager,306			collator_key,307			relay_chain_full_node,308			spawner,309			parachain_consensus,310			import_queue,311		};312313		start_collator(params).await?;314	} else {315		let params = StartFullNodeParams {316			client: client.clone(),317			announce_block,318			task_manager: &mut task_manager,319			para_id: id,320			relay_chain_full_node,321		};322323		start_full_node(params)?;324	}325326	start_network.start_network();327328	Ok((task_manager, client))329}330331/// Build the import queue for the the parachain runtime.332pub fn parachain_build_import_queue(333	client: Arc<TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>>,334	config: &Configuration,335	telemetry: Option<TelemetryHandle>,336	task_manager: &TaskManager,337) -> Result<338	sp_consensus::DefaultImportQueue<339		Block,340		TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>,341	>,342	sc_service::Error,343> {344	let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;345346347	cumulus_client_consensus_aura::import_queue::<348		sp_consensus_aura::sr25519::AuthorityPair,349		_,350		_,351		_,352		_,353		_,354		_,355	>(cumulus_client_consensus_aura::ImportQueueParams {356		block_import:  client.clone(),357		client: client.clone(),358		create_inherent_data_providers: move |_, _| async move {359			let time = sp_timestamp::InherentDataProvider::from_system_time();360361			let slot =362				sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(363					*time,364					slot_duration.slot_duration(),365				);366367			Ok((time, slot))368		},369		registry: config.prometheus_registry().clone(),370		can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),371		spawner: &task_manager.spawn_essential_handle(),372		telemetry,373	})374	.map_err(Into::into)375}376377/// Start a normal parachain node.378pub async fn start_node(379	parachain_config: Configuration,380	collator_key: CollatorPair,381	polkadot_config: Configuration,382	id: ParaId,383) -> sc_service::error::Result<(TaskManager, Arc<TFullClient<Block, RuntimeApi, ParachainRuntimeExecutor>>)> {384	start_node_impl::<RuntimeApi, ParachainRuntimeExecutor, _, _, _>(385		parachain_config,386		collator_key,387		polkadot_config,388		id,389		|_| Default::default(),390		parachain_build_import_queue,391		|client,392		 prometheus_registry,393		 telemetry,394		 task_manager,395		 relay_chain_node,396		 transaction_pool,397		 sync_oracle,398		 keystore,399		 force_authoring| {400			let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?;401402			let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(403				task_manager.spawn_handle(),404				client.clone(),405				transaction_pool,406				prometheus_registry.clone(),407				telemetry.clone(),408			);409410			let relay_chain_backend = relay_chain_node.backend.clone();411			let relay_chain_client = relay_chain_node.client.clone();412			Ok(build_aura_consensus::<413				sp_consensus_aura::sr25519::AuthorityPair,414				_,415				_,416				_,417				_,418				_,419				_,420				_,421				_,422				_,423			>(BuildAuraConsensusParams {424				proposer_factory,425				create_inherent_data_providers: move |_, (relay_parent, validation_data)| {426					let parachain_inherent =427					cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client(428						relay_parent,429						&relay_chain_client,430						&*relay_chain_backend,431						&validation_data,432						id,433					);434					async move {435						let time = sp_timestamp::InherentDataProvider::from_system_time();436437						let slot =438						sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration(439							*time,440							slot_duration.slot_duration(),441						);442443						let parachain_inherent = parachain_inherent.ok_or_else(|| {444							Box::<dyn std::error::Error + Send + Sync>::from(445								"Failed to create parachain inherent",446							)447						})?;448						Ok((time, slot, parachain_inherent))449					}450				},451				block_import: client.clone(),452				relay_chain_client: relay_chain_node.client.clone(),453				relay_chain_backend: relay_chain_node.backend.clone(),454				para_client: client.clone(),455				backoff_authoring_blocks: Option::<()>::None,456				sync_oracle,457				keystore,458				force_authoring,459				slot_duration,460				// We got around 500ms for proposing461				block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32),462				telemetry,463			}))464		},465	)466	.await467}