Refactor and port CLI from Docopt to Clap (#2066) (#6356)

* Refactor and port CLI from Docopt to Clap (#2066)

* Add --can-restart and --force-direct to help

* Add flag support to subc & move import/export options to subcommand

* Reorder subcommand args (put positional args last in CLI help message)
This commit is contained in:
Axel Chalon 2017-09-05 13:30:22 +02:00 committed by Gav Wood
parent a62238c19d
commit be745f711f
15 changed files with 1861 additions and 1243 deletions

1
Cargo.lock generated
View File

@ -1870,6 +1870,7 @@ version = "1.8.0"
dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)",
"daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -11,6 +11,7 @@ log = "0.3"
env_logger = "0.4"
rustc-hex = "1.0"
docopt = "0.8"
clap = "2"
time = "0.1"
num_cpus = "1.2"
number_prefix = "0.2"

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,7 @@ macro_rules! println_stderr(
);
macro_rules! otry {
($e: expr) => (
($e:expr) => (
match $e {
Some(ref v) => v,
None => {
@ -31,21 +31,107 @@ macro_rules! otry {
}
)
}
macro_rules! if_option {
(Option<$type:ty>, THEN {$($then:tt)*} ELSE {$($otherwise:tt)*}) => (
$($then)*
);
($type:ty, THEN {$($then:tt)*} ELSE {$($otherwise:tt)*}) => (
$($otherwise)*
);
}
macro_rules! if_vec {
(Vec<$type:ty>, THEN {$($then:tt)*} ELSE {$($otherwise:tt)*}) => (
$($then)*
);
($type:ty, THEN {$($then:tt)*} ELSE {$($otherwise:tt)*}) => (
$($otherwise)*
);
}
macro_rules! if_option_vec {
(Option<Vec<String>>, THEN {$then:expr} ELSE {$otherwise:expr}) => (
$then
);
(Option<$type:ty>, THEN {$then:expr} ELSE {$otherwise:expr}) => (
$otherwise
);
}
macro_rules! inner_option_type {
(Option<$type:ty>) => (
$type
)
}
macro_rules! inner_vec_type {
(Vec<$type:ty>) => (
$type
)
}
macro_rules! inner_option_vec_type {
(Option<Vec<String>>) => (
String
)
}
macro_rules! usage_with_ident {
($name:expr, $usage:expr, $help:expr) => (
if $usage.contains("<") {
format!("<{}> {} '{}'",$name, $usage, $help)
} else {
format!("[{}] {} '{}'",$name, $usage, $help)
}
);
}
macro_rules! underscore_to_hyphen {
($e:expr) => (
str::replace($e, "_", "-")
)
}
macro_rules! usage {
(
{
$(
$field_a:ident : $typ_a:ty,
CMD $subc:ident
{
$subc_help:expr,
$(
CMD $subc_subc:ident
{
$subc_subc_help:expr,
$(
FLAG $subc_subc_flag:ident : (bool) = false, $subc_subc_flag_usage:expr, $subc_subc_flag_help:expr,
)*
$(
ARG $subc_subc_arg:ident : ($($subc_subc_arg_type_tt:tt)+) = $subc_subc_arg_default:expr, $subc_subc_arg_usage:expr, $subc_subc_arg_help:expr,
)*
}
)*
$(
FLAG $subc_flag:ident : (bool) = false, $subc_flag_usage:expr, $subc_flag_help:expr,
)*
$(
ARG $subc_arg:ident : ($($subc_arg_type_tt:tt)+) = $subc_arg_default:expr, $subc_arg_usage:expr, $subc_arg_help:expr,
)*
}
)*
}
{
$(
$field:ident : $typ:ty = $default:expr, or $from_config:expr,
)*
}
{
[$group_name:expr]
$(
$field_s:ident : $typ_s:ty, display $default_s:expr, or $from_config_s:expr,
FLAG $flag:ident : (bool) = false, or $flag_from_config:expr, $flag_usage:expr, $flag_help:expr,
)*
$(
ARG $arg:ident : ($($arg_type_tt:tt)+) = $arg_default:expr, or $arg_from_config:expr, $arg_usage:expr, $arg_help:expr,
)*
)*
}
) => {
@ -53,12 +139,17 @@ macro_rules! usage {
use std::{fs, io, process};
use std::io::{Read, Write};
use util::version;
use docopt::{Docopt, Error as DocoptError};
use clap::{Arg, App, SubCommand, AppSettings, Error as ClapError};
use helpers::replace_home;
use std::ffi::OsStr;
use std::collections::HashMap;
#[cfg(test)]
use regex::Regex;
#[derive(Debug)]
pub enum ArgsError {
Docopt(DocoptError),
Clap(ClapError),
Decode(toml::de::Error),
Config(String, io::Error),
}
@ -66,7 +157,7 @@ macro_rules! usage {
impl ArgsError {
pub fn exit(self) -> ! {
match self {
ArgsError::Docopt(e) => e.exit(),
ArgsError::Clap(e) => e.exit(),
ArgsError::Decode(e) => {
println_stderr!("You might have supplied invalid parameters in config file.");
println_stderr!("{}", e);
@ -81,9 +172,9 @@ macro_rules! usage {
}
}
impl From<DocoptError> for ArgsError {
fn from(e: DocoptError) -> Self {
ArgsError::Docopt(e)
impl From<ClapError> for ArgsError {
fn from(e: ClapError) -> Self {
ArgsError::Clap(e)
}
}
@ -96,15 +187,33 @@ macro_rules! usage {
#[derive(Debug, PartialEq)]
pub struct Args {
$(
pub $field_a: $typ_a,
pub $subc: bool,
$(
pub $subc_subc: bool,
$(
pub $subc_subc_flag: bool,
)*
$(
pub $subc_subc_arg: $($subc_subc_arg_type_tt)+,
)*
)*
$(
pub $field: $typ,
pub $subc_flag: bool,
)*
$(
pub $subc_arg: $($subc_arg_type_tt)+,
)*
)*
$(
pub $field_s: $typ_s,
$(
pub $flag: bool,
)*
$(
pub $arg: $($arg_type_tt)+,
)*
)*
}
@ -112,15 +221,32 @@ macro_rules! usage {
fn default() -> Self {
Args {
$(
$field_a: Default::default(),
$subc: Default::default(),
$(
$subc_subc: Default::default(),
$(
$subc_subc_flag: Default::default(),
)*
$(
$subc_subc_arg: Default::default(),
)*
)*
$(
$field: $default.into(),
$subc_flag: Default::default(),
)*
$(
$subc_arg: Default::default(),
)*
)*
$(
$field_s: Default::default(),
$(
$flag: Default::default(),
)*
$(
$arg: Default::default(),
)*
)*
}
}
@ -129,13 +255,46 @@ macro_rules! usage {
#[derive(Default, Debug, PartialEq, Clone, Deserialize)]
struct RawArgs {
$(
$field_a: $typ_a,
$subc: bool,
$(
$subc_subc: bool,
$(
$subc_subc_flag: bool,
)*
$(
$field: Option<$typ>,
$subc_subc_arg: if_option!(
$($subc_subc_arg_type_tt)+,
THEN { $($subc_subc_arg_type_tt)+ }
ELSE { Option<$($subc_subc_arg_type_tt)+> }
),
)*
)*
$(
$subc_flag: bool,
)*
$(
$field_s: Option<$typ_s>,
$subc_arg: if_option!(
$($subc_arg_type_tt)+,
THEN { $($subc_arg_type_tt)+ }
ELSE { Option<$($subc_arg_type_tt)+> }
),
)*
)*
$(
$(
$flag: bool,
)*
$(
$arg: if_option!(
$($arg_type_tt)+,
THEN { $($arg_type_tt)+ }
ELSE { Option<$($arg_type_tt)+> }
),
)*
)*
}
@ -149,9 +308,9 @@ macro_rules! usage {
return Ok(raw_args.into_args(Config::default()));
}
let config_file = raw_args.flag_config.clone().unwrap_or_else(|| raw_args.clone().into_args(Config::default()).flag_config);
let config_file = raw_args.arg_config.clone().unwrap_or_else(|| raw_args.clone().into_args(Config::default()).arg_config);
let config_file = replace_home(&::dir::default_data_path(), &config_file);
match (fs::File::open(&config_file), raw_args.flag_config.clone()) {
match (fs::File::open(&config_file), raw_args.arg_config.clone()) {
// Load config file
(Ok(mut file), _) => {
println_stderr!("Loading config file from {}", &config_file);
@ -178,7 +337,7 @@ macro_rules! usage {
#[cfg(test)]
fn parse_with_config<S: AsRef<str>>(command: &[S], config: Config) -> Result<Self, ArgsError> {
RawArgs::parse(command).map(|raw| raw.into_args(config)).map_err(ArgsError::Docopt)
RawArgs::parse(command).map(|raw| raw.into_args(config)).map_err(ArgsError::Clap)
}
fn parse_config(config: &str) -> Result<Config, ArgsError> {
@ -188,41 +347,346 @@ macro_rules! usage {
pub fn print_version() -> String {
format!(include_str!("./version.txt"), version())
}
#[allow(unused_mut)] // subc_subc_exist may be assigned true by the macro
#[allow(unused_assignments)] // Rust issue #22630
pub fn print_help() -> String {
let mut help : String = include_str!("./usage_header.txt").to_owned();
help.push_str("\n\n");
// Subcommands
help.push_str("parity [options]\n");
$(
{
let mut subc_subc_exist = false;
$(
subc_subc_exist = true;
let subc_subc_usages : Vec<&str> = vec![
$(
concat!("[",$subc_subc_flag_usage,"]"),
)*
$(
$subc_subc_arg_usage,
)*
];
if subc_subc_usages.is_empty() {
help.push_str(&format!("parity [options] {} {}\n", underscore_to_hyphen!(&stringify!($subc)[4..]), underscore_to_hyphen!(&stringify!($subc_subc)[stringify!($subc).len()+1..])));
} else {
help.push_str(&format!("parity [options] {} {} {}\n", underscore_to_hyphen!(&stringify!($subc)[4..]), underscore_to_hyphen!(&stringify!($subc_subc)[stringify!($subc).len()+1..]), subc_subc_usages.join(" ")));
}
)*
// Print the subcommand on its own only if it has no subsubcommands
if !subc_subc_exist {
let subc_usages : Vec<&str> = vec![
$(
concat!("[",$subc_flag_usage,"]"),
)*
$(
$subc_arg_usage,
)*
];
if subc_usages.is_empty() {
help.push_str(&format!("parity [options] {}\n", underscore_to_hyphen!(&stringify!($subc)[4..])));
} else {
help.push_str(&format!("parity [options] {} {}\n", underscore_to_hyphen!(&stringify!($subc)[4..]), subc_usages.join(" ")));
}
}
}
)*
// Arguments and flags
$(
help.push_str("\n");
help.push_str($group_name); help.push_str(":\n");
$(
help.push_str(&format!("\t{}\n\t\t{}\n", $flag_usage, $flag_help));
)*
$(
if_option!(
$($arg_type_tt)+,
THEN {
if_option_vec!(
$($arg_type_tt)+,
THEN {
help.push_str(&format!("\t{}\n\t\t{} (default: {:?})\n", $arg_usage, $arg_help, {let x : inner_option_type!($($arg_type_tt)+)> = $arg_default; x}))
}
ELSE {
help.push_str(&format!("\t{}\n\t\t{}{}\n", $arg_usage, $arg_help, $arg_default.map(|x: inner_option_type!($($arg_type_tt)+)| format!(" (default: {})",x)).unwrap_or("".to_owned())))
}
)
}
ELSE {
if_vec!(
$($arg_type_tt)+,
THEN {
help.push_str(&format!("\t{}\n\t\t{} (default: {:?})\n", $arg_usage, $arg_help, {let x : $($arg_type_tt)+ = $arg_default; x}))
}
ELSE {
help.push_str(&format!("\t{}\n\t\t{} (default: {})\n", $arg_usage, $arg_help, $arg_default))
}
)
}
);
)*
)*
help
}
}
impl RawArgs {
fn into_args(self, config: Config) -> Args {
let mut args = Args::default();
$(
args.$field_a = self.$field_a;
args.$subc = self.$subc;
$(
args.$subc_subc = self.$subc_subc;
$(
args.$subc_subc_flag = self.$subc_subc_flag;
)*
$(
args.$field = self.$field.or_else(|| $from_config(&config)).unwrap_or_else(|| $default.into());
args.$subc_subc_arg = if_option!(
$($subc_subc_arg_type_tt)+,
THEN { self.$subc_subc_arg.or($subc_subc_arg_default) }
ELSE { self.$subc_subc_arg.unwrap_or($subc_subc_arg_default.into()) }
);
)*
)*
$(
args.$subc_flag = self.$subc_flag;
)*
$(
args.$field_s = self.$field_s.or_else(|| $from_config_s(&config)).unwrap_or(None);
args.$subc_arg = if_option!(
$($subc_arg_type_tt)+,
THEN { self.$subc_arg.or($subc_arg_default) }
ELSE { self.$subc_arg.unwrap_or($subc_arg_default.into()) }
);
)*
)*
$(
$(
args.$flag = self.$flag || $flag_from_config(&config).unwrap_or(false);
)*
$(
args.$arg = if_option!(
$($arg_type_tt)+,
THEN { self.$arg.or_else(|| $arg_from_config(&config)).or_else(|| $arg_default.into()) }
ELSE { self.$arg.or_else(|| $arg_from_config(&config)).unwrap_or_else(|| $arg_default.into()) }
);
)*
)*
args
}
pub fn parse<S: AsRef<str>>(command: &[S]) -> Result<Self, DocoptError> {
Docopt::new(Self::usage()).and_then(|d| d.argv(command).deserialize())
}
#[allow(unused_variables)] // the submatches of arg-less subcommands aren't used
pub fn parse<S: AsRef<str>>(command: &[S]) -> Result<Self, ClapError> {
fn usage() -> String {
format!(
include_str!("./usage.txt"),
let usages = vec![
$(
$field={ let v: $typ = $default.into(); v },
// Uncomment this to debug
// "named argument never used" error
// $field = $default,
$(
usage_with_ident!(stringify!($arg), $arg_usage, $arg_help),
)*
$(
$field_s = $default_s,
usage_with_ident!(stringify!($flag), $flag_usage, $flag_help),
)*
)*
];
// Hash of subc|subc_subc => Vec<String>
let mut subc_usages = HashMap::new();
$(
{
let this_subc_usages = vec![
$(
usage_with_ident!(stringify!($subc_flag), $subc_flag_usage, $subc_flag_help),
)*
$(
usage_with_ident!(stringify!($subc_arg), $subc_arg_usage, $subc_arg_help),
)*
];
subc_usages.insert(stringify!($subc),this_subc_usages);
$(
{
let this_subc_subc_usages = vec![
$(
usage_with_ident!(stringify!($subc_subc_flag), $subc_subc_flag_usage, $subc_subc_flag_help),
)*
$(
usage_with_ident!(stringify!($subc_subc_arg), $subc_subc_arg_usage, $subc_subc_arg_help),
)*
];
subc_usages.insert(stringify!($subc_subc), this_subc_subc_usages);
}
)*
}
)*
let matches = App::new("Parity")
.global_setting(AppSettings::VersionlessSubcommands)
.global_setting(AppSettings::AllowLeadingHyphen) // allow for example --allow-ips -10.0.0.0/8
.global_setting(AppSettings::DisableHelpSubcommand)
.help(Args::print_help().as_ref())
.args(&usages.iter().map(|u| Arg::from_usage(u).use_delimiter(false)).collect::<Vec<Arg>>())
$(
.subcommand(
SubCommand::with_name(&underscore_to_hyphen!(&stringify!($subc)[4..]))
.about($subc_help)
.args(&subc_usages.get(stringify!($subc)).unwrap().iter().map(|u| Arg::from_usage(u).use_delimiter(false)).collect::<Vec<Arg>>())
$(
.setting(AppSettings::SubcommandRequired) // prevent from running `parity account`
.subcommand(
SubCommand::with_name(&underscore_to_hyphen!(&stringify!($subc_subc)[stringify!($subc).len()+1..]))
.about($subc_subc_help)
.args(&subc_usages.get(stringify!($subc_subc)).unwrap().iter().map(|u| Arg::from_usage(u).use_delimiter(false)).collect::<Vec<Arg>>())
)
)*
)
)*
.get_matches_from_safe(command.iter().map(|x| OsStr::new(x.as_ref())))?;
let mut raw_args : RawArgs = Default::default();
$(
$(
raw_args.$flag = matches.is_present(stringify!($flag));
)*
$(
raw_args.$arg = if_option!(
$($arg_type_tt)+,
THEN {
if_option_vec!(
$($arg_type_tt)+,
THEN { values_t!(matches, stringify!($arg), inner_option_vec_type!($($arg_type_tt)+)).ok() }
ELSE { value_t!(matches, stringify!($arg), inner_option_type!($($arg_type_tt)+)).ok() }
)
}
ELSE {
if_vec!(
$($arg_type_tt)+,
THEN { values_t!(matches, stringify!($arg), inner_vec_type!($($arg_type_tt)+)).ok() }
ELSE { value_t!(matches, stringify!($arg), $($arg_type_tt)+).ok() }
)
}
);
)*
)*
// Subcommands
$(
if let Some(submatches) = matches.subcommand_matches(&underscore_to_hyphen!(&stringify!($subc)[4..])) {
raw_args.$subc = true;
// Subcommand flags
$(
raw_args.$subc_flag = submatches.is_present(&stringify!($subc_flag));
)*
// Subcommand arguments
$(
raw_args.$subc_arg = if_option!(
$($subc_arg_type_tt)+,
THEN {
if_option_vec!(
$($subc_arg_type_tt)+,
THEN { values_t!(submatches, stringify!($subc_arg), inner_option_vec_type!($($subc_arg_type_tt)+)).ok() }
ELSE { value_t!(submatches, stringify!($subc_arg), inner_option_type!($($subc_arg_type_tt)+)).ok() }
)
}
ELSE {
if_vec!(
$($subc_arg_type_tt)+,
THEN { values_t!(submatches, stringify!($subc_arg), inner_vec_type!($($subc_arg_type_tt)+)).ok() }
ELSE { value_t!(submatches, stringify!($subc_arg), $($subc_arg_type_tt)+).ok() }
)
}
);
)*
// Sub-subcommands
$(
if let Some(subsubmatches) = submatches.subcommand_matches(&underscore_to_hyphen!(&stringify!($subc_subc)[stringify!($subc).len()+1..])) {
raw_args.$subc_subc = true;
// Sub-subcommand flags
$(
raw_args.$subc_subc_flag = subsubmatches.is_present(&stringify!($subc_subc_flag));
)*
// Sub-subcommand arguments
$(
raw_args.$subc_subc_arg = if_option!(
$($subc_subc_arg_type_tt)+,
THEN {
if_option_vec!(
$($subc_subc_arg_type_tt)+,
THEN { values_t!(subsubmatches, stringify!($subc_subc_arg), inner_option_vec_type!($($subc_subc_arg_type_tt)+)).ok() }
ELSE { value_t!(subsubmatches, stringify!($subc_subc_arg), inner_option_type!($($subc_subc_arg_type_tt)+)).ok() }
)
}
ELSE {
if_vec!(
$($subc_subc_arg_type_tt)+,
THEN { values_t!(subsubmatches, stringify!($subc_subc_arg), inner_vec_type!($($subc_subc_arg_type_tt)+)).ok() }
ELSE { value_t!(subsubmatches, stringify!($subc_subc_arg), $($subc_subc_arg_type_tt)+).ok() }
)
}
);
)*
}
else {
raw_args.$subc_subc = false;
}
)*
}
else {
raw_args.$subc = false;
}
)*
Ok(raw_args)
}
}
#[test]
fn usages_valid() {
let re = Regex::new(r"^(?:(-[a-zA-Z-]+, )?--[a-z-]+(=\[[a-zA-Z]+\](\.\.\.)?|=<[a-zA-Z]+>(\.\.\.)?)?)|(?:\[[a-zA-Z-]+\])(\.\.\.)?|(?:<[a-zA-Z-]+>)(\.\.\.)?$").unwrap();
let usages = vec![
$(
$(
$(
$subc_subc_arg_usage,
)*
)*
$(
$subc_arg_usage,
)*
)*
$(
$(
$flag_usage,
)*
$(
$arg_usage,
)*
)*
];
for usage in &usages {
assert!(re.is_match(usage));
}
}
}
};
}

View File

@ -1,499 +0,0 @@
Parity. Ethereum Client.
By Wood/Paronyan/Kotewicz/Drwięga/Volf et al.
Copyright 2015, 2016, 2017 Parity Technologies (UK) Ltd
Usage:
parity [options]
parity ui [options]
parity dapp <path> [options]
parity daemon <pid-file> [options]
parity account (new | list ) [options]
parity account import <path>... [options]
parity wallet import <path> --password FILE [options]
parity import [ <file> ] [options]
parity export (blocks | state) [ <file> ] [options]
parity signer new-token [options]
parity signer list [options]
parity signer sign [ <id> ] [ --password FILE ] [options]
parity signer reject <id> [options]
parity snapshot <file> [options]
parity restore [ <file> ] [options]
parity tools hash <file>
parity db kill [options]
Operating Options:
--mode MODE Set the operating mode. MODE can be one of:
last - Uses the last-used mode, active if none.
active - Parity continuously syncs the chain.
passive - Parity syncs initially, then sleeps and
wakes regularly to resync.
dark - Parity syncs only when the RPC is active.
offline - Parity doesn't sync. (default: {flag_mode}).
--mode-timeout SECS Specify the number of seconds before inactivity
timeout occurs when mode is dark or passive
(default: {flag_mode_timeout}).
--mode-alarm SECS Specify the number of seconds before auto sleep
reawake timeout occurs when mode is passive
(default: {flag_mode_alarm}).
--auto-update SET Set a releases set to automatically update and
install.
all - All updates in the our release track.
critical - Only consensus/security updates.
none - No updates will be auto-installed.
(default: {flag_auto_update}).
--release-track TRACK Set which release track we should use for updates.
stable - Stable releases.
beta - Beta releases.
nightly - Nightly releases (unstable).
testing - Testing releases (do not use).
current - Whatever track this executable was
released on (default: {flag_release_track}).
--public-node Start Parity as a public web server. Account storage
and transaction signing will be delegated to the UI.
(default: {flag_public_node}).
--no-download Normally new releases will be downloaded ready for
updating. This disables it. Not recommended.
(default: {flag_no_download}).
--no-consensus Force the binary to run even if there are known
issues regarding consensus. Not recommended.
(default: {flag_no_consensus}).
--force-direct Run the originally installed version of Parity,
ignoring any updates that have since been installed.
--chain CHAIN Specify the blockchain type. CHAIN may be either a
JSON chain specification file or olympic, frontier,
homestead, mainnet, morden, ropsten, classic, expanse,
testnet, kovan or dev (default: {flag_chain}).
-d --base-path PATH Specify the base data storage path.
(default: {flag_base_path}).
--db-path PATH Specify the database directory path
(default: {flag_db_path}).
--keys-path PATH Specify the path for JSON key files to be found
(default: {flag_keys_path}).
--identity NAME Specify your node's name. (default: {flag_identity})
--light Experimental: run in light client mode. Light clients
synchronize a bare minimum of data and fetch necessary
data on-demand from the network. Much lower in storage,
potentially higher in bandwidth. Has no effect with
subcommands (default: {flag_light}).
Convenience Options:
-c --config CONFIG Specify a configuration. CONFIG may be either a
configuration file or a preset: dev, insecure, dev-insecure,
mining, or non-standard-ports.
(default: {flag_config}).
--ports-shift SHIFT Add SHIFT to all port numbers Parity is listening on.
Includes network port and all servers (RPC, WebSockets, UI, IPFS, SecretStore).
(default: {flag_ports_shift})
--unsafe-expose All servers will listen on external interfaces and will
be remotely accessible. It's equivalent with setting
the following: --{{ws,jsonrpc,ui,ipfs,secret_store,stratum}}-interface=all --*-hosts=all
This option is UNSAFE and should be used with great care!
(default: {flag_unsafe_expose})
Account Options:
--unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution.
ACCOUNTS is a comma-delimited list of addresses.
Implies --no-ui. (default: {flag_unlock:?})
--password FILE Provide a file containing a password for unlocking
an account. Leading and trailing whitespace is trimmed.
(default: {flag_password:?})
--keys-iterations NUM Specify the number of iterations to use when
deriving key from the password (bigger is more
secure) (default: {flag_keys_iterations}).
--no-hardware-wallets Disables hardware wallet support. (default: {flag_no_hardware_wallets})
--fast-unlock Use drasticly faster unlocking mode. This setting causes
raw secrets to be stored unprotected in memory,
so use with care. (default: {flag_fast_unlock})
UI Options:
--force-ui Enable Trusted UI WebSocket endpoint,
even when --unlock is in use. (default: {flag_force_ui})
--no-ui Disable Trusted UI WebSocket endpoint.
(default: {flag_no_ui})
--ui-port PORT Specify the port of Trusted UI server
(default: {flag_ui_port}).
--ui-interface IP Specify the hostname portion of the Trusted UI
server, IP should be an interface's IP address,
or local (default: {flag_ui_interface}).
--ui-hosts HOSTS List of allowed Host header values. This option will
validate the Host header sent by the browser, it
is additional security against some attack
vectors. Special options: "all", "none",
(default: {flag_ui_hosts}).
--ui-path PATH Specify directory where Trusted UIs tokens should
be stored. (default: {flag_ui_path})
--ui-no-validation Disable Origin and Host headers validation for
Trusted UI. WARNING: INSECURE. Used only for
development. (default: {flag_ui_no_validation})
Networking Options:
--no-warp Disable syncing from the snapshot over the network. (default: {flag_no_warp})
--port PORT Override the port on which the node should listen
(default: {flag_port}).
--min-peers NUM Try to maintain at least NUM peers (default: {flag_min_peers}).
--max-peers NUM Allow up to NUM peers (default: {flag_max_peers}).
--snapshot-peers NUM Allow additional NUM peers for a snapshot sync
(default: {flag_snapshot_peers}).
--nat METHOD Specify method to use for determining public
address. Must be one of: any, none, upnp,
extip:<IP> (default: {flag_nat}).
--network-id INDEX Override the network identifier from the chain we
are on. (default: {flag_network_id:?})
--bootnodes NODES Override the bootnodes from our chain. NODES should
be comma-delimited enodes. (default: {flag_bootnodes:?})
--no-discovery Disable new peer discovery. (default: {flag_no_discovery})
--node-key KEY Specify node secret key, either as 64-character hex
string or input to SHA3 operation. (default: {flag_node_key:?})
--reserved-peers FILE Provide a file containing enodes, one per line.
These nodes will always have a reserved slot on top
of the normal maximum peers. (default: {flag_reserved_peers:?})
--reserved-only Connect only to reserved nodes. (default: {flag_reserved_only})
--allow-ips FILTER Filter outbound connections. FILTER can be one of:
private - connect to private network IP addresses only;
public - connect to public network IP addresses only;
all - connect to any IP address;
none - block all (for use with a custom filter as below);
a custom filter list in the format: "private ip_range1 -ip_range2 ...".
Where ip_range1 would be allowed and ip_range2 blocked;
Custom blocks ("-ip_range") override custom allows ("ip_range");
(default: {flag_allow_ips}).
--max-pending-peers NUM Allow up to NUM pending connections. (default: {flag_max_pending_peers})
--no-ancient-blocks Disable downloading old blocks after snapshot restoration
or warp sync. (default: {flag_no_ancient_blocks})
--no-serve-light Disable serving of light peers. (default: {flag_no_serve_light})
API and Console Options:
--no-jsonrpc Disable the JSON-RPC API server. (default: {flag_no_jsonrpc})
--jsonrpc-port PORT Specify the port portion of the JSONRPC API server
(default: {flag_jsonrpc_port}).
--jsonrpc-interface IP Specify the hostname portion of the JSONRPC API
server, IP should be an interface's IP address, or
all (all interfaces) or local (default: {flag_jsonrpc_interface}).
--jsonrpc-cors URL Specify CORS header for JSON-RPC API responses.
(default: {flag_jsonrpc_cors:?})
--jsonrpc-apis APIS Specify the APIs available through the JSONRPC
interface. APIS is a comma-delimited list of API
name. Possible name are all, safe, web3, eth, net, personal,
parity, parity_set, traces, rpc, parity_accounts.
You can also disable a specific API by putting '-' in the front: all,-personal
(default: {flag_jsonrpc_apis}).
--jsonrpc-hosts HOSTS List of allowed Host header values. This option will
validate the Host header sent by the browser, it
is additional security against some attack
vectors. Special options: "all", "none",
(default: {flag_jsonrpc_hosts}).
--jsonrpc-server-threads NUM Enables experimental faster implementation of JSON-RPC server.
Requires Dapps server to be disabled
using --no-dapps. (default: {flag_jsonrpc_server_threads:?})
--jsonrpc-threads THREADS Turn on additional processing threads in all RPC servers.
Setting this to non-zero value allows parallel cpu-heavy queries
execution. (default: {flag_jsonrpc_threads})
--no-ws Disable the WebSockets server. (default: {flag_no_ws})
--ws-port PORT Specify the port portion of the WebSockets server
(default: {flag_ws_port}).
--ws-interface IP Specify the hostname portion of the WebSockets
server, IP should be an interface's IP address, or
all (all interfaces) or local (default: {flag_ws_interface}).
--ws-apis APIS Specify the APIs available through the WebSockets
interface. APIS is a comma-delimited list of API
name. Possible name are web3, eth, pubsub, net, personal,
parity, parity_set, traces, rpc, parity_accounts.
(default: {flag_ws_apis}).
--ws-origins URL Specify Origin header values allowed to connect.
Special options: "all", "none".
(default: {flag_ws_origins})
--ws-hosts HOSTS List of allowed Host header values. This option will
validate the Host header sent by the browser, it
is additional security against some attack
vectors. Special options: "all", "none",
(default: {flag_ws_hosts}).
--no-ipc Disable JSON-RPC over IPC service. (default: {flag_no_ipc})
--ipc-path PATH Specify custom path for JSON-RPC over IPC service
(default: {flag_ipc_path}).
--ipc-apis APIS Specify custom API set available via JSON-RPC over
IPC (default: {flag_ipc_apis}).
--no-dapps Disable the Dapps server (e.g. status page). (default: {flag_no_dapps})
--dapps-path PATH Specify directory where dapps should be installed.
(default: {flag_dapps_path})
--ipfs-api Enable IPFS-compatible HTTP API. (default: {flag_ipfs_api})
--ipfs-api-port PORT Configure on which port the IPFS HTTP API should listen.
(default: {flag_ipfs_api_port})
--ipfs-api-interface IP Specify the hostname portion of the IPFS API server,
IP should be an interface's IP address or local.
(default: {flag_ipfs_api_interface})
--ipfs-api-cors URL Specify CORS header for IPFS API responses.
(default: {flag_ipfs_api_cors:?})
--ipfs-api-hosts HOSTS List of allowed Host header values. This option will
validate the Host header sent by the browser, it
is additional security against some attack
vectors. Special options: "all", "none"
(default: {flag_ipfs_api_hosts}).
Secret Store Options:
--no-secretstore Disable Secret Store functionality. (default: {flag_no_secretstore})
--no-secretstore-http Disable Secret Store HTTP API. (default: {flag_no_secretstore_http})
--no-acl-check Disable ACL check (useful for test environments). (default: {flag_no_secretstore_acl_check})
--secretstore-secret SECRET Hex-encoded secret key of this node.
(required, default: {flag_secretstore_secret:?}).
--secretstore-nodes NODES Comma-separated list of other secret store cluster nodes in form
NODE_PUBLIC_KEY_IN_HEX@NODE_IP_ADDR:NODE_PORT.
(required, default: {flag_secretstore_nodes}).
--secretstore-interface IP Specify the hostname portion for listening to Secret Store Key Server
internal requests, IP should be an interface's IP address, or local
(default: {flag_secretstore_interface}).
--secretstore-port PORT Specify the port portion for listening to Secret Store Key Server
internal requests (default: {flag_secretstore_port}).
--secretstore-http-interface IP Specify the hostname portion for listening to Secret Store Key Server
HTTP requests, IP should be an interface's IP address, or local
(default: {flag_secretstore_http_interface}).
--secretstore-http-port PORT Specify the port portion for listening to Secret Store Key Server
HTTP requests (default: {flag_secretstore_http_port}).
--secretstore-path PATH Specify directory where Secret Store should save its data.
(default: {flag_secretstore_path}).
Sealing/Mining Options:
--author ADDRESS Specify the block author (aka "coinbase") address
for sending block rewards from sealed blocks.
NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.
(default: {flag_author:?})
--engine-signer ADDRESS Specify the address which should be used to
sign consensus messages and issue blocks.
Relevant only to non-PoW chains.
(default: {flag_engine_signer:?})
--force-sealing Force the node to author new blocks as if it were
always sealing/mining.
(default: {flag_force_sealing})
--reseal-on-txs SET Specify which transactions should force the node
to reseal a block. SET is one of:
none - never reseal on new transactions;
own - reseal only on a new local transaction;
ext - reseal only on a new external transaction;
all - reseal on all new transactions
(default: {flag_reseal_on_txs}).
--reseal-on-uncle Force the node to author new blocks when a new uncle
block is imported.
(default: {flag_reseal_on_uncle})
--reseal-min-period MS Specify the minimum time between reseals from
incoming transactions. MS is time measured in
milliseconds (default: {flag_reseal_min_period}).
--reseal-max-period MS Specify the maximum time since last block to enable
force-sealing. MS is time measured in
milliseconds (default: {flag_reseal_max_period}).
--work-queue-size ITEMS Specify the number of historical work packages
which are kept cached lest a solution is found for
them later. High values take more memory but result
in fewer unusable solutions (default: {flag_work_queue_size}).
--tx-gas-limit GAS Apply a limit of GAS as the maximum amount of gas
a single transaction may have for it to be mined.
(default: {flag_tx_gas_limit:?})
--tx-time-limit MS Maximal time for processing single transaction.
If enabled senders/recipients/code of transactions
offending the limit will be banned from being included
in transaction queue for 180 seconds.
(default: {flag_tx_time_limit:?})
--relay-set SET Set of transactions to relay. SET may be:
cheap - Relay any transaction in the queue (this
may include invalid transactions);
strict - Relay only executed transactions (this
guarantees we don't relay invalid transactions, but
means we relay nothing if not mining);
lenient - Same as strict when mining, and cheap
when not (default: {flag_relay_set}).
--min-gas-price WEI Minimum amount of Wei per GAS to be paid for a
transaction to be accepted for mining. Overrides
--basic-tx-usd.
(default: {flag_min_gas_price:?})
--usd-per-tx USD Amount of USD to be paid for a basic transaction
(default: {flag_usd_per_tx}). The minimum gas price is set
accordingly.
--usd-per-eth SOURCE USD value of a single ETH. SOURCE may be either an
amount in USD, a web service or 'auto' to use each
web service in turn and fallback on the last known
good value (default: {flag_usd_per_eth}).
--price-update-period T T will be allowed to pass between each gas price
update. T may be daily, hourly, a number of seconds,
or a time string of the form "2 days", "30 minutes"
etc. (default: {flag_price_update_period}).
--gas-floor-target GAS Amount of gas per block to target when sealing a new
block (default: {flag_gas_floor_target}).
--gas-cap GAS A cap on how large we will raise the gas limit per
block due to transaction volume (default: {flag_gas_cap}).
--extra-data STRING Specify a custom extra-data for authored blocks, no
more than 32 characters. (default: {flag_extra_data:?})
--tx-queue-mem-limit MB Maximum amount of memory that can be used by the
transaction queue. Setting this parameter to 0
disables limiting (default: {flag_tx_queue_mem_limit}).
--tx-queue-size LIMIT Maximum amount of transactions in the queue (waiting
to be included in next block) (default: {flag_tx_queue_size}).
--tx-queue-gas LIMIT Maximum amount of total gas for external transactions in
the queue. LIMIT can be either an amount of gas or
'auto' or 'off'. 'auto' sets the limit to be 20x
the current block gas limit. (default: {flag_tx_queue_gas}).
--tx-queue-strategy S Prioritization strategy used to order transactions
in the queue. S may be:
gas - Prioritize txs with low gas limit;
gas_price - Prioritize txs with high gas price;
gas_factor - Prioritize txs using gas price
and gas limit ratio (default: {flag_tx_queue_strategy}).
--tx-queue-ban-count C Number of times maximal time for execution (--tx-time-limit)
can be exceeded before banning sender/recipient/code.
(default: {flag_tx_queue_ban_count})
--tx-queue-ban-time SEC Banning time (in seconds) for offenders of specified
execution time limit. Also number of offending actions
have to reach the threshold within that time.
(default: {flag_tx_queue_ban_time} seconds)
--no-persistent-txqueue Don't save pending local transactions to disk to be
restored whenever the node restarts.
(default: {flag_no_persistent_txqueue}).
--remove-solved Move solved blocks from the work package queue
instead of cloning them. This gives a slightly
faster import speed, but means that extra solutions
submitted for the same work package will go unused.
(default: {flag_remove_solved})
--notify-work URLS URLs to which work package notifications are pushed.
URLS should be a comma-delimited list of HTTP URLs.
(default: {flag_notify_work:?})
--refuse-service-transactions Always refuse service transactions.
(default: {flag_refuse_service_transactions}).
--stratum Run Stratum server for miner push notification. (default: {flag_stratum})
--stratum-interface IP Interface address for Stratum server. (default: {flag_stratum_interface})
--stratum-port PORT Port for Stratum server to listen on. (default: {flag_stratum_port})
--stratum-secret STRING Secret for authorizing Stratum server for peers.
(default: {flag_stratum_secret:?})
Footprint Options:
--tracing BOOL Indicates if full transaction tracing should be
enabled. Works only if client had been fully synced
with tracing enabled. BOOL may be one of auto, on,
off. auto uses last used value of this option (off
if it does not exist) (default: {flag_tracing}).
--pruning METHOD Configure pruning of the state/storage trie. METHOD
may be one of auto, archive, fast:
archive - keep all state trie data. No pruning.
fast - maintain journal overlay. Fast but 50MB used.
auto - use the method most recently synced or
default to fast if none synced (default: {flag_pruning}).
--pruning-history NUM Set a minimum number of recent states to keep when pruning
is active. (default: {flag_pruning_history}).
--pruning-memory MB The ideal amount of memory in megabytes to use to store
recent states. As many states as possible will be kept
within this limit, and at least --pruning-history states
will always be kept. (default: {flag_pruning_memory})
--cache-size-db MB Override database cache size (default: {flag_cache_size_db}).
--cache-size-blocks MB Specify the prefered size of the blockchain cache in
megabytes (default: {flag_cache_size_blocks}).
--cache-size-queue MB Specify the maximum size of memory to use for block
queue (default: {flag_cache_size_queue}).
--cache-size-state MB Specify the maximum size of memory to use for
the state cache (default: {flag_cache_size_state}).
--cache-size MB Set total amount of discretionary memory to use for
the entire system, overrides other cache and queue
options. (default: {flag_cache_size:?})
--fast-and-loose Disables DB WAL, which gives a significant speed up
but means an unclean exit is unrecoverable. (default: {flag_fast_and_loose})
--db-compaction TYPE Database compaction type. TYPE may be one of:
ssd - suitable for SSDs and fast HDDs;
hdd - suitable for slow HDDs;
auto - determine automatically (default: {flag_db_compaction}).
--fat-db BOOL Build appropriate information to allow enumeration
of all accounts and storage keys. Doubles the size
of the state database. BOOL may be one of on, off
or auto. (default: {flag_fat_db})
--scale-verifiers Automatically scale amount of verifier threads based on
workload. Not guaranteed to be faster.
(default: {flag_scale_verifiers})
--num-verifiers INT Amount of verifier threads to use or to begin with, if verifier
auto-scaling is enabled. (default: {flag_num_verifiers:?})
Import/Export Options:
--from BLOCK Export from block BLOCK, which may be an index or
hash (default: {flag_from}).
--to BLOCK Export to (including) block BLOCK, which may be an
index, hash or 'latest' (default: {flag_to}).
--format FORMAT For import/export in given format. FORMAT must be
one of 'hex' and 'binary'.
(default: {flag_format:?} = Import: auto, Export: binary)
--no-seal-check Skip block seal check. (default: {flag_no_seal_check})
--at BLOCK Export state at the given block, which may be an
index, hash, or 'latest'. (default: {flag_at})
--no-storage Don't export account storage. (default: {flag_no_storage})
--no-code Don't export account code. (default: {flag_no_code})
--min-balance WEI Don't export accounts with balance less than specified.
(default: {flag_min_balance:?})
--max-balance WEI Don't export accounts with balance greater than specified.
(default: {flag_max_balance:?})
Snapshot Options:
--at BLOCK Take a snapshot at the given block, which may be an
index, hash, or 'latest'. Note that taking snapshots at
non-recent blocks will only work with --pruning archive
(default: {flag_at})
--no-periodic-snapshot Disable automated snapshots which usually occur once
every 10000 blocks. (default: {flag_no_periodic_snapshot})
Virtual Machine Options:
--jitvm Enable the JIT VM. (default: {flag_jitvm})
Whisper Options:
--whisper Enable the Whisper network. (default: {flag_whisper})
--whisper-pool-size MB Target size of the whisper message pool in megabytes.
(default: {flag_whisper_pool_size})
Legacy Options:
--geth Run in Geth-compatibility mode. Sets the IPC path
to be the same as Geth's. Overrides the --ipc-path
and --ipcpath options. Alters RPCs to reflect Geth
bugs. Includes the personal_ RPC by default.
--testnet Testnet mode. Equivalent to --chain testnet.
Overrides the --keys-path option.
--import-geth-keys Attempt to import keys from Geth client.
--datadir PATH Equivalent to --base-path PATH.
--networkid INDEX Equivalent to --network-id INDEX.
--peers NUM Equivalent to --min-peers NUM.
--nodekey KEY Equivalent to --node-key KEY.
--nodiscover Equivalent to --no-discovery.
-j --jsonrpc Does nothing; JSON-RPC is on by default now.
--jsonrpc-off Equivalent to --no-jsonrpc.
-w --webapp Does nothing; dapps server is on by default now.
--dapps-off Equivalent to --no-dapps.
--dapps-user USERNAME Dapps server authentication has been removed. (default: {flag_dapps_user:?})
--dapps-pass PASSWORD Dapps server authentication has been removed. (default: {flag_dapps_pass:?})
--dapps-apis-all Dapps server is merged with RPC server. Use --jsonrpc-apis. (default: {flag_dapps_apis_all:?})
--dapps-cors URL Dapps server is merged with RPC server. Use --jsonrpc-cors. (default: {flag_dapps_cors:?})
--dapps-hosts HOSTS Dapps server is merged with RPC server. Use --jsonrpc-hosts. (default: {flag_dapps_hosts:?})
--dapps-interface IP Dapps server is merged with RPC server. Use --jsonrpc-interface. (default: {flag_dapps_interface:?})
--dapps-port PORT Dapps server is merged with RPC server. Use --jsonrpc-port. (default: {flag_dapps_port:?})
--rpc Does nothing; JSON-RPC is on by default now.
--warp Does nothing; Warp sync is on by default. (default: {flag_warp})
--rpcaddr IP Equivalent to --jsonrpc-interface IP.
--rpcport PORT Equivalent to --jsonrpc-port PORT.
--rpcapi APIS Equivalent to --jsonrpc-apis APIS.
--rpccorsdomain URL Equivalent to --jsonrpc-cors URL.
--ipcdisable Equivalent to --no-ipc.
--ipc-off Equivalent to --no-ipc.
--ipcapi APIS Equivalent to --ipc-apis APIS.
--ipcpath PATH Equivalent to --ipc-path PATH.
--gasprice WEI Equivalent to --min-gas-price WEI.
--etherbase ADDRESS Equivalent to --author ADDRESS.
--extradata STRING Equivalent to --extra-data STRING.
--cache MB Equivalent to --cache-size MB.
Internal Options:
--can-restart Executable will auto-restart if exiting with 69.
Miscellaneous Options:
--ntp-servers HOSTS Comma separated list of NTP servers to provide current time (host:port).
Used to verify node health. Parity uses pool.ntp.org NTP servers,
consider joining the pool: http://www.pool.ntp.org/join.html
(default: {flag_ntp_servers})
-l --logging LOGGING Specify the logging level. Must conform to the same
format as RUST_LOG. (default: {flag_logging:?})
--log-file FILENAME Specify a filename into which logging should be
appended. (default: {flag_log_file:?})
--no-config Don't load a configuration file.
--no-color Don't use terminal color codes in output. (default: {flag_no_color})
-v --version Show information about version.
-h --help Show this screen.

View File

@ -0,0 +1,3 @@
Parity. Ethereum Client.
By Wood/Paronyan/Kotewicz/Drwięga/Volf et al.
Copyright 2015, 2016, 2017 Parity Technologies (UK) Ltd

View File

@ -7,4 +7,3 @@ There is NO WARRANTY, to the extent permitted by law.
By Wood/Paronyan/Kotewicz/Drwięga/Volf
Habermeier/Czaban/Greeff/Gotchac/Redmann

View File

@ -106,13 +106,13 @@ impl Configuration {
pub fn into_command(self) -> Result<Execute, String> {
let dirs = self.directories();
let pruning = self.args.flag_pruning.parse()?;
let pruning_history = self.args.flag_pruning_history;
let pruning = self.args.arg_pruning.parse()?;
let pruning_history = self.args.arg_pruning_history;
let vm_type = self.vm_type()?;
let spec = self.chain().parse()?;
let mode = match self.args.flag_mode.as_ref() {
let mode = match self.args.arg_mode.as_ref() {
"last" => None,
mode => Some(to_mode(&mode, self.args.flag_mode_timeout, self.args.flag_mode_alarm)?),
mode => Some(to_mode(&mode, self.args.arg_mode_timeout, self.args.arg_mode_alarm)?),
};
let update_policy = self.update_policy()?;
let logger_config = self.logger_config();
@ -123,18 +123,21 @@ impl Configuration {
let ui_conf = self.ui_config();
let network_id = self.network_id();
let cache_config = self.cache_config();
let tracing = self.args.flag_tracing.parse()?;
let fat_db = self.args.flag_fat_db.parse()?;
let compaction = self.args.flag_db_compaction.parse()?;
let tracing = self.args.arg_tracing.parse()?;
let fat_db = self.args.arg_fat_db.parse()?;
let compaction = self.args.arg_db_compaction.parse()?;
let wal = !self.args.flag_fast_and_loose;
match self.args.flag_warp {
// Logging is not initialized yet, so we print directly to stderr
Some(true) if fat_db == Switch::On => writeln!(&mut stderr(), "Warning: Warp Sync is disabled because Fat DB is turned on").expect("Error writing to stderr"),
Some(true) if tracing == Switch::On => writeln!(&mut stderr(), "Warning: Warp Sync is disabled because tracing is turned on").expect("Error writing to stderr"),
Some(true) if pruning == Pruning::Specific(Algorithm::Archive) => writeln!(&mut stderr(), "Warning: Warp Sync is disabled because pruning mode is set to archive").expect("Error writing to stderr"),
_ => {},
};
let public_node = self.args.flag_public_node;
if !self.args.flag_no_warp {
// Logging is not initialized yet, so we print directly to stderr
if fat_db == Switch::On {
writeln!(&mut stderr(), "Warning: Warp Sync is disabled because Fat DB is turned on").expect("Error writing to stderr");
} else if tracing == Switch::On {
writeln!(&mut stderr(), "Warning: Warp Sync is disabled because tracing is turned on").expect("Error writing to stderr");
} else if pruning == Pruning::Specific(Algorithm::Archive) {
writeln!(&mut stderr(), "Warning: Warp Sync is disabled because pruning mode is set to archive").expect("Error writing to stderr");
}
}
let warp_sync = !self.args.flag_no_warp && fat_db != Switch::On && tracing != Switch::On && pruning != Pruning::Specific(Algorithm::Archive);
let geth_compatibility = self.args.flag_geth;
let mut dapps_conf = self.dapps_config();
@ -142,9 +145,9 @@ impl Configuration {
let secretstore_conf = self.secretstore_config()?;
let format = self.format()?;
if self.args.flag_jsonrpc_server_threads.is_some() && dapps_conf.enabled {
if self.args.arg_jsonrpc_server_threads.is_some() && dapps_conf.enabled {
dapps_conf.enabled = false;
writeln!(&mut stderr(), "Warning: Disabling Dapps server because fast RPC server was enabled.").expect("Error writing to stderr.")
writeln!(&mut stderr(), "Warning: Disabling Dapps server because fast RPC server was enabled.").expect("Error writing to stderr.");
}
let cmd = if self.args.flag_version {
@ -152,25 +155,25 @@ impl Configuration {
} else if self.args.cmd_signer {
let authfile = ::signer::codes_path(&ws_conf.signer_path);
if self.args.cmd_new_token {
if self.args.cmd_signer_new_token {
Cmd::SignerToken(ws_conf, ui_conf, logger_config.clone())
} else if self.args.cmd_sign {
let pwfile = self.args.flag_password.get(0).map(|pwfile| {
} else if self.args.cmd_signer_sign {
let pwfile = self.args.arg_signer_sign_password.map(|pwfile| {
PathBuf::from(pwfile)
});
Cmd::SignerSign {
id: self.args.arg_id,
id: self.args.arg_signer_sign_id,
pwfile: pwfile,
port: ws_conf.port,
authfile: authfile,
}
} else if self.args.cmd_reject {
} else if self.args.cmd_signer_reject {
Cmd::SignerReject {
id: self.args.arg_id,
id: self.args.arg_signer_reject_id,
port: ws_conf.port,
authfile: authfile,
}
} else if self.args.cmd_list {
} else if self.args.cmd_signer_list {
Cmd::SignerList {
port: ws_conf.port,
authfile: authfile,
@ -178,32 +181,32 @@ impl Configuration {
} else {
unreachable!();
}
} else if self.args.cmd_tools && self.args.cmd_hash {
Cmd::Hash(self.args.arg_file)
} else if self.args.cmd_db && self.args.cmd_kill {
} else if self.args.cmd_tools && self.args.cmd_tools_hash {
Cmd::Hash(self.args.arg_tools_hash_file)
} else if self.args.cmd_db && self.args.cmd_db_kill {
Cmd::Blockchain(BlockchainCmd::Kill(KillBlockchain {
spec: spec,
dirs: dirs,
pruning: pruning,
}))
} else if self.args.cmd_account {
let account_cmd = if self.args.cmd_new {
let account_cmd = if self.args.cmd_account_new {
let new_acc = NewAccount {
iterations: self.args.flag_keys_iterations,
iterations: self.args.arg_keys_iterations,
path: dirs.keys,
spec: spec,
password_file: self.args.flag_password.first().cloned(),
password_file: self.args.arg_account_new_password.clone(),
};
AccountCmd::New(new_acc)
} else if self.args.cmd_list {
} else if self.args.cmd_account_list {
let list_acc = ListAccounts {
path: dirs.keys,
spec: spec,
};
AccountCmd::List(list_acc)
} else if self.args.cmd_import {
} else if self.args.cmd_account_import {
let import_acc = ImportAccounts {
from: self.args.arg_path.clone(),
from: self.args.arg_account_import_path.expect("CLI argument is required; qed").clone(),
to: dirs.keys,
spec: spec,
};
@ -223,11 +226,11 @@ impl Configuration {
Cmd::Account(account_cmd)
} else if self.args.cmd_wallet {
let presale_cmd = ImportWallet {
iterations: self.args.flag_keys_iterations,
iterations: self.args.arg_keys_iterations,
path: dirs.keys,
spec: spec,
wallet_path: self.args.arg_path.first().unwrap().clone(),
password_file: self.args.flag_password.first().cloned(),
wallet_path: self.args.arg_wallet_import_path.unwrap().clone(),
password_file: self.args.arg_wallet_import_password,
};
Cmd::ImportPresaleWallet(presale_cmd)
} else if self.args.cmd_import {
@ -235,11 +238,11 @@ impl Configuration {
spec: spec,
cache_config: cache_config,
dirs: dirs,
file_path: self.args.arg_file.clone(),
file_path: self.args.arg_import_file.clone(),
format: format,
pruning: pruning,
pruning_history: pruning_history,
pruning_memory: self.args.flag_pruning_memory,
pruning_memory: self.args.arg_pruning_memory,
compaction: compaction,
wal: wal,
tracing: tracing,
@ -252,44 +255,44 @@ impl Configuration {
};
Cmd::Blockchain(BlockchainCmd::Import(import_cmd))
} else if self.args.cmd_export {
if self.args.cmd_blocks {
if self.args.cmd_export_blocks {
let export_cmd = ExportBlockchain {
spec: spec,
cache_config: cache_config,
dirs: dirs,
file_path: self.args.arg_file.clone(),
file_path: self.args.arg_export_blocks_file.clone(),
format: format,
pruning: pruning,
pruning_history: pruning_history,
pruning_memory: self.args.flag_pruning_memory,
pruning_memory: self.args.arg_pruning_memory,
compaction: compaction,
wal: wal,
tracing: tracing,
fat_db: fat_db,
from_block: to_block_id(&self.args.flag_from)?,
to_block: to_block_id(&self.args.flag_to)?,
from_block: to_block_id(&self.args.arg_export_blocks_from)?,
to_block: to_block_id(&self.args.arg_export_blocks_to)?,
check_seal: !self.args.flag_no_seal_check,
};
Cmd::Blockchain(BlockchainCmd::Export(export_cmd))
} else if self.args.cmd_state {
} else if self.args.cmd_export_state {
let export_cmd = ExportState {
spec: spec,
cache_config: cache_config,
dirs: dirs,
file_path: self.args.arg_file.clone(),
file_path: self.args.arg_export_state_file.clone(),
format: format,
pruning: pruning,
pruning_history: pruning_history,
pruning_memory: self.args.flag_pruning_memory,
pruning_memory: self.args.arg_pruning_memory,
compaction: compaction,
wal: wal,
tracing: tracing,
fat_db: fat_db,
at: to_block_id(&self.args.flag_at)?,
storage: !self.args.flag_no_storage,
code: !self.args.flag_no_code,
min_balance: self.args.flag_min_balance.and_then(|s| to_u256(&s).ok()),
max_balance: self.args.flag_max_balance.and_then(|s| to_u256(&s).ok()),
at: to_block_id(&self.args.arg_export_state_at)?,
storage: !self.args.flag_export_state_no_storage,
code: !self.args.flag_export_state_no_code,
min_balance: self.args.arg_export_state_min_balance.and_then(|s| to_u256(&s).ok()),
max_balance: self.args.arg_export_state_max_balance.and_then(|s| to_u256(&s).ok()),
};
Cmd::Blockchain(BlockchainCmd::ExportState(export_cmd))
} else {
@ -302,14 +305,14 @@ impl Configuration {
spec: spec,
pruning: pruning,
pruning_history: pruning_history,
pruning_memory: self.args.flag_pruning_memory,
pruning_memory: self.args.arg_pruning_memory,
tracing: tracing,
fat_db: fat_db,
compaction: compaction,
file_path: self.args.arg_file.clone(),
file_path: self.args.arg_snapshot_file.clone(),
wal: wal,
kind: snapshot::Kind::Take,
block_at: to_block_id(&self.args.flag_at)?,
block_at: to_block_id(&self.args.arg_snapshot_at)?,
};
Cmd::Snapshot(snapshot_cmd)
} else if self.args.cmd_restore {
@ -319,11 +322,11 @@ impl Configuration {
spec: spec,
pruning: pruning,
pruning_history: pruning_history,
pruning_memory: self.args.flag_pruning_memory,
pruning_memory: self.args.arg_pruning_memory,
tracing: tracing,
fat_db: fat_db,
compaction: compaction,
file_path: self.args.arg_file.clone(),
file_path: self.args.arg_restore_file.clone(),
wal: wal,
kind: snapshot::Kind::Restore,
block_at: to_block_id("latest")?, // unimportant.
@ -331,7 +334,7 @@ impl Configuration {
Cmd::Snapshot(restore_cmd)
} else {
let daemon = if self.args.cmd_daemon {
Some(self.args.arg_pid_file.clone())
Some(self.args.arg_daemon_pid_file.clone().expect("CLI argument is required; qed"))
} else {
None
};
@ -345,10 +348,10 @@ impl Configuration {
spec: spec,
pruning: pruning,
pruning_history: pruning_history,
pruning_memory: self.args.flag_pruning_memory,
pruning_memory: self.args.arg_pruning_memory,
daemon: daemon,
logger_config: logger_config.clone(),
miner_options: self.miner_options(self.args.flag_reseal_min_period)?,
miner_options: self.miner_options(self.args.arg_reseal_min_period)?,
ntp_servers: self.ntp_servers(),
ws_conf: ws_conf,
http_conf: http_conf,
@ -376,8 +379,8 @@ impl Configuration {
secretstore_conf: secretstore_conf,
dapp: self.dapp_to_open()?,
ui: self.args.cmd_ui,
name: self.args.flag_identity,
custom_bootnodes: self.args.flag_bootnodes.is_some(),
name: self.args.arg_identity,
custom_bootnodes: self.args.arg_bootnodes.is_some(),
no_periodic_snapshot: self.args.flag_no_periodic_snapshot,
check_seal: !self.args.flag_no_seal_check,
download_old_blocks: !self.args.flag_no_ancient_blocks,
@ -408,8 +411,8 @@ impl Configuration {
let extras = MinerExtras {
author: self.author()?,
extra_data: self.extra_data()?,
gas_floor_target: to_u256(&self.args.flag_gas_floor_target)?,
gas_ceil_target: to_u256(&self.args.flag_gas_cap)?,
gas_floor_target: to_u256(&self.args.arg_gas_floor_target)?,
gas_ceil_target: to_u256(&self.args.arg_gas_cap)?,
engine_signer: self.engine_signer()?,
};
@ -417,37 +420,39 @@ impl Configuration {
}
fn author(&self) -> Result<Address, String> {
to_address(self.args.flag_etherbase.clone().or(self.args.flag_author.clone()))
to_address(self.args.arg_etherbase.clone().or(self.args.arg_author.clone()))
}
fn engine_signer(&self) -> Result<Address, String> {
to_address(self.args.flag_engine_signer.clone())
to_address(self.args.arg_engine_signer.clone())
}
fn format(&self) -> Result<Option<DataFormat>, String> {
match self.args.flag_format {
match self.args.arg_import_format.clone()
.or(self.args.arg_export_blocks_format.clone())
.or(self.args.arg_export_state_format.clone()) {
Some(ref f) => Ok(Some(f.parse()?)),
None => Ok(None),
}
}
fn cache_config(&self) -> CacheConfig {
match self.args.flag_cache_size.or(self.args.flag_cache) {
match self.args.arg_cache_size.or(self.args.arg_cache) {
Some(size) => CacheConfig::new_with_total_cache_size(size),
None => CacheConfig::new(
self.args.flag_cache_size_db,
self.args.flag_cache_size_blocks,
self.args.flag_cache_size_queue,
self.args.flag_cache_size_state,
self.args.arg_cache_size_db,
self.args.arg_cache_size_blocks,
self.args.arg_cache_size_queue,
self.args.arg_cache_size_state,
),
}
}
fn logger_config(&self) -> LogConfig {
LogConfig {
mode: self.args.flag_logging.clone(),
mode: self.args.arg_logging.clone(),
color: !self.args.flag_no_color && !cfg!(windows),
file: self.args.flag_log_file.clone(),
file: self.args.arg_log_file.clone(),
}
}
@ -458,44 +463,44 @@ impl Configuration {
else if self.args.flag_testnet {
"testnet".to_owned()
} else {
self.args.flag_chain.clone()
self.args.arg_chain.clone()
}
}
fn max_peers(&self) -> u32 {
let peers = self.args.flag_max_peers as u32;
let peers = self.args.arg_max_peers as u32;
max(self.min_peers(), peers)
}
fn ip_filter(&self) -> Result<IpFilter, String> {
match IpFilter::parse(self.args.flag_allow_ips.as_str()) {
match IpFilter::parse(self.args.arg_allow_ips.as_str()) {
Ok(allow_ip) => Ok(allow_ip),
Err(_) => Err("Invalid IP filter value".to_owned()),
}
}
fn min_peers(&self) -> u32 {
self.args.flag_peers.unwrap_or(self.args.flag_min_peers) as u32
self.args.arg_peers.unwrap_or(self.args.arg_min_peers) as u32
}
fn max_pending_peers(&self) -> u32 {
self.args.flag_max_pending_peers as u32
self.args.arg_max_pending_peers as u32
}
fn snapshot_peers(&self) -> u32 {
self.args.flag_snapshot_peers as u32
self.args.arg_snapshot_peers as u32
}
fn work_notify(&self) -> Vec<String> {
self.args.flag_notify_work.as_ref().map_or_else(Vec::new, |s| s.split(',').map(|s| s.to_owned()).collect())
self.args.arg_notify_work.as_ref().map_or_else(Vec::new, |s| s.split(',').map(|s| s.to_owned()).collect())
}
fn accounts_config(&self) -> Result<AccountsConfig, String> {
let cfg = AccountsConfig {
iterations: self.args.flag_keys_iterations,
iterations: self.args.arg_keys_iterations,
testnet: self.args.flag_testnet,
password_files: self.args.flag_password.clone(),
unlocked_accounts: to_addresses(&self.args.flag_unlock)?,
password_files: self.args.arg_password.clone(),
unlocked_accounts: to_addresses(&self.args.arg_unlock)?,
enable_hardware_wallets: !self.args.flag_no_hardware_wallets,
enable_fast_unlock: self.args.flag_fast_unlock,
};
@ -508,8 +513,8 @@ impl Configuration {
Ok(Some(StratumOptions {
io_path: self.directories().db,
listen_addr: self.stratum_interface(),
port: self.args.flag_ports_shift + self.args.flag_stratum_port,
secret: self.args.flag_stratum_secret.as_ref().map(|s| s.parse::<H256>().unwrap_or_else(|_| keccak(s))),
port: self.args.arg_ports_shift + self.args.arg_stratum_port,
secret: self.args.arg_stratum_secret.as_ref().map(|s| s.parse::<H256>().unwrap_or_else(|_| keccak(s))),
}))
} else { Ok(None) }
}
@ -519,7 +524,7 @@ impl Configuration {
return Err("Force sealing can't be used with reseal_min_period = 0".into());
}
let reseal = self.args.flag_reseal_on_txs.parse::<ResealPolicy>()?;
let reseal = self.args.arg_reseal_on_txs.parse::<ResealPolicy>()?;
let options = MinerOptions {
new_work_notify: self.work_notify(),
@ -527,26 +532,26 @@ impl Configuration {
reseal_on_external_tx: reseal.external,
reseal_on_own_tx: reseal.own,
reseal_on_uncle: self.args.flag_reseal_on_uncle,
tx_gas_limit: match self.args.flag_tx_gas_limit {
tx_gas_limit: match self.args.arg_tx_gas_limit {
Some(ref d) => to_u256(d)?,
None => U256::max_value(),
},
tx_queue_size: self.args.flag_tx_queue_size,
tx_queue_memory_limit: if self.args.flag_tx_queue_mem_limit > 0 {
Some(self.args.flag_tx_queue_mem_limit as usize * 1024 * 1024)
tx_queue_size: self.args.arg_tx_queue_size,
tx_queue_memory_limit: if self.args.arg_tx_queue_mem_limit > 0 {
Some(self.args.arg_tx_queue_mem_limit as usize * 1024 * 1024)
} else { None },
tx_queue_gas_limit: to_gas_limit(&self.args.flag_tx_queue_gas)?,
tx_queue_strategy: to_queue_strategy(&self.args.flag_tx_queue_strategy)?,
pending_set: to_pending_set(&self.args.flag_relay_set)?,
tx_queue_gas_limit: to_gas_limit(&self.args.arg_tx_queue_gas)?,
tx_queue_strategy: to_queue_strategy(&self.args.arg_tx_queue_strategy)?,
pending_set: to_pending_set(&self.args.arg_relay_set)?,
reseal_min_period: Duration::from_millis(reseal_min_period),
reseal_max_period: Duration::from_millis(self.args.flag_reseal_max_period),
work_queue_size: self.args.flag_work_queue_size,
reseal_max_period: Duration::from_millis(self.args.arg_reseal_max_period),
work_queue_size: self.args.arg_work_queue_size,
enable_resubmission: !self.args.flag_remove_solved,
tx_queue_banning: match self.args.flag_tx_time_limit {
tx_queue_banning: match self.args.arg_tx_time_limit {
Some(limit) => Banning::Enabled {
min_offends: self.args.flag_tx_queue_ban_count,
min_offends: self.args.arg_tx_queue_ban_count,
offend_threshold: Duration::from_millis(limit),
ban_duration: Duration::from_secs(self.args.flag_tx_queue_ban_time as u64),
ban_duration: Duration::from_secs(self.args.arg_tx_queue_ban_time as u64),
},
None => Banning::Disabled,
},
@ -557,11 +562,11 @@ impl Configuration {
}
fn ui_port(&self) -> u16 {
self.args.flag_ports_shift + self.args.flag_ui_port
self.args.arg_ports_shift + self.args.arg_ui_port
}
fn ntp_servers(&self) -> Vec<String> {
self.args.flag_ntp_servers.split(",").map(str::to_owned).collect()
self.args.arg_ntp_servers.split(",").map(str::to_owned).collect()
}
fn ui_config(&self) -> UiConfiguration {
@ -581,7 +586,7 @@ impl Configuration {
enabled: self.dapps_enabled(),
dapps_path: PathBuf::from(self.directories().dapps),
extra_dapps: if self.args.cmd_dapp {
self.args.arg_path.iter().map(|path| PathBuf::from(path)).collect()
self.args.arg_dapp_path.iter().map(|path| PathBuf::from(path)).collect()
} else {
vec![]
},
@ -616,9 +621,9 @@ impl Configuration {
self_secret: self.secretstore_self_secret()?,
nodes: self.secretstore_nodes()?,
interface: self.secretstore_interface(),
port: self.args.flag_ports_shift + self.args.flag_secretstore_port,
port: self.args.arg_ports_shift + self.args.arg_secretstore_port,
http_interface: self.secretstore_http_interface(),
http_port: self.args.flag_ports_shift + self.args.flag_secretstore_http_port,
http_port: self.args.arg_ports_shift + self.args.arg_secretstore_http_port,
data_path: self.directories().secretstore,
})
}
@ -626,7 +631,7 @@ impl Configuration {
fn ipfs_config(&self) -> IpfsConfiguration {
IpfsConfiguration {
enabled: self.args.flag_ipfs_api,
port: self.args.flag_ports_shift + self.args.flag_ipfs_api_port,
port: self.args.arg_ports_shift + self.args.arg_ipfs_api_port,
interface: self.ipfs_interface(),
cors: self.ipfs_cors(),
hosts: self.ipfs_hosts(),
@ -637,7 +642,7 @@ impl Configuration {
if !self.args.cmd_dapp {
return Ok(None);
}
let path = self.args.arg_path.get(0).map(String::as_str).unwrap_or(".");
let path = self.args.arg_dapp_path.as_ref().map(String::as_str).unwrap_or(".");
let path = Path::new(path).canonicalize()
.map_err(|e| format!("Invalid path: {}. Error: {:?}", path, e))?;
let name = path.file_name()
@ -654,14 +659,14 @@ impl Configuration {
U256::from_dec_str(&format!("{:.0}", wei_per_gas)).unwrap()
}
if let Some(dec) = self.args.flag_gasprice.as_ref() {
if let Some(dec) = self.args.arg_gasprice.as_ref() {
return Ok(GasPricerConfig::Fixed(to_u256(dec)?));
} else if let Some(dec) = self.args.flag_min_gas_price {
} else if let Some(dec) = self.args.arg_min_gas_price {
return Ok(GasPricerConfig::Fixed(U256::from(dec)));
}
let usd_per_tx = to_price(&self.args.flag_usd_per_tx)?;
if "auto" == self.args.flag_usd_per_eth.as_str() {
let usd_per_tx = to_price(&self.args.arg_usd_per_tx)?;
if "auto" == self.args.arg_usd_per_eth.as_str() {
// Just a very rough estimate to avoid accepting
// ZGP transactions before the price is fetched
// if user does not want it.
@ -669,11 +674,11 @@ impl Configuration {
return Ok(GasPricerConfig::Calibrated {
initial_minimum: wei_per_gas(usd_per_tx, last_known_usd_per_eth),
usd_per_tx: usd_per_tx,
recalibration_period: to_duration(self.args.flag_price_update_period.as_str())?,
recalibration_period: to_duration(self.args.arg_price_update_period.as_str())?,
});
}
let usd_per_eth = to_price(&self.args.flag_usd_per_eth)?;
let usd_per_eth = to_price(&self.args.arg_usd_per_eth)?;
let wei_per_gas = wei_per_gas(usd_per_tx, usd_per_eth);
info!(
@ -686,7 +691,7 @@ impl Configuration {
}
fn extra_data(&self) -> Result<Bytes, String> {
match self.args.flag_extradata.as_ref().or(self.args.flag_extra_data.as_ref()) {
match self.args.arg_extradata.as_ref().or(self.args.arg_extra_data.as_ref()) {
Some(x) if x.len() <= 32 => Ok(x.as_bytes().to_owned()),
None => Ok(version_data()),
Some(_) => Err("Extra data must be at most 32 characters".into()),
@ -696,7 +701,7 @@ impl Configuration {
fn init_reserved_nodes(&self) -> Result<Vec<String>, String> {
use std::fs::File;
match self.args.flag_reserved_peers {
match self.args.arg_reserved_peers {
Some(ref path) => {
let mut buffer = String::new();
let mut node_file = File::open(path).map_err(|e| format!("Error opening reserved nodes file: {}", e))?;
@ -712,10 +717,10 @@ impl Configuration {
}
fn net_addresses(&self) -> Result<(SocketAddr, Option<SocketAddr>), String> {
let port = self.args.flag_ports_shift + self.args.flag_port;
let port = self.args.arg_ports_shift + self.args.arg_port;
let listen_address = SocketAddr::new("0.0.0.0".parse().unwrap(), port);
let public_address = if self.args.flag_nat.starts_with("extip:") {
let host = &self.args.flag_nat[6..];
let public_address = if self.args.arg_nat.starts_with("extip:") {
let host = &self.args.arg_nat[6..];
let host = host.parse().map_err(|_| format!("Invalid host given with `--nat extip:{}`", host))?;
Some(SocketAddr::new(host, port))
} else {
@ -726,12 +731,12 @@ impl Configuration {
fn net_config(&self) -> Result<NetworkConfiguration, String> {
let mut ret = NetworkConfiguration::new();
ret.nat_enabled = self.args.flag_nat == "any" || self.args.flag_nat == "upnp";
ret.boot_nodes = to_bootnodes(&self.args.flag_bootnodes)?;
ret.nat_enabled = self.args.arg_nat == "any" || self.args.arg_nat == "upnp";
ret.boot_nodes = to_bootnodes(&self.args.arg_bootnodes)?;
let (listen, public) = self.net_addresses()?;
ret.listen_address = Some(format!("{}", listen));
ret.public_address = public.map(|p| format!("{}", p));
ret.use_secret = match self.args.flag_node_key.as_ref()
ret.use_secret = match self.args.arg_node_key.as_ref()
.map(|s| s.parse::<Secret>().or_else(|_| Secret::from_unsafe_slice(&keccak(s))).map_err(|e| format!("Invalid key: {:?}", e))
) {
None => None,
@ -753,13 +758,13 @@ impl Configuration {
}
fn network_id(&self) -> Option<u64> {
self.args.flag_network_id.or(self.args.flag_networkid)
self.args.arg_network_id.or(self.args.arg_networkid)
}
fn rpc_apis(&self) -> String {
let mut apis: Vec<&str> = self.args.flag_rpcapi
let mut apis: Vec<&str> = self.args.arg_rpcapi
.as_ref()
.unwrap_or(&self.args.flag_jsonrpc_apis)
.unwrap_or(&self.args.arg_jsonrpc_apis)
.split(",")
.collect();
@ -775,12 +780,12 @@ impl Configuration {
}
fn rpc_cors(&self) -> Option<Vec<String>> {
let cors = self.args.flag_jsonrpc_cors.as_ref().or(self.args.flag_rpccorsdomain.as_ref());
let cors = self.args.arg_jsonrpc_cors.as_ref().or(self.args.arg_rpccorsdomain.as_ref());
Self::cors(cors)
}
fn ipfs_cors(&self) -> Option<Vec<String>> {
Self::cors(self.args.flag_ipfs_api_cors.as_ref())
Self::cors(self.args.arg_ipfs_api_cors.as_ref())
}
fn hosts(&self, hosts: &str, interface: &str) -> Option<Vec<String>> {
@ -806,15 +811,15 @@ impl Configuration {
}
fn ui_hosts(&self) -> Option<Vec<String>> {
self.hosts(&self.args.flag_ui_hosts, &self.ui_interface())
self.hosts(&self.args.arg_ui_hosts, &self.ui_interface())
}
fn rpc_hosts(&self) -> Option<Vec<String>> {
self.hosts(&self.args.flag_jsonrpc_hosts, &self.rpc_interface())
self.hosts(&self.args.arg_jsonrpc_hosts, &self.rpc_interface())
}
fn ws_hosts(&self) -> Option<Vec<String>> {
self.hosts(&self.args.flag_ws_hosts, &self.ws_interface())
self.hosts(&self.args.arg_ws_hosts, &self.ws_interface())
}
fn ws_origins(&self) -> Option<Vec<String>> {
@ -822,11 +827,11 @@ impl Configuration {
return None;
}
Self::parse_hosts(&self.args.flag_ws_origins)
Self::parse_hosts(&self.args.arg_ws_origins)
}
fn ipfs_hosts(&self) -> Option<Vec<String>> {
self.hosts(&self.args.flag_ipfs_api_hosts, &self.ipfs_interface())
self.hosts(&self.args.arg_ipfs_api_hosts, &self.ipfs_interface())
}
fn ipc_config(&self) -> Result<IpcConfiguration, String> {
@ -834,7 +839,7 @@ impl Configuration {
enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off || self.args.flag_no_ipc),
socket_addr: self.ipc_path(),
apis: {
let mut apis = self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone());
let mut apis = self.args.arg_ipcapi.clone().unwrap_or(self.args.arg_ipc_apis.clone());
if self.args.flag_geth {
if !apis.is_empty() {
apis.push_str(",");
@ -852,19 +857,19 @@ impl Configuration {
let conf = HttpConfiguration {
enabled: self.rpc_enabled(),
interface: self.rpc_interface(),
port: self.args.flag_ports_shift + self.args.flag_rpcport.unwrap_or(self.args.flag_jsonrpc_port),
port: self.args.arg_ports_shift + self.args.arg_rpcport.unwrap_or(self.args.arg_jsonrpc_port),
apis: match self.args.flag_public_node {
false => self.rpc_apis().parse()?,
true => self.rpc_apis().parse::<ApiSet>()?.retain(ApiSet::PublicContext),
},
hosts: self.rpc_hosts(),
cors: self.rpc_cors(),
server_threads: match self.args.flag_jsonrpc_server_threads {
server_threads: match self.args.arg_jsonrpc_server_threads {
Some(threads) if threads > 0 => Some(threads),
None => None,
_ => return Err("--jsonrpc-server-threads number needs to be positive.".into()),
},
processing_threads: self.args.flag_jsonrpc_threads,
processing_threads: self.args.arg_jsonrpc_threads,
};
Ok(conf)
@ -876,8 +881,8 @@ impl Configuration {
let conf = WsConfiguration {
enabled: self.ws_enabled(),
interface: self.ws_interface(),
port: self.args.flag_ports_shift + self.args.flag_ws_port,
apis: self.args.flag_ws_apis.parse()?,
port: self.args.arg_ports_shift + self.args.arg_ws_port,
apis: self.args.arg_ws_apis.parse()?,
hosts: self.ws_hosts(),
origins: self.ws_origins(),
signer_path: self.directories().signer.into(),
@ -892,7 +897,7 @@ impl Configuration {
let http_conf = self.http_config()?;
let net_addresses = self.net_addresses()?;
Ok(NetworkSettings {
name: self.args.flag_identity.clone(),
name: self.args.arg_identity.clone(),
chain: self.chain(),
network_port: net_addresses.0.port(),
rpc_enabled: http_conf.enabled,
@ -905,13 +910,13 @@ impl Configuration {
Ok(UpdatePolicy {
enable_downloading: !self.args.flag_no_download,
require_consensus: !self.args.flag_no_consensus,
filter: match self.args.flag_auto_update.as_ref() {
filter: match self.args.arg_auto_update.as_ref() {
"none" => UpdateFilter::None,
"critical" => UpdateFilter::Critical,
"all" => UpdateFilter::All,
_ => return Err("Invalid value for `--auto-update`. See `--help` for more information.".into()),
},
track: match self.args.flag_release_track.as_ref() {
track: match self.args.arg_release_track.as_ref() {
"stable" => ReleaseTrack::Stable,
"beta" => ReleaseTrack::Beta,
"nightly" => ReleaseTrack::Nightly,
@ -927,23 +932,23 @@ impl Configuration {
use path;
let local_path = default_local_path();
let base_path = self.args.flag_base_path.as_ref().or_else(|| self.args.flag_datadir.as_ref()).map_or_else(|| default_data_path(), |s| s.clone());
let base_path = self.args.arg_base_path.as_ref().or_else(|| self.args.arg_datadir.as_ref()).map_or_else(|| default_data_path(), |s| s.clone());
let data_path = replace_home("", &base_path);
let is_using_base_path = self.args.flag_base_path.is_some();
let is_using_base_path = self.args.arg_base_path.is_some();
// If base_path is set and db_path is not we default to base path subdir instead of LOCAL.
let base_db_path = if is_using_base_path && self.args.flag_db_path.is_none() {
let base_db_path = if is_using_base_path && self.args.arg_db_path.is_none() {
"$BASE/chains"
} else {
self.args.flag_db_path.as_ref().map_or(dir::CHAINS_PATH, |s| &s)
self.args.arg_db_path.as_ref().map_or(dir::CHAINS_PATH, |s| &s)
};
let cache_path = if is_using_base_path { "$BASE/cache" } else { dir::CACHE_PATH };
let db_path = replace_home_and_local(&data_path, &local_path, &base_db_path);
let cache_path = replace_home_and_local(&data_path, &local_path, cache_path);
let keys_path = replace_home(&data_path, &self.args.flag_keys_path);
let dapps_path = replace_home(&data_path, &self.args.flag_dapps_path);
let secretstore_path = replace_home(&data_path, &self.args.flag_secretstore_path);
let ui_path = replace_home(&data_path, &self.args.flag_ui_path);
let keys_path = replace_home(&data_path, &self.args.arg_keys_path);
let dapps_path = replace_home(&data_path, &self.args.arg_dapps_path);
let secretstore_path = replace_home(&data_path, &self.args.arg_secretstore_path);
let ui_path = replace_home(&data_path, &self.args.arg_ui_path);
if self.args.flag_geth && !cfg!(windows) {
let geth_root = if self.chain() == "testnet".to_owned() { path::ethereum::test() } else { path::ethereum::default() };
@ -977,8 +982,8 @@ impl Configuration {
} else {
parity_ipc_path(
&self.directories().base,
&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone()),
self.args.flag_ports_shift,
&self.args.arg_ipcpath.clone().unwrap_or(self.args.arg_ipc_path.clone()),
self.args.arg_ports_shift,
)
}
}
@ -996,32 +1001,32 @@ impl Configuration {
}
fn ui_interface(&self) -> String {
self.interface(&self.args.flag_ui_interface)
self.interface(&self.args.arg_ui_interface)
}
fn rpc_interface(&self) -> String {
let rpc_interface = self.args.flag_rpcaddr.clone().unwrap_or(self.args.flag_jsonrpc_interface.clone());
let rpc_interface = self.args.arg_rpcaddr.clone().unwrap_or(self.args.arg_jsonrpc_interface.clone());
self.interface(&rpc_interface)
}
fn ws_interface(&self) -> String {
self.interface(&self.args.flag_ws_interface)
self.interface(&self.args.arg_ws_interface)
}
fn ipfs_interface(&self) -> String {
self.interface(&self.args.flag_ipfs_api_interface)
self.interface(&self.args.arg_ipfs_api_interface)
}
fn secretstore_interface(&self) -> String {
self.interface(&self.args.flag_secretstore_interface)
self.interface(&self.args.arg_secretstore_interface)
}
fn secretstore_http_interface(&self) -> String {
self.interface(&self.args.flag_secretstore_http_interface)
self.interface(&self.args.arg_secretstore_http_interface)
}
fn secretstore_self_secret(&self) -> Result<Option<NodeSecretKey>, String> {
match self.args.flag_secretstore_secret {
match self.args.arg_secretstore_secret {
Some(ref s) if s.len() == 64 => Ok(Some(NodeSecretKey::Plain(s.parse()
.map_err(|e| format!("Invalid secret store secret: {}. Error: {:?}", s, e))?))),
Some(ref s) if s.len() == 40 => Ok(Some(NodeSecretKey::KeyStore(s.parse()
@ -1033,7 +1038,7 @@ impl Configuration {
fn secretstore_nodes(&self) -> Result<BTreeMap<Public, (String, u16)>, String> {
let mut nodes = BTreeMap::new();
for node in self.args.flag_secretstore_nodes.split(',').filter(|n| n != &"") {
for node in self.args.arg_secretstore_nodes.split(',').filter(|n| n != &"") {
let public_and_addr: Vec<_> = node.split('@').collect();
if public_and_addr.len() != 2 {
return Err(format!("Invalid secret store node: {}", node));
@ -1056,7 +1061,7 @@ impl Configuration {
}
fn stratum_interface(&self) -> String {
self.interface(&self.args.flag_stratum_interface)
self.interface(&self.args.arg_stratum_interface)
}
fn rpc_enabled(&self) -> bool {
@ -1088,7 +1093,7 @@ impl Configuration {
return true;
}
let ui_disabled = self.args.flag_unlock.is_some() ||
let ui_disabled = self.args.arg_unlock.is_some() ||
self.args.flag_geth ||
self.args.flag_no_ui;
@ -1098,7 +1103,7 @@ impl Configuration {
fn verifier_settings(&self) -> VerifierSettings {
let mut settings = VerifierSettings::default();
settings.scale_verifiers = self.args.flag_scale_verifiers;
if let Some(num_verifiers) = self.args.flag_num_verifiers {
if let Some(num_verifiers) = self.args.arg_num_verifiers {
settings.num_verifiers = num_verifiers;
}
@ -1108,7 +1113,7 @@ impl Configuration {
fn whisper_config(&self) -> ::whisper::Config {
::whisper::Config {
enabled: self.args.flag_whisper,
target_message_pool_size: self.args.flag_whisper_pool_size * 1024 * 1024,
target_message_pool_size: self.args.arg_whisper_pool_size * 1024 * 1024,
}
}
}
@ -1404,7 +1409,7 @@ mod tests {
let conf3 = parse(&["parity", "--tx-queue-strategy", "gas"]);
// then
let min_period = conf0.args.flag_reseal_min_period;
let min_period = conf0.args.arg_reseal_min_period;
assert_eq!(conf0.miner_options(min_period).unwrap(), mining_options);
mining_options.tx_queue_strategy = PrioritizationStrategy::GasFactorAndGasPrice;
assert_eq!(conf1.miner_options(min_period).unwrap(), mining_options);
@ -1563,10 +1568,10 @@ mod tests {
// given
// when
let conf0 = parse(&["parity", "--ui-path", "signer"]);
let conf1 = parse(&["parity", "--ui-path", "signer", "--ui-no-validation"]);
let conf2 = parse(&["parity", "--ui-path", "signer", "--ui-port", "3123"]);
let conf3 = parse(&["parity", "--ui-path", "signer", "--ui-interface", "test"]);
let conf0 = parse(&["parity", "--ui-path=signer"]);
let conf1 = parse(&["parity", "--ui-path=signer", "--ui-no-validation"]);
let conf2 = parse(&["parity", "--ui-path=signer", "--ui-port", "3123"]);
let conf3 = parse(&["parity", "--ui-path=signer", "--ui-interface", "test"]);
// then
assert_eq!(conf0.directories().signer, "signer".to_owned());

View File

@ -65,40 +65,40 @@ pub fn find_deprecated(args: &Args) -> Vec<Deprecated> {
result.push(Deprecated::Replaced("--ipc-off", "--no-ipc"));
}
if args.flag_etherbase.is_some() {
if args.arg_etherbase.is_some() {
result.push(Deprecated::Replaced("--etherbase", "--author"));
}
if args.flag_extradata.is_some() {
if args.arg_extradata.is_some() {
result.push(Deprecated::Replaced("--extradata", "--extra-data"));
}
// Removed in 1.7
if args.flag_dapps_port.is_some() {
if args.arg_dapps_port.is_some() {
result.push(Deprecated::Replaced("--dapps-port", "--jsonrpc-port"));
}
if args.flag_dapps_interface.is_some() {
if args.arg_dapps_interface.is_some() {
result.push(Deprecated::Replaced("--dapps-interface", "--jsonrpc-interface"));
}
if args.flag_dapps_hosts.is_some() {
if args.arg_dapps_hosts.is_some() {
result.push(Deprecated::Replaced("--dapps-hosts", "--jsonrpc-hosts"));
}
if args.flag_dapps_cors.is_some() {
if args.arg_dapps_cors.is_some() {
result.push(Deprecated::Replaced("--dapps-cors", "--jsonrpc-cors"));
}
if args.flag_dapps_user.is_some() {
if args.arg_dapps_user.is_some() {
result.push(Deprecated::Removed("--dapps-user"));
}
if args.flag_dapps_pass.is_some() {
if args.arg_dapps_pass.is_some() {
result.push(Deprecated::Removed("--dapps-pass"));
}
if args.flag_dapps_apis_all.is_some() {
if args.flag_dapps_apis_all {
result.push(Deprecated::Replaced("--dapps-apis-all", "--jsonrpc-apis"));
}
@ -124,15 +124,15 @@ mod tests {
args.flag_dapps_off = true;
args.flag_ipcdisable = true;
args.flag_ipc_off = true;
args.flag_etherbase = Some(Default::default());
args.flag_extradata = Some(Default::default());
args.flag_dapps_port = Some(Default::default());
args.flag_dapps_interface = Some(Default::default());
args.flag_dapps_hosts = Some(Default::default());
args.flag_dapps_cors = Some(Default::default());
args.flag_dapps_user = Some(Default::default());
args.flag_dapps_pass = Some(Default::default());
args.flag_dapps_apis_all = Some(Default::default());
args.arg_etherbase = Some(Default::default());
args.arg_extradata = Some(Default::default());
args.arg_dapps_port = Some(Default::default());
args.arg_dapps_interface = Some(Default::default());
args.arg_dapps_hosts = Some(Default::default());
args.arg_dapps_cors = Some(Default::default());
args.arg_dapps_user = Some(Default::default());
args.arg_dapps_pass = Some(Default::default());
args.flag_dapps_apis_all = true;
args
}), vec![
Deprecated::DoesNothing("--jsonrpc"),

View File

@ -26,6 +26,8 @@ extern crate ansi_term;
extern crate app_dirs;
extern crate ctrlc;
extern crate docopt;
#[macro_use]
extern crate clap;
extern crate env_logger;
extern crate fdlimit;
extern crate futures;