Trait sc_cli::SubstrateCli

source ·
pub trait SubstrateCli: Sized {
Show 16 methods fn impl_name() -> String; fn impl_version() -> String; fn description() -> String; fn author() -> String; fn support_url() -> String; fn copyright_start_year() -> i32; fn load_spec(&self, id: &str) -> Result<Box<dyn ChainSpec>, String>; fn native_runtime_version(
        chain_spec: &Box<dyn ChainSpec>
    ) -> &'static RuntimeVersion; fn executable_name() -> String { ... } fn from_args() -> Self
    where
        Self: Parser + Sized
, { ... } fn from_iter<I>(iter: I) -> Self
    where
        Self: Parser + Sized,
        I: IntoIterator,
        I::Item: Into<OsString> + Clone
, { ... } fn try_from_iter<I>(iter: I) -> Result<Self>
    where
        Self: Parser + Sized,
        I: IntoIterator,
        I::Item: Into<OsString> + Clone
, { ... } fn client_id() -> String { ... } fn create_configuration<T: CliConfiguration<DVC>, DVC: DefaultConfigurationValues>(
        &self,
        command: &T,
        tokio_handle: Handle
    ) -> Result<Configuration> { ... } fn create_runner<T: CliConfiguration<DVC>, DVC: DefaultConfigurationValues>(
        &self,
        command: &T
    ) -> Result<Runner<Self>> { ... } fn create_runner_with_logger_hook<T: CliConfiguration, F>(
        &self,
        command: &T,
        logger_hook: F
    ) -> Result<Runner<Self>>
    where
        F: FnOnce(&mut LoggerBuilder, &Configuration)
, { ... }
}
Expand description

Substrate client CLI

This trait needs to be implemented on the root CLI struct of the application. It will provide the implementation name, version, executable name, description, author, support_url, copyright start year and most importantly: how to load the chain spec.

Required Methods§

Implementation name.

Implementation version.

By default this will look like this:

2.0.0-b950f731c

Where the hash is the short commit hash of the commit of in the Git repository.

Executable file description.

Executable file author.

Support URL.

Copyright starting year (x-current year)

Chain spec factory

Native runtime version.

Provided Methods§

Executable file name.

Extracts the file name from std::env::current_exe(). Resorts to the env var CARGO_PKG_NAME in case of Error.

Examples found in repository?
src/lib.rs (line 127)
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
	fn from_iter<I>(iter: I) -> Self
	where
		Self: Parser + Sized,
		I: IntoIterator,
		I::Item: Into<std::ffi::OsString> + Clone,
	{
		let app = <Self as CommandFactory>::command();

		let mut full_version = Self::impl_version();
		full_version.push('\n');

		let name = Self::executable_name();
		let author = Self::author();
		let about = Self::description();
		let app = app
			.name(name)
			.author(author)
			.about(about)
			.version(full_version)
			.propagate_version(true)
			.args_conflicts_with_subcommands(true)
			.subcommand_negates_reqs(true);

		let matches = app.try_get_matches_from(iter).unwrap_or_else(|e| e.exit());

		<Self as FromArgMatches>::from_arg_matches(&matches).unwrap_or_else(|e| e.exit())
	}

	/// Helper function used to parse the command line arguments. This is the equivalent of
	/// [`clap::Parser::try_parse_from`]
	///
	/// To allow running the node without subcommand, it also sets a few more settings:
	/// [`clap::Command::propagate_version`], [`clap::Command::args_conflicts_with_subcommands`],
	/// [`clap::Command::subcommand_negates_reqs`].
	///
	/// Creates `Self` from any iterator over arguments.
	/// Print the error message and quit the program in case of failure.
	///
	/// **NOTE:** This method WILL NOT exit when `--help` or `--version` (or short versions) are
	/// used. It will return a [`clap::Error`], where the [`clap::Error::kind`] is a
	/// [`clap::error::ErrorKind::DisplayHelp`] or [`clap::error::ErrorKind::DisplayVersion`]
	/// respectively. You must call [`clap::Error::exit`] or perform a [`std::process::exit`].
	fn try_from_iter<I>(iter: I) -> clap::error::Result<Self>
	where
		Self: Parser + Sized,
		I: IntoIterator,
		I::Item: Into<std::ffi::OsString> + Clone,
	{
		let app = <Self as CommandFactory>::command();

		let mut full_version = Self::impl_version();
		full_version.push('\n');

		let name = Self::executable_name();
		let author = Self::author();
		let about = Self::description();
		let app = app.name(name).author(author).about(about).version(full_version);

		let matches = app.try_get_matches_from(iter)?;

		<Self as FromArgMatches>::from_arg_matches(&matches)
	}
