Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bin/node-template/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub fn run<I, T, E>(args: I, exit: E, version: VersionInfo) -> error::Result<()>
Ok(new_full_start!(config).0), load_spec, exit),
ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_>|
Ok(new_full_start!(config).0), load_spec, exit),
ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(|config: Config<_>|
Ok(new_full_start!(config).0), load_spec, exit),
ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec),
ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_>|
Ok(new_full_start!(config).0), load_spec),
Expand Down
2 changes: 2 additions & 0 deletions bin/node/cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ pub fn run<I, T, E>(args: I, exit: E, version: substrate_cli::VersionInfo) -> er
Ok(new_full_start!(config).0), load_spec, exit),
ParseAndPrepare::ImportBlocks(cmd) => cmd.run_with_builder(|config: Config<_, _>|
Ok(new_full_start!(config).0), load_spec, exit),
ParseAndPrepare::CheckBlock(cmd) => cmd.run_with_builder(|config: Config<_, _>|
Ok(new_full_start!(config).0), load_spec, exit),
ParseAndPrepare::PurgeChain(cmd) => cmd.run(load_spec),
ParseAndPrepare::RevertChain(cmd) => cmd.run_with_builder(|config: Config<_, _>|
Ok(new_full_start!(config).0), load_spec),
Expand Down
1 change: 1 addition & 0 deletions bin/node/cli/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ mod tests {
auxiliary: Vec::new(),
fork_choice: ForkChoiceStrategy::LongestChain,
allow_missing_state: false,
import_existing: false,
};

