referrerpolicy=no-referrer-when-downgrade

sc_cli/
config.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
19//! Configuration trait for a CLI based on substrate
20
21use crate::{
22	arg_enums::Database, error::Result, DatabaseParams, ImportParams, KeystoreParams,
23	NetworkParams, NodeKeyParams, OffchainWorkerParams, PruningParams, RpcEndpoint, SharedParams,
24	SubstrateCli,
25};
26use log::warn;
27use names::{Generator, Name};
28use sc_service::{
29	config::{
30		BasePath, Configuration, DatabaseSource, ExecutorConfiguration, IpNetwork, KeystoreConfig,
31		NetworkConfiguration, NodeKeyConfig, OffchainWorkerConfig, PrometheusConfig, PruningMode,
32		Role, RpcBatchRequestConfig, RpcConfiguration, RpcMethods, TelemetryEndpoints,
33		TransactionPoolOptions, WasmExecutionMethod,
34	},
35	BlocksPruning, ChainSpec, TracingReceiver,
36};
37use sc_tracing::logging::LoggerBuilder;
38use std::{num::NonZeroU32, path::PathBuf};
39
40/// The maximum number of characters for a node name.
41pub(crate) const NODE_NAME_MAX_LENGTH: usize = 64;
42
43/// Default sub directory to store network config.
44pub(crate) const DEFAULT_NETWORK_CONFIG_PATH: &str = "network";
45
46/// The recommended open file descriptor limit to be configured for the process.
47const RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT: u64 = 10_000;
48
49/// The default port.
50pub const RPC_DEFAULT_PORT: u16 = 9944;
51/// The default max number of subscriptions per connection.
52pub const RPC_DEFAULT_MAX_SUBS_PER_CONN: u32 = 1024;
53/// The default max request size in MB.
54pub const RPC_DEFAULT_MAX_REQUEST_SIZE_MB: u32 = 15;
55/// The default max response size in MB.
56pub const RPC_DEFAULT_MAX_RESPONSE_SIZE_MB: u32 = 15;
57/// The default concurrent connection limit.
58pub const RPC_DEFAULT_MAX_CONNECTIONS: u32 = 100;
59/// The default number of messages the RPC server
60/// is allowed to keep in memory per connection.
61pub const RPC_DEFAULT_MESSAGE_CAPACITY_PER_CONN: u32 = 64;
62
63/// Default configuration values used by Substrate
64///
65/// These values will be used by [`CliConfiguration`] to set
66/// default values for e.g. the listen port or the RPC port.
67pub trait DefaultConfigurationValues {
68	/// The port Substrate should listen on for p2p connections.
69	///
70	/// By default this is `30333`.
71	fn p2p_listen_port() -> u16 {
72		30333
73	}
74
75	/// The port Substrate should listen on for JSON-RPC connections.
76	///
77	/// By default this is `9944`.
78	fn rpc_listen_port() -> u16 {
79		RPC_DEFAULT_PORT
80	}
81
82	/// The port Substrate should listen on for prometheus connections.
83	///
84	/// By default this is `9615`.
85	fn prometheus_listen_port() -> u16 {
86		9615
87	}
88}
89
90impl DefaultConfigurationValues for () {}
91
92/// A trait that allows converting an object to a Configuration
93pub trait CliConfiguration<DCV: DefaultConfigurationValues = ()>: Sized {
94	/// Get the SharedParams for this object
95	fn shared_params(&self) -> &SharedParams;
96
97	/// Get the ImportParams for this object
98	fn import_params(&self) -> Option<&ImportParams> {
99		None
100	}
101
102	/// Get the PruningParams for this object
103	fn pruning_params(&self) -> Option<&PruningParams> {
104		self.import_params().map(|x| &x.pruning_params)
105	}
106
107	/// Get the KeystoreParams for this object
108	fn keystore_params(&self) -> Option<&KeystoreParams> {
109		None
110	}
111
112	/// Get the NetworkParams for this object
113	fn network_params(&self) -> Option<&NetworkParams> {
114		None
115	}
116
117	/// Get a reference to `OffchainWorkerParams` for this object.
118	fn offchain_worker_params(&self) -> Option<&OffchainWorkerParams> {
119		None
120	}
121
122	/// Get the NodeKeyParams for this object
123	fn node_key_params(&self) -> Option<&NodeKeyParams> {
124		self.network_params().map(|x| &x.node_key_params)
125	}
126
127	/// Get the DatabaseParams for this object
128	fn database_params(&self) -> Option<&DatabaseParams> {
129		self.import_params().map(|x| &x.database_params)
130	}
131
132	/// Get the base path of the configuration (if any)
133	///
134	/// By default this is retrieved from `SharedParams`.
135	fn base_path(&self) -> Result<Option<BasePath>> {
136		self.shared_params().base_path()
137	}
138
139	/// Returns `true` if the node is for development or not
140	///
141	/// By default this is retrieved from `SharedParams`.
142	fn is_dev(&self) -> Result<bool> {
143		Ok(self.shared_params().is_dev())
144	}
145
146	/// Gets the role
147	///
148	/// By default this is `Role::Full`.
149	fn role(&self, _is_dev: bool) -> Result<Role> {
150		Ok(Role::Full)
151	}
152
153	/// Get the transaction pool options
154	///
155	/// By default this is `TransactionPoolOptions::default()`.
156	fn transaction_pool(&self, _is_dev: bool) -> Result<TransactionPoolOptions> {
157		Ok(Default::default())
158	}
159
160	/// Get the network configuration
161	///
162	/// By default this is retrieved from `NetworkParams` if it is available otherwise it creates
163	/// a default `NetworkConfiguration` based on `node_name`, `client_id`, `node_key` and
164	/// `net_config_dir`.
165	fn network_config(
166		&self,
167		chain_spec: &Box<dyn ChainSpec>,
168		is_dev: bool,
169		is_validator: bool,
170		net_config_dir: PathBuf,
171		client_id: &str,
172		node_name: &str,
173		node_key: NodeKeyConfig,
174		default_listen_port: u16,
175	) -> Result<NetworkConfiguration> {
176		let network_config = if let Some(network_params) = self.network_params() {
177			network_params.network_config(
178				chain_spec,
179				is_dev,
180				is_validator,
181				Some(net_config_dir),
182				client_id,
183				node_name,
184				node_key,
185				default_listen_port,
186			)
187		} else {
188			NetworkConfiguration::new(node_name, client_id, node_key, Some(net_config_dir))
189		};
190
191		// TODO: Return error here in the next release:
192		// https://github.com/paritytech/polkadot-sdk/issues/5266
193		// if is_validator && network_config.public_addresses.is_empty() {}
194
195		Ok(network_config)
196	}
197
198	/// Get the keystore configuration.
199	///
200	/// By default this is retrieved from `KeystoreParams` if it is available. Otherwise it uses
201	/// `KeystoreConfig::InMemory`.
202	fn keystore_config(&self, config_dir: &PathBuf) -> Result<KeystoreConfig> {
203		self.keystore_params()
204			.map(|x| x.keystore_config(config_dir))
205			.unwrap_or_else(|| Ok(KeystoreConfig::InMemory))
206	}
207
208	/// Get the database cache size.
209	///
210	/// By default this is retrieved from `DatabaseParams` if it is available. Otherwise its `None`.
211	fn database_cache_size(&self) -> Result<Option<usize>> {
212		Ok(self.database_params().map(|x| x.database_cache_size()).unwrap_or_default())
213	}
214
215	/// Get the database backend variant.
216	///
217	/// By default this is retrieved from `DatabaseParams` if it is available. Otherwise its `None`.
218	fn database(&self) -> Result<Option<Database>> {
219		Ok(self.database_params().and_then(|x| x.database()))
220	}
221
222	/// Get the database configuration object for the parameters provided
223	fn database_config(
224		&self,
225		base_path: &PathBuf,
226		cache_size: usize,
227		database: Database,
228	) -> Result<DatabaseSource> {
229		let role_dir = "full";
230		let rocksdb_path = base_path.join("db").join(role_dir);
231		let paritydb_path = base_path.join("paritydb").join(role_dir);
232		Ok(match database {
233			#[cfg(feature = "rocksdb")]
234			Database::RocksDb => DatabaseSource::RocksDb { path: rocksdb_path, cache_size },
235			Database::ParityDb => DatabaseSource::ParityDb { path: paritydb_path },
236			Database::ParityDbDeprecated => {
237				eprintln!(
238					"WARNING: \"paritydb-experimental\" database setting is deprecated and will be removed in future releases. \
239				Please update your setup to use the new value: \"paritydb\"."
240				);
241				DatabaseSource::ParityDb { path: paritydb_path }
242			},
243			Database::Auto => DatabaseSource::Auto { paritydb_path, rocksdb_path, cache_size },
244		})
245	}
246
247	/// Get the trie cache maximum size.
248	///
249	/// By default this is retrieved from `ImportParams` if it is available. Otherwise its `0`.
250	/// If `None` is returned the trie cache is disabled.
251	fn trie_cache_maximum_size(&self) -> Result<Option<usize>> {
252		Ok(self.import_params().map(|x| x.trie_cache_maximum_size()).unwrap_or_default())
253	}
254
255	/// Get if we should warm up the trie cache.
256	///
257	/// By default this is retrieved from `ImportParams` if it is available. Otherwise its `None`.
258	fn warm_up_trie_cache(&self) -> Result<Option<sc_service::config::TrieCacheWarmUpStrategy>> {
259		Ok(self
260			.import_params()
261			.map(|x| x.warm_up_trie_cache().map(|x| x.into()))
262			.unwrap_or_default())
263	}
264
265	/// Get the state pruning mode.
266	///
267	/// By default this is retrieved from `PruningMode` if it is available. Otherwise its
268	/// `PruningMode::default()`.
269	fn state_pruning(&self) -> Result<Option<PruningMode>> {
270		self.pruning_params()
271			.map(|x| x.state_pruning())
272			.unwrap_or_else(|| Ok(Default::default()))
273	}
274
275	/// Get the block pruning mode.
276	///
277	/// By default this is retrieved from `block_pruning` if it is available. Otherwise its
278	/// `BlocksPruning::KeepFinalized`.
279	fn blocks_pruning(&self) -> Result<BlocksPruning> {
280		self.pruning_params()
281			.map(|x| x.blocks_pruning())
282			.unwrap_or_else(|| Ok(BlocksPruning::KeepFinalized))
283	}
284
285	/// Get the chain ID (string).
286	///
287	/// By default this is retrieved from `SharedParams`.
288	fn chain_id(&self, is_dev: bool) -> Result<String> {
289		Ok(self.shared_params().chain_id(is_dev))
290	}
291
292	/// Get the name of the node.
293	///
294	/// By default a random name is generated.
295	fn node_name(&self) -> Result<String> {
296		Ok(generate_node_name())
297	}
298
299	/// Get the WASM execution method.
300	///
301	/// By default this is retrieved from `ImportParams` if it is available. Otherwise its
302	/// `WasmExecutionMethod::default()`.
303	fn wasm_method(&self) -> Result<WasmExecutionMethod> {
304		Ok(self.import_params().map(|x| x.wasm_method()).unwrap_or_default())
305	}
306
307	/// Get the path where WASM overrides live.
308	///
309	/// By default this is `None`.
310	fn wasm_runtime_overrides(&self) -> Option<PathBuf> {
311		self.import_params().map(|x| x.wasm_runtime_overrides()).unwrap_or_default()
312	}
313
314	/// Get the RPC address.
315	fn rpc_addr(&self, _default_listen_port: u16) -> Result<Option<Vec<RpcEndpoint>>> {
316		Ok(None)
317	}
318
319	/// Returns the RPC method set to expose.
320	///
321	/// By default this is `RpcMethods::Auto` (unsafe RPCs are denied iff
322	/// `rpc_external` returns true, respectively).
323	fn rpc_methods(&self) -> Result<RpcMethods> {
324		Ok(Default::default())
325	}
326
327	/// Get the maximum number of RPC server connections.
328	fn rpc_max_connections(&self) -> Result<u32> {
329		Ok(RPC_DEFAULT_MAX_CONNECTIONS)
330	}
331
332	/// Get the RPC cors (`None` if disabled)
333	///
334	/// By default this is `Some(Vec::new())`.
335	fn rpc_cors(&self, _is_dev: bool) -> Result<Option<Vec<String>>> {
336		Ok(Some(Vec::new()))
337	}
338
339	/// Get maximum RPC request payload size.
340	fn rpc_max_request_size(&self) -> Result<u32> {
341		Ok(RPC_DEFAULT_MAX_REQUEST_SIZE_MB)
342	}
343
344	/// Get maximum RPC response payload size.
345	fn rpc_max_response_size(&self) -> Result<u32> {
346		Ok(RPC_DEFAULT_MAX_RESPONSE_SIZE_MB)
347	}
348
349	/// Get maximum number of subscriptions per connection.
350	fn rpc_max_subscriptions_per_connection(&self) -> Result<u32> {
351		Ok(RPC_DEFAULT_MAX_SUBS_PER_CONN)
352	}
353
354	/// The number of messages the RPC server is allowed to keep in memory per connection.
355	fn rpc_buffer_capacity_per_connection(&self) -> Result<u32> {
356		Ok(RPC_DEFAULT_MESSAGE_CAPACITY_PER_CONN)
357	}
358
359	/// RPC server batch request configuration.
360	fn rpc_batch_config(&self) -> Result<RpcBatchRequestConfig> {
361		Ok(RpcBatchRequestConfig::Unlimited)
362	}
363
364	/// RPC rate limit configuration.
365	fn rpc_rate_limit(&self) -> Result<Option<NonZeroU32>> {
366		Ok(None)
367	}
368
369	/// RPC rate limit whitelisted ip addresses.
370	fn rpc_rate_limit_whitelisted_ips(&self) -> Result<Vec<IpNetwork>> {
371		Ok(vec![])
372	}
373
374	/// RPC rate limit trust proxy headers.
375	fn rpc_rate_limit_trust_proxy_headers(&self) -> Result<bool> {
376		Ok(false)
377	}
378
379	/// Get the prometheus configuration (`None` if disabled)
380	///
381	/// By default this is `None`.
382	fn prometheus_config(
383		&self,
384		_default_listen_port: u16,
385		_chain_spec: &Box<dyn ChainSpec>,
386	) -> Result<Option<PrometheusConfig>> {
387		Ok(None)
388	}
389
390	/// Get the telemetry endpoints (if any)
391	///
392	/// By default this is retrieved from the chain spec loaded by `load_spec`.
393	fn telemetry_endpoints(
394		&self,
395		chain_spec: &Box<dyn ChainSpec>,
396	) -> Result<Option<TelemetryEndpoints>> {
397		Ok(chain_spec.telemetry_endpoints().clone())
398	}
399
400	/// Get the default value for heap pages
401	///
402	/// By default this is `None`.
403	fn default_heap_pages(&self) -> Result<Option<u64>> {
404		Ok(None)
405	}
406
407	/// Returns an offchain worker config wrapped in `Ok(_)`
408	///
409	/// By default offchain workers are disabled.
410	fn offchain_worker(&self, role: &Role) -> Result<OffchainWorkerConfig> {
411		self.offchain_worker_params()
412			.map(|x| x.offchain_worker(role))
413			.unwrap_or_else(|| Ok(OffchainWorkerConfig::default()))
414	}
415
416	/// Returns `Ok(true)` if authoring should be forced
417	///
418	/// By default this is `false`.
419	fn force_authoring(&self) -> Result<bool> {
420		Ok(Default::default())
421	}
422
423	/// Returns `Ok(true)` if grandpa should be disabled
424	///
425	/// By default this is `false`.
426	fn disable_grandpa(&self) -> Result<bool> {
427		Ok(Default::default())
428	}
429
430	/// Get the development key seed from the current object
431	///
432	/// By default this is `None`.
433	fn dev_key_seed(&self, _is_dev: bool) -> Result<Option<String>> {
434		Ok(Default::default())
435	}
436
437	/// Get the tracing targets from the current object (if any)
438	///
439	/// By default this is retrieved from [`SharedParams`] if it is available. Otherwise its
440	/// `None`.
441	fn tracing_targets(&self) -> Result<Option<String>> {
442		Ok(self.shared_params().tracing_targets())
443	}
444
445	/// Get the TracingReceiver value from the current object
446	///
447	/// By default this is retrieved from [`SharedParams`] if it is available. Otherwise its
448	/// `TracingReceiver::default()`.
449	fn tracing_receiver(&self) -> Result<TracingReceiver> {
450		Ok(self.shared_params().tracing_receiver())
451	}
452
453	/// Get the node key from the current object
454	///
455	/// By default this is retrieved from `NodeKeyParams` if it is available. Otherwise its
456	/// `NodeKeyConfig::default()`.
457	fn node_key(&self, net_config_dir: &PathBuf) -> Result<NodeKeyConfig> {
458		let is_dev = self.is_dev()?;
459		let role = self.role(is_dev)?;
460		self.node_key_params()
461			.map(|x| x.node_key(net_config_dir, role, is_dev))
462			.unwrap_or_else(|| Ok(Default::default()))
463	}
464
465	/// Get maximum runtime instances
466	///
467	/// By default this is `None`.
468	fn max_runtime_instances(&self) -> Result<Option<usize>> {
469		Ok(Default::default())
470	}
471
472	/// Get maximum different runtimes in cache
473	///
474	/// By default this is `2`.
475	fn runtime_cache_size(&self) -> Result<u8> {
476		Ok(2)
477	}
478
479	/// Activate or not the automatic announcing of blocks after import
480	///
481	/// By default this is `false`.
482	fn announce_block(&self) -> Result<bool> {
483		Ok(true)
484	}
485
486	/// Create a Configuration object from the current object
487	fn create_configuration<C: SubstrateCli>(
488		&self,
489		cli: &C,
490		tokio_handle: tokio::runtime::Handle,
491	) -> Result<Configuration> {
492		let is_dev = self.is_dev()?;
493		let chain_id = self.chain_id(is_dev)?;
494		let chain_spec = cli.load_spec(&chain_id)?;
495		let base_path = base_path_or_default(self.base_path()?, &C::executable_name());
496		let config_dir = build_config_dir(&base_path, chain_spec.id());
497		let net_config_dir = build_net_config_dir(&config_dir);
498		let client_id = C::client_id();
499		let database_cache_size = self.database_cache_size()?.unwrap_or(1024);
500		let database = self.database()?.unwrap_or(
501			#[cfg(feature = "rocksdb")]
502			{
503				Database::RocksDb
504			},
505			#[cfg(not(feature = "rocksdb"))]
506			{
507				Database::ParityDb
508			},
509		);
510		let node_key = self.node_key(&net_config_dir)?;
511		let role = self.role(is_dev)?;
512		let max_runtime_instances = self.max_runtime_instances()?.unwrap_or(8);
513		let is_validator = role.is_authority();
514		let keystore = self.keystore_config(&config_dir)?;
515		let telemetry_endpoints = self.telemetry_endpoints(&chain_spec)?;
516		let runtime_cache_size = self.runtime_cache_size()?;
517
518		let rpc_addrs: Option<Vec<sc_service::config::RpcEndpoint>> = self
519			.rpc_addr(DCV::rpc_listen_port())?
520			.map(|addrs| addrs.into_iter().map(Into::into).collect());
521
522		Ok(Configuration {
523			impl_name: C::impl_name(),
524			impl_version: C::impl_version(),
525			tokio_handle,
526			transaction_pool: self.transaction_pool(is_dev)?,
527			network: self.network_config(
528				&chain_spec,
529				is_dev,
530				is_validator,
531				net_config_dir,
532				client_id.as_str(),
533				self.node_name()?.as_str(),
534				node_key,
535				DCV::p2p_listen_port(),
536			)?,
537			keystore,
538			database: self.database_config(&config_dir, database_cache_size, database)?,
539			data_path: config_dir,
540			trie_cache_maximum_size: self.trie_cache_maximum_size()?,
541			warm_up_trie_cache: self.warm_up_trie_cache()?,
542			state_pruning: self.state_pruning()?,
543			blocks_pruning: self.blocks_pruning()?,
544			executor: ExecutorConfiguration {
545				wasm_method: self.wasm_method()?,
546				default_heap_pages: self.default_heap_pages()?,
547				max_runtime_instances,
548				runtime_cache_size,
549			},
550			wasm_runtime_overrides: self.wasm_runtime_overrides(),
551			rpc: RpcConfiguration {
552				addr: rpc_addrs,
553				methods: self.rpc_methods()?,
554				max_connections: self.rpc_max_connections()?,
555				cors: self.rpc_cors(is_dev)?,
556				max_request_size: self.rpc_max_request_size()?,
557				max_response_size: self.rpc_max_response_size()?,
558				id_provider: None,
559				max_subs_per_conn: self.rpc_max_subscriptions_per_connection()?,
560				port: DCV::rpc_listen_port(),
561				message_buffer_capacity: self.rpc_buffer_capacity_per_connection()?,
562				batch_config: self.rpc_batch_config()?,
563				rate_limit: self.rpc_rate_limit()?,
564				rate_limit_whitelisted_ips: self.rpc_rate_limit_whitelisted_ips()?,
565				rate_limit_trust_proxy_headers: self.rpc_rate_limit_trust_proxy_headers()?,
566			},
567			prometheus_config: self
568				.prometheus_config(DCV::prometheus_listen_port(), &chain_spec)?,
569			telemetry_endpoints,
570			offchain_worker: self.offchain_worker(&role)?,
571			force_authoring: self.force_authoring()?,
572			disable_grandpa: self.disable_grandpa()?,
573			dev_key_seed: self.dev_key_seed(is_dev)?,
574			tracing_targets: self.tracing_targets()?,
575			tracing_receiver: self.tracing_receiver()?,
576			chain_spec,
577			announce_block: self.announce_block()?,
578			role,
579			base_path,
580		})
581	}
582
583	/// Get the filters for the logging.
584	///
585	/// This should be a list of comma-separated values.
586	/// Example: `foo=trace,bar=debug,baz=info`
587	///
588	/// By default this is retrieved from `SharedParams`.
589	fn log_filters(&self) -> Result<String> {
590		Ok(self.shared_params().log_filters().join(","))
591	}
592
593	/// Should the detailed log output be enabled.
594	fn detailed_log_output(&self) -> Result<bool> {
595		Ok(self.shared_params().detailed_log_output())
596	}
597
598	/// Is log reloading enabled?
599	fn enable_log_reloading(&self) -> Result<bool> {
600		Ok(self.shared_params().enable_log_reloading())
601	}
602
603	/// Should the log color output be disabled?
604	fn disable_log_color(&self) -> Result<bool> {
605		Ok(self.shared_params().disable_log_color())
606	}
607
608	/// Initialize substrate. This must be done only once per process.
609	///
610	/// This method:
611	///
612	/// 1. Sets the panic handler
613	/// 2. Optionally customize logger/profiling
614	/// 2. Initializes the logger
615	/// 3. Raises the FD limit
616	///
617	/// The `logger_hook` closure is executed before the logger is constructed
618	/// and initialized. It is useful for setting up a custom profiler.
619	///
620	/// Example:
621	/// ```
622	/// use sc_tracing::{SpanDatum, TraceEvent};
623	/// struct TestProfiler;
624	///
625	/// impl sc_tracing::TraceHandler for TestProfiler {
626	///  	fn handle_span(&self, sd: &SpanDatum) {}
627	/// 		fn handle_event(&self, _event: &TraceEvent) {}
628	/// };
629	///
630	/// fn logger_hook() -> impl FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration) -> () {
631	/// 	|logger_builder, config| {
632	/// 			logger_builder.with_custom_profiling(Box::new(TestProfiler{}));
633	/// 	}
634	/// }
635	/// ```
636	fn init<F>(&self, support_url: &String, impl_version: &String, logger_hook: F) -> Result<()>
637	where
638		F: FnOnce(&mut LoggerBuilder),
639	{
640		sp_panic_handler::set(support_url, impl_version);
641
642		let mut logger = LoggerBuilder::new(self.log_filters()?);
643		logger
644			.with_log_reloading(self.enable_log_reloading()?)
645			.with_detailed_output(self.detailed_log_output()?);
646
647		if let Some(tracing_targets) = self.tracing_targets()? {
648			let tracing_receiver = self.tracing_receiver()?;
649			logger.with_profiling(tracing_receiver, tracing_targets);
650		}
651
652		if self.disable_log_color()? {
653			logger.with_colors(false);
654		}
655
656		// Call hook for custom profiling setup.
657		logger_hook(&mut logger);
658
659		logger.init()?;
660
661		match fdlimit::raise_fd_limit() {
662			Ok(fdlimit::Outcome::LimitRaised { to, .. }) =>
663				if to < RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT {
664					warn!(
665						"Low open file descriptor limit configured for the process. \
666						Current value: {:?}, recommended value: {:?}.",
667						to, RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT,
668					);
669				},
670			Ok(fdlimit::Outcome::Unsupported) => {
671				// Unsupported platform (non-Linux)
672			},
673			Err(error) => {
674				warn!(
675					"Failed to configure file descriptor limit for the process: \
676					{}, recommended value: {:?}.",
677					error, RECOMMENDED_OPEN_FILE_DESCRIPTOR_LIMIT,
678				);
679			},
680		}
681
682		Ok(())
683	}
684}
685
686/// Generate a valid random name for the node
687pub fn generate_node_name() -> String {
688	loop {
689		let node_name = Generator::with_naming(Name::Numbered)
690			.next()
691			.expect("RNG is available on all supported platforms; qed");
692		let count = node_name.chars().count();
693
694		if count < NODE_NAME_MAX_LENGTH {
695			return node_name
696		}
697	}
698}
699
700/// Returns the value of `base_path` or the default_path if it is None
701pub(crate) fn base_path_or_default(
702	base_path: Option<BasePath>,
703	executable_name: &String,
704) -> BasePath {
705	base_path.unwrap_or_else(|| BasePath::from_project("", "", executable_name))
706}
707
708/// Returns the default path for configuration  directory based on the chain_spec
709pub(crate) fn build_config_dir(base_path: &BasePath, chain_spec_id: &str) -> PathBuf {
710	base_path.config_dir(chain_spec_id)
711}
712
713/// Returns the default path for the network configuration inside the configuration dir
714pub(crate) fn build_net_config_dir(config_dir: &PathBuf) -> PathBuf {
715	config_dir.join(DEFAULT_NETWORK_CONFIG_PATH)
716}
717
718/// Returns the default path for the network directory starting from the provided base_path
719/// or from the default base_path.
720pub(crate) fn build_network_key_dir_or_default(
721	base_path: Option<BasePath>,
722	chain_spec_id: &str,
723	executable_name: &String,
724) -> PathBuf {
725	let config_dir =
726		build_config_dir(&base_path_or_default(base_path, executable_name), chain_spec_id);
727	build_net_config_dir(&config_dir)
728}