More examples
Hide additional examples
src/commands/insert_key.rs (line 64)
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
	pub fn run<C: SubstrateCli>(&self, cli: &C) -> Result<(), Error> {
		let suri = utils::read_uri(self.suri.as_ref())?;
		let base_path = self
			.shared_params
			.base_path()?
			.unwrap_or_else(|| BasePath::from_project("", "", &C::executable_name()));
		let chain_id = self.shared_params.chain_id(self.shared_params.is_dev());
		let chain_spec = cli.load_spec(&chain_id)?;
		let config_dir = base_path.config_dir(chain_spec.id());

		let (keystore, public) = match self.keystore_params.keystore_config(&config_dir)? {
			(_, KeystoreConfig::Path { path, password }) => {
				let public = with_crypto_scheme!(self.scheme, to_vec(&suri, password.clone()))?;
				let keystore: SyncCryptoStorePtr = Arc::new(LocalKeystore::open(path, password)?);
				(keystore, public)
			},
			_ => unreachable!("keystore_config always returns path and password; qed"),
		};

		let key_type =
			KeyTypeId::try_from(self.key_type.as_str()).map_err(|_| Error::KeyTypeInvalid)?;

		SyncCryptoStore::insert_unknown(&*keystore, key_type, &suri, &public[..])
			.map_err(|_| Error::KeyStoreOperation)?;

		Ok(())
	}
src/config.rs (line 489)
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
	fn create_configuration<C: SubstrateCli>(
		&self,
		cli: &C,
		tokio_handle: tokio::runtime::Handle,
	) -> Result<Configuration> {
		let is_dev = self.is_dev()?;
		let chain_id = self.chain_id(is_dev)?;
		let chain_spec = cli.load_spec(&chain_id)?;
		let base_path = self
			.base_path()?
			.unwrap_or_else(|| BasePath::from_project("", "", &C::executable_name()));
		let config_dir = base_path.config_dir(chain_spec.id());
		let net_config_dir = config_dir.join(DEFAULT_NETWORK_CONFIG_PATH);
		let client_id = C::client_id();
		let database_cache_size = self.database_cache_size()?.unwrap_or(1024);
		let database = self.database()?.unwrap_or(
			#[cfg(feature = "rocksdb")]
			{
				Database::RocksDb
			},
			#[cfg(not(feature = "rocksdb"))]
			{
				Database::ParityDb
			},
		);
		let node_key = self.node_key(&net_config_dir)?;
		let role = self.role(is_dev)?;
		let max_runtime_instances = self.max_runtime_instances()?.unwrap_or(8);
		let is_validator = role.is_authority();
		let (keystore_remote, keystore) = self.keystore_config(&config_dir)?;
		let telemetry_endpoints = self.telemetry_endpoints(&chain_spec)?;
		let runtime_cache_size = self.runtime_cache_size()?;

		Ok(Configuration {
			impl_name: C::impl_name(),
			impl_version: C::impl_version(),
			tokio_handle,
			transaction_pool: self.transaction_pool(is_dev)?,
			network: self.network_config(
				&chain_spec,
				is_dev,
				is_validator,
				net_config_dir,
				client_id.as_str(),
				self.node_name()?.as_str(),
				node_key,
				DCV::p2p_listen_port(),
			)?,
			keystore_remote,
			keystore,
			database: self.database_config(&config_dir, database_cache_size, database)?,
			trie_cache_maximum_size: self.trie_cache_maximum_size()?,
			state_pruning: self.state_pruning()?,
			blocks_pruning: self.blocks_pruning()?,
			wasm_method: self.wasm_method()?,
			wasm_runtime_overrides: self.wasm_runtime_overrides(),
			execution_strategies: self.execution_strategies(is_dev, is_validator)?,
			rpc_http: self.rpc_http(DCV::rpc_http_listen_port())?,
			rpc_ws: self.rpc_ws(DCV::rpc_ws_listen_port())?,
			rpc_ipc: self.rpc_ipc()?,
			rpc_methods: self.rpc_methods()?,
			rpc_ws_max_connections: self.rpc_ws_max_connections()?,
			rpc_cors: self.rpc_cors(is_dev)?,
			rpc_max_payload: self.rpc_max_payload()?,
			rpc_max_request_size: self.rpc_max_request_size()?,
			rpc_max_response_size: self.rpc_max_response_size()?,
			rpc_id_provider: None,
			rpc_max_subs_per_conn: self.rpc_max_subscriptions_per_connection()?,
			ws_max_out_buffer_capacity: self.ws_max_out_buffer_capacity()?,
			prometheus_config: self
				.prometheus_config(DCV::prometheus_listen_port(), &chain_spec)?,
			telemetry_endpoints,
			default_heap_pages: self.default_heap_pages()?,
			offchain_worker: self.offchain_worker(&role)?,
			force_authoring: self.force_authoring()?,
			disable_grandpa: self.disable_grandpa()?,
			dev_key_seed: self.dev_key_seed(is_dev)?,
			tracing_targets: self.tracing_targets()?,
			tracing_receiver: self.tracing_receiver()?,
			chain_spec,
			max_runtime_instances,
			announce_block: self.announce_block()?,
			role,
			base_path: Some(base_path),
			informant_output_format: Default::default(),
			runtime_cache_size,
		})
	}

