pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
	params: SpawnTasksParams<TBl, TCl, TExPool, TRpc, TBackend>,
) -> Result<RpcHandlers, Error>
	where
		TCl: ProvideRuntimeApi<TBl> + HeaderMetadata<TBl, Error=sp_blockchain::Error> + Chain<TBl> +
		BlockBackend<TBl> + BlockIdTo<TBl, Error=sp_blockchain::Error> + ProofProvider<TBl> +
		HeaderBackend<TBl> + BlockchainEvents<TBl> + ExecutorProvider<TBl> + UsageProvider<TBl> +
		StorageProvider<TBl, TBackend> + CallApiAt<TBl, Error=sp_blockchain::Error> +
		Send + 'static,
		<TCl as ProvideRuntimeApi<TBl>>::Api:
			sp_api::Metadata<TBl> +
			sc_offchain::OffchainWorkerApi<TBl> +
			sp_transaction_pool::runtime_api::TaggedTransactionQueue<TBl> +
			sp_session::SessionKeys<TBl> +
			sp_api::ApiErrorExt<Error = sp_blockchain::Error> +
			sp_api::ApiExt<TBl, StateBackend = TBackend::State>,
		TBl: BlockT,
		TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
		TExPool: MaintainedTransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash> +
			MallocSizeOfWasm + 'static,
		TRpc: sc_rpc::RpcExtension<sc_rpc::Metadata>
{
	let SpawnTasksParams {
		mut config,
		task_manager,
		client,
		on_demand,
		backend,
		keystore,
		transaction_pool,
		rpc_extensions_builder,
		remote_blockchain,
		network,
		network_status_sinks,
		system_rpc_tx,
		telemetry_connection_sinks,
	} = params;

	let chain_info = client.usage_info().chain;

	sp_session::generate_initial_session_keys(
		client.clone(),
		&BlockId::Hash(chain_info.best_hash),
		config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(),
	)?;

	info!("📦 Highest known block at #{}", chain_info.best_number);
	telemetry!(
		SUBSTRATE_INFO;
		"node.start";
		"height" => chain_info.best_number.saturated_into::<u64>(),
		"best" => ?chain_info.best_hash
	);

	let spawn_handle = task_manager.spawn_handle();

	// Inform the tx pool about imported and finalized blocks.
	spawn_handle.spawn(
		"txpool-notifications",
		sc_transaction_pool::notification_future(client.clone(), transaction_pool.clone()),
	);

	spawn_handle.spawn(
		"on-transaction-imported",
		transaction_notifications(transaction_pool.clone(), network.clone()),
	);

	// Prometheus metrics.
	let metrics_service = if let Some(PrometheusConfig { port, registry }) =
		config.prometheus_config.clone()
	{
		// Set static metrics.
		let metrics = MetricsService::with_prometheus(&registry, &config)?;
		spawn_handle.spawn(
			"prometheus-endpoint",
			prometheus_endpoint::init_prometheus(port, registry).map(drop)
		);

		metrics
	} else {
		MetricsService::new()
	};

	// Periodically updated metrics and telemetry updates.
	spawn_handle.spawn("telemetry-periodic-send",
		metrics_service.run(
			client.clone(),
			transaction_pool.clone(),
			network_status_sinks.clone()
		)
	);

	// RPC
	let gen_handler = |
		deny_unsafe: sc_rpc::DenyUnsafe,
		rpc_middleware: sc_rpc_server::RpcMiddleware
	| gen_handler(
		deny_unsafe, rpc_middleware, &config, task_manager.spawn_handle(),
		client.clone(), transaction_pool.clone(), keystore.clone(),
		on_demand.clone(), remote_blockchain.clone(), &*rpc_extensions_builder,
		backend.offchain_storage(), system_rpc_tx.clone()
	);
	let rpc_metrics = sc_rpc_server::RpcMetrics::new(config.prometheus_registry())?;
	let rpc = start_rpc_servers(&config, gen_handler, rpc_metrics.clone())?;
	// This is used internally, so don't restrict access to unsafe RPC
	let rpc_handlers = RpcHandlers(Arc::new(gen_handler(
		sc_rpc::DenyUnsafe::No,
		sc_rpc_server::RpcMiddleware::new(rpc_metrics, "inbrowser")
	).into()));

	// Telemetry
	let telemetry = config.telemetry_endpoints.clone().and_then(|endpoints| {
		if endpoints.is_empty() {
			// we don't want the telemetry to be initialized if telemetry_endpoints == Some([])
			return None;
		}

		let genesis_hash = match client.block_hash(Zero::zero()) {
			Ok(Some(hash)) => hash,
			_ => Default::default(),
		};

		Some(build_telemetry(
			&mut config, endpoints, telemetry_connection_sinks.clone(), network.clone(),
			task_manager.spawn_handle(), genesis_hash,
		))
	});

	// Spawn informant task
	spawn_handle.spawn("informant", sc_informant::build(
		client.clone(),
		network_status_sinks.status.clone(),
		transaction_pool.clone(),
		config.informant_output_format,
	));

	task_manager.keep_alive((telemetry, config.base_path, rpc, rpc_handlers.clone()));

	Ok(rpc_handlers)
}
/// Spawn the tasks that are required to run a node.
Spawn the tasks that are required to run a node.
Spawn the tasks that are required to run a node .
pub fn spawn_tasks<TBl, TBackend, TExPool, TRpc, TCl>(
	params: SpawnTasksParams<TBl, TCl, TExPool, TRpc, TBackend>,
) -> Result<RpcHandlers, Error>
	where
		TCl: ProvideRuntimeApi<TBl> + HeaderMetadata<TBl, Error=sp_blockchain::Error> + Chain<TBl> +
		BlockBackend<TBl> + BlockIdTo<TBl, Error=sp_blockchain::Error> + ProofProvider<TBl> +
		HeaderBackend<TBl> + BlockchainEvents<TBl> + ExecutorProvider<TBl> + UsageProvider<TBl> +
		StorageProvider<TBl, TBackend> + CallApiAt<TBl, Error=sp_blockchain::Error> +
		Send + 'static,
		<TCl as ProvideRuntimeApi<TBl>>::Api:
			sp_api::Metadata<TBl> +
			sc_offchain::OffchainWorkerApi<TBl> +
			sp_transaction_pool::runtime_api::TaggedTransactionQueue<TBl> +
			sp_session::SessionKeys<TBl> +
			sp_api::ApiErrorExt<Error = sp_blockchain::Error> +
			sp_api::ApiExt<TBl, StateBackend = TBackend::State>,
		TBl: BlockT,
		TBackend: 'static + sc_client_api::backend::Backend<TBl> + Send,
		TExPool: MaintainedTransactionPool<Block=TBl, Hash = <TBl as BlockT>::Hash> +
			MallocSizeOfWasm + 'static,
		TRpc: sc_rpc::RpcExtension<sc_rpc::Metadata>
{
	let SpawnTasksParams {
		mut config,
		task_manager,
		client,
		on_demand,
		backend,
		keystore,
		transaction_pool,
		rpc_extensions_builder,
		remote_blockchain,
		network,
		network_status_sinks,
		system_rpc_tx,
		telemetry_connection_sinks,
	} = params;
	let chain_info = client.usage_info().chain;
	sp_session::generate_initial_session_keys(
		client.clone(),
		&BlockId::Hash(chain_info.best_hash),
		config.dev_key_seed.clone().map(|s| vec![s]).unwrap_or_default(),
	)?;
	info!("📦 Highest known block at #{}", chain_info.best_number);
	telemetry!(
		SUBSTRATE_INFO;
		"node.start";
		"height" => chain_info.best_number.saturated_into::<u64>(),
		"best" => ?chain_info.best_hash
	);
	let spawn_handle = task_manager.spawn_handle();
	// Inform the tx pool about imported and finalized blocks.
	spawn_handle.spawn(
		"txpool-notifications",
		sc_transaction_pool::notification_future(client.clone(), transaction_pool.clone()),
	);
	spawn_handle.spawn(
		"on-transaction-imported",
		transaction_notifications(transaction_pool.clone(), network.clone()),
	);
	// Prometheus metrics.
	let metrics_service = if let Some(PrometheusConfig { port, registry }) =
		config.prometheus_config.clone()
	{
		// Set static metrics.
		let metrics = MetricsService::with_prometheus(&registry, &config)?;
		spawn_handle.spawn(
			"prometheus-endpoint",
			prometheus_endpoint::init_prometheus(port, registry).map(drop)
		);
		metrics
	} else {
		MetricsService::new()
	};
	// Periodically updated metrics and telemetry updates.
	spawn_handle.spawn("telemetry-periodic-send",
		metrics_service.run(
			client.clone(),
			transaction_pool.clone(),
			network_status_sinks.clone()
		)
	);
	// RPC
	let gen_handler = |
		deny_unsafe: sc_rpc::DenyUnsafe,
		rpc_middleware: sc_rpc_server::RpcMiddleware
	| gen_handler(
		deny_unsafe, rpc_middleware, &config, task_manager.spawn_handle(),
		client.clone(), transaction_pool.clone(), keystore.clone(),
		on_demand.clone(), remote_blockchain.clone(), &*rpc_extensions_builder,
		backend.offchain_storage(), system_rpc_tx.clone()
	);
	let rpc_metrics = sc_rpc_server::RpcMetrics::new(config.prometheus_registry())?;
	let rpc = start_rpc_servers(&config, gen_handler, rpc_metrics.clone())?;
	// This is used internally, so don't restrict access to unsafe RPC
	let rpc_handlers = RpcHandlers(Arc::new(gen_handler(
		sc_rpc::DenyUnsafe::No,
		sc_rpc_server::RpcMiddleware::new(rpc_metrics, "inbrowser")
	).into()));
	// Telemetry
	let telemetry = config.telemetry_endpoints.clone().and_then(|endpoints| {
		if endpoints.is_empty() {
			// we don't want the telemetry to be initialized if telemetry_endpoints == Some([])
			return None;
		}
		let genesis_hash = match client.block_hash(Zero::zero()) {
			Ok(Some(hash)) => hash,
			_ => Default::default(),
		};
		Some(build_telemetry(
			&mut config, endpoints, telemetry_connection_sinks.clone(), network.clone(),
			task_manager.spawn_handle(), genesis_hash,
		))
	});
	// Spawn informant task
	spawn_handle.spawn("informant", sc_informant::build(
		client.clone(),
		network_status_sinks.status.clone(),
		transaction_pool.clone(),
		config.informant_output_format,
	));
	task_manager.keep_alive((telemetry, config.base_path, rpc, rpc_handlers.clone()));
	Ok(rpc_handlers)
}
pub fn spawn_tasks < TBl , TBackend , TExPool , TRpc , TCl > ( params : SpawnTasksParams < TBl , TCl , TExPool , TRpc , TBackend > , ) -> Result < RpcHandlers , Error > where TCl : ProvideRuntimeApi < TBl > + HeaderMetadata < TBl , Error = sp_blockchain :: Error > + Chain < TBl > + BlockBackend < TBl > + BlockIdTo < TBl , Error = sp_blockchain :: Error > + ProofProvider < TBl > + HeaderBackend < TBl > + BlockchainEvents < TBl > + ExecutorProvider < TBl > + UsageProvider < TBl > + StorageProvider < TBl , TBackend > + CallApiAt < TBl , Error = sp_blockchain :: Error > + Send + ' static , < TCl as ProvideRuntimeApi < TBl > > :: Api : sp_api :: Metadata < TBl > + sc_offchain :: OffchainWorkerApi < TBl > + sp_transaction_pool :: runtime_api :: TaggedTransactionQueue < TBl > + sp_session :: SessionKeys < TBl > + sp_api :: ApiErrorExt < Error = sp_blockchain :: Error > + sp_api :: ApiExt < TBl , StateBackend = TBackend :: State > , TBl : BlockT , TBackend : ' static + sc_client_api :: backend :: Backend < TBl > + Send , TExPool : MaintainedTransactionPool < Block = TBl , Hash = < TBl as BlockT > :: Hash > + MallocSizeOfWasm + ' static , TRpc : sc_rpc :: RpcExtension < sc_rpc :: Metadata > { let SpawnTasksParams { mut config , task_manager , client , on_demand , backend , keystore , transaction_pool , rpc_extensions_builder , remote_blockchain , network , network_status_sinks , system_rpc_tx , telemetry_connection_sinks , } = params ; let chain_info = client . usage_info ( ) . chain ; sp_session :: generate_initial_session_keys ( client . clone ( ) , & BlockId :: Hash ( chain_info . best_hash ) , config . dev_key_seed . clone ( ) . map ( | s | vec ! [ s ] ) . unwrap_or_default ( ) , ) ? ; info ! ( " c in_info.be t_number); telemetry ! ( SUBSTRATE_INFO " " " " chain_info best_number saturated_into u64 ( ) " " chain_info best_hash ) ; let spawn_handle = task_manager . spawn_handle ( ) ; // Inform the tx pool about imported and finalized blocks. spawn_handle . spawn ( " " , sc_transaction_pool :: notification_future ( client . clone ( ) , transaction_pool . clone ( ) ) , ) ; spawn_handle . spawn ( " " , transaction_notifications ( transaction_pool . clone ( ) , network . clone ( ) ) , ) ; // Prometheus metrics. let metrics_service = if let Some ( PrometheusConfig { port , registry } ) = config . prometheus_config . clone ( ) { // Set static metrics. let metrics = MetricsService :: with_prometheus ( & registry , & config ) ? ; spawn_handle . spawn ( " " , prometheus_endpoint :: init_prometheus ( port , registry ) . map ( drop ) ) ; metrics } else { MetricsService :: new ( ) } ; // Periodically updated metrics and telemetry updates. spawn_handle . spawn ( " " , metrics_service . run ( client . clone ( ) , transaction_pool . clone ( ) , network_status_sinks . clone ( ) ) ) ; // RPC let gen_handler = | deny_unsafe : sc_rpc :: DenyUnsafe , rpc_middleware : sc_rpc_server :: RpcMiddleware | gen_handler ( deny_unsafe , rpc_middleware , & config , task_manager . spawn_handle ( ) , client . clone ( ) , transaction_pool . clone ( ) , keystore . clone ( ) , on_demand . clone ( ) , remote_blockchain . clone ( ) , & * rpc_extensions_builder , backend . offchain_storage ( ) , system_rpc_tx . clone ( ) ) ; let rpc_metrics = sc_rpc_server :: RpcMetrics :: new ( config . prometheus_registry ( ) ) ? ; let rpc = start_rpc_servers ( & config , gen_handler , rpc_metrics . clone ( ) ) ? ; // This is used internally, so don't restrict access to unsafe RPC let rpc_handlers = RpcHandlers ( Arc :: new ( gen_handler ( sc_rpc :: DenyUnsafe :: No , sc_rpc_server :: RpcMiddleware :: new ( rpc_metrics , " " ) ) . into ( ) ) ) ; // Telemetry let telemetry = config . telemetry_endpoints . clone ( ) . and_then ( | endpoints | { if endpoints . is_empty ( ) { // we don't want the telemetry to be initialized if telemetry_endpoints == Some([]) return None ; } let genesis_hash = match client . block_hash ( Zero :: zero ( ) ) { Ok ( Some ( hash ) ) => hash , _ => Default :: default ( ) , } ; Some ( build_telemetry ( & mut config , endpoints , telemetry_connection_sinks . clone ( ) , network . clone ( ) , task_manager . spawn_handle ( ) , genesis_hash , ) ) } ) ; // Spawn informant task spawn_handle . spawn ( " " , sc_informant :: build ( client . clone ( ) , network_status_sinks . status . clone ( ) , transaction_pool . clone ( ) , config . informant_output_format , ) ) ; task_manager . keep_alive ( ( telemetry , config . base_path , rpc , rpc_handlers . clone ( ) ) ) ; Ok ( rpc_handlers ) }
Spawn the tasks that are required to run a node.
Spawn the tasks that are required to run a node .
params
SpawnTasksParams<TBl, TCl, TExPool, TRpc, TBackend>
params
SpawnTasksParams<TBl, TCl, TExPool, TRpc, TBackend>