referrerpolicy=no-referrer-when-downgrade

sc_service/
builder.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19use crate::{
20	build_network_future, build_system_rpc_future,
21	client::{Client, ClientConfig},
22	config::{Configuration, ExecutorConfiguration, KeystoreConfig, Multiaddr, PrometheusConfig},
23	error::Error,
24	metrics::MetricsService,
25	start_rpc_servers, BuildGenesisBlock, GenesisBlockBuilder, RpcHandlers,
26	SpawnEssentialTaskHandle, SpawnTaskHandle, TaskManager, TransactionPoolAdapter,
27};
28use futures::{select, FutureExt, StreamExt};
29use jsonrpsee::RpcModule;
30use log::{debug, error, info};
31use prometheus_endpoint::Registry;
32use sc_chain_spec::{get_extension, ChainSpec};
33use sc_client_api::{
34	execution_extensions::ExecutionExtensions, proof_provider::ProofProvider, BadBlocks,
35	BlockBackend, BlockchainEvents, ExecutorProvider, ForkBlocks, KeysIter, StorageProvider,
36	TrieCacheContext, UsageProvider,
37};
38use sc_client_db::{Backend, BlocksPruning, DatabaseSettings, PruningMode};
39use sc_consensus::import_queue::{ImportQueue, ImportQueueService};
40use sc_executor::{
41	sp_wasm_interface::HostFunctions, HeapAllocStrategy, RuntimeVersionOf, WasmExecutor,
42	DEFAULT_HEAP_ALLOC_STRATEGY,
43};
44use sc_keystore::LocalKeystore;
45use sc_network::{
46	config::{FullNetworkConfiguration, IpfsConfig, ProtocolId, SyncMode},
47	multiaddr::Protocol,
48	service::{
49		traits::{PeerStore, RequestResponseConfig},
50		NotificationMetrics,
51	},
52	IpfsIndexedTransactions, NetworkBackend, NetworkStateInfo,
53};
54use sc_network_common::role::{Role, Roles};
55use sc_network_light::light_client_requests::handler::LightClientRequestHandler;
56use sc_network_sync::{
57	block_relay_protocol::{BlockDownloader, BlockRelayParams},
58	block_request_handler::BlockRequestHandler,
59	engine::SyncingEngine,
60	service::network::{NetworkServiceHandle, NetworkServiceProvider},
61	state_request_handler::StateRequestHandler,
62	strategy::{
63		polkadot::{PolkadotSyncingStrategy, PolkadotSyncingStrategyConfig},
64		SyncingStrategy,
65	},
66	warp_request_handler::RequestHandler as WarpSyncRequestHandler,
67	SyncingService, WarpSyncConfig,
68};
69use sc_rpc::{
70	author::AuthorApiServer,
71	chain::ChainApiServer,
72	offchain::OffchainApiServer,
73	state::{ChildStateApiServer, StateApiServer},
74	system::SystemApiServer,
75	DenyUnsafe, SubscriptionTaskExecutor,
76};
77use sc_rpc_spec_v2::{
78	archive::ArchiveApiServer,
79	bitswap::BitswapApiServer,
80	chain_head::ChainHeadApiServer,
81	chain_spec::ChainSpecApiServer,
82	transaction::{TransactionApiServer, TransactionBroadcastApiServer},
83};
84use sc_telemetry::{telemetry, ConnectionMessage, Telemetry, TelemetryHandle, SUBSTRATE_INFO};
85use sc_tracing::block::TracingExecuteBlock;
86use sc_transaction_pool_api::{MaintainedTransactionPool, TransactionPool};
87use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender};
88use sp_api::{CallApiAt, ProvideRuntimeApi};
89use sp_blockchain::{HeaderBackend, HeaderMetadata};
90use sp_consensus::block_validation::{
91	BlockAnnounceValidator, Chain, DefaultBlockAnnounceValidator,
92};
93use sp_core::traits::{CodeExecutor, SpawnNamed};
94use sp_keystore::KeystorePtr;
95use sp_runtime::traits::{Block as BlockT, BlockIdTo, NumberFor, Zero};
96use sp_storage::{ChildInfo, ChildType, PrefixedStorageKey};
97use std::{
98	str::FromStr,
99	sync::Arc,
100	time::{Duration, SystemTime},
101};
102
103/// Cap the maximum number of blocks advertized to IPFS to two weeks at 6-second block time.
104/// Block pruning depth will be used if it is shorter.
105const IPFS_MAX_BLOCKS: u32 = 201600;
106
107/// Full client type.
108pub type TFullClient<TBl, TRtApi, TExec> =
109	Client<TFullBackend<TBl>, TFullCallExecutor<TBl, TExec>, TBl, TRtApi>;
110
111/// Full client backend type.
112pub type TFullBackend<TBl> = Backend<TBl>;
113
114/// Full client call executor type.
115pub type TFullCallExecutor<TBl, TExec> = crate::client::LocalCallExecutor<TBl, Backend<TBl>, TExec>;
116
117type TFullParts<TBl, TRtApi, TExec> =
118	(TFullClient<TBl, TRtApi, TExec>, Arc<TFullBackend<TBl>>, KeystoreContainer, TaskManager);
119
120/// Construct a local keystore shareable container
121pub struct KeystoreContainer(Arc<LocalKeystore>);
122
123impl KeystoreContainer {
124	/// Construct KeystoreContainer
125	pub fn new(config: &KeystoreConfig) -> Result<Self, Error> {
126		let keystore = Arc::new(match config {
127			KeystoreConfig::Path { path, password } => {
128				LocalKeystore::open(path.clone(), password.clone())?
129			},
130			KeystoreConfig::InMemory => LocalKeystore::in_memory(),
131		});
132
133		Ok(Self(keystore))
134	}
135
136	/// Returns a shared reference to a dynamic `Keystore` trait implementation.
137	pub fn keystore(&self) -> KeystorePtr {
138		self.0.clone()
139	}
140
141	/// Returns a shared reference to the local keystore .
142	pub fn local_keystore(&self) -> Arc<LocalKeystore> {
143		self.0.clone()
144	}
145}
146
147/// Creates a new full client for the given config.
148pub fn new_full_client<TBl, TRtApi, TExec>(
149	config: &Configuration,
150	telemetry: Option<TelemetryHandle>,
151	executor: TExec,
152	pruning_filters: Vec<Arc<dyn sc_client_db::PruningFilter>>,
153) -> Result<TFullClient<TBl, TRtApi, TExec>, Error>
154where
155	TBl: BlockT,
156	TExec: CodeExecutor + RuntimeVersionOf + Clone,
157{
158	new_full_parts(config, telemetry, executor, pruning_filters).map(|parts| parts.0)
159}
160
161/// Create the initial parts of a full node with the default genesis block builder.
162///
163/// The `pruning_filters` parameter allows configuring which blocks should be preserved
164/// during pruning.
165pub fn new_full_parts_record_import<TBl, TRtApi, TExec>(
166	config: &Configuration,
167	telemetry: Option<TelemetryHandle>,
168	executor: TExec,
169	enable_import_proof_recording: bool,
170	pruning_filters: Vec<Arc<dyn sc_client_db::PruningFilter>>,
171) -> Result<TFullParts<TBl, TRtApi, TExec>, Error>
172where
173	TBl: BlockT,
174	TExec: CodeExecutor + RuntimeVersionOf + Clone,
175{
176	let mut db_config = config.db_config();
177	db_config.pruning_filters = pruning_filters;
178	let backend = new_db_backend(db_config)?;
179
180	let genesis_block_builder = GenesisBlockBuilder::new(
181		config.chain_spec.as_storage_builder(),
182		!config.no_genesis(),
183		backend.clone(),
184		executor.clone(),
185	)?;
186
187	new_full_parts_with_genesis_builder(
188		config,
189		telemetry,
190		executor,
191		backend,
192		genesis_block_builder,
193		enable_import_proof_recording,
194	)
195}
196
197/// Create the initial parts of a full node with the default genesis block builder.
198///
199/// The `pruning_filters` parameter allows configuring which blocks should be preserved
200/// during pruning.
201pub fn new_full_parts<TBl, TRtApi, TExec>(
202	config: &Configuration,
203	telemetry: Option<TelemetryHandle>,
204	executor: TExec,
205	pruning_filters: Vec<Arc<dyn sc_client_db::PruningFilter>>,
206) -> Result<TFullParts<TBl, TRtApi, TExec>, Error>
207where
208	TBl: BlockT,
209	TExec: CodeExecutor + RuntimeVersionOf + Clone,
210{
211	new_full_parts_record_import(config, telemetry, executor, false, pruning_filters)
212}
213
214/// Create the initial parts of a full node.
215pub fn new_full_parts_with_genesis_builder<TBl, TRtApi, TExec, TBuildGenesisBlock>(
216	config: &Configuration,
217	telemetry: Option<TelemetryHandle>,
218	executor: TExec,
219	backend: Arc<TFullBackend<TBl>>,
220	genesis_block_builder: TBuildGenesisBlock,
221	enable_import_proof_recording: bool,
222) -> Result<TFullParts<TBl, TRtApi, TExec>, Error>
223where
224	TBl: BlockT,
225	TExec: CodeExecutor + RuntimeVersionOf + Clone,
226	TBuildGenesisBlock: BuildGenesisBlock<
227		TBl,
228		BlockImportOperation = <Backend<TBl> as sc_client_api::backend::Backend<TBl>>::BlockImportOperation
229	>,
230{
231	let keystore_container = KeystoreContainer::new(&config.keystore)?;
232
233	let task_manager = {
234		let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry);
235		TaskManager::new(config.tokio_handle.clone(), registry)?
236	};
237
238	let chain_spec = &config.chain_spec;
239	let fork_blocks = get_extension::<ForkBlocks<TBl>>(chain_spec.extensions())
240		.cloned()
241		.unwrap_or_default();
242
243	let bad_blocks = get_extension::<BadBlocks<TBl>>(chain_spec.extensions())
244		.cloned()
245		.unwrap_or_default();
246
247	let client = {
248		let extensions = ExecutionExtensions::new(None, Arc::new(executor.clone()));
249
250		let wasm_runtime_substitutes = config
251			.chain_spec
252			.code_substitutes()
253			.into_iter()
254			.map(|(n, c)| {
255				let number = NumberFor::<TBl>::from_str(&n).map_err(|_| {
256					Error::Application(Box::from(format!(
257						"Failed to parse `{}` as block number for code substitutes. \
258						 In an old version the key for code substitute was a block hash. \
259						 Please update the chain spec to a version that is compatible with your node.",
260						n
261					)))
262				})?;
263				Ok((number, c))
264			})
265			.collect::<Result<std::collections::HashMap<_, _>, Error>>()?;
266
267		let client = new_client(
268			backend.clone(),
269			executor,
270			genesis_block_builder,
271			fork_blocks,
272			bad_blocks,
273			extensions,
274			Box::new(task_manager.spawn_handle()),
275			config.prometheus_config.as_ref().map(|config| config.registry.clone()),
276			telemetry,
277			ClientConfig {
278				offchain_worker_enabled: config.offchain_worker.enabled,
279				offchain_indexing_api: config.offchain_worker.indexing_enabled,
280				wasm_runtime_overrides: config.wasm_runtime_overrides.clone(),
281				no_genesis: config.no_genesis(),
282				wasm_runtime_substitutes,
283				enable_import_proof_recording,
284			},
285		)?;
286
287		if let Some(warm_up_strategy) = config.warm_up_trie_cache {
288			let storage_root = client.usage_info().chain.best_hash;
289			let backend_clone = backend.clone();
290
291			if warm_up_strategy.is_blocking() {
292				// We use the blocking strategy for testing purposes.
293				// So better to error out if it fails.
294				warm_up_trie_cache(backend_clone, storage_root)?;
295			} else {
296				task_manager.spawn_handle().spawn_blocking(
297					"warm-up-trie-cache",
298					None,
299					async move {
300						if let Err(e) = warm_up_trie_cache(backend_clone, storage_root) {
301							error!("Failed to warm up trie cache: {e}");
302						}
303					},
304				);
305			}
306		}
307
308		client
309	};
310
311	Ok((client, backend, keystore_container, task_manager))
312}
313
314fn child_info(key: Vec<u8>) -> Option<ChildInfo> {
315	let prefixed_key = PrefixedStorageKey::new(key);
316	ChildType::from_prefixed_key(&prefixed_key).and_then(|(child_type, storage_key)| {
317		(child_type == ChildType::ParentKeyId).then(|| ChildInfo::new_default(storage_key))
318	})
319}
320
321fn warm_up_trie_cache<TBl: BlockT>(
322	backend: Arc<TFullBackend<TBl>>,
323	storage_root: TBl::Hash,
324) -> Result<(), Error> {
325	use sc_client_api::backend::Backend;
326	use sp_state_machine::Backend as StateBackend;
327
328	let untrusted_state = || backend.state_at(storage_root, TrieCacheContext::Untrusted);
329	let trusted_state = || backend.state_at(storage_root, TrieCacheContext::Trusted);
330
331	debug!("Populating trie cache started",);
332	let start_time = std::time::Instant::now();
333	let mut keys_count = 0;
334	let mut child_keys_count = 0;
335	for key in KeysIter::<_, TBl>::new(untrusted_state()?, None, None)? {
336		if keys_count != 0 && keys_count % 100_000 == 0 {
337			debug!("{} keys and {} child keys have been warmed", keys_count, child_keys_count);
338		}
339		match child_info(key.0.clone()) {
340			Some(info) => {
341				for child_key in
342					KeysIter::<_, TBl>::new_child(untrusted_state()?, info.clone(), None, None)?
343				{
344					if trusted_state()?
345						.child_storage(&info, &child_key.0)
346						.unwrap_or_default()
347						.is_none()
348					{
349						debug!("Child storage value unexpectedly empty: {child_key:?}");
350					}
351					child_keys_count += 1;
352				}
353			},
354			None => {
355				if trusted_state()?.storage(&key.0).unwrap_or_default().is_none() {
356					debug!("Storage value unexpectedly empty: {key:?}");
357				}
358				keys_count += 1;
359			},
360		}
361	}
362	debug!(
363		"Trie cache populated with {keys_count} keys and {child_keys_count} child keys in {} s",
364		start_time.elapsed().as_secs_f32()
365	);
366
367	Ok(())
368}
369
370/// Creates a [`WasmExecutor`] according to [`ExecutorConfiguration`].
371pub fn new_wasm_executor<H: HostFunctions>(config: &ExecutorConfiguration) -> WasmExecutor<H> {
372	let strategy = config
373		.default_heap_pages
374		.map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |p| HeapAllocStrategy::Static { extra_pages: p as _ });
375	WasmExecutor::<H>::builder()
376		.with_execution_method(config.wasm_method)
377		.with_onchain_heap_alloc_strategy(strategy)
378		.with_offchain_heap_alloc_strategy(strategy)
379		.with_max_runtime_instances(config.max_runtime_instances)
380		.with_runtime_cache_size(config.runtime_cache_size)
381		.build()
382}
383
384/// Create an instance of the default DB-backend.
385///
386/// Pruning filters can be configured via `settings.pruning_filters`.
387/// If any filter returns `true` for a block's justifications, the block will not be pruned.
388pub fn new_db_backend<Block>(
389	settings: DatabaseSettings,
390) -> Result<Arc<Backend<Block>>, sp_blockchain::Error>
391where
392	Block: BlockT,
393{
394	const CANONICALIZATION_DELAY: u64 = 4096;
395
396	Ok(Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?))
397}
398
399/// Create an instance of client backed by given backend.
400pub fn new_client<E, Block, RA, G>(
401	backend: Arc<Backend<Block>>,
402	executor: E,
403	genesis_block_builder: G,
404	fork_blocks: ForkBlocks<Block>,
405	bad_blocks: BadBlocks<Block>,
406	execution_extensions: ExecutionExtensions<Block>,
407	spawn_handle: Box<dyn SpawnNamed>,
408	prometheus_registry: Option<Registry>,
409	telemetry: Option<TelemetryHandle>,
410	config: ClientConfig<Block>,
411) -> Result<
412	Client<
413		Backend<Block>,
414		crate::client::LocalCallExecutor<Block, Backend<Block>, E>,
415		Block,
416		RA,
417	>,
418	sp_blockchain::Error,
419>
420where
421	Block: BlockT,
422	E: CodeExecutor + RuntimeVersionOf,
423	G: BuildGenesisBlock<
424		Block,
425		BlockImportOperation = <Backend<Block> as sc_client_api::backend::Backend<Block>>::BlockImportOperation
426	>,
427{
428	let executor = crate::client::LocalCallExecutor::new(
429		backend.clone(),
430		executor,
431		config.clone(),
432		execution_extensions,
433	)?;
434
435	Client::new(
436		backend,
437		executor,
438		spawn_handle,
439		genesis_block_builder,
440		fork_blocks,
441		bad_blocks,
442		prometheus_registry,
443		telemetry,
444		config,
445	)
446}
447
448/// Parameters to pass into `build`.
449pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> {
450	/// The service configuration.
451	pub config: Configuration,
452	/// A shared client returned by `new_full_parts`.
453	pub client: Arc<TCl>,
454	/// A shared backend returned by `new_full_parts`.
455	pub backend: Arc<Backend>,
456	/// A task manager returned by `new_full_parts`.
457	pub task_manager: &'a mut TaskManager,
458	/// A shared keystore returned by `new_full_parts`.
459	pub keystore: KeystorePtr,
460	/// A shared transaction pool.
461	pub transaction_pool: Arc<TExPool>,
462	/// Builds additional [`RpcModule`]s that should be added to the server
463	pub rpc_builder: Box<dyn Fn(SubscriptionTaskExecutor) -> Result<RpcModule<TRpc>, Error>>,
464	/// A shared network instance.
465	pub network: Arc<dyn sc_network::service::traits::NetworkService>,
466	/// A Sender for RPC requests.
467	pub system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
468	/// Controller for transactions handlers
469	pub tx_handler_controller:
470		sc_network_transactions::TransactionsHandlerController<<TBl as BlockT>::Hash>,
471	/// Syncing service.
472	pub sync_service: Arc<SyncingService<TBl>>,
473	/// Telemetry instance for this node.
474	pub telemetry: Option<&'a mut Telemetry>,
475	/// Optional [`TracingExecuteBlock`] handle.
476	///
477	/// Will be used by the `trace_block` RPC to execute the actual block.
478	pub tracing_execute_block: Option<Arc<dyn TracingExecuteBlock<TBl>>>,
479}
480
481/// Spawn the tasks that are required to run a node.
482pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
483	SpawnTasksParams {
484		mut config,
485		task_manager,
486		client,
487		backend,
488		keystore,
489		transaction_pool,
490		rpc_builder,
491		network,
492		system_rpc_tx,
493		tx_handler_controller,
494		sync_service,
495		telemetry,
496		tracing_execute_block: execute_block,
497	}: SpawnTasksParams<TBl, TCl, TExPool, TRpc, TBackend>,
498) -> Result<RpcHandlers, Error>
499where
500	TCl: ProvideRuntimeApi<TBl>
501		+ HeaderMetadata<TBl, Error = sp_blockchain::Error>
502		+ Chain<TBl>
503		+ BlockBackend<TBl>
504		+ BlockIdTo<TBl, Error = sp_blockchain::Error>
505		+ ProofProvider<TBl>
506		+ HeaderBackend<TBl>
507		+ BlockchainEvents<TBl>
508		+ ExecutorProvider<TBl>
509		+ UsageProvider<TBl>
510		+ StorageProvider<TBl, TBackend>
511		+ CallApiAt<TBl>
512		+ Send
513		+ 'static,
514	<TCl as ProvideRuntimeApi<TBl>>::Api: sp_api::Metadata<TBl>
515		+ sp_transaction_pool::runtime_api::TaggedTransactionQueue<TBl>
516		+ sp_session::SessionKeys<TBl>
517		+ sp_api::ApiExt<TBl>,
518	TBl: BlockT,
519	TBl::Hash: Unpin,
520	TBl::Header: Unpin,
521	TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
522	TExPool: MaintainedTransactionPool<Block = TBl, Hash = <TBl as BlockT>::Hash> + 'static,
523{
524	let chain_info = client.usage_info().chain;
525
526	sp_session::generate_initial_session_keys(
527		client.clone(),
528		chain_info.best_hash,
529		config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(),
530		keystore.clone(),
531	)
532	.map_err(|e| Error::Application(Box::new(e)))?;
533
534	let sysinfo = sc_sysinfo::gather_sysinfo();
535	sc_sysinfo::print_sysinfo(&sysinfo);
536
537	let telemetry = telemetry
538		.map(|telemetry| {
539			init_telemetry(
540				config.network.node_name.clone(),
541				config.impl_name.clone(),
542				config.impl_version.clone(),
543				config.chain_spec.name().to_string(),
544				config.role.is_authority(),
545				network.clone(),
546				client.clone(),
547				telemetry,
548				Some(sysinfo),
549			)
550		})
551		.transpose()?;
552
553	info!("📦 Highest known block at #{}", chain_info.best_number);
554
555	let spawn_handle = task_manager.spawn_handle();
556
557	// Inform the tx pool about imported and finalized blocks.
558	spawn_handle.spawn(
559		"txpool-notifications",
560		Some("transaction-pool"),
561		sc_transaction_pool::notification_future(
562			client.clone(),
563			transaction_pool.clone(),
564			config.transaction_pool.use_all_block_notifications(),
565		),
566	);
567
568	spawn_handle.spawn(
569		"on-transaction-imported",
570		Some("transaction-pool"),
571		propagate_transaction_notifications(
572			transaction_pool.clone(),
573			tx_handler_controller,
574			telemetry.clone(),
575		),
576	);
577
578	// Prometheus metrics.
579	let metrics_service =
580		if let Some(PrometheusConfig { port, registry }) = config.prometheus_config.clone() {
581			// Set static metrics.
582			let metrics = MetricsService::with_prometheus(
583				telemetry,
584				&registry,
585				config.role,
586				&config.network.node_name,
587				&config.impl_version,
588			)?;
589			spawn_handle.spawn(
590				"prometheus-endpoint",
591				None,
592				prometheus_endpoint::init_prometheus(port, registry).map(drop),
593			);
594
595			metrics
596		} else {
597			MetricsService::new(telemetry)
598		};
599
600	// Periodically updated metrics and telemetry updates.
601	spawn_handle.spawn(
602		"telemetry-periodic-send",
603		None,
604		metrics_service.run(
605			client.clone(),
606			transaction_pool.clone(),
607			network.clone(),
608			sync_service.clone(),
609		),
610	);
611
612	let rpc_id_provider = config.rpc.id_provider.take();
613
614	// jsonrpsee RPC
615	// RPC-V2 specific metrics need to be registered before the RPC server is started,
616	// since we might have two instances running (one for the in-memory RPC and one for the network
617	// RPC).
618	let rpc_v2_metrics = config
619		.prometheus_registry()
620		.map(|registry| sc_rpc_spec_v2::transaction::TransactionMetrics::new(registry))
621		.transpose()?;
622
623	// Create dedicated RPC runtime with limited blocking threads.
624	// This isolates RPC blocking operations from the rest of the node.
625	let rpc_runtime = sc_rpc_server::create_rpc_runtime(config.rpc.max_connections)
626		.map_err(|e| Error::Application(Box::new(e)))?;
627
628	// Create spawn handle for RPC tasks
629	let rpc_spawn_handle: Arc<dyn sp_core::traits::SpawnNamed> =
630		Arc::new(sc_rpc_server::RpcSpawnHandle::new(rpc_runtime.handle().clone()));
631
632	// Factory that creates RPC module
633	let gen_rpc_module = || {
634		gen_rpc_module(GenRpcModuleParams {
635			spawn_handle: rpc_spawn_handle.clone(),
636			client: client.clone(),
637			transaction_pool: transaction_pool.clone(),
638			keystore: keystore.clone(),
639			system_rpc_tx: system_rpc_tx.clone(),
640			impl_name: config.impl_name.clone(),
641			impl_version: config.impl_version.clone(),
642			chain_spec: config.chain_spec.as_ref(),
643			state_pruning: &config.state_pruning,
644			blocks_pruning: config.blocks_pruning,
645			backend: backend.clone(),
646			rpc_builder: &*rpc_builder,
647			metrics: rpc_v2_metrics.clone(),
648			sync_oracle: sync_service.clone(),
649			tracing_execute_block: execute_block.clone(),
650		})
651	};
652
653	// Generate the RPC module for the server
654	let rpc_api = gen_rpc_module()?;
655
656	let rpc_server_handle = start_rpc_servers(
657		&config.rpc,
658		config.prometheus_registry(),
659		&config.tokio_handle,
660		rpc_api,
661		rpc_runtime,
662		rpc_id_provider,
663	)?;
664
665	let listen_addrs = rpc_server_handle
666		.listen_addrs()
667		.into_iter()
668		.map(|socket_addr| {
669			let mut multiaddr: Multiaddr = socket_addr.ip().into();
670			multiaddr.push(Protocol::Tcp(socket_addr.port()));
671			multiaddr
672		})
673		.collect();
674
675	// In-memory RPC uses the same dedicated RPC runtime
676	let in_memory_rpc = {
677		let mut module = gen_rpc_module()?;
678		module.extensions_mut().insert(DenyUnsafe::No);
679		module
680	};
681
682	let in_memory_rpc_handle = RpcHandlers::new(Arc::new(in_memory_rpc), listen_addrs);
683
684	// Spawn informant task
685	spawn_handle.spawn(
686		"informant",
687		None,
688		sc_informant::build(client.clone(), network, sync_service.clone()),
689	);
690
691	task_manager.keep_alive((config.base_path, rpc_server_handle));
692
693	Ok(in_memory_rpc_handle)
694}
695
696/// Returns a future that forwards imported transactions to the transaction networking protocol.
697pub async fn propagate_transaction_notifications<Block, ExPool>(
698	transaction_pool: Arc<ExPool>,
699	tx_handler_controller: sc_network_transactions::TransactionsHandlerController<
700		<Block as BlockT>::Hash,
701	>,
702	telemetry: Option<TelemetryHandle>,
703) where
704	Block: BlockT,
705	ExPool: MaintainedTransactionPool<Block = Block, Hash = <Block as BlockT>::Hash>,
706{
707	const TELEMETRY_INTERVAL: Duration = Duration::from_secs(1);
708
709	// transaction notifications
710	let mut notifications = transaction_pool.import_notification_stream().fuse();
711	let mut timer = futures_timer::Delay::new(TELEMETRY_INTERVAL).fuse();
712	let mut tx_imported = false;
713
714	loop {
715		select! {
716			notification = notifications.next() => {
717				let Some(hash) = notification else { return };
718
719				tx_handler_controller.propagate_transaction(hash);
720
721				tx_imported = true;
722			},
723			_ = timer => {
724				timer = futures_timer::Delay::new(TELEMETRY_INTERVAL).fuse();
725
726				if !tx_imported {
727					continue;
728				}
729
730				tx_imported = false;
731				let status = transaction_pool.status();
732
733				telemetry!(
734					telemetry;
735					SUBSTRATE_INFO;
736					"txpool.import";
737					"ready" => status.ready,
738					"future" => status.future,
739				);
740			}
741		}
742	}
743}
744
745/// Initialize telemetry with provided configuration and return telemetry handle
746pub fn init_telemetry<Block, Client, Network>(
747	name: String,
748	implementation: String,
749	version: String,
750	chain: String,
751	authority: bool,
752	network: Network,
753	client: Arc<Client>,
754	telemetry: &mut Telemetry,
755	sysinfo: Option<sc_telemetry::SysInfo>,
756) -> sc_telemetry::Result<TelemetryHandle>
757where
758	Block: BlockT,
759	Client: BlockBackend<Block>,
760	Network: NetworkStateInfo,
761{
762	let genesis_hash = client.block_hash(Zero::zero()).ok().flatten().unwrap_or_default();
763	let connection_message = ConnectionMessage {
764		name,
765		implementation,
766		version,
767		target_os: sc_sysinfo::TARGET_OS.into(),
768		target_arch: sc_sysinfo::TARGET_ARCH.into(),
769		target_env: sc_sysinfo::TARGET_ENV.into(),
770		config: String::new(),
771		chain,
772		genesis_hash: format!("{:?}", genesis_hash),
773		authority,
774		startup_time: SystemTime::UNIX_EPOCH
775			.elapsed()
776			.map(|dur| dur.as_millis())
777			.unwrap_or(0)
778			.to_string(),
779		network_id: network.local_peer_id().to_base58(),
780		sysinfo,
781	};
782
783	telemetry.start_telemetry(connection_message)?;
784
785	Ok(telemetry.handle())
786}
787
788/// Parameters for [`gen_rpc_module`].
789pub struct GenRpcModuleParams<'a, TBl: BlockT, TBackend, TCl, TRpc, TExPool> {
790	/// The handle to spawn tasks on the RPC runtime.
791	pub spawn_handle: Arc<dyn sp_core::traits::SpawnNamed>,
792	/// Access to the client.
793	pub client: Arc<TCl>,
794	/// The transaction pool.
795	pub transaction_pool: Arc<TExPool>,
796	/// Keystore handle.
797	pub keystore: KeystorePtr,
798	/// Sender for system requests.
799	pub system_rpc_tx: TracingUnboundedSender<sc_rpc::system::Request<TBl>>,
800	/// Implementation name of this node.
801	pub impl_name: String,
802	/// Implementation version of this node.
803	pub impl_version: String,
804	/// The chain spec.
805	pub chain_spec: &'a dyn ChainSpec,
806	/// Enabled pruning mode for this node.
807	pub state_pruning: &'a Option<PruningMode>,
808	/// Enabled blocks pruning mode.
809	pub blocks_pruning: BlocksPruning,
810	/// Backend of the node.
811	pub backend: Arc<TBackend>,
812	/// RPC builder.
813	pub rpc_builder: &'a dyn Fn(SubscriptionTaskExecutor) -> Result<RpcModule<TRpc>, Error>,
814	/// Transaction metrics handle.
815	pub metrics: Option<sc_rpc_spec_v2::transaction::TransactionMetrics>,
816	/// Sync oracle for determining sync status.
817	pub sync_oracle: Arc<dyn sp_consensus::SyncOracle + Send + Sync>,
818	/// Optional [`TracingExecuteBlock`] handle.
819	///
820	/// Will be used by the `trace_block` RPC to execute the actual block.
821	pub tracing_execute_block: Option<Arc<dyn TracingExecuteBlock<TBl>>>,
822}
823
824/// Generate RPC module using provided configuration
825pub fn gen_rpc_module<TBl, TBackend, TCl, TRpc, TExPool>(
826	GenRpcModuleParams {
827		spawn_handle,
828		client,
829		transaction_pool,
830		keystore,
831		system_rpc_tx,
832		impl_name,
833		impl_version,
834		chain_spec,
835		state_pruning,
836		blocks_pruning,
837		backend,
838		rpc_builder,
839		metrics,
840		sync_oracle,
841		tracing_execute_block: execute_block,
842	}: GenRpcModuleParams<TBl, TBackend, TCl, TRpc, TExPool>,
843) -> Result<RpcModule<()>, Error>
844where
845	TBl: BlockT,
846	TCl: ProvideRuntimeApi<TBl>
847		+ BlockchainEvents<TBl>
848		+ HeaderBackend<TBl>
849		+ HeaderMetadata<TBl, Error = sp_blockchain::Error>
850		+ ExecutorProvider<TBl>
851		+ CallApiAt<TBl>
852		+ ProofProvider<TBl>
853		+ StorageProvider<TBl, TBackend>
854		+ BlockBackend<TBl>
855		+ Send
856		+ Sync
857		+ 'static,
858	TBackend: sc_client_api::backend::Backend<TBl> + 'static,
859	<TCl as ProvideRuntimeApi<TBl>>::Api: sp_session::SessionKeys<TBl> + sp_api::Metadata<TBl>,
860	TExPool: MaintainedTransactionPool<Block = TBl, Hash = <TBl as BlockT>::Hash> + 'static,
861	TBl::Hash: Unpin,
862	TBl::Header: Unpin,
863{
864	let system_info = sc_rpc::system::SystemInfo {
865		chain_name: chain_spec.name().into(),
866		impl_name,
867		impl_version,
868		properties: chain_spec.properties(),
869		chain_type: chain_spec.chain_type(),
870	};
871
872	let mut rpc_api = RpcModule::new(());
873	let task_executor = spawn_handle;
874
875	let (chain, state, child_state) = {
876		let chain = sc_rpc::chain::new_full(client.clone(), task_executor.clone()).into_rpc();
877		let (state, child_state) =
878			sc_rpc::state::new_full(client.clone(), task_executor.clone(), execute_block);
879		let state = state.into_rpc();
880		let child_state = child_state.into_rpc();
881
882		(chain, state, child_state)
883	};
884
885	const MAX_TRANSACTION_PER_CONNECTION: usize = 16;
886
887	let transaction_broadcast_rpc_v2 = sc_rpc_spec_v2::transaction::TransactionBroadcast::new(
888		client.clone(),
889		transaction_pool.clone(),
890		task_executor.clone(),
891		MAX_TRANSACTION_PER_CONNECTION,
892	)
893	.into_rpc();
894
895	let transaction_v2 = sc_rpc_spec_v2::transaction::Transaction::new(
896		client.clone(),
897		transaction_pool.clone(),
898		task_executor.clone(),
899		metrics,
900	)
901	.into_rpc();
902
903	let chain_head_v2 = sc_rpc_spec_v2::chain_head::ChainHead::new(
904		client.clone(),
905		backend.clone(),
906		task_executor.clone(),
907		// Defaults to sensible limits for the `ChainHead`.
908		sc_rpc_spec_v2::chain_head::ChainHeadConfig::default(),
909	)
910	.into_rpc();
911
912	// Part of the RPC v2 spec.
913	// An archive node that can respond to the `archive` RPC-v2 queries is a node with:
914	// - state pruning in archive mode: The storage of blocks is kept around
915	// - block pruning in archive mode: The block's body is kept around
916	let is_archive_node = state_pruning.as_ref().map(|sp| sp.is_archive()).unwrap_or(false) &&
917		blocks_pruning.is_archive();
918	let genesis_hash = client.hash(Zero::zero()).ok().flatten().expect("Genesis block exists; qed");
919	if is_archive_node {
920		let archive_v2 = sc_rpc_spec_v2::archive::Archive::new(
921			client.clone(),
922			backend.clone(),
923			genesis_hash,
924			task_executor.clone(),
925		)
926		.into_rpc();
927		rpc_api.merge(archive_v2).map_err(|e| Error::Application(e.into()))?;
928	}
929
930	// ChainSpec RPC-v2.
931	let chain_spec_v2 = sc_rpc_spec_v2::chain_spec::ChainSpec::new(
932		chain_spec.name().into(),
933		genesis_hash,
934		chain_spec.properties(),
935	)
936	.into_rpc();
937
938	// Bitswap RPC-v2 (do not confuse with v1 from `bitswap_v1_get`).
939	let bitswap_v2 = sc_rpc_spec_v2::bitswap::Bitswap::new(client.clone(), sync_oracle).into_rpc();
940
941	let author = sc_rpc::author::Author::new(
942		client.clone(),
943		transaction_pool,
944		keystore,
945		task_executor.clone(),
946	)
947	.into_rpc();
948
949	let system = sc_rpc::system::System::new(system_info, system_rpc_tx).into_rpc();
950
951	if let Some(storage) = backend.offchain_storage() {
952		let offchain = sc_rpc::offchain::Offchain::new(storage).into_rpc();
953
954		rpc_api.merge(offchain).map_err(|e| Error::Application(e.into()))?;
955	}
956
957	// Part of the RPC v2 spec.
958	rpc_api.merge(transaction_v2).map_err(|e| Error::Application(e.into()))?;
959	rpc_api
960		.merge(transaction_broadcast_rpc_v2)
961		.map_err(|e| Error::Application(e.into()))?;
962	rpc_api.merge(chain_head_v2).map_err(|e| Error::Application(e.into()))?;
963	rpc_api.merge(chain_spec_v2).map_err(|e| Error::Application(e.into()))?;
964	rpc_api.merge(bitswap_v2).map_err(|e| Error::Application(e.into()))?;
965
966	// Part of the old RPC spec.
967	rpc_api.merge(chain).map_err(|e| Error::Application(e.into()))?;
968	rpc_api.merge(author).map_err(|e| Error::Application(e.into()))?;
969	rpc_api.merge(system).map_err(|e| Error::Application(e.into()))?;
970	rpc_api.merge(state).map_err(|e| Error::Application(e.into()))?;
971	rpc_api.merge(child_state).map_err(|e| Error::Application(e.into()))?;
972	// Additional [`RpcModule`]s defined in the node to fit the specific blockchain
973	let extra_rpcs = rpc_builder(task_executor.clone())?;
974	rpc_api.merge(extra_rpcs).map_err(|e| Error::Application(e.into()))?;
975
976	Ok(rpc_api)
977}
978
979/// Parameters to pass into [`build_network`].
980pub struct BuildNetworkParams<'a, Block, Net, TxPool, IQ, Client>
981where
982	Block: BlockT,
983	Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
984{
985	/// The service configuration.
986	pub config: &'a Configuration,
987	/// Full network configuration.
988	pub net_config: FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
989	/// A shared client returned by `new_full_parts`.
990	pub client: Arc<Client>,
991	/// A shared transaction pool.
992	pub transaction_pool: Arc<TxPool>,
993	/// A handle for spawning tasks.
994	pub spawn_handle: SpawnTaskHandle,
995	/// A handle for spawning essential tasks.
996	pub spawn_essential_handle: SpawnEssentialTaskHandle,
997	/// An import queue.
998	pub import_queue: IQ,
999	/// A block announce validator builder.
1000	pub block_announce_validator_builder: Option<
1001		Box<dyn FnOnce(Arc<Client>) -> Box<dyn BlockAnnounceValidator<Block> + Send> + Send>,
1002	>,
1003	/// Optional warp sync config.
1004	pub warp_sync_config: Option<WarpSyncConfig<Block>>,
1005	/// User specified block relay params. If not specified, the default
1006	/// block request handler will be used.
1007	pub block_relay: Option<BlockRelayParams<Block, Net>>,
1008	/// Metrics.
1009	pub metrics: NotificationMetrics,
1010}
1011
1012/// Build the network service, the network status sinks and an RPC sender.
1013pub fn build_network<Block, Net, TxPool, IQ, Client>(
1014	params: BuildNetworkParams<Block, Net, TxPool, IQ, Client>,
1015) -> Result<
1016	(
1017		Arc<dyn sc_network::service::traits::NetworkService>,
1018		TracingUnboundedSender<sc_rpc::system::Request<Block>>,
1019		sc_network_transactions::TransactionsHandlerController<<Block as BlockT>::Hash>,
1020		Arc<SyncingService<Block>>,
1021	),
1022	Error,
1023>
1024where
1025	Block: BlockT,
1026	Client: ProvideRuntimeApi<Block>
1027		+ HeaderMetadata<Block, Error = sp_blockchain::Error>
1028		+ Chain<Block>
1029		+ BlockBackend<Block>
1030		+ BlockIdTo<Block, Error = sp_blockchain::Error>
1031		+ ProofProvider<Block>
1032		+ HeaderBackend<Block>
1033		+ BlockchainEvents<Block>
1034		+ 'static,
1035	TxPool: TransactionPool<Block = Block, Hash = <Block as BlockT>::Hash> + 'static,
1036	IQ: ImportQueue<Block> + 'static,
1037	Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1038{
1039	let BuildNetworkParams {
1040		config,
1041		mut net_config,
1042		client,
1043		transaction_pool,
1044		spawn_handle,
1045		spawn_essential_handle,
1046		import_queue,
1047		block_announce_validator_builder,
1048		warp_sync_config,
1049		block_relay,
1050		metrics,
1051	} = params;
1052
1053	let block_announce_validator = if let Some(f) = block_announce_validator_builder {
1054		f(client.clone())
1055	} else {
1056		Box::new(DefaultBlockAnnounceValidator)
1057	};
1058
1059	let network_service_provider = NetworkServiceProvider::new();
1060	let protocol_id = config.protocol_id();
1061	let fork_id = config.chain_spec.fork_id();
1062	let metrics_registry = config.prometheus_config.as_ref().map(|config| &config.registry);
1063
1064	let block_downloader = match block_relay {
1065		Some(params) => {
1066			let BlockRelayParams { mut server, downloader, request_response_config } = params;
1067
1068			net_config.add_request_response_protocol(request_response_config);
1069
1070			spawn_handle.spawn("block-request-handler", Some("networking"), async move {
1071				server.run().await;
1072			});
1073
1074			downloader
1075		},
1076		None => build_default_block_downloader(
1077			&protocol_id,
1078			fork_id,
1079			&mut net_config,
1080			network_service_provider.handle(),
1081			Arc::clone(&client),
1082			config.network.default_peers_set.in_peers as usize +
1083				config.network.default_peers_set.out_peers as usize,
1084			&spawn_handle,
1085		),
1086	};
1087
1088	let syncing_strategy = build_polkadot_syncing_strategy(
1089		protocol_id.clone(),
1090		fork_id,
1091		&mut net_config,
1092		warp_sync_config,
1093		block_downloader,
1094		client.clone(),
1095		&spawn_handle,
1096		metrics_registry,
1097		config.blocks_pruning.is_archive(),
1098	)?;
1099
1100	let (syncing_engine, sync_service, block_announce_config) = SyncingEngine::new(
1101		Roles::from(&config.role),
1102		Arc::clone(&client),
1103		metrics_registry,
1104		metrics.clone(),
1105		&net_config,
1106		protocol_id.clone(),
1107		fork_id,
1108		block_announce_validator,
1109		syncing_strategy,
1110		network_service_provider.handle(),
1111		import_queue.service(),
1112		net_config.peer_store_handle(),
1113	)?;
1114
1115	spawn_handle.spawn_blocking("syncing", None, syncing_engine.run());
1116
1117	build_network_advanced(BuildNetworkAdvancedParams {
1118		role: config.role,
1119		protocol_id,
1120		fork_id,
1121		announce_block: config.announce_block,
1122		net_config,
1123		client,
1124		transaction_pool,
1125		spawn_handle,
1126		spawn_essential_handle,
1127		import_queue,
1128		sync_service,
1129		block_announce_config,
1130		network_service_provider,
1131		metrics_registry,
1132		metrics,
1133		blocks_pruning: config.blocks_pruning,
1134	})
1135}
1136
1137/// Parameters to pass into [`build_network_advanced`].
1138pub struct BuildNetworkAdvancedParams<'a, Block, Net, TxPool, IQ, Client>
1139where
1140	Block: BlockT,
1141	Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1142{
1143	/// Role of the local node.
1144	pub role: Role,
1145	/// Protocol name prefix.
1146	pub protocol_id: ProtocolId,
1147	/// Fork ID.
1148	pub fork_id: Option<&'a str>,
1149	/// Announce block automatically after they have been imported.
1150	pub announce_block: bool,
1151	/// Full network configuration.
1152	pub net_config: FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1153	/// A shared client returned by `new_full_parts`.
1154	pub client: Arc<Client>,
1155	/// A shared transaction pool.
1156	pub transaction_pool: Arc<TxPool>,
1157	/// A handle for spawning tasks.
1158	pub spawn_handle: SpawnTaskHandle,
1159	/// A handle for spawning essential tasks.
1160	pub spawn_essential_handle: SpawnEssentialTaskHandle,
1161	/// An import queue.
1162	pub import_queue: IQ,
1163	/// Syncing service to communicate with syncing engine.
1164	pub sync_service: SyncingService<Block>,
1165	/// Block announce config.
1166	pub block_announce_config: Net::NotificationProtocolConfig,
1167	/// Network service provider to drive with network internally.
1168	pub network_service_provider: NetworkServiceProvider,
1169	/// Prometheus metrics registry.
1170	pub metrics_registry: Option<&'a Registry>,
1171	/// Metrics.
1172	pub metrics: NotificationMetrics,
1173	/// Block pruning configuration.
1174	pub blocks_pruning: BlocksPruning,
1175}
1176
1177/// Build the network service, the network status sinks and an RPC sender, this is a lower-level
1178/// version of [`build_network`] for those needing more control.
1179pub fn build_network_advanced<Block, Net, TxPool, IQ, Client>(
1180	params: BuildNetworkAdvancedParams<Block, Net, TxPool, IQ, Client>,
1181) -> Result<
1182	(
1183		Arc<dyn sc_network::service::traits::NetworkService>,
1184		TracingUnboundedSender<sc_rpc::system::Request<Block>>,
1185		sc_network_transactions::TransactionsHandlerController<<Block as BlockT>::Hash>,
1186		Arc<SyncingService<Block>>,
1187	),
1188	Error,
1189>
1190where
1191	Block: BlockT,
1192	Client: ProvideRuntimeApi<Block>
1193		+ HeaderMetadata<Block, Error = sp_blockchain::Error>
1194		+ Chain<Block>
1195		+ BlockBackend<Block>
1196		+ BlockIdTo<Block, Error = sp_blockchain::Error>
1197		+ ProofProvider<Block>
1198		+ HeaderBackend<Block>
1199		+ BlockchainEvents<Block>
1200		+ 'static,
1201	TxPool: TransactionPool<Block = Block, Hash = <Block as BlockT>::Hash> + 'static,
1202	IQ: ImportQueue<Block> + 'static,
1203	Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1204{
1205	let BuildNetworkAdvancedParams {
1206		role,
1207		protocol_id,
1208		fork_id,
1209		announce_block,
1210		mut net_config,
1211		client,
1212		transaction_pool,
1213		spawn_handle,
1214		spawn_essential_handle,
1215		import_queue,
1216		sync_service,
1217		block_announce_config,
1218		network_service_provider,
1219		metrics_registry,
1220		metrics,
1221		blocks_pruning,
1222	} = params;
1223
1224	let genesis_hash = client.info().genesis_hash;
1225
1226	let light_client_request_protocol_config = {
1227		// Allow both outgoing and incoming requests.
1228		let (handler, protocol_config) =
1229			LightClientRequestHandler::new::<Net>(&protocol_id, fork_id, client.clone());
1230		spawn_handle.spawn("light-client-request-handler", Some("networking"), handler.run());
1231		protocol_config
1232	};
1233
1234	// install request handlers to `FullNetworkConfiguration`
1235	net_config.add_request_response_protocol(light_client_request_protocol_config);
1236
1237	// Initialize IPFS server.
1238	let ipfs_config = net_config.network_config.ipfs_server.then(|| {
1239		let (handler, bitswap_config) =
1240			Net::bitswap_server(client.clone(), metrics_registry.cloned());
1241		spawn_handle.spawn("bitswap-request-handler", Some("networking"), handler);
1242
1243		let ipfs_num_blocks = match blocks_pruning {
1244			BlocksPruning::KeepAll | BlocksPruning::KeepFinalized => IPFS_MAX_BLOCKS,
1245			BlocksPruning::Some(num) => std::cmp::min(num, IPFS_MAX_BLOCKS),
1246		};
1247
1248		IpfsConfig {
1249			bitswap_config,
1250			block_provider: Box::new(IpfsIndexedTransactions::new(client.clone(), ipfs_num_blocks)),
1251			bootnodes: net_config.network_config.ipfs_bootnodes.clone(),
1252		}
1253	});
1254
1255	// Create transactions protocol and add it to the list of supported protocols of
1256	let (transactions_handler_proto, transactions_config) =
1257		sc_network_transactions::TransactionsHandlerPrototype::new::<_, Block, Net>(
1258			protocol_id.clone(),
1259			genesis_hash,
1260			fork_id,
1261			metrics.clone(),
1262			net_config.peer_store_handle(),
1263		);
1264	net_config.add_notification_protocol(transactions_config);
1265
1266	// Start task for `PeerStore`
1267	let peer_store = net_config.take_peer_store();
1268	spawn_handle.spawn("peer-store", Some("networking"), peer_store.run());
1269
1270	let sync_service = Arc::new(sync_service);
1271
1272	let network_params = sc_network::config::Params::<Block, <Block as BlockT>::Hash, Net> {
1273		role,
1274		executor: {
1275			let spawn_handle = Clone::clone(&spawn_handle);
1276			Box::new(move |fut| {
1277				spawn_handle.spawn("libp2p-node", Some("networking"), fut);
1278			})
1279		},
1280		network_config: net_config,
1281		genesis_hash,
1282		protocol_id,
1283		fork_id: fork_id.map(ToOwned::to_owned),
1284		metrics_registry: metrics_registry.cloned(),
1285		block_announce_config,
1286		ipfs_config,
1287		notification_metrics: metrics,
1288	};
1289
1290	let has_bootnodes = !network_params.network_config.network_config.boot_nodes.is_empty();
1291	let network_mut = Net::new(network_params)?;
1292	let network = network_mut.network_service().clone();
1293
1294	let (tx_handler, tx_handler_controller) = transactions_handler_proto.build(
1295		network.clone(),
1296		sync_service.clone(),
1297		Arc::new(TransactionPoolAdapter { pool: transaction_pool, client: client.clone() }),
1298		metrics_registry,
1299	)?;
1300	spawn_handle.spawn_blocking(
1301		"network-transactions-handler",
1302		Some("networking"),
1303		tx_handler.run(),
1304	);
1305
1306	spawn_handle.spawn_blocking(
1307		"chain-sync-network-service-provider",
1308		Some("networking"),
1309		network_service_provider.run(Arc::new(network.clone())),
1310	);
1311	spawn_handle.spawn("import-queue", None, {
1312		let sync_service = sync_service.clone();
1313
1314		async move { import_queue.run(sync_service.as_ref()).await }
1315	});
1316
1317	let (system_rpc_tx, system_rpc_rx) = tracing_unbounded("mpsc_system_rpc", 10_000);
1318	spawn_handle.spawn(
1319		"system-rpc-handler",
1320		Some("networking"),
1321		build_system_rpc_future::<_, _, <Block as BlockT>::Hash>(
1322			role,
1323			network_mut.network_service(),
1324			sync_service.clone(),
1325			client.clone(),
1326			system_rpc_rx,
1327			has_bootnodes,
1328		),
1329	);
1330
1331	let future = build_network_future::<_, _, <Block as BlockT>::Hash, _>(
1332		network_mut,
1333		client,
1334		sync_service.clone(),
1335		announce_block,
1336	);
1337
1338	// The network worker is responsible for gathering all network messages and processing
1339	// them. This is quite a heavy task, and at the time of the writing of this comment it
1340	// frequently happens that this future takes several seconds or in some situations
1341	// even more than a minute until it has processed its entire queue. This is clearly an
1342	// issue, and ideally we would like to fix the network future to take as little time as
1343	// possible, but we also take the extra harm-prevention measure to execute the networking
1344	// future using `spawn_blocking`.
1345	//
1346	// The network worker is spawned as an essential task, meaning if it exits unexpectedly
1347	// the service will shut down.
1348	spawn_essential_handle.spawn_blocking("network-worker", Some("networking"), future);
1349
1350	Ok((network, system_rpc_tx, tx_handler_controller, sync_service.clone()))
1351}
1352
1353/// Configuration for [`build_default_syncing_engine`].
1354pub struct DefaultSyncingEngineConfig<'a, Block, Client, Net>
1355where
1356	Block: BlockT,
1357	Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1358{
1359	/// Role of the local node.
1360	pub role: Role,
1361	/// Protocol name prefix.
1362	pub protocol_id: ProtocolId,
1363	/// Fork ID.
1364	pub fork_id: Option<&'a str>,
1365	/// Full network configuration.
1366	pub net_config: &'a mut FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1367	/// Validator for incoming block announcements.
1368	pub block_announce_validator: Box<dyn BlockAnnounceValidator<Block> + Send>,
1369	/// Handle to communicate with `NetworkService`.
1370	pub network_service_handle: NetworkServiceHandle,
1371	/// Warp sync configuration (when used).
1372	pub warp_sync_config: Option<WarpSyncConfig<Block>>,
1373	/// A shared client returned by `new_full_parts`.
1374	pub client: Arc<Client>,
1375	/// Blocks import queue API.
1376	pub import_queue_service: Box<dyn ImportQueueService<Block>>,
1377	/// Expected max total number of peer connections (in + out).
1378	pub num_peers_hint: usize,
1379	/// A handle for spawning tasks.
1380	pub spawn_handle: &'a SpawnTaskHandle,
1381	/// Prometheus metrics registry.
1382	pub metrics_registry: Option<&'a Registry>,
1383	/// Metrics.
1384	pub metrics: NotificationMetrics,
1385	/// Whether to archive blocks. When `true`, gap sync requests bodies to maintain complete
1386	/// block history.
1387	pub archive_blocks: bool,
1388}
1389
1390/// Build default syncing engine using [`build_default_block_downloader`] and
1391/// [`build_polkadot_syncing_strategy`] internally.
1392pub fn build_default_syncing_engine<Block, Client, Net>(
1393	config: DefaultSyncingEngineConfig<Block, Client, Net>,
1394) -> Result<(SyncingService<Block>, Net::NotificationProtocolConfig), Error>
1395where
1396	Block: BlockT,
1397	Client: HeaderBackend<Block>
1398		+ BlockBackend<Block>
1399		+ HeaderMetadata<Block, Error = sp_blockchain::Error>
1400		+ ProofProvider<Block>
1401		+ Send
1402		+ Sync
1403		+ 'static,
1404	Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1405{
1406	let DefaultSyncingEngineConfig {
1407		role,
1408		protocol_id,
1409		fork_id,
1410		net_config,
1411		block_announce_validator,
1412		network_service_handle,
1413		warp_sync_config,
1414		client,
1415		import_queue_service,
1416		num_peers_hint,
1417		spawn_handle,
1418		metrics_registry,
1419		metrics,
1420		archive_blocks,
1421	} = config;
1422
1423	let block_downloader = build_default_block_downloader(
1424		&protocol_id,
1425		fork_id,
1426		net_config,
1427		network_service_handle.clone(),
1428		client.clone(),
1429		num_peers_hint,
1430		spawn_handle,
1431	);
1432	let syncing_strategy = build_polkadot_syncing_strategy(
1433		protocol_id.clone(),
1434		fork_id,
1435		net_config,
1436		warp_sync_config,
1437		block_downloader,
1438		client.clone(),
1439		spawn_handle,
1440		metrics_registry,
1441		archive_blocks,
1442	)?;
1443
1444	let (syncing_engine, sync_service, block_announce_config) = SyncingEngine::new(
1445		Roles::from(&role),
1446		client,
1447		metrics_registry,
1448		metrics,
1449		&net_config,
1450		protocol_id,
1451		fork_id,
1452		block_announce_validator,
1453		syncing_strategy,
1454		network_service_handle,
1455		import_queue_service,
1456		net_config.peer_store_handle(),
1457	)?;
1458
1459	spawn_handle.spawn_blocking("syncing", None, syncing_engine.run());
1460
1461	Ok((sync_service, block_announce_config))
1462}
1463
1464/// Build default block downloader
1465pub fn build_default_block_downloader<Block, Client, Net>(
1466	protocol_id: &ProtocolId,
1467	fork_id: Option<&str>,
1468	net_config: &mut FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1469	network_service_handle: NetworkServiceHandle,
1470	client: Arc<Client>,
1471	num_peers_hint: usize,
1472	spawn_handle: &SpawnTaskHandle,
1473) -> Arc<dyn BlockDownloader<Block>>
1474where
1475	Block: BlockT,
1476	Client: HeaderBackend<Block> + BlockBackend<Block> + Send + Sync + 'static,
1477	Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1478{
1479	// Custom protocol was not specified, use the default block handler.
1480	// Allow both outgoing and incoming requests.
1481	let BlockRelayParams { mut server, downloader, request_response_config } =
1482		BlockRequestHandler::new::<Net>(
1483			network_service_handle,
1484			&protocol_id,
1485			fork_id,
1486			client.clone(),
1487			num_peers_hint,
1488		);
1489
1490	spawn_handle.spawn("block-request-handler", Some("networking"), async move {
1491		server.run().await;
1492	});
1493
1494	net_config.add_request_response_protocol(request_response_config);
1495
1496	downloader
1497}
1498
1499/// Build standard polkadot syncing strategy
1500pub fn build_polkadot_syncing_strategy<Block, Client, Net>(
1501	protocol_id: ProtocolId,
1502	fork_id: Option<&str>,
1503	net_config: &mut FullNetworkConfiguration<Block, <Block as BlockT>::Hash, Net>,
1504	warp_sync_config: Option<WarpSyncConfig<Block>>,
1505	block_downloader: Arc<dyn BlockDownloader<Block>>,
1506	client: Arc<Client>,
1507	spawn_handle: &SpawnTaskHandle,
1508	metrics_registry: Option<&Registry>,
1509	archive_blocks: bool,
1510) -> Result<Box<dyn SyncingStrategy<Block>>, Error>
1511where
1512	Block: BlockT,
1513	Client: HeaderBackend<Block>
1514		+ BlockBackend<Block>
1515		+ HeaderMetadata<Block, Error = sp_blockchain::Error>
1516		+ ProofProvider<Block>
1517		+ Send
1518		+ Sync
1519		+ 'static,
1520	Net: NetworkBackend<Block, <Block as BlockT>::Hash>,
1521{
1522	if warp_sync_config.is_none() && net_config.network_config.sync_mode.is_warp() {
1523		return Err("Warp sync enabled, but no warp sync provider configured.".into());
1524	}
1525
1526	if client.requires_full_sync() {
1527		match net_config.network_config.sync_mode {
1528			SyncMode::LightState { .. } => {
1529				return Err("Fast sync doesn't work for archive nodes".into())
1530			},
1531			SyncMode::Warp => return Err("Warp sync doesn't work for archive nodes".into()),
1532			SyncMode::Full => {},
1533		}
1534	}
1535
1536	let genesis_hash = client.info().genesis_hash;
1537
1538	let (state_request_protocol_config, state_request_protocol_name) = {
1539		let num_peer_hint = net_config.network_config.default_peers_set_num_full as usize +
1540			net_config.network_config.default_peers_set.reserved_nodes.len();
1541		// Allow both outgoing and incoming requests.
1542		let (handler, protocol_config) =
1543			StateRequestHandler::new::<Net>(&protocol_id, fork_id, client.clone(), num_peer_hint);
1544		let config_name = protocol_config.protocol_name().clone();
1545
1546		spawn_handle.spawn("state-request-handler", Some("networking"), handler.run());
1547		(protocol_config, config_name)
1548	};
1549	net_config.add_request_response_protocol(state_request_protocol_config);
1550
1551	let (warp_sync_protocol_config, warp_sync_protocol_name) = match warp_sync_config.as_ref() {
1552		Some(WarpSyncConfig::WithProvider(warp_with_provider)) => {
1553			// Allow both outgoing and incoming requests.
1554			let (handler, protocol_config) = WarpSyncRequestHandler::new::<_, Net>(
1555				protocol_id,
1556				genesis_hash,
1557				fork_id,
1558				warp_with_provider.clone(),
1559			);
1560			let config_name = protocol_config.protocol_name().clone();
1561
1562			spawn_handle.spawn("warp-sync-request-handler", Some("networking"), handler.run());
1563			(Some(protocol_config), Some(config_name))
1564		},
1565		_ => (None, None),
1566	};
1567	if let Some(config) = warp_sync_protocol_config {
1568		net_config.add_request_response_protocol(config);
1569	}
1570
1571	let syncing_config = PolkadotSyncingStrategyConfig {
1572		mode: net_config.network_config.sync_mode,
1573		max_parallel_downloads: net_config.network_config.max_parallel_downloads,
1574		max_blocks_per_request: net_config.network_config.max_blocks_per_request,
1575		min_peers_to_start_warp_sync: net_config.network_config.min_peers_to_start_warp_sync,
1576		metrics_registry: metrics_registry.cloned(),
1577		state_request_protocol_name,
1578		block_downloader,
1579		archive_blocks,
1580	};
1581	Ok(Box::new(PolkadotSyncingStrategy::new(
1582		syncing_config,
1583		client,
1584		warp_sync_config,
1585		warp_sync_protocol_name,
1586	)?))
1587}