Helper function used to parse the command line arguments. This is the equivalent of clap::Parser::parse().

To allow running the node without subcommand, it also sets a few more settings: clap::Command::propagate_version, clap::Command::args_conflicts_with_subcommands, clap::Command::subcommand_negates_reqs.

Creates Self from the command line arguments. Print the error message and quit the program in case of failure.

Helper function used to parse the command line arguments. This is the equivalent of clap::Parser::parse_from.

To allow running the node without subcommand, it also sets a few more settings: clap::Command::propagate_version, clap::Command::args_conflicts_with_subcommands, clap::Command::subcommand_negates_reqs.

Creates Self from any iterator over arguments. Print the error message and quit the program in case of failure.

Examples found in repository?
src/lib.rs (line 104)
100
101
102
103
104
105
	fn from_args() -> Self
	where
		Self: Parser + Sized,
	{
		<Self as SubstrateCli>::from_iter(&mut std::env::args_os())
	}

Helper function used to parse the command line arguments. This is the equivalent of clap::Parser::try_parse_from

To allow running the node without subcommand, it also sets a few more settings: clap::Command::propagate_version, clap::Command::args_conflicts_with_subcommands, clap::Command::subcommand_negates_reqs.

Creates Self from any iterator over arguments. Print the error message and quit the program in case of failure.

NOTE: This method WILL NOT exit when --help or --version (or short versions) are used. It will return a clap::Error, where the clap::Error::kind is a clap::error::ErrorKind::DisplayHelp or clap::error::ErrorKind::DisplayVersion respectively. You must call clap::Error::exit or perform a std::process::exit.

Returns the client ID: {impl_name}/v{impl_version}