block_import.import_block(params, Default::default())
Expand Down
193 changes: 122 additions & 71 deletions client/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub mod informant;
use client_api::execution_extensions::ExecutionStrategies;
use service::{
config::{Configuration, DatabaseConfig},
ServiceBuilderExport, ServiceBuilderImport, ServiceBuilderRevert,
ServiceBuilderCommand,
RuntimeGenesis, ChainSpecExtension, PruningMode, ChainSpec,
};
use network::{
Expand All @@ -54,7 +54,7 @@ pub use structopt::clap::App;
use params::{
RunCmd, PurgeChainCmd, RevertCmd, ImportBlocksCmd, ExportBlocksCmd, BuildSpecCmd,
NetworkConfigurationParams, MergeParameters, TransactionPoolParams,
NodeKeyParams, NodeKeyType, Cors,
NodeKeyParams, NodeKeyType, Cors, CheckBlockCmd,
};
pub use params::{NoCustom, CoreParams, SharedParams, ExecutionStrategy as ExecutionStrategyParam};
pub use traits::{GetLogFilter, AugmentClap};
Expand All @@ -64,6 +64,8 @@ use lazy_static::lazy_static;
use futures::{Future, FutureExt, TryFutureExt};
use futures01::{Async, Future as _};
use substrate_telemetry::TelemetryEndpoints;
use sr_primitives::generic::BlockId;
use sr_primitives::traits::Block as BlockT;

/// default sub directory to store network config
const DEFAULT_NETWORK_CONFIG_PATH : &'static str = "network";
Expand Down Expand Up @@ -231,6 +233,9 @@ where
params::CoreParams::ImportBlocks(params) => ParseAndPrepare::ImportBlocks(
ParseAndPrepareImport { params, version }
),
params::CoreParams::CheckBlock(params) => ParseAndPrepare::CheckBlock(
CheckBlock { params, version }
),
params::CoreParams::PurgeChain(params) => ParseAndPrepare::PurgeChain(
ParseAndPreparePurge { params, version }
),
Expand Down Expand Up @@ -263,6 +268,8 @@ pub enum ParseAndPrepare<'a, CC, RP> {
ExportBlocks(ParseAndPrepareExport<'a>),
/// Command ready to import the chain.
ImportBlocks(ParseAndPrepareImport<'a>),
/// Command to check a block.
CheckBlock(CheckBlock<'a>),
/// Command ready to purge the chain.
PurgeChain(ParseAndPreparePurge<'a>),
/// Command ready to revert the chain.
Expand Down Expand Up @@ -366,7 +373,7 @@ impl<'a> ParseAndPrepareExport<'a> {
) -> error::Result<()>
where S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
F: FnOnce(Configuration<C, G, E>) -> Result<B, error::Error>,
B: ServiceBuilderExport,
B: ServiceBuilderCommand,
C: Default,
G: RuntimeGenesis,
E: ChainSpecExtension,
Expand Down Expand Up @@ -427,19 +434,13 @@ impl<'a> ParseAndPrepareImport<'a> {
) -> error::Result<()>
where S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
F: FnOnce(Configuration<C, G, E>) -> Result<B, error::Error>,
B: ServiceBuilderImport,
B: ServiceBuilderCommand,
C: Default,
G: RuntimeGenesis,
E: ChainSpecExtension,
Exit: IntoExit
{
let mut config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?;
config.wasm_method = self.params.wasm_method.into();
config.execution_strategies = ExecutionStrategies {
importing: self.params.execution.into(),
other: self.params.execution.into(),
..Default::default()
};
let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?;

let file: Box<dyn ReadPlusSeek + Send> = match self.params.input {
Some(filename) => Box::new(File::open(filename)?),
Expand All @@ -461,7 +462,7 @@ impl<'a> ParseAndPrepareImport<'a> {
let _ = exit_send.send(());
});

let mut import_fut = builder(config)?.import_blocks(file);
let mut import_fut = builder(config)?.import_blocks(file, false);
let fut = futures01::future::poll_fn(|| {
if exit_recv.try_recv().is_ok() {
return Ok(Async::Ready(()));
Expand All @@ -475,6 +476,49 @@ impl<'a> ParseAndPrepareImport<'a> {
}
}

/// Command to check a block.
pub struct CheckBlock<'a> {
params: CheckBlockCmd,
version: &'a VersionInfo,
}

impl<'a> CheckBlock<'a> {
/// Runs the command and imports to the chain.
pub fn run_with_builder<C, G, E, F, B, S, Exit>(
self,
builder: F,
spec_factory: S,
_exit: Exit,
) -> error::Result<()>
where S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
F: FnOnce(Configuration<C, G, E>) -> Result<B, error::Error>,
B: ServiceBuilderCommand,
<<B as ServiceBuilderCommand>::Block as BlockT>::Hash: FromStr,
C: Default,
G: RuntimeGenesis,
E: ChainSpecExtension,
Exit: IntoExit
{
let config = create_config_with_db_path(spec_factory, &self.params.shared_params, self.version)?;

let input = if self.params.input.starts_with("0x") { &self.params.input[2..] } else { &self.params.input[..] };
let block_id = match FromStr::from_str(input) {
Ok(hash) => BlockId::hash(hash),
Err(_) => match self.params.input.parse::<u32>() {
Ok(n) => BlockId::number((n as u32).into()),
Err(_) => return Err(error::Error::Input("Invalid hash or number specified".into())),
}
};

let start = std::time::Instant::now();
let check = builder(config)?.check_block(block_id);
let mut runtime = tokio::runtime::current_thread::Runtime::new().unwrap();
runtime.block_on(check)?;
println!("Completed in {} ms.", start.elapsed().as_millis());
Ok(())
}
}

/// Command ready to purge the chain.
pub struct ParseAndPreparePurge<'a> {
params: PurgeChainCmd,
Expand Down Expand Up @@ -548,7 +592,7 @@ impl<'a> ParseAndPrepareRevert<'a> {
) -> error::Result<()> where
S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
F: FnOnce(Configuration<C, G, E>) -> Result<B, error::Error>,
B: ServiceBuilderRevert,
B: ServiceBuilderCommand,
C: Default,
G: RuntimeGenesis,
E: ChainSpecExtension,
Expand Down Expand Up @@ -694,69 +738,24 @@ fn fill_config_keystore_password<C, G, E>(
Ok(())
}

fn create_run_node_config<C, G, E, S>(
cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo,
) -> error::Result<Configuration<C, G, E>>
fn fill_shared_config<C, G, E>(config: &mut Configuration<C, G, E>, cli: &SharedParams, role: service::Roles)
-> error::Result<()>
where
C: Default,
G: RuntimeGenesis,
E: ChainSpecExtension,
S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
{
let spec = load_spec(&cli.shared_params, spec_factory)?;
let base_path = base_path(&cli.shared_params, &version);
let mut config = service::Configuration::default_with_spec_and_base_path(spec.clone(), Some(base_path));

fill_config_keystore_password(&mut config, &cli)?;

config.impl_name = impl_name;
config.impl_commit = version.commit;
config.impl_version = version.version;

config.name = match cli.name.or(cli.keyring.account.map(|a| a.to_string())) {
None => generate_node_name(),
Some(name) => name,
};
match is_node_name_valid(&config.name) {
Ok(_) => (),
Err(msg) => Err(
error::Error::Input(
format!("Invalid node name '{}'. Reason: {}. If unsure, use none.",
config.name,
msg
)
)
)?
}

config.keystore_path = cli.keystore_path.or_else(|| config.in_chain_config_dir(DEFAULT_KEYSTORE_CONFIG_PATH));

config.database = DatabaseConfig::Path {
path: config.in_chain_config_dir(DEFAULT_DB_CONFIG_PATH).expect("We provided a base_path."),
cache_size: Some(cli.database_cache_size),
};
config.state_cache_size = cli.state_cache_size;

let is_dev = cli.shared_params.dev;
let is_authority = cli.validator || cli.sentry || is_dev || cli.keyring.account.is_some();

let role =
if cli.light {
service::Roles::LIGHT
} else if is_authority {
service::Roles::AUTHORITY
} else {
service::Roles::FULL
};

// set sentry mode (i.e. act as an authority but **never** actively participate)
config.sentry_mode = cli.sentry;

// by default we disable pruning if the node is an authority (i.e.
// `ArchiveAll`), otherwise we keep state for the last 256 blocks. if the
// node is an authority and pruning is enabled explicitly, then we error
// unless `unsafe_pruning` is set.
config.pruning = match cli.pruning {
config.pruning = match &cli.pruning {
Some(ref s) if s == "archive" => PruningMode::ArchiveAll,
None if role == service::Roles::AUTHORITY => PruningMode::ArchiveAll,
None => PruningMode::default(),
Expand All @@ -776,7 +775,7 @@ where

config.wasm_method = cli.wasm_method.into();

let exec = cli.execution_strategies;
let exec = &cli.execution_strategies;
let exec_all_or = |strat: params::ExecutionStrategy| exec.execution.unwrap_or(strat).into();
config.execution_strategies = ExecutionStrategies {
syncing: exec_all_or(exec.execution_syncing),
Expand All @@ -785,6 +784,61 @@ where
offchain_worker: exec_all_or(exec.execution_offchain_worker),
other: exec_all_or(exec.execution_other),
};
Ok(())
}

fn create_run_node_config<C, G, E, S>(
cli: RunCmd, spec_factory: S, impl_name: &'static str, version: &VersionInfo,
) -> error::Result<Configuration<C, G, E>>
where
C: Default,
G: RuntimeGenesis,
E: ChainSpecExtension,
S: FnOnce(&str) -> Result<Option<ChainSpec<G, E>>, String>,
{
let spec = load_spec(&cli.shared_params, spec_factory)?;
let base_path = base_path(&cli.shared_params, &version);
let mut config = service::Configuration::default_with_spec_and_base_path(spec.clone(), Some(base_path));

fill_config_keystore_password(&mut config, &cli)?;

let is_dev = cli.shared_params.dev;
let is_authority = cli.validator || cli.sentry || is_dev || cli.keyring.account.is_some();
let role =
if cli.light {
service::Roles::LIGHT
} else if is_authority {
service::Roles::AUTHORITY
} else {
service::Roles::FULL
};

fill_shared_config(&mut config, &cli.shared_params, role)?;

config.impl_name = impl_name;
config.impl_commit = version.commit;
config.impl_version = version.version;

config.name = match cli.name.or(cli.keyring.account.map(|a| a.to_string())) {
None => generate_node_name(),
Some(name) => name,
};
match is_node_name_valid(&config.name) {
Ok(_) => (),
Err(msg) => Err(
error::Error::Input(
format!("Invalid node name '{}'. Reason: {}. If unsure, use none.",
config.name,
msg
)
)
)?
}

config.keystore_path = cli.keystore_path.or_else(|| config.in_chain_config_dir(DEFAULT_KEYSTORE_CONFIG_PATH));

// set sentry mode (i.e. act as an authority but **never** actively participate)
config.sentry_mode = cli.sentry;

config.offchain_worker = match (cli.offchain_worker, role) {
(params::OffchainWorkerEnabled::WhenValidating, service::Roles::AUTHORITY) => true,
Expand Down Expand Up @@ -871,11 +925,7 @@ where
let base_path = base_path(cli, version);

let mut config = service::Configuration::default_with_spec_and_base_path(spec.clone(), Some(base_path));
config.database = DatabaseConfig::Path {
path: config.in_chain_config_dir(DEFAULT_DB_CONFIG_PATH).expect("We provided a base_path."),
cache_size: None,
};

fill_shared_config(&mut config, &cli, service::Roles::FULL)?;
Ok(config)
}

Expand Down Expand Up @@ -943,14 +993,15 @@ fn init_logger(pattern: &str) {
)
};

if !enable_color {
output = kill_color(output.as_ref());
}

if !isatty && record.level() <= log::Level::Info && atty::is(atty::Stream::Stdout) {
// duplicate INFO/WARN output to console
println!("{}", output);
}

if !enable_color {
output = kill_color(output.as_ref());
}

writeln!(buf, "{}", output)
});

Expand Down
Loading