mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-01 08:57:56 +00:00
CLI: refactoring: remove Options from sc_service::Configuration's fields (#5271)
* WIP Forked at:d6aa8e954cParent branch: origin/master * Rename IntoConfiguration to CliConfiguration * Renamed into_configuration to create_configuration * WIP Forked at:d6aa8e954cParent branch: origin/master * WIP Forked at:d6aa8e954cParent branch: origin/master * Move keystore params to its own module * Use in-memory keystore even for build-spec * Enforce proper value for node name * dev_key_seed * Telemetry endpoints * rustfmt * Converted all RunCmd * rustfmt * Added export-blocks * Missed something * Removed config_path in NetworkConfiguration (not used) * Fixed warnings * public_addresses is used but never set, keeping it * Merge Configuration.node and NetworkConfiguration.node_name ...because they are the same thing * Added: import-blocks * Adding a proc_macro to help impl SubstrateCli * WIP Forked at:d6aa8e954cParent branch: origin/master * WIP Forked at:d6aa8e954cParent branch: origin/master * WIP Forked at:d6aa8e954cParent branch: origin/master * Re-export spec_factory from sc_cli * Re-added all the commands * Refactored node_key_params * Fixed previous refucktoring * Clean-up and removed full_version() * Renamed get_is_dev to not confuse with Configuration field * Fixed sc-cli-derive example * Fixing tests * Fixing tests and removing some (will re-add later) * Fixing more tests * Removes the need of type parameter * Converting bin/node and simplifying API * Converting more * Converting last command * WIP Forked at:d6aa8e954cParent branch: origin/master * Fixing tests and added default for WasmExecutionMethod * Fixing stuff * Fixed something I broke oops * Update Cargo.lock * Moving things around * Convert everything to Result * Added new macros to simplify the impl of CliConfiguration * Added a macro to generate CliConfiguration automatically for subcommands * Revert... too many macros (this one is not really useful) This reverts commit 9c516dd38b40fbc420b02c1f8e61d5b2b1a4e434. * Renamed is_dev to get_is_dev Good enough for now * Fixed name roles (this is plural, not singular) * Clean-up * Re-export NodeKeyConfig and TelemetryEndpoints from sc_service * Improve styling/formatting * Added copyrights * Added doc and fixed warnings * Added myself to code owners * Yes it is needed according to the history * Revert formatting * Fixing conflict * Updated build.rs * Cargo.lock * Clean-up * Update client/cli-derive/Cargo.toml Co-Authored-By: Seun Lanlege <seunlanlege@gmail.com> * Fail if using proc_macro and build.rs is not set properly * Dropped all get_ in front of methods * Clean-up * Fixing proc macro missing env var * Get the configuration inside the Runtime (needed for polkadot) * Clean-up * Get is_dev from argument like the others * Get chain ID instead of chain spec from shared params * &self is passed to spec_factory/load_spec * Wrong text * Fix example * Officialize macro and made a cool doc * Renamed spec_factory to load_spec (substrate_cli_configuration) * Removed not so useful ChainSpec * Renamed SubstrateCLI to SubstrateCli * Added changelog for impl_version being full now * Renamed Runtime to Runner * Update changelog to show example * Removed option on database cache size * WIP Forked at:d6aa8e954cParent branch: origin/master * Fix on removal of option * typo * Clean-up imports * Added info in Cargo.toml * typo * remarks * Moved function for build.rs to substrate-build-script-utils * Fixed example & test of cli-derive * Moved function for build.rs to substrate-build-script-utils * Renamed substrate_cli_configuration to substrate_cli oops It implements SubstrateCli not CliConfiguration! * Added documentation and wrapper macro * Removed option on database cache size * Removed option on database cache size * Clean-up * Reduce risk of errors due to typos * Removed option on database cache size * Added NOTE as suggested * Added doc as suggested * Fixed test * typo * renamed runtime to runner * Fixed weird argument * More commas * Moved client/cli-derive to client/cli/derive * Added 7 tests for the macros * Improve error message * Upgrade assert_cmd * Fixing missing stuff * Fixed unused import * Improve SubstrateCli doc * Applied suggestions * Fix and clean-up imports * Started replacing macros WIP * WIP Forked at:d6aa8e954cParent branch: origin/master * WIP Forked at:d6aa8e954cParent branch: origin/master * WIP Forked at:d6aa8e954cParent branch: origin/master * Started removing substrate_cli * WIP Forked at:d6aa8e954cParent branch: origin/master * WIP Forked at:d6aa8e954cParent branch: origin/master * WIP Forked at:d6aa8e954cParent branch: origin/master * fixed bug introduced while refactoring * Renamed NetworkConfigurationParams to NetworkParams for consistency sake * Fixed test * Update client/cli/src/commands/runcmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/commands/runcmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/commands/export_blocks_cmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/commands/check_block_cmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update bin/node/cli/src/command.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update bin/node/cli/src/command.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/commands/export_blocks_cmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Revert "Update client/cli/src/commands/export_blocks_cmd.rs" This reverts commit 5906776953392c02beac6bc0bf50f8cbe1a12a01. * Revert "Update client/cli/src/commands/check_block_cmd.rs" This reverts commit f705f42b7f3d732be001141afee210fe46a1ef47. * Revert "Update client/cli/src/commands/export_blocks_cmd.rs" This reverts commit 8d57c0550164449e6eb2d3bacb04c750c714fcea. * Revert "Update client/cli/src/commands/runcmd.rs" This reverts commit 93e74cf5d2e1c0dc49cdff8608d59fc40fc59338. * Revert "Update client/cli/src/commands/runcmd.rs" This reverts commit 11d527ba345c0d79f0d3b5b071933d95474d0614. * Update client/cli/src/commands/export_blocks_cmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/commands/import_blocks_cmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/commands/purge_chain_cmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Changed ::sc_cli to $crate in the macro * fixed tests * fixed conflicts * Fixing test * Update client/cli/src/commands/purge_chain_cmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/params/pruning_params.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Remove comment as suggested * Apply suggestion * Update client/cli/src/commands/purge_chain_cmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/commands/purge_chain_cmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/commands/purge_chain_cmd.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update utils/frame/benchmarking-cli/src/command.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/runner.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/runner.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/runner.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/params/pruning_params.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/params/node_key_params.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/params/network_params.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/lib.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/cli/src/config.rs Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Added doc * Fixed error introduced after applying suggestion * Revert "Update client/cli/src/params/pruning_params.rs" This reverts commit 0574d06a4f1efd86e94c1214420a12e7a4be0099. * Print error * Apply suggestions from code review * Remove useless Results * Fixed CI failing on polkadot approval Co-authored-by: Seun Lanlege <seunlanlege@gmail.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -14,15 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use structopt::StructOpt;
|
||||
use log::info;
|
||||
use sc_network::config::{build_multiaddr, MultiaddrWithPeerId};
|
||||
use sc_service::{Configuration, ChainSpec};
|
||||
|
||||
use crate::error;
|
||||
use crate::VersionInfo;
|
||||
use crate::params::SharedParams;
|
||||
use crate::params::NodeKeyParams;
|
||||
use crate::params::SharedParams;
|
||||
use crate::CliConfiguration;
|
||||
use log::info;
|
||||
use sc_network::config::build_multiaddr;
|
||||
use sc_service::{config::MultiaddrWithPeerId, Configuration};
|
||||
use structopt::StructOpt;
|
||||
|
||||
/// The `build-spec` command used to build a specification.
|
||||
#[derive(Debug, StructOpt, Clone)]
|
||||
@@ -49,12 +48,9 @@ pub struct BuildSpecCmd {
|
||||
|
||||
impl BuildSpecCmd {
|
||||
/// Run the build-spec command
|
||||
pub fn run(
|
||||
self,
|
||||
config: Configuration,
|
||||
) -> error::Result<()> {
|
||||
pub fn run(&self, config: Configuration) -> error::Result<()> {
|
||||
info!("Building chain spec");
|
||||
let mut spec = config.chain_spec.expect("`chain_spec` is set to `Some` in `update_config`");
|
||||
let mut spec = config.chain_spec;
|
||||
let raw_output = self.raw;
|
||||
|
||||
if spec.boot_nodes().is_empty() && !self.disable_default_bootnode {
|
||||
@@ -73,25 +69,14 @@ impl BuildSpecCmd {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Update and prepare a `Configuration` with command line parameters
|
||||
pub fn update_config<F>(
|
||||
&self,
|
||||
mut config: &mut Configuration,
|
||||
spec_factory: F,
|
||||
version: &VersionInfo,
|
||||
) -> error::Result<()> where
|
||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||
{
|
||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||
|
||||
let net_config_path = config
|
||||
.in_chain_config_dir(crate::commands::DEFAULT_NETWORK_CONFIG_PATH)
|
||||
.expect("We provided a base_path");
|
||||
|
||||
self.node_key_params.update_config(&mut config, Some(&net_config_path))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl CliConfiguration for BuildSpecCmd {
|
||||
fn shared_params(&self) -> &SharedParams {
|
||||
&self.shared_params
|
||||
}
|
||||
|
||||
fn node_key_params(&self) -> Option<&NodeKeyParams> {
|
||||
Some(&self.node_key_params)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,20 +14,16 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error;
|
||||
use crate::params::ImportParams;
|
||||
use crate::params::SharedParams;
|
||||
use crate::CliConfiguration;
|
||||
use sc_service::{Configuration, ServiceBuilderCommand};
|
||||
use sp_runtime::generic::BlockId;
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
use std::fmt::Debug;
|
||||
use std::str::FromStr;
|
||||
use structopt::StructOpt;
|
||||
use sc_service::{
|
||||
Configuration, ServiceBuilderCommand, Role, ChainSpec,
|
||||
};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
use sp_runtime::generic::BlockId;
|
||||
|
||||
use crate::error;
|
||||
use crate::VersionInfo;
|
||||
use crate::runtime::run_until_exit;
|
||||
use crate::params::SharedParams;
|
||||
use crate::params::ImportParams;
|
||||
|
||||
/// The `check-block` command used to validate blocks.
|
||||
#[derive(Debug, StructOpt, Clone)]
|
||||
@@ -53,8 +49,8 @@ pub struct CheckBlockCmd {
|
||||
|
||||
impl CheckBlockCmd {
|
||||
/// Run the check-block command
|
||||
pub fn run<B, BC, BB>(
|
||||
self,
|
||||
pub async fn run<B, BC, BB>(
|
||||
&self,
|
||||
config: Configuration,
|
||||
builder: B,
|
||||
) -> error::Result<()>
|
||||
@@ -65,37 +61,37 @@ impl CheckBlockCmd {
|
||||
<<<BB as BlockT>::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug,
|
||||
<BB as BlockT>::Hash: std::str::FromStr,
|
||||
{
|
||||
let input = if self.input.starts_with("0x") { &self.input[2..] } else { &self.input[..] };
|
||||
let input = if self.input.starts_with("0x") {
|
||||
&self.input[2..]
|
||||
} else {
|
||||
&self.input[..]
|
||||
};
|
||||
let block_id = match FromStr::from_str(input) {
|
||||
Ok(hash) => BlockId::hash(hash),
|
||||
Err(_) => match self.input.parse::<u32>() {
|
||||
Ok(n) => BlockId::number((n as u32).into()),
|
||||
Err(_) => return Err(error::Error::Input("Invalid hash or number specified".into())),
|
||||
}
|
||||
Err(_) => {
|
||||
return Err(error::Error::Input(
|
||||
"Invalid hash or number specified".into(),
|
||||
))
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let start = std::time::Instant::now();
|
||||
run_until_exit(config, |config| {
|
||||
Ok(builder(config)?.check_block(block_id))
|
||||
})?;
|
||||
builder(config)?.check_block(block_id).await?;
|
||||
println!("Completed in {} ms.", start.elapsed().as_millis());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Update and prepare a `Configuration` with command line parameters
|
||||
pub fn update_config<F>(
|
||||
&self,
|
||||
mut config: &mut Configuration,
|
||||
spec_factory: F,
|
||||
version: &VersionInfo,
|
||||
) -> error::Result<()> where
|
||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||
{
|
||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||
self.import_params.update_config(&mut config, &Role::Full, self.shared_params.dev)?;
|
||||
config.use_in_memory_keystore()?;
|
||||
impl CliConfiguration for CheckBlockCmd {
|
||||
fn shared_params(&self) -> &SharedParams {
|
||||
&self.shared_params
|
||||
}
|
||||
|
||||
Ok(())
|
||||
fn import_params(&self) -> Option<&ImportParams> {
|
||||
Some(&self.import_params)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,22 +14,19 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::io;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::fmt::Debug;
|
||||
use crate::error;
|
||||
use crate::params::{BlockNumber, PruningParams, SharedParams};
|
||||
use crate::CliConfiguration;
|
||||
use log::info;
|
||||
use structopt::StructOpt;
|
||||
use sc_service::{
|
||||
Configuration, ServiceBuilderCommand, ChainSpec,
|
||||
config::DatabaseConfig, Role,
|
||||
config::DatabaseConfig, Configuration, ServiceBuilderCommand,
|
||||
};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
|
||||
use crate::error;
|
||||
use crate::VersionInfo;
|
||||
use crate::runtime::run_until_exit;
|
||||
use crate::params::{SharedParams, BlockNumber, PruningParams};
|
||||
use std::fmt::Debug;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
|
||||
/// The `export-blocks` command used to export blocks.
|
||||
#[derive(Debug, StructOpt, Clone)]
|
||||
@@ -65,8 +62,8 @@ pub struct ExportBlocksCmd {
|
||||
|
||||
impl ExportBlocksCmd {
|
||||
/// Run the export-blocks command
|
||||
pub fn run<B, BC, BB>(
|
||||
self,
|
||||
pub async fn run<B, BC, BB>(
|
||||
&self,
|
||||
config: Configuration,
|
||||
builder: B,
|
||||
) -> error::Result<()>
|
||||
@@ -77,9 +74,10 @@ impl ExportBlocksCmd {
|
||||
<<<BB as BlockT>::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug,
|
||||
<BB as BlockT>::Hash: std::str::FromStr,
|
||||
{
|
||||
if let DatabaseConfig::Path { ref path, .. } = config.expect_database() {
|
||||
if let DatabaseConfig::Path { ref path, .. } = &config.database {
|
||||
info!("DB path: {}", path.display());
|
||||
}
|
||||
|
||||
let from = self.from.as_ref().and_then(|f| f.parse().ok()).unwrap_or(1);
|
||||
let to = self.to.as_ref().and_then(|t| t.parse().ok());
|
||||
|
||||
@@ -90,24 +88,19 @@ impl ExportBlocksCmd {
|
||||
None => Box::new(io::stdout()),
|
||||
};
|
||||
|
||||
run_until_exit(config, |config| {
|
||||
Ok(builder(config)?.export_blocks(file, from.into(), to, binary))
|
||||
})
|
||||
}
|
||||
|
||||
/// Update and prepare a `Configuration` with command line parameters
|
||||
pub fn update_config<F>(
|
||||
&self,
|
||||
mut config: &mut Configuration,
|
||||
spec_factory: F,
|
||||
version: &VersionInfo,
|
||||
) -> error::Result<()> where
|
||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||
{
|
||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||
self.pruning_params.update_config(&mut config, &Role::Full, true)?;
|
||||
config.use_in_memory_keystore()?;
|
||||
|
||||
Ok(())
|
||||
builder(config)?
|
||||
.export_blocks(file, from.into(), to, binary)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl CliConfiguration for ExportBlocksCmd {
|
||||
fn shared_params(&self) -> &SharedParams {
|
||||
&self.shared_params
|
||||
}
|
||||
|
||||
fn pruning_params(&self) -> Option<&PruningParams> {
|
||||
Some(&self.pruning_params)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,21 +14,17 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error;
|
||||
use crate::params::ImportParams;
|
||||
use crate::params::SharedParams;
|
||||
use crate::CliConfiguration;
|
||||
use sc_service::{Configuration, ServiceBuilderCommand};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
use std::fmt::Debug;
|
||||
use std::io::{Read, Seek, self};
|
||||
use std::fs;
|
||||
use std::io::{self, Read, Seek};
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
use sc_service::{
|
||||
Configuration, ServiceBuilderCommand, ChainSpec, Role,
|
||||
};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
|
||||
use crate::error;
|
||||
use crate::VersionInfo;
|
||||
use crate::runtime::run_until_exit;
|
||||
use crate::params::SharedParams;
|
||||
use crate::params::ImportParams;
|
||||
|
||||
/// The `import-blocks` command used to import blocks.
|
||||
#[derive(Debug, StructOpt, Clone)]
|
||||
@@ -59,8 +55,8 @@ impl<T: Read + Seek> ReadPlusSeek for T {}
|
||||
|
||||
impl ImportBlocksCmd {
|
||||
/// Run the import-blocks command
|
||||
pub fn run<B, BC, BB>(
|
||||
self,
|
||||
pub async fn run<B, BC, BB>(
|
||||
&self,
|
||||
config: Configuration,
|
||||
builder: B,
|
||||
) -> error::Result<()>
|
||||
@@ -77,27 +73,22 @@ impl ImportBlocksCmd {
|
||||
let mut buffer = Vec::new();
|
||||
io::stdin().read_to_end(&mut buffer)?;
|
||||
Box::new(io::Cursor::new(buffer))
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
run_until_exit(config, |config| {
|
||||
Ok(builder(config)?.import_blocks(file, false))
|
||||
})
|
||||
}
|
||||
|
||||
/// Update and prepare a `Configuration` with command line parameters
|
||||
pub fn update_config<F>(
|
||||
&self,
|
||||
mut config: &mut Configuration,
|
||||
spec_factory: F,
|
||||
version: &VersionInfo,
|
||||
) -> error::Result<()> where
|
||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||
{
|
||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||
self.import_params.update_config(&mut config, &Role::Full, self.shared_params.dev)?;
|
||||
config.use_in_memory_keystore()?;
|
||||
|
||||
Ok(())
|
||||
builder(config)?
|
||||
.import_blocks(file, false)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl CliConfiguration for ImportBlocksCmd {
|
||||
fn shared_params(&self) -> &SharedParams {
|
||||
&self.shared_params
|
||||
}
|
||||
|
||||
fn import_params(&self) -> Option<&ImportParams> {
|
||||
Some(&self.import_params)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,35 +14,24 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
mod runcmd;
|
||||
mod export_blocks_cmd;
|
||||
mod build_spec_cmd;
|
||||
mod import_blocks_cmd;
|
||||
mod check_block_cmd;
|
||||
mod revert_cmd;
|
||||
mod export_blocks_cmd;
|
||||
mod import_blocks_cmd;
|
||||
mod purge_chain_cmd;
|
||||
mod revert_cmd;
|
||||
mod runcmd;
|
||||
|
||||
pub use crate::commands::build_spec_cmd::BuildSpecCmd;
|
||||
pub use crate::commands::check_block_cmd::CheckBlockCmd;
|
||||
pub use crate::commands::export_blocks_cmd::ExportBlocksCmd;
|
||||
pub use crate::commands::import_blocks_cmd::ImportBlocksCmd;
|
||||
pub use crate::commands::purge_chain_cmd::PurgeChainCmd;
|
||||
pub use crate::commands::revert_cmd::RevertCmd;
|
||||
pub use crate::commands::runcmd::RunCmd;
|
||||
use std::fmt::Debug;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use sc_service::{ Configuration, ServiceBuilderCommand, ChainSpec };
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
|
||||
use crate::error;
|
||||
use crate::VersionInfo;
|
||||
use crate::params::SharedParams;
|
||||
|
||||
pub use crate::commands::runcmd::RunCmd;
|
||||
pub use crate::commands::export_blocks_cmd::ExportBlocksCmd;
|
||||
pub use crate::commands::build_spec_cmd::BuildSpecCmd;
|
||||
pub use crate::commands::import_blocks_cmd::ImportBlocksCmd;
|
||||
pub use crate::commands::check_block_cmd::CheckBlockCmd;
|
||||
pub use crate::commands::revert_cmd::RevertCmd;
|
||||
pub use crate::commands::purge_chain_cmd::PurgeChainCmd;
|
||||
|
||||
/// default sub directory to store network config
|
||||
const DEFAULT_NETWORK_CONFIG_PATH : &'static str = "network";
|
||||
|
||||
/// All core commands that are provided by default.
|
||||
///
|
||||
/// The core commands are split into multiple subcommands and `Run` is the default subcommand. From
|
||||
@@ -51,89 +40,338 @@ const DEFAULT_NETWORK_CONFIG_PATH : &'static str = "network";
|
||||
#[derive(Debug, Clone, StructOpt)]
|
||||
pub enum Subcommand {
|
||||
/// Build a spec.json file, outputs to stdout.
|
||||
BuildSpec(build_spec_cmd::BuildSpecCmd),
|
||||
BuildSpec(BuildSpecCmd),
|
||||
|
||||
/// Export blocks to a file.
|
||||
ExportBlocks(export_blocks_cmd::ExportBlocksCmd),
|
||||
ExportBlocks(ExportBlocksCmd),
|
||||
|
||||
/// Import blocks from file.
|
||||
ImportBlocks(import_blocks_cmd::ImportBlocksCmd),
|
||||
ImportBlocks(ImportBlocksCmd),
|
||||
|
||||
/// Validate a single block.
|
||||
CheckBlock(check_block_cmd::CheckBlockCmd),
|
||||
CheckBlock(CheckBlockCmd),
|
||||
|
||||
/// Revert chain to the previous state.
|
||||
Revert(revert_cmd::RevertCmd),
|
||||
Revert(RevertCmd),
|
||||
|
||||
/// Remove the whole chain data.
|
||||
PurgeChain(purge_chain_cmd::PurgeChainCmd),
|
||||
PurgeChain(PurgeChainCmd),
|
||||
}
|
||||
|
||||
impl Subcommand {
|
||||
/// Get the shared parameters of a `CoreParams` command.
|
||||
pub fn get_shared_params(&self) -> &SharedParams {
|
||||
use Subcommand::*;
|
||||
// TODO: move to config.rs?
|
||||
/// Macro that helps implement CliConfiguration on an enum of subcommand automatically
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # #[macro_use] extern crate sc_cli;
|
||||
///
|
||||
/// # struct EmptyVariant {}
|
||||
///
|
||||
/// # impl sc_cli::CliConfiguration for EmptyVariant {
|
||||
/// # fn shared_params(&self) -> &sc_cli::SharedParams { unimplemented!() }
|
||||
/// # fn chain_id(&self, _: bool) -> sc_cli::Result<String> { Ok("test-chain-id".to_string()) }
|
||||
/// # }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// enum Subcommand {
|
||||
/// Variant1(EmptyVariant),
|
||||
/// Variant2(EmptyVariant),
|
||||
/// }
|
||||
///
|
||||
/// substrate_cli_subcommands!(
|
||||
/// Subcommand => Variant1, Variant2
|
||||
/// );
|
||||
///
|
||||
/// # use sc_cli::CliConfiguration;
|
||||
/// # assert_eq!(Subcommand::Variant1(EmptyVariant {}).chain_id(false).unwrap(), "test-chain-id");
|
||||
///
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Which will expand to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// impl CliConfiguration for Subcommand {
|
||||
/// fn base_path(&self) -> Result<Option<PathBuf>> {
|
||||
/// match self {
|
||||
/// Subcommand::Variant1(cmd) => cmd.base_path(),
|
||||
/// Subcommand::Variant2(cmd) => cmd.base_path(),
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn is_dev(&self) -> Result<bool> {
|
||||
/// match self {
|
||||
/// Subcommand::Variant1(cmd) => cmd.is_dev(),
|
||||
/// Subcommand::Variant2(cmd) => cmd.is_dev(),
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! substrate_cli_subcommands {
|
||||
($enum:ident => $($variant:ident),*) => {
|
||||
impl $crate::CliConfiguration for $enum {
|
||||
fn shared_params(&self) -> &$crate::SharedParams {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.shared_params()),*
|
||||
}
|
||||
}
|
||||
|
||||
match self {
|
||||
BuildSpec(params) => ¶ms.shared_params,
|
||||
ExportBlocks(params) => ¶ms.shared_params,
|
||||
ImportBlocks(params) => ¶ms.shared_params,
|
||||
CheckBlock(params) => ¶ms.shared_params,
|
||||
Revert(params) => ¶ms.shared_params,
|
||||
PurgeChain(params) => ¶ms.shared_params,
|
||||
fn import_params(&self) -> Option<&$crate::ImportParams> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.import_params()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn pruning_params(&self) -> Option<&$crate::PruningParams> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.pruning_params()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn keystore_params(&self) -> Option<&$crate::KeystoreParams> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.keystore_params()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn network_params(&self) -> Option<&$crate::NetworkParams> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.network_params()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn base_path(&self) -> $crate::Result<::std::option::Option<::std::path::PathBuf>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.base_path()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn is_dev(&self) -> $crate::Result<bool> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.is_dev()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn role(&self, is_dev: bool) -> $crate::Result<::sc_service::Role> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.role(is_dev)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn transaction_pool(&self)
|
||||
-> $crate::Result<::sc_service::config::TransactionPoolOptions> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.transaction_pool()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn network_config(
|
||||
&self,
|
||||
chain_spec: &::std::boxed::Box<dyn ::sc_service::ChainSpec>,
|
||||
is_dev: bool,
|
||||
net_config_dir: &::std::path::PathBuf,
|
||||
client_id: &str,
|
||||
node_name: &str,
|
||||
node_key: ::sc_service::config::NodeKeyConfig,
|
||||
) -> $crate::Result<::sc_service::config::NetworkConfiguration> {
|
||||
match self {
|
||||
$(
|
||||
$enum::$variant(cmd) => cmd.network_config(
|
||||
chain_spec, is_dev, net_config_dir, client_id, node_name, node_key
|
||||
)
|
||||
),*
|
||||
}
|
||||
}
|
||||
|
||||
fn keystore_config(&self, base_path: &::std::path::PathBuf)
|
||||
-> $crate::Result<::sc_service::config::KeystoreConfig> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.keystore_config(base_path)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn database_cache_size(&self) -> $crate::Result<::std::option::Option<usize>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.database_cache_size()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn database_config(
|
||||
&self,
|
||||
base_path: &::std::path::PathBuf,
|
||||
cache_size: usize,
|
||||
) -> $crate::Result<::sc_service::config::DatabaseConfig> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.database_config(base_path, cache_size)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn state_cache_size(&self) -> $crate::Result<usize> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.state_cache_size()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn state_cache_child_ratio(&self) -> $crate::Result<::std::option::Option<usize>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.state_cache_child_ratio()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn pruning(&self, is_dev: bool, role: &::sc_service::Role)
|
||||
-> $crate::Result<::sc_service::config::PruningMode> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.pruning(is_dev, role)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn chain_id(&self, is_dev: bool) -> $crate::Result<String> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.chain_id(is_dev)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn init<C: $crate::SubstrateCli>(&self) -> $crate::Result<()> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.init::<C>()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn node_name(&self) -> $crate::Result<String> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.node_name()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn wasm_method(&self) -> $crate::Result<::sc_service::config::WasmExecutionMethod> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.wasm_method()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn execution_strategies(&self, is_dev: bool)
|
||||
-> $crate::Result<::sc_service::config::ExecutionStrategies> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.execution_strategies(is_dev)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn rpc_http(&self) -> $crate::Result<::std::option::Option<::std::net::SocketAddr>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.rpc_http()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn rpc_ws(&self) -> $crate::Result<::std::option::Option<::std::net::SocketAddr>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.rpc_ws()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn rpc_ws_max_connections(&self) -> $crate::Result<::std::option::Option<usize>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.rpc_ws_max_connections()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn rpc_cors(&self, is_dev: bool)
|
||||
-> $crate::Result<::std::option::Option<::std::vec::Vec<String>>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.rpc_cors(is_dev)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn prometheus_config(&self)
|
||||
-> $crate::Result<::std::option::Option<::sc_service::config::PrometheusConfig>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.prometheus_config()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn telemetry_endpoints(
|
||||
&self,
|
||||
chain_spec: &Box<dyn ::sc_service::ChainSpec>,
|
||||
) -> $crate::Result<::std::option::Option<::sc_service::config::TelemetryEndpoints>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.telemetry_endpoints(chain_spec)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn telemetry_external_transport(&self)
|
||||
-> $crate::Result<::std::option::Option<::sc_service::config::ExtTransport>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.telemetry_external_transport()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn default_heap_pages(&self) -> $crate::Result<::std::option::Option<u64>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.default_heap_pages()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn offchain_worker(&self, role: &::sc_service::Role) -> $crate::Result<bool> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.offchain_worker(role)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn force_authoring(&self) -> $crate::Result<bool> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.force_authoring()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn disable_grandpa(&self) -> $crate::Result<bool> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.disable_grandpa()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn dev_key_seed(&self, is_dev: bool) -> $crate::Result<::std::option::Option<String>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.dev_key_seed(is_dev)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn tracing_targets(&self) -> $crate::Result<::std::option::Option<String>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.tracing_targets()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn tracing_receiver(&self) -> $crate::Result<::sc_service::TracingReceiver> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.tracing_receiver()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn node_key(&self, net_config_dir: &::std::path::PathBuf)
|
||||
-> $crate::Result<::sc_service::config::NodeKeyConfig> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.node_key(net_config_dir)),*
|
||||
}
|
||||
}
|
||||
|
||||
fn max_runtime_instances(&self) -> $crate::Result<::std::option::Option<usize>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.max_runtime_instances()),*
|
||||
}
|
||||
}
|
||||
|
||||
fn log_filters(&self) -> $crate::Result<::std::option::Option<String>> {
|
||||
match self {
|
||||
$($enum::$variant(cmd) => cmd.log_filters()),*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Run any `CoreParams` command.
|
||||
pub fn run<B, BC, BB>(
|
||||
self,
|
||||
config: Configuration,
|
||||
builder: B,
|
||||
) -> error::Result<()>
|
||||
where
|
||||
B: FnOnce(Configuration) -> Result<BC, sc_service::error::Error>,
|
||||
BC: ServiceBuilderCommand<Block = BB> + Unpin,
|
||||
BB: sp_runtime::traits::Block + Debug,
|
||||
<<<BB as BlockT>::Header as HeaderT>::Number as std::str::FromStr>::Err: std::fmt::Debug,
|
||||
<BB as BlockT>::Hash: std::str::FromStr,
|
||||
{
|
||||
match self {
|
||||
Subcommand::BuildSpec(cmd) => cmd.run(config),
|
||||
Subcommand::ExportBlocks(cmd) => cmd.run(config, builder),
|
||||
Subcommand::ImportBlocks(cmd) => cmd.run(config, builder),
|
||||
Subcommand::CheckBlock(cmd) => cmd.run(config, builder),
|
||||
Subcommand::PurgeChain(cmd) => cmd.run(config),
|
||||
Subcommand::Revert(cmd) => cmd.run(config, builder),
|
||||
}
|
||||
}
|
||||
|
||||
/// Update and prepare a `Configuration` with command line parameters.
|
||||
pub fn update_config<F>(
|
||||
&self,
|
||||
mut config: &mut Configuration,
|
||||
spec_factory: F,
|
||||
version: &VersionInfo,
|
||||
) -> error::Result<()> where
|
||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||
{
|
||||
match self {
|
||||
Subcommand::BuildSpec(cmd) => cmd.update_config(&mut config, spec_factory, version),
|
||||
Subcommand::ExportBlocks(cmd) => cmd.update_config(&mut config, spec_factory, version),
|
||||
Subcommand::ImportBlocks(cmd) => cmd.update_config(&mut config, spec_factory, version),
|
||||
Subcommand::CheckBlock(cmd) => cmd.update_config(&mut config, spec_factory, version),
|
||||
Subcommand::PurgeChain(cmd) => cmd.update_config(&mut config, spec_factory, version),
|
||||
Subcommand::Revert(cmd) => cmd.update_config(&mut config, spec_factory, version),
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize substrate. This must be done only once.
|
||||
///
|
||||
/// This method:
|
||||
///
|
||||
/// 1. Set the panic handler
|
||||
/// 2. Raise the FD limit
|
||||
/// 3. Initialize the logger
|
||||
pub fn init(&self, version: &VersionInfo) -> error::Result<()> {
|
||||
self.get_shared_params().init(version)
|
||||
}
|
||||
}
|
||||
|
||||
substrate_cli_subcommands!(
|
||||
Subcommand => BuildSpec, ExportBlocks, ImportBlocks, CheckBlock, Revert, PurgeChain
|
||||
);
|
||||
|
||||
@@ -14,15 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::io::{Write, self};
|
||||
use std::fs;
|
||||
use structopt::StructOpt;
|
||||
use sc_service::{ Configuration, ChainSpec, config::{DatabaseConfig} };
|
||||
|
||||
use crate::error;
|
||||
use crate::VersionInfo;
|
||||
use crate::params::SharedParams;
|
||||
use crate::CliConfiguration;
|
||||
use sc_service::{config::DatabaseConfig, Configuration};
|
||||
use std::fmt::Debug;
|
||||
use std::fs;
|
||||
use std::io::{self, Write};
|
||||
use structopt::StructOpt;
|
||||
|
||||
/// The `purge-chain` command used to remove the whole chain.
|
||||
#[derive(Debug, StructOpt, Clone)]
|
||||
@@ -38,11 +37,8 @@ pub struct PurgeChainCmd {
|
||||
|
||||
impl PurgeChainCmd {
|
||||
/// Run the purge command
|
||||
pub fn run(
|
||||
self,
|
||||
config: Configuration,
|
||||
) -> error::Result<()> {
|
||||
let db_path = match config.expect_database() {
|
||||
pub fn run(&self, config: Configuration) -> error::Result<()> {
|
||||
let db_path = match &config.database {
|
||||
DatabaseConfig::Path { path, .. } => path,
|
||||
_ => {
|
||||
eprintln!("Cannot purge custom database implementation");
|
||||
@@ -76,22 +72,13 @@ impl PurgeChainCmd {
|
||||
eprintln!("{:?} did not exist.", &db_path);
|
||||
Ok(())
|
||||
},
|
||||
Err(err) => Result::Err(err.into())
|
||||
Err(err) => Result::Err(err.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Update and prepare a `Configuration` with command line parameters
|
||||
pub fn update_config<F>(
|
||||
&self,
|
||||
mut config: &mut Configuration,
|
||||
spec_factory: F,
|
||||
version: &VersionInfo,
|
||||
) -> error::Result<()> where
|
||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||
{
|
||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||
config.use_in_memory_keystore()?;
|
||||
|
||||
Ok(())
|
||||
impl CliConfiguration for PurgeChainCmd {
|
||||
fn shared_params(&self) -> &SharedParams {
|
||||
&self.shared_params
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,16 +14,13 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error;
|
||||
use crate::params::{BlockNumber, PruningParams, SharedParams};
|
||||
use crate::CliConfiguration;
|
||||
use sc_service::{Configuration, ServiceBuilderCommand};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
use std::fmt::Debug;
|
||||
use structopt::StructOpt;
|
||||
use sc_service::{
|
||||
Configuration, ServiceBuilderCommand, ChainSpec, Role,
|
||||
};
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||
|
||||
use crate::error;
|
||||
use crate::VersionInfo;
|
||||
use crate::params::{BlockNumber, SharedParams, PruningParams};
|
||||
|
||||
/// The `revert` command used revert the chain to a previous state.
|
||||
#[derive(Debug, StructOpt, Clone)]
|
||||
@@ -43,11 +40,7 @@ pub struct RevertCmd {
|
||||
|
||||
impl RevertCmd {
|
||||
/// Run the revert command
|
||||
pub fn run<B, BC, BB>(
|
||||
self,
|
||||
config: Configuration,
|
||||
builder: B,
|
||||
) -> error::Result<()>
|
||||
pub fn run<B, BC, BB>(&self, config: Configuration, builder: B) -> error::Result<()>
|
||||
where
|
||||
B: FnOnce(Configuration) -> Result<BC, sc_service::error::Error>,
|
||||
BC: ServiceBuilderCommand<Block = BB> + Unpin,
|
||||
@@ -60,20 +53,14 @@ impl RevertCmd {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Update and prepare a `Configuration` with command line parameters
|
||||
pub fn update_config<F>(
|
||||
&self,
|
||||
mut config: &mut Configuration,
|
||||
spec_factory: F,
|
||||
version: &VersionInfo,
|
||||
) -> error::Result<()> where
|
||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||
{
|
||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||
self.pruning_params.update_config(&mut config, &Role::Full, true)?;
|
||||
config.use_in_memory_keystore()?;
|
||||
impl CliConfiguration for RevertCmd {
|
||||
fn shared_params(&self) -> &SharedParams {
|
||||
&self.shared_params
|
||||
}
|
||||
|
||||
Ok(())
|
||||
fn pruning_params(&self) -> Option<&PruningParams> {
|
||||
Some(&self.pruning_params)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,34 +14,21 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::net::SocketAddr;
|
||||
use std::fs;
|
||||
use std::fmt;
|
||||
use log::info;
|
||||
use structopt::{StructOpt, clap::arg_enum};
|
||||
use names::{Generator, Name};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::params::ImportParams;
|
||||
use crate::params::KeystoreParams;
|
||||
use crate::params::NetworkParams;
|
||||
use crate::params::SharedParams;
|
||||
use crate::params::TransactionPoolParams;
|
||||
use crate::CliConfiguration;
|
||||
use regex::Regex;
|
||||
use chrono::prelude::*;
|
||||
use sc_service::{
|
||||
AbstractService, Configuration, ChainSpec, Role,
|
||||
config::{MultiaddrWithPeerId, KeystoreConfig, PrometheusConfig},
|
||||
config::{MultiaddrWithPeerId, PrometheusConfig, TransactionPoolOptions},
|
||||
ChainSpec, Role,
|
||||
};
|
||||
use sc_telemetry::TelemetryEndpoints;
|
||||
|
||||
use crate::VersionInfo;
|
||||
use crate::error;
|
||||
use crate::params::ImportParams;
|
||||
use crate::params::SharedParams;
|
||||
use crate::params::NetworkConfigurationParams;
|
||||
use crate::params::TransactionPoolParams;
|
||||
use crate::runtime::run_service_until_exit;
|
||||
|
||||
/// The maximum number of characters for a node name.
|
||||
const NODE_NAME_MAX_LENGTH: usize = 32;
|
||||
|
||||
/// default sub directory for the key store
|
||||
const DEFAULT_KEYSTORE_CONFIG_PATH : &'static str = "keystore";
|
||||
use std::net::SocketAddr;
|
||||
use structopt::{clap::arg_enum, StructOpt};
|
||||
|
||||
arg_enum! {
|
||||
/// Whether off-chain workers are enabled.
|
||||
@@ -200,7 +187,7 @@ pub struct RunCmd {
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[structopt(flatten)]
|
||||
pub network_config: NetworkConfigurationParams,
|
||||
pub network_params: NetworkParams,
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[structopt(flatten)]
|
||||
@@ -242,38 +229,23 @@ pub struct RunCmd {
|
||||
#[structopt(long = "force-authoring")]
|
||||
pub force_authoring: bool,
|
||||
|
||||
/// Specify custom keystore path.
|
||||
#[structopt(long = "keystore-path", value_name = "PATH", parse(from_os_str))]
|
||||
pub keystore_path: Option<PathBuf>,
|
||||
|
||||
/// Use interactive shell for entering the password used by the keystore.
|
||||
#[structopt(
|
||||
long = "password-interactive",
|
||||
conflicts_with_all = &[ "password", "password-filename" ]
|
||||
)]
|
||||
pub password_interactive: bool,
|
||||
|
||||
/// Password used by the keystore.
|
||||
#[structopt(
|
||||
long = "password",
|
||||
conflicts_with_all = &[ "password-interactive", "password-filename" ]
|
||||
)]
|
||||
pub password: Option<String>,
|
||||
|
||||
/// File that contains the password used by the keystore.
|
||||
#[structopt(
|
||||
long = "password-filename",
|
||||
value_name = "PATH",
|
||||
parse(from_os_str),
|
||||
conflicts_with_all = &[ "password-interactive", "password" ]
|
||||
)]
|
||||
pub password_filename: Option<PathBuf>,
|
||||
#[allow(missing_docs)]
|
||||
#[structopt(flatten)]
|
||||
pub keystore_params: KeystoreParams,
|
||||
|
||||
/// The size of the instances cache for each runtime.
|
||||
///
|
||||
/// The default value is 8 and the values higher than 256 are ignored.
|
||||
#[structopt(long = "max-runtime-instances", default_value = "8")]
|
||||
pub max_runtime_instances: usize,
|
||||
#[structopt(long)]
|
||||
pub max_runtime_instances: Option<usize>,
|
||||
|
||||
/// Specify a list of sentry node public addresses.
|
||||
#[structopt(
|
||||
long = "sentry-nodes",
|
||||
value_name = "ADDR",
|
||||
conflicts_with_all = &[ "sentry" ]
|
||||
)]
|
||||
pub sentry_nodes: Vec<MultiaddrWithPeerId>,
|
||||
}
|
||||
|
||||
impl RunCmd {
|
||||
@@ -281,219 +253,203 @@ impl RunCmd {
|
||||
pub fn get_keyring(&self) -> Option<sp_keyring::Sr25519Keyring> {
|
||||
use sp_keyring::Sr25519Keyring::*;
|
||||
|
||||
if self.alice { Some(Alice) }
|
||||
else if self.bob { Some(Bob) }
|
||||
else if self.charlie { Some(Charlie) }
|
||||
else if self.dave { Some(Dave) }
|
||||
else if self.eve { Some(Eve) }
|
||||
else if self.ferdie { Some(Ferdie) }
|
||||
else if self.one { Some(One) }
|
||||
else if self.two { Some(Two) }
|
||||
else { None }
|
||||
}
|
||||
|
||||
/// Update and prepare a `Configuration` with command line parameters of `RunCmd` and `VersionInfo`.
|
||||
pub fn update_config<F>(
|
||||
&self,
|
||||
mut config: &mut Configuration,
|
||||
spec_factory: F,
|
||||
version: &VersionInfo,
|
||||
) -> error::Result<()>
|
||||
where
|
||||
F: FnOnce(&str) -> Result<Box<dyn ChainSpec>, String>,
|
||||
{
|
||||
self.shared_params.update_config(&mut config, spec_factory, version)?;
|
||||
|
||||
let password = if self.password_interactive {
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
{
|
||||
Some(input_keystore_password()?.into())
|
||||
}
|
||||
#[cfg(target_os = "unknown")]
|
||||
None
|
||||
} else if let Some(ref file) = self.password_filename {
|
||||
Some(fs::read_to_string(file).map_err(|e| format!("{}", e))?.into())
|
||||
} else if let Some(ref password) = self.password {
|
||||
Some(password.clone().into())
|
||||
if self.alice {
|
||||
Some(Alice)
|
||||
} else if self.bob {
|
||||
Some(Bob)
|
||||
} else if self.charlie {
|
||||
Some(Charlie)
|
||||
} else if self.dave {
|
||||
Some(Dave)
|
||||
} else if self.eve {
|
||||
Some(Eve)
|
||||
} else if self.ferdie {
|
||||
Some(Ferdie)
|
||||
} else if self.one {
|
||||
Some(One)
|
||||
} else if self.two {
|
||||
Some(Two)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let path = self.keystore_path.clone().or(
|
||||
config.in_chain_config_dir(DEFAULT_KEYSTORE_CONFIG_PATH)
|
||||
);
|
||||
impl CliConfiguration for RunCmd {
|
||||
fn shared_params(&self) -> &SharedParams {
|
||||
&self.shared_params
|
||||
}
|
||||
|
||||
config.keystore = KeystoreConfig::Path {
|
||||
path: path.ok_or_else(|| "No `base_path` provided to create keystore path!".to_string())?,
|
||||
password,
|
||||
};
|
||||
fn import_params(&self) -> Option<&ImportParams> {
|
||||
Some(&self.import_params)
|
||||
}
|
||||
|
||||
let keyring = self.get_keyring();
|
||||
let is_dev = self.shared_params.dev;
|
||||
let is_light = self.light;
|
||||
let is_authority = (self.validator || is_dev || keyring.is_some())
|
||||
&& !is_light;
|
||||
let role =
|
||||
if is_light {
|
||||
sc_service::Role::Light
|
||||
} else if is_authority {
|
||||
sc_service::Role::Authority { sentry_nodes: self.network_config.sentry_nodes.clone() }
|
||||
} else if !self.sentry.is_empty() {
|
||||
sc_service::Role::Sentry { validators: self.sentry.clone() }
|
||||
} else {
|
||||
sc_service::Role::Full
|
||||
};
|
||||
fn network_params(&self) -> Option<&NetworkParams> {
|
||||
Some(&self.network_params)
|
||||
}
|
||||
|
||||
self.import_params.update_config(&mut config, &role, is_dev)?;
|
||||
fn keystore_params(&self) -> Option<&KeystoreParams> {
|
||||
Some(&self.keystore_params)
|
||||
}
|
||||
|
||||
config.name = match (self.name.as_ref(), keyring) {
|
||||
fn node_name(&self) -> Result<String> {
|
||||
let name: String = match (self.name.as_ref(), self.get_keyring()) {
|
||||
(Some(name), _) => name.to_string(),
|
||||
(_, Some(keyring)) => keyring.to_string(),
|
||||
(None, None) => generate_node_name(),
|
||||
(None, None) => crate::generate_node_name(),
|
||||
};
|
||||
if let Err(msg) = is_node_name_valid(&config.name) {
|
||||
return Err(error::Error::Input(
|
||||
format!("Invalid node name '{}'. Reason: {}. If unsure, use none.",
|
||||
config.name,
|
||||
msg,
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
config.offchain_worker = match (&self.offchain_worker, &role) {
|
||||
(OffchainWorkerEnabled::WhenValidating, sc_service::Role::Authority { .. }) => true,
|
||||
is_node_name_valid(&name).map_err(|msg| {
|
||||
Error::Input(format!(
|
||||
"Invalid node name '{}'. Reason: {}. If unsure, use none.",
|
||||
name, msg
|
||||
));
|
||||
})?;
|
||||
|
||||
Ok(name)
|
||||
}
|
||||
|
||||
fn dev_key_seed(&self, is_dev: bool) -> Result<Option<String>> {
|
||||
Ok(self.get_keyring().map(|a| format!("//{}", a)).or_else(|| {
|
||||
if is_dev && !self.light {
|
||||
Some("//Alice".into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
fn telemetry_endpoints(
|
||||
&self,
|
||||
chain_spec: &Box<dyn ChainSpec>,
|
||||
) -> Result<Option<TelemetryEndpoints>> {
|
||||
Ok(if self.no_telemetry {
|
||||
None
|
||||
} else if !self.telemetry_endpoints.is_empty() {
|
||||
Some(
|
||||
TelemetryEndpoints::new(self.telemetry_endpoints.clone())
|
||||
.map_err(|e| e.to_string())?,
|
||||
)
|
||||
} else {
|
||||
chain_spec.telemetry_endpoints().clone()
|
||||
})
|
||||
}
|
||||
|
||||
fn role(&self, is_dev: bool) -> Result<Role> {
|
||||
let keyring = self.get_keyring();
|
||||
let is_light = self.light;
|
||||
let is_authority = (self.validator || is_dev || keyring.is_some()) && !is_light;
|
||||
|
||||
Ok(if is_light {
|
||||
sc_service::Role::Light
|
||||
} else if is_authority {
|
||||
sc_service::Role::Authority {
|
||||
sentry_nodes: self.sentry_nodes.clone(),
|
||||
}
|
||||
} else if !self.sentry.is_empty() {
|
||||
sc_service::Role::Sentry {
|
||||
validators: self.sentry.clone(),
|
||||
}
|
||||
} else {
|
||||
sc_service::Role::Full
|
||||
})
|
||||
}
|
||||
|
||||
fn force_authoring(&self) -> Result<bool> {
|
||||
// Imply forced authoring on --dev
|
||||
Ok(self.shared_params.dev || self.force_authoring)
|
||||
}
|
||||
|
||||
fn prometheus_config(&self) -> Result<Option<PrometheusConfig>> {
|
||||
if self.no_prometheus {
|
||||
Ok(None)
|
||||
} else {
|
||||
let prometheus_interface: &str = if self.prometheus_external {
|
||||
"0.0.0.0"
|
||||
} else {
|
||||
"127.0.0.1"
|
||||
};
|
||||
|
||||
Ok(Some(PrometheusConfig::new_with_default_registry(
|
||||
parse_address(
|
||||
&format!("{}:{}", prometheus_interface, 9615),
|
||||
self.prometheus_port,
|
||||
)?,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn disable_grandpa(&self) -> Result<bool> {
|
||||
Ok(self.no_grandpa)
|
||||
}
|
||||
|
||||
fn rpc_ws_max_connections(&self) -> Result<Option<usize>> {
|
||||
Ok(self.ws_max_connections)
|
||||
}
|
||||
|
||||
fn rpc_cors(&self, is_dev: bool) -> Result<Option<Vec<String>>> {
|
||||
Ok(self
|
||||
.rpc_cors
|
||||
.clone()
|
||||
.unwrap_or_else(|| {
|
||||
if is_dev {
|
||||
log::warn!("Running in --dev mode, RPC CORS has been disabled.");
|
||||
Cors::All
|
||||
} else {
|
||||
Cors::List(vec![
|
||||
"http://localhost:*".into(),
|
||||
"http://127.0.0.1:*".into(),
|
||||
"https://localhost:*".into(),
|
||||
"https://127.0.0.1:*".into(),
|
||||
"https://polkadot.js.org".into(),
|
||||
])
|
||||
}
|
||||
})
|
||||
.into())
|
||||
}
|
||||
|
||||
fn rpc_http(&self) -> Result<Option<SocketAddr>> {
|
||||
let rpc_interface: &str =
|
||||
interface_str(self.rpc_external, self.unsafe_rpc_external, self.validator)?;
|
||||
|
||||
Ok(Some(parse_address(
|
||||
&format!("{}:{}", rpc_interface, 9933),
|
||||
self.rpc_port,
|
||||
)?))
|
||||
}
|
||||
|
||||
fn rpc_ws(&self) -> Result<Option<SocketAddr>> {
|
||||
let ws_interface: &str =
|
||||
interface_str(self.ws_external, self.unsafe_ws_external, self.validator)?;
|
||||
|
||||
Ok(Some(parse_address(
|
||||
&format!("{}:{}", ws_interface, 9944),
|
||||
self.ws_port,
|
||||
)?))
|
||||
}
|
||||
|
||||
fn offchain_worker(&self, role: &Role) -> Result<bool> {
|
||||
Ok(match (&self.offchain_worker, role) {
|
||||
(OffchainWorkerEnabled::WhenValidating, Role::Authority { .. }) => true,
|
||||
(OffchainWorkerEnabled::Always, _) => true,
|
||||
(OffchainWorkerEnabled::Never, _) => false,
|
||||
(OffchainWorkerEnabled::WhenValidating, _) => false,
|
||||
};
|
||||
|
||||
config.role = role;
|
||||
config.disable_grandpa = self.no_grandpa;
|
||||
|
||||
let client_id = config.client_id();
|
||||
let network_path = config
|
||||
.in_chain_config_dir(crate::commands::DEFAULT_NETWORK_CONFIG_PATH)
|
||||
.expect("We provided a basepath");
|
||||
self.network_config.update_config(
|
||||
&mut config,
|
||||
network_path,
|
||||
client_id,
|
||||
is_dev,
|
||||
)?;
|
||||
|
||||
self.pool_config.update_config(&mut config)?;
|
||||
|
||||
config.dev_key_seed = keyring
|
||||
.map(|a| format!("//{}", a)).or_else(|| {
|
||||
if is_dev && !is_light {
|
||||
Some("//Alice".into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if config.rpc_http.is_none() || self.rpc_port.is_some() {
|
||||
let rpc_interface: &str = interface_str(self.rpc_external, self.unsafe_rpc_external, self.validator)?;
|
||||
config.rpc_http = Some(parse_address(&format!("{}:{}", rpc_interface, 9933), self.rpc_port)?);
|
||||
}
|
||||
if config.rpc_ws.is_none() || self.ws_port.is_some() {
|
||||
let ws_interface: &str = interface_str(self.ws_external, self.unsafe_ws_external, self.validator)?;
|
||||
config.rpc_ws = Some(parse_address(&format!("{}:{}", ws_interface, 9944), self.ws_port)?);
|
||||
}
|
||||
|
||||
config.rpc_ws_max_connections = self.ws_max_connections;
|
||||
config.rpc_cors = self.rpc_cors.clone().unwrap_or_else(|| if is_dev {
|
||||
log::warn!("Running in --dev mode, RPC CORS has been disabled.");
|
||||
Cors::All
|
||||
} else {
|
||||
Cors::List(vec![
|
||||
"http://localhost:*".into(),
|
||||
"http://127.0.0.1:*".into(),
|
||||
"https://localhost:*".into(),
|
||||
"https://127.0.0.1:*".into(),
|
||||
"https://polkadot.js.org".into(),
|
||||
])
|
||||
}).into();
|
||||
|
||||
// Override telemetry
|
||||
if self.no_telemetry {
|
||||
config.telemetry_endpoints = None;
|
||||
} else if !self.telemetry_endpoints.is_empty() {
|
||||
config.telemetry_endpoints = Some(
|
||||
TelemetryEndpoints::new(self.telemetry_endpoints.clone()).map_err(|e| e.to_string())?
|
||||
);
|
||||
}
|
||||
|
||||
// Override prometheus
|
||||
if self.no_prometheus {
|
||||
config.prometheus_config = None;
|
||||
} else if config.prometheus_config.is_none() {
|
||||
let prometheus_interface: &str = if self.prometheus_external { "0.0.0.0" } else { "127.0.0.1" };
|
||||
config.prometheus_config = Some(PrometheusConfig::new_with_default_registry(
|
||||
parse_address(&format!("{}:{}", prometheus_interface, 9615), self.prometheus_port)?,
|
||||
));
|
||||
}
|
||||
|
||||
config.tracing_targets = self.import_params.tracing_targets.clone().into();
|
||||
config.tracing_receiver = self.import_params.tracing_receiver.clone().into();
|
||||
|
||||
// Imply forced authoring on --dev
|
||||
config.force_authoring = self.shared_params.dev || self.force_authoring;
|
||||
|
||||
config.max_runtime_instances = self.max_runtime_instances.min(256);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Run the command that runs the node.
|
||||
pub fn run<FNL, FNF, SL, SF>(
|
||||
self,
|
||||
config: Configuration,
|
||||
new_light: FNL,
|
||||
new_full: FNF,
|
||||
version: &VersionInfo,
|
||||
) -> error::Result<()>
|
||||
where
|
||||
FNL: FnOnce(Configuration) -> Result<SL, sc_service::error::Error>,
|
||||
FNF: FnOnce(Configuration) -> Result<SF, sc_service::error::Error>,
|
||||
SL: AbstractService + Unpin,
|
||||
SF: AbstractService + Unpin,
|
||||
{
|
||||
info!("{}", version.name);
|
||||
info!("✌️ version {}", config.full_version());
|
||||
info!("❤️ by {}, {}-{}", version.author, version.copyright_start_year, Local::today().year());
|
||||
info!("📋 Chain specification: {}", config.expect_chain_spec().name());
|
||||
info!("🏷 Node name: {}", config.name);
|
||||
info!("👤 Role: {}", config.display_role());
|
||||
|
||||
match config.role {
|
||||
Role::Light => run_service_until_exit(
|
||||
config,
|
||||
new_light,
|
||||
),
|
||||
_ => run_service_until_exit(
|
||||
config,
|
||||
new_full,
|
||||
),
|
||||
}
|
||||
fn transaction_pool(&self) -> Result<TransactionPoolOptions> {
|
||||
Ok(self.pool_config.transaction_pool())
|
||||
}
|
||||
|
||||
/// Initialize substrate. This must be done only once.
|
||||
///
|
||||
/// This method:
|
||||
///
|
||||
/// 1. Set the panic handler
|
||||
/// 2. Raise the FD limit
|
||||
/// 3. Initialize the logger
|
||||
pub fn init(&self, version: &VersionInfo) -> error::Result<()> {
|
||||
self.shared_params.init(version)
|
||||
fn max_runtime_instances(&self) -> Result<Option<usize>> {
|
||||
Ok(self.max_runtime_instances.map(|x| x.min(256)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Check whether a node name is considered as valid.
|
||||
pub fn is_node_name_valid(_name: &str) -> Result<(), &str> {
|
||||
pub fn is_node_name_valid(_name: &str) -> std::result::Result<(), &str> {
|
||||
let name = _name.to_string();
|
||||
if name.chars().count() >= NODE_NAME_MAX_LENGTH {
|
||||
if name.chars().count() >= crate::NODE_NAME_MAX_LENGTH {
|
||||
return Err("Node name too long");
|
||||
}
|
||||
|
||||
@@ -512,32 +468,10 @@ pub fn is_node_name_valid(_name: &str) -> Result<(), &str> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
fn input_keystore_password() -> Result<String, String> {
|
||||
rpassword::read_password_from_tty(Some("Keystore password: "))
|
||||
.map_err(|e| format!("{:?}", e))
|
||||
}
|
||||
|
||||
fn generate_node_name() -> String {
|
||||
let result = loop {
|
||||
let node_name = Generator::with_naming(Name::Numbered).next().unwrap();
|
||||
let count = node_name.chars().count();
|
||||
|
||||
if count < NODE_NAME_MAX_LENGTH {
|
||||
break node_name
|
||||
}
|
||||
};
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn parse_address(
|
||||
address: &str,
|
||||
port: Option<u16>,
|
||||
) -> Result<SocketAddr, String> {
|
||||
let mut address: SocketAddr = address.parse().map_err(
|
||||
|_| format!("Invalid address: {}", address)
|
||||
)?;
|
||||
fn parse_address(address: &str, port: Option<u16>) -> std::result::Result<SocketAddr, String> {
|
||||
let mut address: SocketAddr = address
|
||||
.parse()
|
||||
.map_err(|_| format!("Invalid address: {}", address))?;
|
||||
if let Some(port) = port {
|
||||
address.set_port(port);
|
||||
}
|
||||
@@ -549,16 +483,21 @@ fn interface_str(
|
||||
is_external: bool,
|
||||
is_unsafe_external: bool,
|
||||
is_validator: bool,
|
||||
) -> Result<&'static str, error::Error> {
|
||||
) -> Result<&'static str> {
|
||||
if is_external && is_validator {
|
||||
return Err(error::Error::Input("--rpc-external and --ws-external options shouldn't be \
|
||||
return Err(Error::Input(
|
||||
"--rpc-external and --ws-external options shouldn't be \
|
||||
used if the node is running as a validator. Use `--unsafe-rpc-external` if you understand \
|
||||
the risks. See the options description for more information.".to_owned()));
|
||||
the risks. See the options description for more information."
|
||||
.to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
if is_external || is_unsafe_external {
|
||||
log::warn!("It isn't safe to expose RPC publicly without a proxy server that filters \
|
||||
available set of RPC methods.");
|
||||
log::warn!(
|
||||
"It isn't safe to expose RPC publicly without a proxy server that filters \
|
||||
available set of RPC methods."
|
||||
);
|
||||
|
||||
Ok("0.0.0.0")
|
||||
} else {
|
||||
@@ -574,8 +513,8 @@ enum TelemetryParsingError {
|
||||
|
||||
impl std::error::Error for TelemetryParsingError {}
|
||||
|
||||
impl fmt::Display for TelemetryParsingError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl std::fmt::Display for TelemetryParsingError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match &*self {
|
||||
TelemetryParsingError::MissingVerbosity => write!(f, "Verbosity level missing"),
|
||||
TelemetryParsingError::VerbosityParsingError(e) => write!(f, "{}", e),
|
||||
@@ -583,13 +522,15 @@ impl fmt::Display for TelemetryParsingError {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_telemetry_endpoints(s: &str) -> Result<(String, u8), TelemetryParsingError> {
|
||||
fn parse_telemetry_endpoints(s: &str) -> std::result::Result<(String, u8), TelemetryParsingError> {
|
||||
let pos = s.find(' ');
|
||||
match pos {
|
||||
None => Err(TelemetryParsingError::MissingVerbosity),
|
||||
Some(pos_) => {
|
||||
let url = s[..pos_].to_string();
|
||||
let verbosity = s[pos_ + 1..].parse().map_err(TelemetryParsingError::VerbosityParsingError)?;
|
||||
let verbosity = s[pos_ + 1..]
|
||||
.parse()
|
||||
.map_err(TelemetryParsingError::VerbosityParsingError)?;
|
||||
Ok((url, verbosity))
|
||||
}
|
||||
}
|
||||
@@ -617,7 +558,7 @@ impl From<Cors> for Option<Vec<String>> {
|
||||
}
|
||||
|
||||
/// Parse cors origins.
|
||||
fn parse_cors(s: &str) -> Result<Cors, Box<dyn std::error::Error>> {
|
||||
fn parse_cors(s: &str) -> std::result::Result<Cors, Box<dyn std::error::Error>> {
|
||||
let mut is_all = false;
|
||||
let mut origins = Vec::new();
|
||||
for part in s.split(',') {
|
||||
@@ -625,29 +566,21 @@ fn parse_cors(s: &str) -> Result<Cors, Box<dyn std::error::Error>> {
|
||||
"all" | "*" => {
|
||||
is_all = true;
|
||||
break;
|
||||
},
|
||||
}
|
||||
other => origins.push(other.to_owned()),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(if is_all { Cors::All } else { Cors::List(origins) })
|
||||
Ok(if is_all {
|
||||
Cors::All
|
||||
} else {
|
||||
Cors::List(origins)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sc_service::{GenericChainSpec, config::DatabaseConfig};
|
||||
|
||||
const TEST_VERSION_INFO: &'static VersionInfo = &VersionInfo {
|
||||
name: "node-test",
|
||||
version: "0.1.0",
|
||||
commit: "some_commit",
|
||||
executable_name: "node-test",
|
||||
description: "description",
|
||||
author: "author",
|
||||
support_url: "http://example.org",
|
||||
copyright_start_year: 2020,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn tests_node_name_good() {
|
||||
@@ -663,94 +596,4 @@ mod tests {
|
||||
assert!(is_node_name_valid("www.visit.me").is_err());
|
||||
assert!(is_node_name_valid("email@domain").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keystore_path_is_generated_correctly() {
|
||||
let chain_spec = GenericChainSpec::from_genesis(
|
||||
"test",
|
||||
"test-id",
|
||||
|| (),
|
||||
Vec::new(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None::<()>,
|
||||
);
|
||||
|
||||
for keystore_path in vec![None, Some("/keystore/path")] {
|
||||
let args: Vec<&str> = vec![];
|
||||
let mut cli = RunCmd::from_iter(args);
|
||||
cli.keystore_path = keystore_path.clone().map(PathBuf::from);
|
||||
|
||||
let mut config = Configuration::default();
|
||||
config.config_dir = Some(PathBuf::from("/test/path"));
|
||||
config.chain_spec = Some(Box::new(chain_spec.clone()));
|
||||
let chain_spec = chain_spec.clone();
|
||||
cli.update_config(&mut config, move |_| Ok(Box::new(chain_spec)), TEST_VERSION_INFO).unwrap();
|
||||
|
||||
let expected_path = match keystore_path {
|
||||
Some(path) => PathBuf::from(path),
|
||||
None => PathBuf::from("/test/path/chains/test-id/keystore"),
|
||||
};
|
||||
|
||||
assert_eq!(expected_path, config.keystore.path().unwrap().to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ensure_load_spec_provide_defaults() {
|
||||
let chain_spec = GenericChainSpec::from_genesis(
|
||||
"test",
|
||||
"test-id",
|
||||
|| (),
|
||||
vec!["/ip4/127.0.0.1/tcp/30333/p2p/QmdSHZLmwEL5Axz5JvWNE2mmxU7qyd7xHBFpyUfktgAdg7".parse().unwrap()],
|
||||
Some(TelemetryEndpoints::new(vec![("wss://foo/bar".to_string(), 42)])
|
||||
.expect("provided url should be valid")),
|
||||
None,
|
||||
None,
|
||||
None::<()>,
|
||||
);
|
||||
|
||||
let args: Vec<&str> = vec![];
|
||||
let cli = RunCmd::from_iter(args);
|
||||
|
||||
let mut config = Configuration::from_version(TEST_VERSION_INFO);
|
||||
cli.update_config(&mut config, |_| Ok(Box::new(chain_spec)), TEST_VERSION_INFO).unwrap();
|
||||
|
||||
assert!(config.chain_spec.is_some());
|
||||
assert!(!config.network.boot_nodes.is_empty());
|
||||
assert!(config.telemetry_endpoints.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ensure_update_config_for_running_node_provides_defaults() {
|
||||
let chain_spec = GenericChainSpec::from_genesis(
|
||||
"test",
|
||||
"test-id",
|
||||
|| (),
|
||||
vec![],
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None::<()>,
|
||||
);
|
||||
|
||||
let args: Vec<&str> = vec![];
|
||||
let cli = RunCmd::from_iter(args);
|
||||
|
||||
let mut config = Configuration::from_version(TEST_VERSION_INFO);
|
||||
cli.init(&TEST_VERSION_INFO).unwrap();
|
||||
cli.update_config(&mut config, |_| Ok(Box::new(chain_spec)), TEST_VERSION_INFO).unwrap();
|
||||
|
||||
assert!(config.config_dir.is_some());
|
||||
assert!(config.database.is_some());
|
||||
if let Some(DatabaseConfig::Path { ref cache_size, .. }) = config.database {
|
||||
assert!(cache_size.is_some());
|
||||
} else {
|
||||
panic!("invalid config.database variant");
|
||||
}
|
||||
assert!(!config.name.is_empty());
|
||||
assert!(config.network.config_path.is_some());
|
||||
assert!(!config.network.listen_addresses.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user