Examples found in repository?
src/config.rs (line 492)
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
	fn create_configuration<C: SubstrateCli>(
		&self,
		cli: &C,
		tokio_handle: tokio::runtime::Handle,
	) -> Result<Configuration> {
		let is_dev = self.is_dev()?;
		let chain_id = self.chain_id(is_dev)?;
		let chain_spec = cli.load_spec(&chain_id)?;
		let base_path = self
			.base_path()?
			.unwrap_or_else(|| BasePath::from_project("", "", &C::executable_name()));
		let config_dir = base_path.config_dir(chain_spec.id());
		let net_config_dir = config_dir.join(DEFAULT_NETWORK_CONFIG_PATH);
		let client_id = C::client_id();
		let database_cache_size = self.database_cache_size()?.unwrap_or(1024);
		let database = self.database()?.unwrap_or(
			#[cfg(feature = "rocksdb")]
			{
				Database::RocksDb
			},
			#[cfg(not(feature = "rocksdb"))]
			{
				Database::ParityDb
			},
		);
		let node_key = self.node_key(&net_config_dir)?;
		let role = self.role(is_dev)?;
		let max_runtime_instances = self.max_runtime_instances()?.unwrap_or(8);
		let is_validator = role.is_authority();
		let (keystore_remote, keystore) = self.keystore_config(&config_dir)?;
		let telemetry_endpoints = self.telemetry_endpoints(&chain_spec)?;
		let runtime_cache_size = self.runtime_cache_size()?;

		Ok(Configuration {
			impl_name: C::impl_name(),
			impl_version: C::impl_version(),
			tokio_handle,
			transaction_pool: self.transaction_pool(is_dev)?,
			network: self.network_config(
				&chain_spec,
				is_dev,
				is_validator,
				net_config_dir,
				client_id.as_str(),
				self.node_name()?.as_str(),
				node_key,
				DCV::p2p_listen_port(),
			)?,
			keystore_remote,
			keystore,
			database: self.database_config(&config_dir, database_cache_size, database)?,
			trie_cache_maximum_size: self.trie_cache_maximum_size()?,
			state_pruning: self.state_pruning()?,
			blocks_pruning: self.blocks_pruning()?,
			wasm_method: self.wasm_method()?,
			wasm_runtime_overrides: self.wasm_runtime_overrides(),
			execution_strategies: self.execution_strategies(is_dev, is_validator)?,
			rpc_http: self.rpc_http(DCV::rpc_http_listen_port())?,
			rpc_ws: self.rpc_ws(DCV::rpc_ws_listen_port())?,
			rpc_ipc: self.rpc_ipc()?,
			rpc_methods: self.rpc_methods()?,
			rpc_ws_max_connections: self.rpc_ws_max_connections()?,
			rpc_cors: self.rpc_cors(is_dev)?,
			rpc_max_payload: self.rpc_max_payload()?,
			rpc_max_request_size: self.rpc_max_request_size()?,
			rpc_max_response_size: self.rpc_max_response_size()?,
			rpc_id_provider: None,
			rpc_max_subs_per_conn: self.rpc_max_subscriptions_per_connection()?,
			ws_max_out_buffer_capacity: self.ws_max_out_buffer_capacity()?,
			prometheus_config: self
				.prometheus_config(DCV::prometheus_listen_port(), &chain_spec)?,
			telemetry_endpoints,
			default_heap_pages: self.default_heap_pages()?,
			offchain_worker: self.offchain_worker(&role)?,
			force_authoring: self.force_authoring()?,
			disable_grandpa: self.disable_grandpa()?,
			dev_key_seed: self.dev_key_seed(is_dev)?,
			tracing_targets: self.tracing_targets()?,
			tracing_receiver: self.tracing_receiver()?,
			chain_spec,
			max_runtime_instances,
			announce_block: self.announce_block()?,
			role,
			base_path: Some(base_path),
			informant_output_format: Default::default(),
			runtime_cache_size,
		})
	}

Only create a Configuration for the command provided in argument

Create a runner for the command provided in argument. This will create a Configuration and a tokio runtime

Create a runner for the command provided in argument. The logger_hook can be used to setup a custom profiler or update the logger configuration before it is initialized.

Example:

use sc_tracing::{SpanDatum, TraceEvent};
struct TestProfiler;

impl sc_tracing::TraceHandler for TestProfiler {
 	fn handle_span(&self, sd: &SpanDatum) {}
		fn handle_event(&self, _event: &TraceEvent) {}
};

fn logger_hook() -> impl FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration) -> () {
	|logger_builder, config| {
			logger_builder.with_custom_profiling(Box::new(TestProfiler{}));
	}
}

Implementors§